AI Assistant

MCP Tools

Claude Code integrates with external services through the Model Context Protocol (MCP). The MCP tool system provides a dynamic proxy for server tools, resource access, and authentication flows.

MCPTool (Dynamic Proxy)

MCPTool is a base tool definition that serves as a template for dynamically generated MCP tool instances. It is not used directly. Instead, the MCP client (src/services/mcp/client.ts) creates concrete tool instances by cloning MCPTool and overriding its properties with server-specific metadata.

How MCP Tools Are Created

When an MCP server connects, it advertises its available tools via the tools/list method. The MCP client:

  1. Receives each tool's name, description, and input schema from the server
  2. Creates a copy of MCPTool with overridden name, description, prompt, call, and userFacingName
  3. Sets the tool's inputJSONSchema directly from the server (MCP tools define schemas in JSON Schema format, not Zod)
  4. Registers the tool in appState.mcp.tools

Base Properties

const MCPTool = buildTool({
  isMcp: true,
  name: 'mcp',  // Overridden per tool instance
  maxResultSizeChars: 100_000,
  async checkPermissions(): Promise<PermissionResult> {
    return { behavior: 'passthrough', message: 'MCPTool requires permission.' }
  },
  // ... all rendering and behavior methods are overridden per instance
})

Input Schema

MCP tools use a passthrough Zod schema (z.object({}).passthrough()) for the internal type system, since actual validation is defined by the server's JSON Schema. The inputJSONSchema property carries the server-provided schema for API serialization.

Permission Model

MCP tools use passthrough behavior by default, meaning permission checks fall through to the general permission system. Users can set allow/deny rules scoped to MCP server prefixes:

  • mcp__server: blanket deny/allow for all tools from a server
  • mcp__server__tool: per-tool permission rules

When a blanket deny rule matches an MCP server prefix (e.g., mcp__server), all tools from that server are filtered out before the model sees them, not just at call time but at tool pool assembly time via filterToolsByDenyRules.


ListMcpResourcesTool

Lists resources available from connected MCP servers.

Parameters

serverstring

Optional server name to filter resources by. If omitted, lists resources from all connected servers.

Behavior

  • Iterates over all connected MCP clients (or the specified server)
  • Calls fetchResourcesForClient which is LRU-cached and pre-warmed at startup
  • Cache is invalidated on connection close and on resources/list_changed notifications
  • Uses ensureConnectedClient to reconnect if a server has disconnected

Output

Returns an array of resource descriptors:

{
  uri: string          // Resource URI
  name: string         // Resource display name
  mimeType?: string    // MIME type
  description?: string // Resource description
  server: string       // Server that provides this resource
}

Key Properties

  • Read-only: Yes
  • Concurrency-safe: Yes
  • Deferred: Yes
  • maxResultSizeChars: 100,000

ReadMcpResourceTool

Reads a specific resource from an MCP server by URI.

Parameters

serverstringrequired

The MCP server name.

uristringrequired

The resource URI to read.

Behavior

  1. Finds the specified MCP client by name
  2. Verifies the server is connected and supports the resources capability
  3. Sends a resources/read request to the server
  4. For binary content (blobs), persists the data to a temporary file and returns the file path
  5. For text content, returns the text directly

Output

{
  contents: Array<{
    uri: string           // Resource URI
    mimeType?: string     // MIME type of the content
    text?: string         // Text content (for text resources)
    blobSavedTo?: string  // File path (for binary resources)
  }>
}

Key Properties

  • Read-only: Yes
  • Concurrency-safe: Yes
  • Deferred: Yes
  • maxResultSizeChars: 100,000

McpAuthTool

A pseudo-tool created for MCP servers that require authentication. It replaces the server's real tools until authentication is complete.

How It Works

When an MCP server fails to connect due to an HTTP 401 (UnauthorizedError), the system creates a single McpAuthTool in place of the server's real tools. This tool:

  1. Is named mcp__<server>__authenticate
  2. Describes the authentication requirement in its prompt so the model knows the server exists
  3. When called, starts the OAuth flow via performMCPOAuthFlow
  4. Returns an authorization URL for the user to visit
  5. Once authentication completes in the background, the server reconnects and its real tools replace this pseudo-tool

OAuth Flow

[Model calls mcp__server__authenticate]
    |
    v
performMCPOAuthFlow(skipBrowserOpen)
    |
    v
Returns { status: 'auth_url', authUrl: '...' }
    |
    v
User visits URL and authenticates
    |
    v
OAuth callback fires
    |
    v
reconnectMcpServerImpl() runs
    |
    v
Real tools replace auth tool in appState.mcp.tools

For claude.ai MCP connectors (type: "claudeai-proxy"), the programmatic auth flow is not available. The tool instead instructs the user to run /mcp and authenticate through the MCP server menu.

Key Properties

  • Auto-allowed: Yes (no permission prompt needed to start the auth flow)
  • Concurrency-safe: No

Key Source Files

  • src/tools/MCPTool/MCPTool.ts: Base MCP tool template
  • src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts: Resource listing
  • src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts: Resource reading
  • src/tools/McpAuthTool/McpAuthTool.ts: OAuth authentication pseudo-tool
  • src/services/mcp/client.ts: MCP client connection and tool registration