Skip to content

Support multiple MCP endpoints per app #338

Description

@cboettig

Today an app configures a single MCP server: mcp_url in layers-input.json, read once in app/main.js:64 and used to construct one MCPClient. toolRegistry.registerRemote() is already called more than once, so the registry side looks ready — the constraint is upstream of it, in config and client construction.

Why

We're building a domain library for SEEA-EA ecosystem accounting (SchmidtDSE/unseea) that we'd like to serve as its own MCP endpoint: a small set of typed tools (extent_account, condition_account, …) that internally dispatch SQL to duckdb-mcp. An app then wants both endpoints — the generic engine for exploration, plus the domain server for the fixed account definitions.

Keeping domain tools out of mcp-data-server is deliberate: that server is domain-agnostic by design, and its roadmap is engines and data types, not domain semantics. Composing two servers is the MCP-native answer, and it seems generically useful — any app wanting to combine the shared catalog engine with a specialised toolset hits the same wall.

Sketch

{
  "mcp_url": "https://duckdb-mcp.nrp-nautilus.io/mcp",
  "mcp_servers": [
    { "url": "https://duckdb-mcp.nrp-nautilus.io/mcp" },
    { "url": "https://unseea-mcp.nrp-nautilus.io/mcp", "auth_token": "..." }
  ]
}

Keeping mcp_url as the single-server shorthand would avoid churn in existing apps.

Things that presumably need thought, rather than a proposal from me:

  • Tool-name collisions across servers — prefix, first-wins, or error at startup?
  • ReconnectsetOnReconnect currently clears and re-registers all remote tools; with several clients that wants to be per-server so one flapping server doesn't drop another's tools.
  • Credential redaction and the chat export presumably just work, since they key off tool-call arguments rather than the client, but worth confirming.
  • Per-server auth headers, since a domain server may be bearer-walled while the public engine is not.

Happy to take this on if it's wanted and the design direction is settled — wanted to check the approach before writing code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions