Skip to content

fix(mcp): overlong minted MCP tool names no longer 400 every turn on strict providers (#81331, salvage #81417) - #92659

Merged
teknium1 merged 1 commit into
mainfrom
omp-port/mcp-tool-name-clamp
Sep 14, 2026
Merged

teknium1 merged 1 commit into
mainfrom
omp-port/mcp-tool-name-clamp

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Summary

MCP tool names longer than 64 chars no longer make OpenAI-compatible providers reject the whole request with HTTP 400 — mcp_prefixed_tool_name() now clamps overlong names deterministically with a stable hash suffix.

Salvage of #81417 by @chelsealong (cherry-picked, authorship preserved), whose fix independently matches the same mechanism oh-my-pi shipped this week for the identical bug (can1357/oh-my-pi#9131: chrome-devtools-mcp's performance_analyze_insight minted a 68-char name and every turn failed with name must be at most 64 characters).

Root cause: mcp__<server>__<tool> minting had no length cap while OpenAI/Meta Responses validate function names against ^[a-zA-Z0-9_-]{1,64}$. Portable Agent Plugin server keys embed the plugin name three times, so their minted names routinely overflow (#81331). Hermes already fixed the sibling defect for Codex call_ids (#73492) — this closes the tool-name half.

Changes

  • tools/mcp_tool.py: mcp_prefixed_tool_name() clamps names >64 chars to a readable prefix + _<8-hex sha256> suffix; deterministic across processes, distinct long names never collide. Warning logged when clamping fires. All mint sites (tool schemas, resource/prompt utility tools) go through this one choke point.
  • tests/tools/test_mcp_tool.py: clamp length, determinism, and collision tests.

Validation

Before After
73-char minted name sent as-is → provider HTTP 400 every turn 64 chars, ^[a-zA-Z0-9_-]{1,64}$-valid
same inputs, repeated calls n/a identical clamped name (cache/replay-stable)
two distinct long names n/a distinct clamped names
tests/tools/test_mcp_tool.py — 98/98 pass

E2E: real mcp_prefixed_tool_name import, regex-validated output against the provider pattern, determinism + uniqueness asserted.

Related open PRs covering adjacent surfaces (not superseded): #54881/#90016 (Bedrock adapter aliasing), #35843 (chat-completions-side truncation — broader, unfocused), #15617 (older single-underscore-era equivalent of this fix).

Infographic

MCP tool name clamp

@github-actions

github-actions Bot commented Aug 23, 2026 •

Copy link
Copy Markdown

૮ >ﻌ< ა ci review

ran on d0b0c45 — fix(mcp): clamp generated MCP tool names to 64 chars

⚠️ Warnings

OSV vulnerability scan · View job

76 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.


debug info

CI timings

CI timings · View report · View job

Wall time 5m26s vs 5m33s (-2.1%). 7 job(s) slower, 5 faster, 2 unchanged.

  • Python tests / Run tests: +47.0s
  • OSV scan / Scan lockfiles / osv-scan: +9.0s
  • Python lints / Windows footguns (blocking): -8.0s
  • Check contributors / check-attribution: +8.0s
  • OS-specific tests / Windows-only tests: -6.0s

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists tool/mcp MCP client and OAuth labels Aug 23, 2026
@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference, author can ignore or act on any point.

Overall: correct fix for a nasty failure mode (one overlong name poisoning the whole tools array on strict providers) — deterministic SHA-256 suffix keeps registry names stable across sessions, the length arithmetic ([:55] + "_" + 8 hex = exactly 64) is right, and tests pin the limit, distinctness of near-identical tools, and repeatability. Points:

  1. tools/mcp_tool.py:6479-6493 — truncating the head means the bloated server prefix survives and the discriminating tool name gets hashed away: two tools from the same portable-plugin server become mcp__agent_plugin_my_server_997167c9__my_ser_ab12cd34 vs ..._ef56ab78, which is opaque to both model and human. Since the server component is what's over budget, consider clamping only the server chunk (keep safe_tool verbatim): mcp__{server_head}_{digest}__{safe_tool} — same 64-char bound, but the semantic tool name stays readable and tool_search results stay interpretable.

  2. Same function — logger.warning fires per offending tool at registration; a fleet of portable plugins could emit dozens of these every startup. Consider warning once per server name, or dropping to debug after the first occurrence, to keep logs signal-dense.

  3. Migration note — any user config keyed by the old unclamped names (tool allowlists, disabled-tool sets, UI references) silently stops matching after this change since the registry name itself changed. Worth calling out in the PR/changelog even if no migration path is offered; 32 bits of hash suffix is fine collision-wise at realistic scales.

Portable Agent Plugin packages fold the plugin name into the MCP
registry name three times over (slug, digest, and again as the server
key), so mcp__<server>__<tool> routinely exceeds the 64-char function
name limit OpenAI-compatible providers enforce — while the same server
registered via `hermes mcp add` stays well under it. The oversized name
is never rejected loudly; the tool just becomes unreachable. Clamp
mcp_prefixed_tool_name() to 64 chars with a deterministic, collision-
safe hash suffix, mirroring the existing property-key clamp in
schema_sanitizer.py. Dispatch is unaffected since handlers already
close over the original unprefixed tool name.

Fixes #81331
@teknium1
teknium1 force-pushed the omp-port/mcp-tool-name-clamp branch from 820c9b7 to d0b0c45 Compare September 14, 2026 02:55
@teknium1
teknium1 merged commit ef01363 into main Sep 14, 2026
37 checks passed
@teknium1
teknium1 deleted the omp-port/mcp-tool-name-clamp branch September 14, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium — degraded but workaround exists tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants