Repository navigation
Description
Which version line?
v2 — current (@modelcontextprotocol/inspector@latest)
Which client?
All / shared core
Inspector version
2.1.0
Node version
v22.23.2
Operating system (and browser, for the web client)
No response
Transport
Not applicable / never connected
MCP server under inspection
- Docker Image: ghcr.io/modelcontextprotocol/inspector:2.1.0
- Runtime: Docker Swarm / Linux container
- Deployment style: non-interactive server container behind Traefik
- No desktop/session keyring available inside the container
Steps to reproduce
POST /api/serverssucceeds when adding a new server.- Re-adding the same server returns:
409 {"error":"Server 'server-mcp' already exists"} - UI shows no configured servers.
GET /api/serversreturns500.- Container logs show:
Couldn't access platform storage: PermissionDenied
Expected behavior
The server list should render even when the container has no usable platform keyring. If no secret is available, the API should fall back gracefully, return the non-secret server metadata, or report per-server secret retrieval failure without making the whole catalog unreadable.
Actual behavior
When running ghcr.io/modelcontextprotocol/inspector:2.1.0 in a minimal Linux container, adding a server succeeds, but the UI remains empty. Adding the same server again returns 409, which confirms the server was persisted. The failing path is the server list endpoint: GET /api/servers returns 500 because the keyring backend cannot access platform storage.
Probable root cause
The code catches failures from keyring password reads, but the failure can happen earlier while constructing/accessing the keyring entry/provider itself. In a minimal Linux container this throws PermissionDenied, so GET /api/servers fails before it can return the catalog.
Logs, errors, or screenshots
Already prototyped a fix?
The v2.1.0 image was patched so keyring initialization/read failures are caught and treated as unavailable secret storage. After that:
GET /api/serversreturns200- the previously added server appears in the UI
- Inspector can continue operating in the containerized deployment
Before you submit
- I searched existing issues and this is not a duplicate.
- This is not a security vulnerability report (those go through the private advisory process).
Activity
cliffhall commentedon Aug 5, 2026
Triage: Priority High (total 10)
GET /api/servers500s, so the catalog is unreadable and the UI shows no servers even thoughPOSTpersisted them (the409on re-add confirms it). Not 5 — it is scoped to containers with no usable platform keyring, not broken on arrival for everyone.ghcr.io/modelcontextprotocol/inspector:2.1.0image.buglabel. No milestone (a pass-1 triage never earns that one, by rule), no engagement yet, unassigned, not a sub-issue, and no reporter-setFields → Priority.Board: #28, Status
Incoming— awaiting maintainer review, so no milestone yet. Labeledv2per the reported version line.Thanks for the unusually complete report — the probable-root-cause note (failure while constructing the keyring entry, not just reading a password, so the
catcharound the read never sees it) and the confirmation that patching it restores a200are exactly what makes this actionable.Per
CONTRIBUTING.mdwe take fixes as issues rather than PRs, so nothing further is needed from you — but if you still have the patch you applied to the image, pasting the diff or the prompt you used here would help whoever picks this up.cliffhall commentedon Aug 5, 2026
Closing as a duplicate of #1848, which is now the single tracking issue for this bug.
Thanks for the report — it was not wasted. Three people hit this independently in different environments, which is a large part of the evidence that it affects essentially any containerized or keyring-less deployment rather than one unusual setup:
PermissionDeniedonGET /api/serversgnome-keyring/org.freedesktop.secretsGET /api/serversfails in container withCouldn't access platform storage: PermissionDenied#1931 — Docker Swarm container behind Traefik,ghcr.io/…/inspector:2.1.0Root cause:
@napi-rs/keyring'sAsyncEntryconstructor does the platform-store setup and throws when no secret service is reachable. It is constructed outside thetryinget/set/deleteincore/auth/node/secret-store.ts, so the graceful-degradation path that already exists never engages — the raw error escapes and 500s everyGET /api/servers.Your confirmation that patching the 2.1.0 image to treat keyring init/read failures as unavailable storage restores a
200is independent evidence that this diagnosis is complete.Subscribe to #1848 for the fix. No further action needed here.
cliffhall commentedon Aug 6, 2026
For the record, since this was closed as a duplicate of #1848: the fix is now open as #1945, and it is the change you root-caused here —
AsyncEntryconstruction moved inside thetryinget/set/delete, so a construction-time keychain failure follows the documented degradation contract instead of escaping as a raw error.After it,
GET /api/serversreturns 200 with the server list in a container with no D-Bus session, and only an actual attempt to save a secret hard-fails — as aKeychainUnavailableError, which the routes translate to a 503 with an actionable message rather than a generic 500.A related follow-up you may want to watch: #1950 covers what secret persistence should actually mean in a container, since #1945 makes the non-secret flows work but leaves the affected platforms with no way to store an OAuth client secret or a stdio
env:secret at all.