Skip to content

Latest commit

 

History

History
137 lines (83 loc) · 6.63 KB

File metadata and controls

137 lines (83 loc) · 6.63 KB

Tool Discovery & Visibility Logic (MCP server + CLI)

This document describes how XcodeBuildMCP discovers workflows/tools and decides which ones are visible in:

  • the MCP server (xcodebuildmcp mcp), and
  • the CLI (node build/cli.js / xcodebuildmcp ...).

It also documents the current and intended visibility filtering behavior (post workflow-selection filtering).

Terminology

  • Workflow: a directory under src/mcp/tools/<workflow>/ containing an index.ts with workflow metadata and tool modules.
  • Tool: a PluginMeta exported from a workflow module with name, schema, and handler.
  • Workflow selection: picking which workflows are active (coarse-grained inclusion).
  • Visibility filtering: hiding specific tools even if their workflow is enabled (fine-grained exclusion).
  • Dynamic tools: tools registered at runtime that do not come from static workflows (e.g. proxied Xcode Tools).

Where workflows/tools come from (source of truth)

Workflows are discovered via generated loaders in src/core/generated-plugins.ts (the WORKFLOW_LOADERS map). At runtime, loadWorkflowGroups() imports each workflow module via these loaders and collects tools from it (src/core/plugin-registry.ts).

Key properties of this design:

  • Workflows are “discoverable” by enumerating Object.keys(WORKFLOW_LOADERS).
  • Tools within a workflow are whatever index.ts exports (excluding workflow itself).
  • A single tool name can appear in multiple workflows (re-exports). This matters for workflow management and hiding.

MCP server: registration pipeline

At MCP server startup:

  1. Runtime config is loaded (bootstrapRuntimeinitConfigStore) from:

    • config file (project config),
    • env (XCODEBUILDMCP_*),
    • explicit overrides.
  2. Enabled workflows are taken from config (enabledWorkflows).

  3. registerWorkflows(enabledWorkflows) runs, which calls applyWorkflowSelection(...) (src/utils/tool-registry.ts).

  4. Workflow selection uses selectWorkflowsForMcp(...) (src/visibility/exposure.ts) which:

    • includes auto-include workflows whose predicates pass (e.g., session-management with no predicates is always included),
    • includes explicitly requested workflows from config,
    • defaults to defaultEnabled: true workflows (e.g., simulator) when enabledWorkflows is empty,
    • filters all selected workflows by availability + predicates.
  5. For each selected workflow, each tool is considered for registration, then filtered by shouldExposeTool(workflowName, toolName) (src/utils/tool-registry.ts).

  6. If visible, the tool is registered via server.registerTool(...).

Runtime workflow management (MCP)

The manage-workflows tool updates the enabled workflow list at runtime and re-applies workflow selection (src/mcp/tools/workflow-discovery/manage_workflows.tsapplyWorkflowSelection(...)).

Important nuance:

  • Because tools can be re-exported across workflows, disabling one workflow may not remove a tool if another enabled workflow still provides that same tool name.
  • Visibility filtering operates on the tool name (and workflow name) at registration time; it is layered after workflow selection.

CLI: discovery and help output

The CLI has two related but distinct concepts:

  1. Command registration / --help tree (yargs commands)
  2. Tool listing (xcodebuildmcp tools) which is driven by a manifest

CLI command registration (yargs)

CLI mode builds a tool catalog using buildCliToolCatalog() which enables all workflows returned by listWorkflowDirectoryNames() except session-management and workflow-discovery (src/cli/cli-tool-catalog.ts).

The catalog is built via buildToolCatalog(...) (src/runtime/tool-catalog.ts), which:

  • loads workflow groups via loadWorkflowGroups(),
  • resolves selected workflows (as above),
  • applies shouldExposeTool(...) as a per-tool visibility filter,
  • generates CLI names and disambiguates collisions.

Yargs then registers workflow command groups and per-tool subcommands from the catalog (src/cli/register-tool-commands.ts).

Additionally, the CLI registers workflow command groups from workflow metadata even if there are currently zero visible tools in that workflow (so the workflow still appears in --help output).

CLI tools command (manifest-driven)

xcodebuildmcp tools reads build/tools-manifest.json (src/cli/commands/tools.ts) which is generated by npm run generate:tools-manifest (invoked by npm run build:tsup).

Key implications:

  • The manifest is a static analysis snapshot (canonical source for docs/CLI listing).
  • Dynamic runtime tools (see below) are not represented in the manifest.

Dynamic tools: Xcode Tools via xcrun mcpbridge

When the xcode-ide workflow is enabled, XcodeBuildMCP can proxy Xcode’s IDE tool service through xcrun mcpbridge and register proxied tools at runtime.

Properties:

  • Proxied tools are registered dynamically and prefixed as xcode_tools_<RemoteToolName> (see src/integrations/xcode-tools-bridge/registry.ts).
  • Proxied tools are not part of any static workflow and are not present in build/tools-manifest.json.
  • Proxied tool registration can change over time if Xcode’s tool catalog changes (the bridge supports tools/listChanged).

Visibility filtering (post-selection hiding)

Current behavior (implemented)

shouldExposeTool(...) is the single, shared visibility gate for:

  • MCP server tool registration (src/utils/tool-registry.ts)
  • CLI catalog building (src/runtime/tool-catalog.ts)

Currently it is used to hide Xcode IDE bridge debug tools unless debugging is enabled:

  • xcode_tools_bridge_status
  • xcode_tools_bridge_sync
  • xcode_tools_bridge_disconnect

These tools are gated behind debug: true / XCODEBUILDMCP_DEBUG=true (src/utils/tool-visibility.ts).

Intended behavior (documented policy)

We also want a broader “Xcode agent mode” visibility filter where specific XcodeBuildMCP tools are hidden when:

  • runningUnderXcode === true, AND
  • Xcode Tools MCP is enabled/available

This is documented in docs/dev/XCODE_IDE_TOOL_CONFLICTS.md.

Design principle:

  • Workflow selection stays the primary “what areas are enabled” control.
  • Visibility filtering is a secondary control to reduce confusion/duplication and align behavior with the environment (e.g. “inside Xcode, builds/tests should run inside Xcode”).

Layering summary (what wins)

  1. Workflow selection decides which workflows are in play.
  2. Visibility filtering can hide individual tools even within enabled workflows.
  3. Dynamic tools may appear even if there are no static tools in a workflow (e.g. proxied xcode_tools_*).