CLAUDE LABJP
MCP — Support for the 2026-07-28 spec is rolling out across Claude. The protocol moves from bidirectional and stateful to request/response, so MCP servers can now live on serverless and edge infrastructureEXTENSIONS — Three official extensions have landed: MCP Apps for server-rendered UI, Tasks for async and long-running work, and Enterprise Managed Auth for IdP-based org-wide provisioningADOPTION — MCP passed 400 million monthly SDK downloads, roughly 4x growth this year, settling into its role as the standard way to connect agents to applicationsQUOTA — Today, August 19, is the last day of the 50 percent weekly usage boost for Claude Code subscribers. If you have long agent runs queued, this is the windowPRICING — Claude Sonnet 5's introductory rate of $2 per million input tokens and $10 output ends August 31; standard pricing of $3 and $15 takes over on September 1, twelve days outFIX — A bug where MCP v2 connections endlessly reopened subscriptions against servers with fixed timeouts is resolved, and a forward_user_identity setting was added for user attributionMCP — Support for the 2026-07-28 spec is rolling out across Claude. The protocol moves from bidirectional and stateful to request/response, so MCP servers can now live on serverless and edge infrastructureEXTENSIONS — Three official extensions have landed: MCP Apps for server-rendered UI, Tasks for async and long-running work, and Enterprise Managed Auth for IdP-based org-wide provisioningADOPTION — MCP passed 400 million monthly SDK downloads, roughly 4x growth this year, settling into its role as the standard way to connect agents to applicationsQUOTA — Today, August 19, is the last day of the 50 percent weekly usage boost for Claude Code subscribers. If you have long agent runs queued, this is the windowPRICING — Claude Sonnet 5's introductory rate of $2 per million input tokens and $10 output ends August 31; standard pricing of $3 and $15 takes over on September 1, twelve days outFIX — A bug where MCP v2 connections endlessly reopened subscriptions against servers with fixed timeouts is resolved, and a forward_user_identity setting was added for user attribution
Articles/API & SDK
API & SDK/2026-05-20Advanced

Resolving Tool Name Collisions When Bundling Multiple MCP Servers in the Claude Agent SDK

When the GitHub MCP and Linear MCP both expose create_issue, Sonnet 4.6 cannot tell them apart. This article covers the structure of MCP tool name collisions, a TypeScript reconciler implementation, and a measured correction: the schemaHash I originally published missed all five schema drifts I tested it against.

Claude Agent SDK13MCP51TypeScript24Production23Namespacing

Premium Article

The day I plugged the GitHub MCP and the Linear MCP into the same Claude Agent SDK app, Sonnet 4.6 received a user instruction to "open a ticket on Linear" and confidently created a GitHub issue instead. Both servers exposed a tool named create_issue, and the GitHub schema had silently overwritten the Linear one when the second server registered. I only found the cause after dumping the SDK's tool list to the debug log.

Back when I wired REST APIs together by hand, the endpoint URL settled the routing question for me. MCP removes that handle. All the model gets is a tool name and a description, and overlapping verbs across servers turn out to be far more common than they were in the pre-MCP era.

This article walks through the namespace design and the TypeScript reconciler I now use. It also corrects something: the schemaHash I originally published in this article was broken, and I only noticed months later. The correction comes with measurements.

How tool name collisions actually happen

The Claude Agent SDK hands off the tool list from each MCP server straight into the tools array of the Anthropic Messages API and leaves collision detection to the caller. The API itself only allows alphanumerics, underscores, and hyphens in name. If the same name appears twice, the SDK implementations I've inspected push them through a Map that ends up keeping the last entry, which makes the earlier server's tool vanish silently.

From the model's perspective, a tool is a triple of name, description, and input_schema. Two tools with the same name get collapsed before the request leaves your process, so the model never sees the duplicate. If the descriptions differ, the model is choosing based on whichever description survived the merge. That mismatch is exactly what produced the GitHub-vs-Linear mistake above.

Typical collision-prone verbs include:

VerbLikely MCP servers
create_issueGitHub MCP / Linear MCP / Jira MCP
searchNotion MCP / Slack MCP / Web Search MCP
uploadS3 MCP / Cloudflare R2 MCP / Stripe Files MCP
send_messageSlack MCP / Discord MCP / SendGrid MCP

In my own setup, having three or more of these servers alive in a single agent session is the default rather than the exception. A workflow that pulls AdMob revenue numbers into Slack, opens a fix PR on GitHub, and closes the related Linear ticket walks straight into this minefield.

Comparing three namespacing strategies

There are several ways to resolve collisions. After running a few in production I kept the "prefix with server identifier" approach. Here is how the three candidates compare.

The first candidate is dot notation. Names like github.create_issue read well to humans, but the Anthropic Messages API rejects . in name and you have to escape or substitute it. That forces you to maintain a bidirectional mapping back to the original name on every dispatch.

The second is slash notation, which runs into the same character restriction and the same escape cost.

The third is double underscore separation: github__create_issue, linear__create_issue. It uses only API-legal characters and the model parses it as "the GitHub side's create_issue" without prompting. I ran the same prompt 50 times each across Sonnet 4.6 and Haiku 4.5 with temperature: 0.0, comparing strategies. Double underscore had the lowest misfire rate and beat a 2-character prefix like gh_ by about 7 points. Short prefixes also get confused with other meanings ("gh" vs "ghp"), so I do not recommend them.

I also keep the following rules around prefixing:

  1. Prefixes are lowercase ASCII, between 3 and 10 characters
  2. Original tool names stay untouched; the prefix is additive
  3. Prefixes are applied only when there is an actual collision; never blanket-prefix everything

Rule 3 matters. Renaming every tool unconditionally hides the "idiomatic" names the model already knows (web_search, for instance) and degrades selection accuracy. Limiting prefixes to the servers that actually collide is the most model-friendly setting.

It is worth saying a word about the benchmark setup. Fifty samples is just enough to see the differences, but only if you pin the temperature to zero and replay the exact same system prompt and user message. I also kept the working set close to production, with four AdMob-related MCP servers, two GitHub-side servers, and one Slack server in the bundle — about 60 tools in total. Toy benchmarks with five tools always look rosier than reality.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Observed misfire patterns when GitHub MCP and Linear MCP both ship create_issue, and whether the model relies more on name or description
A TypeScript Reconciler that prefixes only colliding tool names with double underscores and returns a bidirectional alias map
A measured correction: the schemaHash originally published here misused the JSON.stringify replacer and reported all five tested schema drifts as identical, plus a recursive canonicalization that fixes it
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API & SDK2026-07-08
Contract-Test Every Tool Before You Submit or Automate an MCP Connector
A connector that works once in a chat can still break silently in an unattended job through misread response shapes or double-fired writes. Here is a small harness that machine-checks tool descriptions, response contracts, idempotency, and latency, with measured numbers.
API & SDK2026-07-01
When Claude API Document Extraction Is Confidently Wrong — Field Notes on Catching Silent Errors with Invariants
In structured extraction from invoices and contracts, the real danger isn't a crash — it's a value that's silently wrong while the schema validates and confidence reads high. Field notes on invariants, two-pass extraction, and tracking field-level error rates.
API & SDK2026-06-25
When the Previous Run Hasn't Finished and the Next One Starts: Leases and Fencing Tokens for Scheduled Agents
A scheduled agent that runs on a fixed clock can overtake itself and start twice. From the moment a naive lock breaks to leases, fencing tokens, and bounded catch-up — worked through with the implementation I actually run.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →