Skip to content

MCP Tool Name Compatibility#1400

Open
kmeirlaen wants to merge 2 commits into
MrNeRF:masterfrom
kmeirlaen:fix-mcp-names
Open

MCP Tool Name Compatibility#1400
kmeirlaen wants to merge 2 commits into
MrNeRF:masterfrom
kmeirlaen:fix-mcp-names

Conversation

@kmeirlaen

Copy link
Copy Markdown
Collaborator

Summary

This patch makes MCP tool names Claude-compatible by exposing underscore-separated names in tools/list while preserving dotted-name compatibility for existing callers. It also fixes strict-client parsing by ensuring every MCP tool inputSchema.properties value is serialized as a JSON object, never null.

Observed Symptoms And Replication

Claude-compatible MCP clients validate tool names with a restricted pattern similar to ^[a-zA-Z0-9_-]{1,64}$. LichtFeld Studio exposed tools such as editor.run, scene.load_dataset, and runtime.job.wait, which contain dots. Clients that enforce this validation can silently drop those tools, leaving resources visible but no tools available.

A second strict-client failure was observed in the live tools/list payload after the name and metadata fixes: the generated session tools session_pause, session_request_stop, and session_resume returned {"type":"object","properties":null}. JSON Schema requires properties to be an object. A strict client that parses the tools array as one payload can fail on that single invalid schema and drop the full tool list.

Replication for the original issue:

  1. Start LichtFeld Studio MCP on http://127.0.0.1:45677/mcp.
  2. Connect with an MCP inspector or Claude connector.
  3. Call resources/list and observe resources are available.
  4. Call or inspect tools/list in a strict client and observe dotted tool names are rejected or omitted.
  5. On the affected build, inspect the raw tools/list JSON and observe inputSchema.properties is null for session_pause, session_request_stop, and session_resume.

Root Cause

The MCP server registered and returned tool names exactly as internal namespaces used them. Dotted names are convenient for internal grouping, but they are not accepted by clients that validate tool names as alphanumeric, underscore, or hyphen only. Runtime job IDs, operator IDs, event types, plugin capability names, and resource URIs are separate domain identifiers and should remain dotted.

The null-schema issue came from the CommandCenter-generated tool path. ToolRegistry::operation_to_tool default-initialized the schema properties JSON value, which leaves it as null for zero-argument operations. Other zero-argument tools used an explicitly empty object, so only tools generated through this path exposed the invalid shape. The protocol serializer also trusted stored schema values directly, so a bad registration could reach MCP clients unchanged.

What This Patch Fixes

  • Normalizes only MCP tool names at ToolRegistry boundaries by replacing . with _.
  • Keeps old dotted tools/call and unregister paths working by normalizing incoming names before lookup.
  • Keeps annotations limited to standard MCP annotation hints and moves LichtFeld-specific metadata into tool _meta.
  • Initializes CommandCenter-generated tool schemas with properties: {} for zero-argument operations.
  • Defensively serializes inputSchema.properties as {} if a stored tool schema has null or non-object properties.
  • Leaves non-tool identifiers untouched, including training.main, editor.python, operator.modal, transform.translate, event types, and lichtfeld:// resource URIs.
  • Updates MCP-facing descriptions and MCP docs so examples use the returned underscore tool names.
  • Adds protocol-level test coverage for tools/list, dotted and underscore tools/call, null schema property serialization, and unchanged structured response shape.

Impact Notes

  • GUI: GUI-registered MCP tools are normalized through the shared registry, so no GUI registration sites need mass renaming.
  • CLI/MCP server: tools/list returns Claude-compatible names; tools/call accepts both old dotted names and new underscore names; custom metadata is exposed under _meta with app.lichtfeld/... keys instead of non-standard x-lfs-* annotation keys.
  • Python API: Python-registered MCP tools pass through the same registry behavior; existing dotted lichtfeld.mcp.call_tool(...) callers remain compatible.
  • MCP clients: returned tool names are compatible with ^[a-zA-Z0-9_-]{1,64}$, x-lfs-* keys no longer appear in annotations, and strict JSON Schema parsers no longer encounter inputSchema.properties: null.
  • Docs: MCP recipes and AGENTS.md now use underscore tool names while preserving dotted domain IDs.

Copilot AI review requested due to automatic review settings July 8, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates LichtFeld Studio’s MCP tool surface to be compatible with strict MCP clients (e.g., Claude connectors) by (1) exposing underscore-separated tool names in tools/list while keeping dotted-name calls compatible, and (2) ensuring JSON Schema inputSchema.properties always serializes as an object (never null). It also relocates LichtFeld-specific tool metadata from non-standard annotations keys into _meta, and updates MCP documentation/examples accordingly.

Changes:

  • Normalize MCP tool names by replacing . with _ for listing, while accepting both dotted/underscore names for tools/call lookups.
  • Harden MCP tool schema serialization so inputSchema.properties is always {} when missing/invalid.
  • Move LichtFeld-specific tool metadata from annotations (x-lfs-*) into _meta (app.lichtfeld/...) and update docs/examples to reference underscore tool names.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/test_mcp_protocol.cpp Adds/updates protocol-level tests for underscore tool-name exposure, dotted/underscore call compatibility, _meta metadata, and null properties serialization.
src/mcp/mcp_training_context.cpp Updates tool description text to reference normalized (underscore) tool names in user-facing guidance.
src/mcp/mcp_tools.cpp Implements tool name normalization in the registry and fixes CommandCenter-generated tool schemas to use properties: {}.
src/mcp/mcp_protocol.cpp Ensures inputSchema.properties serializes as an object and moves LichtFeld-specific metadata into _meta.
src/app/mcp_ui_registry_tools.cpp Updates schema descriptions to reference normalized tool names (e.g., ui_menu_describe).
src/app/mcp_gui_tools.cpp Updates user-facing messages/descriptions to reference normalized tool names.
docs/docs/development/mcp/recipes/selection-and-gaussians.md Updates recipe examples to use underscore tool names.
docs/docs/development/mcp/recipes/operators-and-modal.md Updates recipe examples to use underscore tool names (while keeping dotted non-tool ids like operator.modal).
docs/docs/development/mcp/recipes/load-dataset-and-train.md Updates recipe examples to use underscore tool names for scene/training/runtime tools.
docs/docs/development/mcp/recipes/export-scene.md Updates export recipe examples to use underscore tool names.
docs/docs/development/mcp/recipes/editor-and-runtime.md Updates editor/runtime recipe examples to use underscore tool names.
docs/docs/development/mcp/index.md Updates namespace overview and runtime tool references to underscore tool names.
docs/docs/development/mcp/bootstrap.md Updates bootstrap guidance/examples to underscore tool names.
AGENTS.md Updates agent guidance to use underscore tool names in recommended flows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/mcp/mcp_tools.cpp
…ted McpTool.name internally - copilot remark
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.

2 participants