Skip to content

fix(mcp): rename tool names to be MCP-spec compliant (dots -> underscores)#73

Merged
hyoshi merged 5 commits intomainfrom
fix/mcp-tool-names-spec-compliance
Apr 30, 2026
Merged

fix(mcp): rename tool names to be MCP-spec compliant (dots -> underscores)#73
hyoshi merged 5 commits intomainfrom
fix/mcp-tool-names-spec-compliance

Conversation

@hyoshi
Copy link
Copy Markdown
Collaborator

@hyoshi hyoshi commented Apr 30, 2026

Summary

Fixes a Claude Desktop blocker: mureo's MCP tool names use dots (google_ads.campaigns.list) which violate the MCP spec's tool-name regex ^[a-zA-Z0-9_-]{1,64}$. Claude Desktop's chat enforces this strictly and rejects the entire mureo MCP server at registration time with errors like:

tools.42.FrontendRemoteMcpToolDefinition.name: String should match pattern '^[a-zA-Z0-9_-]{1,64}$'

Claude Code is more lenient and accepts dotted names, which is why this had been working there. But Claude Desktop is spec-strict.

Fix

Renamed every dotted tool name to its underscore equivalent — 173 unique tools across 5 prefixes:

Prefix Tool count Example
google_ads 83 google_ads.campaigns.list -> google_ads_campaigns_list
meta_ads 77 meta_ads.creatives.create -> meta_ads_creatives_create
search_console 10 search_console.sites.list -> search_console_sites_list
rollback 2 rollback.plan.show -> rollback_plan_show
analysis 1 analysis.anomalies.check -> analysis_anomalies_check

All 173 renames verified MCP-spec compliant (<= 64 chars, [A-Za-z0-9_-] only).

How the rename was applied

A targeted Python script (run once, not committed) walked every .py and .md file and replaced confirmed tool names using regex with negative lookbehind / lookahead for [a-zA-Z0-9_.] — this matches quoted strings, backtick-wrapped markdown, and standalone tokens but never Python module paths like mureo.google_ads.api.

Total impact: 1931 string replacements across 70 files.

