MCP Server
Inherent exposes its knowledge base directly to AI agents over the Model Context Protocol (MCP), so an agent can search, read, and manage your documents without going through a REST client you have to write yourself.
MCP tools use the same API keys as the REST API (ink_..., created under API Keys in the dashboard) and enforce the same read / write / search permissions per tool.
Endpoint
| Transport | Streamable HTTP (POST /mcp) |
| URL | https://api.inherent.sh/mcp |
| Served by | inh-public-api-svc -- the same service and process as the REST API |
| Auth | X-API-Key header (or Authorization: Bearer ink_...) |
The MCP server is not a separate process and does not run on the ingestion service or on any localhost default -- it rides the same ASGI app, port, rate limiting, and audit logging as /v1/*.
Install
Claude Code
claude mcp add --transport http inherent https://api.inherent.sh/mcp \
--header "X-API-Key: $INHERENT_API_KEY"
Run /mcp inside Claude Code afterward to confirm it connected.
Cursor
Add this to your MCP config (Settings → MCP):
{
"mcpServers": {
"inherent": {
"url": "https://api.inherent.sh/mcp",
"headers": { "X-API-Key": "YOUR_KEY" }
}
}
}
Cursor needs the key inside the headers block -- the URL alone isn't enough to authenticate.
Claude Desktop and ChatGPT currently only offer OAuth-based custom connectors. Inherent's OAuth flow is still being built, so those two clients aren't supported yet -- use Claude Code or Cursor in the meantime.
Tools
10 tools are exposed over HTTP. Every tool requires the permission listed below on your API key; a key missing it gets an authorization_failed error class and the tool body never runs.
| Tool | Permission | What it does |
|---|---|---|
search_documents | search | Semantic, hybrid, or keyword search. Returns an event_id you can pass to report_feedback. |
list_documents | read | Paginated list of documents across one or every authorized workspace. |
get_document | read | A single document's metadata (name, source_type, size, chunk_count, status). |
list_chunks | read | All chunks belonging to a document (id, content, chunk_index, token_count). |
get_document_context | read | A bounded window of a document's content, capped by max_chars (default 20,000) with offset-based paging. |
explain_lineage | read | Provenance and freshness for a document or chunk -- source_uri, content_hash, is_stale. |
upload_document | write | Ingest UTF-8 text content (binary uploads -- PDF/DOCX/PNG -- stay REST-only). |
delete_document | write | Permanently delete a document and its vectors, chunks, and stored bytes. |
refresh_stale_source | write | Re-ingest an already-uploaded document to clear stale evidence. |
get_retrieval_health | search | Retrieval-quality scorecard for a workspace -- answer rate, verdict mix, corpus gaps. |
Stdio-only tools
Four more tools exist in the same registry but are declared http_exposed=False -- they run for a self-hosted deployment connecting over stdio, but are never advertised or callable on POST /mcp:
| Tool | Why it's stdio-only |
|---|---|
search_memory | Identical behavior to search_documents -- kept for stdio agents already wired to it, not duplicated on HTTP. |
get_citations | search_documents's results already carry the same citation object per result. |
verify_claim | An offline lexical overlap checker with no negation handling -- safe as a stdio pre-filter, unsafe under a tool name an HTTP agent could read as entailment. |
report_feedback | Not yet decided for HTTP exposure; unchanged on stdio. |
Error Classes
A failed HTTP tool call returns isError: true with a branchable structuredContent.error_class, so an agent can decide what to do next without string-matching the human-readable message. There are 7 values; treat an unrecognised one as retryable-once and log it. Stdio callers do not get error_class -- they keep the plain-text "Error: ..." convention.
error_class | Meaning |
|---|---|
authentication_failed | Missing, invalid, or expired API key / bearer token. |
authorization_failed | Key lacks the tool's required permission, or the workspace isn't authorized for this key. |
validation_error | A required argument was missing or malformed. |
unknown_tool | The named tool doesn't exist, or exists but isn't exposed on HTTP. |
not_found | The referenced document or chunk doesn't exist (or isn't visible to this key). |
tool_error | A handler-specific failure not covered by the classes above. |
internal_error | An unhandled exception inside the tool handler. |
{
"isError": true,
"content": [{ "type": "text", "text": "Error: API key does not have 'write' permission" }],
"structuredContent": { "error_class": "authorization_failed" }
}
Coming in engine 0.7.0
Built and merged upstream, not yet in the released engine this API runs on. Calling either tool today returns unknown_tool; quota_exceeded is never emitted today.
| Addition | What it will do |
|---|---|
whoami tool (read) | Identify the authenticated key, its binding, and every workspace it can access. |
list_workspaces tool (read) | The caller's authorized workspaces with name and document_count -- so an agent can discover what to pass as workspace_id instead of needing it out-of-band. |
quota_exceeded error class | Returned when the caller is over a per-identity entitlement (rate, monthly calls, writes/day, or document count). |
Next Steps
- API Access & Environments -- how the REST API and MCP server relate
- Searching Your Knowledge Base -- the retrieval modes
search_documentsuses under the hood - Authentication -- creating and scoping API keys