Troubleshooting
The server tries to put the fix in the error text, so read the message before reaching for this page. When it does not, start here.
Nothing works, and there is no error
Section titled “Nothing works, and there is no error”The server writes to stderr, and MCP clients hide stderr by default. On startup it logs:
[mero-mcp] ready on stdio; the node connects when a client opens the connectionA down node or bad credentials do not fail at startup.
When the client connects, the server tries once to read the installed apps; if that fails it logs [mero-mcp] app list unavailable at connect: <error> and serves only the fixed tools until a later read reaches the node.
After that a failure hits only the tool call that met it, and the next call retries.
If tools fail and you cannot see why, find your client’s MCP server log (in Claude Code, claude --debug, or the MCP output panel in editors) and read the stderr.
No Calimero node found
Section titled “No Calimero node found”No Calimero node found. Start one in the Calimero desktop app, or setCALIMERO_NODE_URL. (Looked in ~/.calimero and probed local ports.)Discovery found nothing at any rung. Either the node is not running, or it is
somewhere the server does not look: a non-default CALIMERO_NODE_HOME, a port
outside the probe set (2528, 2428, 2529, 2429), or a remote host. Set
CALIMERO_NODE_URL and the whole search is skipped. See
node discovery.
Several nodes found in …
Section titled “Several nodes found in …”Several nodes found in ~/.calimero: alice (http://localhost:2428),bob (http://localhost:2429). Set CALIMERO_NODE_NAME or CALIMERO_NODE_URL.More than one node config, none of them named default, so the server refuses to
guess. Name one with CALIMERO_NODE_NAME, or address it directly with
CALIMERO_NODE_URL. list_nodes shows the candidates.
Node "x" not found in …
Section titled “Node "x" not found in …”CALIMERO_NODE_NAME did not match a directory under CALIMERO_NODE_HOME. The error
lists the available names. Note that a node directory only counts if its
config.toml yields a listen address — a directory the server cannot read a port
out of is skipped entirely.
This node's merod does not support the ABI endpoint
Section titled “This node's merod does not support the ABI endpoint”This node's merod does not support the ABI endpoint(GET /admin-api/applications/:id/abi). Upgrade merod to a release that includes it.The whole generated-tool mechanism reads the ABI from that route. It is newer than
the current merod release, so until a release carries it, build merod from
core master:
cd core && cargo build -p merodEvery other tool works without it: only the app tools (describe_app, select_app, call and the generated tools) need an ABI.
An app whose ABI cannot be read is left out of the tool list, and stderr says why.
The generated tools do not appear
Section titled “The generated tools do not appear”The generated tools are listed from the moment the client connects, one per method of every installed app except init, which create_context runs.
If an app was installed after that and its tools are missing, wait for the 30-second refresh or reconnect.
If the node was down when the client connected, the first select_app, describe_app or call that reaches the node reads the list again, adds the app tools and starts the 30-second refresh.
select_app names the tools in its result along with a note:
These are the server-side tool names. An MCP client may expose them under a prefix of its own (commonly
mcp__<server>__<tool>), so if a name does not resolve, look for the prefixed form.
Two separate things go wrong here:
-
The name is prefixed.
kv_store_getmay be exposed asmcp__mero-mcp__kv_store_get. Look for the prefixed form before concluding it is missing. -
The client did not pick up the new tool list. Not every client refreshes on a
tools/list_changednotification. Thecalltool exists for exactly this: it is registered at startup, so it is always visible, and it reaches every method with the same handle:Call the `call` tool with the app_handle, method "get" and args {"key": "greeting"}.
Call select_app for <package> and retry with the returned app_handle.
Section titled “Call select_app for <package> and retry with the returned app_handle.”An app tool or call refused the app_handle and ran nothing.
The refusal carries the app’s guide when it has one, so read it before retrying.
Either the handle is missing or was not issued by this server, or it has gone stale for one of four reasons:
- The app was upgraded. A handle names the app version it was issued for.
- The app’s guide changed. A handle carries a hash of the guide it was issued with.
- The context is gone. The handle names a context that no longer exists for that app.
- The handle key changed. Handles are signed with the key in
handle.keyin the state directory, so they survive a restart, but not that file being deleted or replaced.
In every case, call select_app again and use the handle it returns.
A handle from describe_app names no context, so app tools refuse it with a request to call select_app with a context.
A handle binds one application, so the tools of the same package from another signer refuse it.
Application "x" has no contexts on this node
Section titled “Application "x" has no contexts on this node”Application "kv-store" has no contexts on this node. Create one in the Calimerodesktop app, or use create_context.Installing an application does not create a context. This is the single most common failure — see contexts and namespaces.
Application "x" has N contexts; pass context with one of: …
Section titled “Application "x" has N contexts; pass context with one of: …”The application has several contexts, so select_app cannot choose one for you.
Pass context to select_app; the handle it returns names that context.
Application "x" is ambiguous
Section titled “Application "x" is ambiguous”The short name you used — the trailing package segment — matches more than one installed application. Use the full package name or the application id. Matching is on whole segments, so this is never a prefix collision. A display name that several installed applications carry is refused the same way.
Application "x" is published by several signers
Section titled “Application "x" is published by several signers”The package is installed from more than one signer, and each is a separate app with its own tools and handles.
The error lists each application id with its signer; pass the id of the one you mean to select_app or describe_app.
Context "x" not found: it is neither a context id nor an alias
Section titled “Context "x" not found: it is neither a context id nor an alias”The value did not look like a base58 context id and no alias by that name resolved.
The error lists the contexts that application does have. Create the alias with
create_alias, or use the id.
A method call fails with the app’s own error
Section titled “A method call fails with the app’s own error”Guest (WASM) errors arrive from the node without a readable message — just
FunctionCallError and a Rust-debug-formatted byte array. The server decodes that
back into the real text, so what you see is the application’s own error:
Error: label must not be emptyIf you are seeing a bare FunctionCallError with no explanation, the payload was not
in either shape the decoder knows, and the raw error is in the server’s stderr.
Cannot reach the node at …
Section titled “Cannot reach the node at …”A transport failure rather than anything the node rejected — wrong port, node not
listening, TLS mismatch. Confirm with node_status, and check the URL with
list_nodes.
Auth failures
Section titled “Auth failures”node_status reports authMode. If it says none and calls are rejected, the node
wants auth and the server found no credentials. If it says handoff but the node
rejects the token, the handoff file may be stale — the desktop app’s
Connect AI agent action rewrites it.
The server ignores a handoff file that points at a non-loopback origin and logs
why: only the local desktop app writes that file, so a remote URL in it means
something else did. Use CALIMERO_NODE_URL to reach a remote node.
Tokens are cached per node and identity under the state directory. To force
re-authentication, delete tokens-*.json from ~/.config/calimero/mcp (or your
CALIMERO_MCP_STATE_DIR). See authentication.
A tool is missing entirely
Section titled “A tool is missing entirely”Check CALIMERO_MCP_TOOLSETS. It defaults to all three, but if it is set, only the
named toolsets are registered — plus core, which is always on regardless. An
unrecognised name in that list simply matches nothing, silently.