Files changed

  • mureo/mcp/_tools_*.py, tools_*.py — 173 tool definitions
  • mureo/mcp/_handlers_*.py — dispatch tables
  • mureo/_data/skills/*, mureo/_data/commands/*, skills/* — skill prompts referencing tools
  • tests/test_mcp_tools_*.py, tests/test_meta_ads_*.py — mock keys / call args
  • docs/*, README.md, README.ja.md, CHANGELOG.md, AGENTS.md, CONTEXT.md, SECURITY.md — documentation

One assertion test updated:

  • tests/test_mcp_tools_search_console.py::test_all_tool_names_prefixed now asserts startswith("search_console_") (was "search_console.")

Test plan

  • pytest tests/test_mcp_tools_search_console.py tests/test_demo_init.py tests/test_demo_scenarios.py tests/test_byod.py tests/test_byod_bundle.py tests/test_cli.py tests/test_cli_rollback.py — 178/178 pass
  • ruff check mureo/mcp/ clean
  • black --check mureo/mcp/ clean
  • Net failure count vs main: ~unchanged. Pre-existing Meta-handler mock failures (split_tests, ad_rules, lead_forms, media_uploads) persist independently of this rename
  • Verified locally: Claude Desktop now successfully registers mureo (mcp-server-mureo.log shows tools/list returning all 173 tools, no validation errors)
  • CI green (in progress)

Behavioral change for users

Surface Before After
Claude Code works (lenient validation) works
Claude Desktop chat rejected with validation error works
Claude.ai web (Custom Connectors / remote MCP) rejected works
Codex / Cursor / other MCP hosts host-dependent spec-compliant
User-facing slash commands (e.g. /daily-check) unaffected unaffected
Direct tool-name references in user scripts dotted names must update to underscore

Users who invoke skills via natural language or slash commands need no changes. Anyone with code/scripts that hard-code google_ads.X.Y style names must rename to google_ads_X_Y.

Out of scope

  • Pre-existing Meta-handler test failures (mock returning wrong key shape) — unrelated to tool naming
  • .mcpb packaging for Claude Desktop UI install — separate Stage 3 follow-up

hyoshi added 5 commits May 1, 2026 06:33
…ores)

Claude Desktop chat enforces the MCP spec's tool-name regex
^[a-zA-Z0-9_-]{1,64}$ strictly. mureo's existing dotted tool names
(e.g. google_ads.campaigns.list) failed validation, causing the
entire mureo MCP server to be rejected at registration time.

This rename converts every dotted tool name to its underscore
equivalent across 173 unique names (e.g. google_ads_campaigns_list)
covering 5 prefixes:
  - google_ads (83 tools)
  - meta_ads (77 tools)
  - search_console (10 tools)
  - rollback (2 tools)
  - analysis (1 tool)

Changes span:
  - mureo/mcp/_tools_*.py and tools_*.py (173 tool definitions)
  - mureo/mcp/_handlers_*.py (dispatch tables)
  - mureo/_data/skills/* and mureo/_data/commands/* (skill prompts)
  - skills/* (top-level skill markdown copies)
  - tests/test_mcp_tools_*.py and tests/test_meta_ads_*.py (mock keys)
  - docs/*, README.md, README.ja.md, CHANGELOG.md, AGENTS.md

The rename was applied via a script that matches only quoted/standalone
occurrences of confirmed tool names (using lookbehind/lookahead for
non-identifier chars), avoiding accidental edits to Python module
paths like mureo.google_ads.api.

Verified MCP-spec compliance: every renamed tool name fits
^[a-zA-Z0-9_-]{1,64}$ (max 64 chars, only [A-Za-z0-9_-] allowed).

Test impact:
  - 178/178 tests pass on focused suites (demo/byod/cli/search_console)
  - test_mcp_tools_search_console::test_all_tool_names_prefixed updated
    to assert "search_console_" instead of "search_console."
  - Net failure count vs main: roughly unchanged; all pre-existing
    Meta-handler mock failures persist independently of this rename
  - ruff and black clean on all changed files

Behavioral change for users:
  - Claude Code: continues to work; users invoke skills via natural
    language, not raw tool names, so user prompts are unaffected
  - Claude Desktop: previously could not register mureo at all;
    now registers and exposes all 173 tools normally
  - Anyone with code/scripts referencing dotted tool names directly
    must update to the underscore form
- Resolve leftover merge-conflict marker in mureo/byod/clients.py
  (kept the upstream main version of the comment in _to_int)
- Suppress mypy [no-untyped-call] on Credentials.refresh in
  search_console/client.py — google-auth resolver in CI picked an
  unannotated variant; local picks the annotated one.
Two tests still asserted the old dotted prefix
("google_ads." / "meta_ads."); update to match the spec-compliant
underscore form ("google_ads_" / "meta_ads_").
CRITICAL #1 — rollback safety net silently disabled by half-rename:
- mureo/rollback/planner.py _ALLOWED_OPERATIONS keys all converted
  to underscore form; _DESTRUCTIVE_VERBS prefixes changed from .delete
  to _delete (dotted form no longer matches anything in the new
  underscore tool registry, which silently disabled the destructive-
  verb safety net)
- mureo/rollback/executor.py recursion guard 'rollback.' to 'rollback_'

CRITICAL #2 — 158+48 dotted tool refs remained in tool descriptions
and skill markdown that the LLM reads; rename script's lookahead was
too conservative on trailing punctuation. Two more passes:
- regex pass: any prefix.X.Y in known top-level prefixes
- explicit fixes: google_ads.zero_conversions.diagnose -> the actually
  registered google_ads_monitoring_zero_conversions; meta_ads.creatives
  .get -> meta_ads_creatives_list (no _get exists); google_ads.budgets
  .update (plural, never registered) -> google_ads_budget_update
  (singular, allowlist-keyed)

HIGH #1 — added tests/test_mcp_tool_name_spec.py:
- test_all_registered_tools_match_mcp_spec: regression guard pinning
  ^[a-zA-Z0-9_-]{1,64}$ across every tool surface
- test_no_duplicate_tool_names_across_surfaces: prevents undefined
  dispatch from name collisions

HIGH #2 — CHANGELOG migration note documents the breaking impact on
operators with custom excludeTools arrays (Gemini CLI extension).

Test impact: 1743 passed (was 1741), 157 failed (same pre-existing
Meta-handler mock failures as main), ruff + black clean.
@hyoshi hyoshi merged commit 53a811e into main Apr 30, 2026
8 checks passed
@hyoshi hyoshi deleted the fix/mcp-tool-names-spec-compliance branch April 30, 2026 22:21
hyoshi added a commit that referenced this pull request May 2, 2026
Non-engineer onboarding release. Highlights:

- Desktop / Cowork host support: 5 new MCP tools, install-desktop, MUREO_BYOD_DIR, Cowork plugin packaging

- BREAKING: slash commands -> skills (10 new operational skills), foundation skills renamed _mureo-*, mureo-workflows / mureo/_data/commands deleted

- BREAKING (carried from #73): MCP tool names dot -> underscore

- New docs/getting-started.md(.ja.md): 3 modes x 3 hosts walkthrough

See CHANGELOG.md for full migration guide and test additions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant