Direct answer

Do not give the model every MCP tool schema at session start. Give it a compact catalog of sources, let it open the source it needs, and expose that source's tool schemas only when the task points there. This keeps the initial tool list small while preserving access to a large workspace.

The Boundary To Draw

The expensive part of a large MCP setup is not usually the transport handshake. It is the moment a client imports dozens or hundreds of tool names, descriptions and input schemas into the model context before the user has asked for anything specific. MCP defines normal discovery with tools/list and invocation with tools/call; a server that supports tools returns the currently available tools, including each tool's name, description and JSON Schema input contract. That is exactly what the model needs when it is about to use a source, and exactly what it does not need when the user asks a question that has nothing to do with that source.

The practical boundary is source first, tool second. A source is a human-scale drawer such as github, linear, stripe, postgres_reporting or google_drive_board_docs. The initial list should describe those drawers with enough precision for routing: what system it reaches, whether it is read-only, what account or workspace it represents, and a few examples of tasks that belong there. Only after the agent chooses a drawer should the server reveal the individual tool schemas for that drawer.

This is different from simply shortening descriptions. Short descriptions help, and the sibling article on tool descriptions goes deeper on that craft, but a short description for 180 tools is still 180 routing decisions in the model's working set. A source catalog turns the first decision into a smaller classification problem: which system should I open?

What The Protocol Still Sees

You do not have to invent a second protocol. The client can still connect to one MCP server and call ordinary MCP tools. The pattern is to make the always-visible tools be control-plane tools, then let opened sources contribute data-plane tools. A minimal always-visible set looks like this:

{
  "tools": [
    { "name": "list_sources", "description": "List connected systems and their status." },
    { "name": "list_toolsets", "description": "List source-level toolsets and whether each is enabled." },
    { "name": "enable_toolset", "description": "Open one source and return its available tools and arguments." },
    { "name": "disable_toolset", "description": "Close one source for this session." }
  ]
}

After enable_toolset, there are two implementation choices. If the client refreshes tool discovery during the session, the server can emit a changed list and the client can call tools/list again. MCP includes a notifications/tools/list_changed notification for servers that declare the capability, but clients vary in when they refresh and how much of the refreshed list reaches the model. The safer design is to make enable_toolset return the opened source's tool names and argument shapes immediately, then provide a stable dispatcher such as call_tool for clients that keep their first tool list for the whole session.

The dispatch call should remain explicit:

{
  "source": "linear",
  "tool": "search_issues",
  "arguments": {
    "query": "label:bug status:triage auth redirect"
  }
}

That shape preserves auditability. Logs can record the source, tool and arguments as separate fields, and policy can still reject the call before it reaches the upstream system.

Client Setup Stays Small

The endpoint configuration should stay boring. Claude Code can add a remote HTTP MCP server from a URL with claude mcp add --transport http, so the whole workspace can appear as one server:

claude mcp add --transport http spyn3 https://api.spyn3.com/agent/mcp \
  --header "Authorization: Bearer $SPYN3_API_KEY"

Cursor's manual MCP setup uses .cursor/mcp.json for project-specific servers or ~/.cursor/mcp.json for global servers. A remote server is configured with a url, and headers can carry the API key:

{
  "mcpServers": {
    "workspace-tools": {
      "url": "https://api.spyn3.com/agent/mcp",
      "headers": {
        "Authorization": "Bearer ${SPYN3_API_KEY}"
      }
    }
  }
}

VS Code supports a workspace .vscode/mcp.json with a top-level servers object, and also the portable root .mcp.json shape for compatible tools. A VS Code workspace file can keep the same single remote endpoint:

{
  "servers": {
    "workspace-tools": {
      "type": "http",
      "url": "https://api.spyn3.com/agent/mcp"
    }
  }
}

The important point is that none of these client configs enumerates GitHub, Linear, Drive, Stripe and Postgres separately. The config gives the client one server. The on-demand source catalog inside that server decides what the model sees next.

