MCP
Troubleshooting
Engram's MCP errors are written to be acted on, by a model or by you. Each one names the cause and the next step. This page is the index: find the sentence you saw and read across.
The client shows no Engram tools
The client could not connect. Four things account for almost all of it.
- Is the trailing slash on the url? The server is mounted at
https://api.engramdynamics.org/mcp-http/. The un-slashed path answers with a redirect, which some clients do not follow. - Is the block in your client's own shape? Every client reaches this one endpoint with this one key, but they spell a remote server differently: Claude Code and VS Code want
"type": "http", Cursor wants only aurl, Windsurf calls itserverUrl, Gemini CLI calls ithttpUrl, Cline wants"type": "streamableHttp", and VS Code keys the file onserversrather thanmcpServers. A client given another client's block reads it as nothing at all. The right block for each is on Quick start, andengram mcp --client <name>prints it. - Is the header spelled exactly
Authorization: Bearer <key>? The wordBearer, one space, then the wholeek_key. A missingBearerreads as no credential at all. - Did you restart the client? Claude Desktop and Cursor read their config at startup, so a pasted block does nothing until they are restarted, and Claude Desktop has to be fully quit from the tray or menu bar rather than closed. A trailing comma in
claude_desktop_config.jsontakes out every server in the file, not just this one.
Check the credential itself from the terminal, which prints the server's own message rather than the client's summary of it:
curl -i https://api.engramdynamics.org/corpora \
-H "Authorization: Bearer <your API key>"
A 200 with your document bases in it means the key is good and the problem is in the client config. Anything else is covered below.
Claude Desktop shows an error and there is no engram log
The giveaway is the missing log. Claude Desktop writes one file per server it starts, so no mcp-server-engram.log in %APPDATA%\Claude\logs (or ~/Library/Logs/Claude) means it never tried to start ours.
That happens because Claude Desktop cannot take a remote server. Its claude_desktop_config.json only launches programs on your machine, so an entry built around a url and a type of http is skipped without comment, and the Connectors screen in settings only accepts servers that sign in with OAuth, not an API key on a header. The HTTP block works in Claude Code and Cursor, which is why it reads like it should work here.
The fix is the mcp-remote bridge: a small local program that speaks to Claude Desktop the way it expects and relays to the hosted server. The block to paste, for both operating systems, is in Quick start. Three things account for the rest of the failures:
- Node.js is missing. The bridge runs through
npx, which ships with Node.node --versionin a terminal settles it. - The app was closed, not quit. Closing the window leaves it running in the tray on Windows or the menu bar on macOS, and a running Claude Desktop never re-reads the file. Quit it properly and reopen.
- The key did not survive the launch. Some older Claude Desktop builds on Windows mangle an argument containing a space, which turns the header into a rejected credential. If the log now exists and shows a 401, put the whole header value in the environment instead:
"--header", "Authorization:${ENGRAM_AUTH}"with"env": { "ENGRAM_AUTH": "Bearer <your API key>" }.
Once it connects, Claude Desktop lists the Engram tools like any other client, and everything else on this page applies unchanged.
The key is rejected
An unauthorised call is refused before any MCP machinery runs, so the client reports a failed connection rather than a failed tool call. Inside a tool call the same refusal reads:
Your Engram API key was rejected for this call (it may be revoked, expired, or missing
the query scope). Mint a new key with the query scope and reconnect.
One message covers several causes on purpose, because a more specific one would turn the endpoint into an oracle for which keys and workspaces exist. Check in this order:
- Was the key revoked, or has it expired?
engram keys listshowsrevoked_atandexpires_atper key, and the API keys page shows the same. - Does the key carry the
queryscope? Without it the server refuses the connection outright. Create a replacement withengram keys create --name mcp --scope query. - Was the whole key pasted? A key is one long
ek_string. A copy that stopped at a line break fails exactly the way a wrong key does. - Is the key from the right workspace? A key only reaches bases in its own workspace.
engram statusnames the workspace's base count, andlist_corporacoming back empty is the same signal.
Revoking a key is also the deliberate version of this error. It is how you cut a client, a laptop or a contractor off from every document base at once, and it takes effect on the next call.
A restricted environment refuses everything
Some environments, staging ones in particular, only answer from named networks. A request from anywhere else gets a plain 403 with one line of text, whatever credential it carried:
This environment is restricted.
That is the network in front of the environment rather than anything about your key, so no new key or scope changes it. Connect from an allowed network, ask an admin to add the address, or point the client at production instead. Your own workspace can be locked down the same way on purpose, which is on IP allowlist.
The agent names a document base that does not exist
Every tool but list_corpora takes a corpus argument, and the server resolves it against the workspace before doing anything else. A miss is an error that names what is actually there, so the model can correct itself in one turn:
No document base matches 'Suport KB'. Call list_corpora first.
Available: Support KB (c-8f2a41), Sales collateral (c-1d77b0).
Names are matched exactly, including case, so "support kb" misses "Support KB". Two bases sharing a name is the one case with no right answer, and the error says so with both ids rather than guessing:
More than one document base is named 'Support'. Pass one of these ids instead:
c-8f2a41, c-1d77b0.
Either way there are two fixes: tell the assistant to call list_corpora and use the name it reports, or give it the id, which never moves. Keeping base names distinct is worth doing once, because ambiguity costs a turn every time.
Temporarily unavailable, and rate limits
Two failures are transient and both say so, so an agent can wait instead of treating the question as unanswerable.
The document base is temporarily unavailable (offline). Retry in 300 seconds.
Uploads and syncs still work.
That is the serving side being down, still coming up, or refusing a request. Three facts travel with it: it is temporary, how long to wait, and that writes are still landing. The same sentence appears when the control plane itself is unreachable, deliberately, because an agent should not have to tell those apart to know what to do next. add_document keeps working throughout.
Rate limited: too many requests per minute. Wait 60 seconds and retry the same call.
Space out further calls rather than retrying in a tight loop.
Queries are rate-limited per workspace and per credential, so one leaked key cannot saturate the serving box. If the workspace has hit a monthly allowance instead of a per-minute burst, the message names the allowance and links the upgrade. Allowances are on plans and allowances.
add_document is refused
| Message | Cause and fix |
|---|---|
The key is missing the ingest scope | The scope is checked before anything goes over the wire, so this costs one round trip rather than a confusing 401. Create a key with --scope query --scope ingest and reconnect. |
| That document is n KB and this tool takes up to m KB | The tool takes one small document at a time. Use engram push or the REST API, which handle any size and report progress. |
| This Engram backend does not accept document writes over MCP yet | The control plane you are pointed at predates the ingest tools. Load the document with the CLI or POST /corpora/{id}/documents. |
A successful write is not immediately searchable. The result says so and names the next step: the document is queued for onboarding, and sync_status reports when it lands.
Thin, missing or stale answers
When the answer is disappointing rather than an error, the cause is usually one of four, and each has a tell.
- The documents are still onboarding. The freshness line at the end of every result counts them: "42 ready, 3 still onboarding". Only ready documents answer.
sync_statusgives the fuller picture. - Nothing matched closely. When retrieval found nothing that cleared the relevance floor, the result says plainly that no document sources matched and the answer should be treated as general knowledge. That is a real signal, not a formatting quirk: the base does not cover the question.
- The question spanned the whole base. The server decides how many documents to consult, keeping the ones whose evidence is close to the best match, so a sprawling question gets a narrow answer. Ask it as a few focused questions, or pin the documents you want with
doc_ids. - The follow-up lost the thread. Pass
history, or pin the previous answer's ids withdoc_idsso the same evidence is used again.
If a document you expect is missing entirely, call list_documents with a substring filter. It lists only documents that are ready, so absence there means the document failed or has not finished building. engram docs list <base> shows every document with its lifecycle and any error.