fix(mcp): rename tool names to be MCP-spec compliant (dots -> underscores)#73
Merged
fix(mcp): rename tool names to be MCP-spec compliant (dots -> underscores)#73
Conversation
…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
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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: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:
google_adsgoogle_ads.campaigns.list->google_ads_campaigns_listmeta_adsmeta_ads.creatives.create->meta_ads_creatives_createsearch_consolesearch_console.sites.list->search_console_sites_listrollbackrollback.plan.show->rollback_plan_showanalysisanalysis.anomalies.check->analysis_anomalies_checkAll 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
.pyand.mdfile 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 likemureo.google_ads.api.Total impact: 1931 string replacements across 70 files.
Files changed
mureo/mcp/_tools_*.py,tools_*.py— 173 tool definitionsmureo/mcp/_handlers_*.py— dispatch tablesmureo/_data/skills/*,mureo/_data/commands/*,skills/*— skill prompts referencing toolstests/test_mcp_tools_*.py,tests/test_meta_ads_*.py— mock keys / call argsdocs/*,README.md,README.ja.md,CHANGELOG.md,AGENTS.md,CONTEXT.md,SECURITY.md— documentationOne assertion test updated:
tests/test_mcp_tools_search_console.py::test_all_tool_names_prefixednow assertsstartswith("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 passruff check mureo/mcp/cleanblack --check mureo/mcp/cleanmcp-server-mureo.logshowstools/listreturning all 173 tools, no validation errors)Behavioral change for users
/daily-check)Users who invoke skills via natural language or slash commands need no changes. Anyone with code/scripts that hard-code
google_ads.X.Ystyle names must rename togoogle_ads_X_Y.Out of scope
.mcpbpackaging for Claude Desktop UI install — separate Stage 3 follow-up