Design The Toolset Catalog

A good catalog entry is not a marketing label. It is routing metadata. Include a stable source id, a short display name, the provider, current reachability, whether the caller is allowed to open it, and a terse description of its job. If the source has hidden tools because the current key lacks permission, say so. Hiding the source entirely makes the model infer absence; reporting that tools are withheld tells it to ask for a different key or stop.

{
  "id": "github_app",
  "provider": "github",
  "status": "reachable",
  "enabled": false,
  "readOnly": false,
  "withheld": 4,
  "summary": "Repositories, pull requests, issues and code search for the app workspace."
}

Keep the catalog deterministic. MCP recommends deterministic tool ordering when the underlying set has not changed because stable lists are easier for clients to cache and for model prompts to reuse. The same applies one level up: if list_toolsets returns a random order, the model has to re-read a subtly different menu every turn. Sort by provider and stable id, not by recency or temporary health.

Use source-level boundaries that match how people ask for work. Splitting github_issues, github_prs and github_code_search may look tidy in code, but a user often asks one task that needs all three. Conversely, combining production Postgres, billing Stripe and support Gmail into one mega-source recreates the original context problem. The sibling pieces on context bloat and namespacing are useful when choosing those boundaries.

Failure Cases To Test

Test the boring edge cases before rolling this pattern to a team. First, check the first-turn route: ask for a GitHub issue, a Drive file and a billing lookup in separate fresh sessions, then confirm the agent opens only the matching source. If it opens three sources for every request, your catalog summaries are too vague.

Second, test stale client behavior. Start a session, call tools/list, open a source, and verify the task can proceed even if the visible MCP tool list does not refresh. That is where a stable dispatcher earns its keep. The model should be able to read the returned tool arguments from enable_toolset and then call call_tool with source, tool and arguments.

Third, test permission mismatch. Give a key read-only access and open a source that contains both read and write tools. The catalog should report withheld write tools or mark them unavailable, and attempted write calls should fail before proxying upstream. The article on read-only versus write tools covers the permission side; for this pattern, the key point is that loading fewer schemas is not a substitute for authorization.

Finally, test a down upstream. A source that is unreachable should remain listed with health metadata, not disappear. Disappearance teaches the model the wrong map. A visible unreachable state lets it tell the user the right failure: the integration exists, but the provider could not be reached.

How SPYN3 applies it

A SPYN3 agent starts with navigation, not with every upstream tool: list_toolsets shows each source with its tool count, and enable_toolset opens one. Open folders are remembered per credential, so two agents sharing a workspace each keep their own short list. The reply to enable_toolset carries the opened tools and their arguments, and call_tool calls them even when the client has not refreshed its list, which in our Claude Code test it had not.

Built for the next step

Give the model a map, not a warehouse

Let SPYN3 expose sources first and load detailed tools only when the agent opens them.

Review MCP tools
About SPYN3

SPYN3 is a consolidated MCP layer: one hosted endpoint in front of every system you connect — MCP servers, Postgres, REST APIs, Google Drive — with tools foldered by source and read/write permissions per key. Switching agents means moving one URL. Free plan available; current capabilities are documented on the product facts page.

Sources

  1. MCP specification: tools — tool discovery, invocation and security considerations. Verified 14 Oct 2026
  2. Anthropic: effective context engineering — high-signal context and progressive disclosure. Verified 14 Oct 2026
  3. OpenAI API: MCP servers and connectors — remote MCP servers, deferred loading, approvals and risks. Verified 14 Oct 2026
  4. Anthropic docs: Claude Code MCP setup — Claude Code MCP commands, scopes, transports and JSON configuration. Verified 14 Oct 2026
  5. VS Code documentation: add and manage MCP servers — VS Code MCP configuration, trust and logging behavior. Verified 14 Oct 2026
  6. Cursor documentation: MCP integrations — Cursor MCP configuration locations, remote URL entries, headers and approval behavior. Verified 14 Oct 2026