Skip to content

Persist server list to ~/.mcp-inspector/mcp.json (replace SEED_SERVERS) #1343

@cliffhall

Description

@cliffhall

Background

clients/web/src/App.tsx:47 currently hardcodes two seed servers (filesystem-server-default, everything-server-default) in SEED_SERVERS, with a note that "Persistence + an 'Add server' UI are explicitly out of scope for #1244." The four onServerAdd / onServerEdit / onServerClone / onServerRemove callbacks at App.tsx:639646 are wired to todoNoop. Time to fix that.

The v1.5 port already brought us most of the building blocks:

  • core/storage/store-io.ts — atomic R/W, ENOENT handling, mkdir -p, 0o600. Plus getDefaultStorageDir() resolving ~/.mcp-inspector/storage/.
  • core/mcp/node/config.tsloadMcpServersConfig parses the canonical { mcpServers: { ... } } format and normalizes server types (missing → stdio, httpstreamable-http).
  • core/mcp/remote/node/server.ts — Hono backend with the /api/storage/:storeId route as a clear template for new endpoints.

Scope

Persist the server list to ~/.mcp-inspector/mcp.json (Windows: %USERPROFILE%\.mcp-inspector\mcp.json), in the canonical { mcpServers: { ... } } format so the file is interoperable with Claude Desktop / Cursor / Cline and hand-editable. Full CRUD in one issue (read → write → UI dialogs).

Full design and rationale in specification/v2_servers_file.md.

Backend (core)

  • Add getDefaultMcpConfigPath() to core/storage/store-io.ts (sibling of getDefaultStorageDir()).
  • Add core/mcp/serverList.ts: pure converters mcpConfigToServerEntries / serverEntriesToMcpConfig, plus DEFAULT_SEED_CONFIG (the two current seeds). Re-export normalizeServerType from core/mcp/node/config.ts.
  • Add to core/mcp/remote/node/server.ts:
    • GET /api/servers — returns MCPConfig; writes DEFAULT_SEED_CONFIG to disk if file absent.
    • POST /api/servers — body { id, config }; 409 on duplicate id.
    • PUT /api/servers/:id — body { id?, config }; supports id rename.
    • DELETE /api/servers/:id — idempotent.
    • All ids validated with validateStoreId (alphanum + hyphen + underscore).
    • RemoteServerOptions.mcpConfigPath?: string defaulting to getDefaultMcpConfigPath().

Frontend

  • Add core/react/useServers.ts: returns { servers, loading, error, refresh, addServer, updateServer, removeServer }. Calls the new endpoints with the existing x-mcp-remote-auth token.
  • clients/web/src/App.tsx: drop SEED_SERVERS; wire to useServers; connect the four todo-noop server callbacks to the hook's mutators. On remove of the active server, disconnect first. On rename of the active server, update activeServerId.
  • Add minimal Add / Edit Mantine Modal dialogs per AGENTS.md's React rules (subcomponent constants via .withProps(), theme variants in src/theme/, no inline styles, no hex literals).

Tests

  • Unit: clients/web/src/test/core/mcp/serverList.test.ts, clients/web/src/test/core/storage/getDefaultMcpConfigPath.test.ts.
  • Integration: clients/web/src/test/integration/mcp/remote/servers-route.test.ts (real createRemoteApp against a tmp mcpConfigPath), clients/web/src/test/integration/react/useServers.test.tsx (hook against a real Hono instance).
  • Per-file 90% gate applies. Cover network / 4xx / 5xx error paths on the hook.
  • Manual smoke: first-launch seed-write, hand-edit + reload, add/edit/remove + hard reload, delete-active-server disconnect.

Out of scope (separate follow-ups)

  • Import-from-Claude-Desktop button.
  • fs.watch-based hot reload of external edits.
  • Wiring CLI/TUI to default to getDefaultMcpConfigPath() when no --config is passed — touch when those clients are wired up to v2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Issues and PRs for v2

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions