Claude Code 源码分析Claude Code 源码分析
首页
源码统计
系统架构
UML 图表
工具系统
CodeGraph
首页
源码统计
系统架构
UML 图表
工具系统
CodeGraph
  • 概览

    • Claude Code 源码分析
    • 源码统计
    • CodeGraph 图谱
  • 架构

    • 系统架构
    • UML 图表索引
    • 查询引擎
    • 核心流程
    • 消息系统
    • 状态管理
  • 功能模块

    • 工具系统
    • 斜杠命令
    • 服务层
    • MCP 协议
    • Skills 技能
    • 子代理系统
  • 分层深度

    • 入口层
    • UI / Ink 层
    • utils 基础设施
    • 桥接 / 远程
    • 上下文压缩
  • 原理与安全

    • 底层原理
    • 技术难点
    • 权限与安全
    • 内部机制
    • 遥测与分析
  • 深度专题

    • Hooks 系统
    • 插件系统
    • 记忆系统
    • API 通信层
    • Ink 终端 UI
    • 认证系统
    • 构建与发布
    • 术语表
  • 调用分析

    • 调用链分析
    • 核心文件索引
  • 模块详解

    • utils

      • 模块: utils
      • messages · 消息工厂与规范化
      • session-storage · JSONL 会话持久化
      • permissions · 工具权限决策
      • shell-hooks · 用户 Shell Hook 系统
    • components

      • 模块: components
      • REPL · 主屏编排
      • messages · 消息行渲染
      • PermissionRequest · 权限弹窗
      • PromptInput · 底部输入
    • services

      • 模块: services
      • api-claude · Anthropic API 流式与重试
      • mcp-client · MCP 连接与工具调用
      • compact · 上下文压缩与自动触发
      • analytics · GrowthBook、Datadog 与 1P 事件
    • tools

      • 模块: tools
      • tool-interface · Tool 契约与注册表
      • bash-tool · Shell 执行与权限
      • streaming-executor · 流式工具并发调度
      • agent-tool · 子 Agent 委派
    • commands

      • 模块: commands
      • command-registry · commands.ts 注册与分派
      • model-command · /model 模型选择
      • mcp-commands · /mcp 服务器管理
      • compact-memory-commands · /compact 与 /memory
    • ink

      • 模块: ink
      • Ink 渲染管线 · Screen 与终端输出
      • 终端事件 · resize、paste、stdin
      • Ink Hooks · 输入、搜索、终端状态
      • Ink 组件 · Box、Text、ScrollBox 原语
    • hooks

      • 模块: hooks
      • useCanUseTool · 权限 UI 接缝
      • 输入与快捷键 Hook
      • 合并态 Hook(MCP + 本地)
      • notifs 通知 Hook
    • bridge

      • 模块: bridge
      • repl-bridge · REPL 桥初始化与传输
      • bridge-messaging · 桥消息路由与入站处理
      • remote-bridge-core · env-less 核心与守护主循环
      • bridge-permissions-ui · 权限、API 与 TUI
    • cli

      • 模块: cli
      • Structured IO · NDJSON SDK 协议
      • CLI Transports · Session Ingress 传输层
      • CLI Handlers · 子命令懒加载实现
      • Update & Upload · 自更新与串行上传原语
    • screens

      • 模块: screens
      • REPL 屏 · Screen 类型与顶层路由
      • ResumeConversation · 会话恢复选择器
      • Doctor · 安装诊断全屏
    • entrypoints

      • 模块: entrypoints
      • cli-entrypoint · Bootstrap 与快路径
      • sdk-types · core / control / runtime 类型体系
      • mcp-entrypoint · MCP stdio 服务器
      • sandbox-types · 沙箱配置单一真相源
    • skills

      • 模块: skills
      • skills-loading · 磁盘加载与 bundled 注册表
      • bundled-skills · 内置 skill 与 initBundledSkills
      • mcp-skills · MCP prompt 转 skill
      • skill-tool-integration · SkillTool 与命令注册
    • types

      • 模块: types
      • message-types · Message 联合与 content blocks
      • tool-permission-types · Tool、Permission、Command 类型
      • api-sdk-types · API 与 Hooks 协议类型
      • misc-types · ids、plugin、generated 与其余类型
    • tasks

      • 模块: tasks
      • local-agent-task · 本地 Agent 与主会话后台化
      • remote-agent-task · 远程 CCR 与 In-Process Teammate
      • shell-workflow-tasks · Bash 后台、Workflow 与 stopTask
      • dream-monitor-tasks · Dream、Monitor MCP 与 pill 文案
    • keybindings

      • 模块: keybindings
      • keybinding-registry · 注册、Provider 与 useKeybinding
      • default-bindings · 默认键位表与平台差异
      • command-bindings · command:* 动态斜杠命令绑定
      • vim-bindings · Vim 模式与 keybindings 边界
    • memdir

      • 模块: memdir
      • memdir-core · 路径、加载与 MEMORY.md
      • memory-extraction · extractMemories 与 SessionMemory
      • memdir-commands · /memory、/remember 与命令集成
    • state

      • 模块: state
      • app-state-core · store、AppState 类型与 Provider
      • app-state-selectors · selectors 与 onChangeAppState
      • teammate-state · 队友视图与 swarm 状态
      • state-boundaries · bootstrap、sessionStorage、FileStateCache
    • query

      • 模块: query
      • query config 与 deps · 配置快照与依赖注入
      • query tokenBudget · +500k 自动续跑
      • query transitions · Continue / Terminal 状态机
      • query stopHooks · Stop 事件与 turn 结束编排
  • 模块详解(扩展)

    • messages · 消息工厂与规范化
    • session-storage · JSONL 会话持久化
    • permissions · 工具权限决策
    • shell-hooks · 用户 Shell Hook 系统
    • REPL · 主屏编排
    • messages · 消息行渲染
    • PermissionRequest · 权限弹窗
    • PromptInput · 底部输入
    • api-claude · Anthropic API 流式与重试
    • mcp-client · MCP 连接与工具调用
    • compact · 上下文压缩与自动触发
    • analytics · GrowthBook、Datadog 与 1P 事件
    • tool-interface · Tool 契约与注册表
    • bash-tool · Shell 执行与权限
    • streaming-executor · 流式工具并发调度
    • agent-tool · 子 Agent 委派
    • command-registry · commands.ts 注册与分派
    • model-command · /model 模型选择
    • mcp-commands · /mcp 服务器管理
    • compact-memory-commands · /compact 与 /memory
    • Ink 渲染管线 · Screen 与终端输出
    • 终端事件 · resize、paste、stdin
    • Ink Hooks · 输入、搜索、终端状态
    • Ink 组件 · Box、Text、ScrollBox 原语
    • useCanUseTool · 权限 UI 接缝
    • 输入与快捷键 Hook
    • 合并态 Hook(MCP + 本地)
    • notifs 通知 Hook
    • repl-bridge · REPL 桥初始化与传输
    • bridge-messaging · 桥消息路由与入站处理
    • remote-bridge-core · env-less 核心与守护主循环
    • bridge-permissions-ui · 权限、API 与 TUI
    • Structured IO · NDJSON SDK 协议
    • CLI Transports · Session Ingress 传输层
    • CLI Handlers · 子命令懒加载实现
    • Update & Upload · 自更新与串行上传原语
    • REPL 屏 · Screen 类型与顶层路由
    • ResumeConversation · 会话恢复选择器
    • Doctor · 安装诊断全屏
    • cli-entrypoint · Bootstrap 与快路径
    • sdk-types · core / control / runtime 类型体系
    • mcp-entrypoint · MCP stdio 服务器
    • sandbox-types · 沙箱配置单一真相源
    • skills-loading · 磁盘加载与 bundled 注册表
    • bundled-skills · 内置 skill 与 initBundledSkills
    • mcp-skills · MCP prompt 转 skill
    • skill-tool-integration · SkillTool 与命令注册
    • message-types · Message 联合与 content blocks
    • tool-permission-types · Tool、Permission、Command 类型
    • api-sdk-types · API 与 Hooks 协议类型
    • misc-types · ids、plugin、generated 与其余类型
    • local-agent-task · 本地 Agent 与主会话后台化
    • remote-agent-task · 远程 CCR 与 In-Process Teammate
    • shell-workflow-tasks · Bash 后台、Workflow 与 stopTask
    • dream-monitor-tasks · Dream、Monitor MCP 与 pill 文案
    • keybinding-registry · 注册、Provider 与 useKeybinding
    • default-bindings · 默认键位表与平台差异
    • command-bindings · command:* 动态斜杠命令绑定
    • vim-bindings · Vim 模式与 keybindings 边界
    • memdir-core · 路径、加载与 MEMORY.md
    • memory-extraction · extractMemories 与 SessionMemory
    • memdir-commands · /memory、/remember 与命令集成
    • app-state-core · store、AppState 类型与 Provider
    • app-state-selectors · selectors 与 onChangeAppState
    • teammate-state · 队友视图与 swarm 状态
    • state-boundaries · bootstrap、sessionStorage、FileStateCache
    • query config 与 deps · 配置快照与依赖注入
    • query tokenBudget · +500k 自动续跑
    • query transitions · Continue / Terminal 状态机
    • query stopHooks · Stop 事件与 turn 结束编排
  • 工具详解

    • tool-interface · Tool 契约与注册表
    • tool-permission-types · Tool、Permission、Command 类型
    • 工具: Bash
    • 工具: PowerShell
    • 工具: Agent
    • 工具: LSP
    • 工具: FileEdit
    • 工具: FileRead
    • 工具: Skill
    • 工具: WebFetch
    • 工具: MCP
    • 工具: SendMessage
    • 工具: FileWrite
    • 工具: Config
    • 工具: Grep
    • 工具: Brief
    • 工具: ExitPlanMode
    • 工具: ToolSearch
    • 工具: NotebookEdit
    • 工具: TaskOutput
    • 工具: WebSearch
    • 工具: ScheduleCron

本章总览

entrypoints/mcp.ts 实现 Claude Code 作为 MCP Server 的 stdio 模式:对外暴露内置 tools(getTools)与 review 命令,供外部 MCP client 调用。与 services/mcp/(Claude Code 作为 MCP client 连接外部 server)方向相反。本章讲解 startMCPServer、ListTools/CallTool handler 与 agentSdkTypes 的类型对称。

学完本章你应该能

  • 区分 mcp.ts server 与 services/mcp client 架构角色
  • 说明 setCwd、readFileStateCache、getEmptyToolPermissionContext 初始化
  • 理解 zodToJsonSchema 与 outputSchema type:object 根级限制
  • 描述 CallTool 内 hasPermissionsToUseTool 与 abort 行为
  • 关联 agentSdkTypes tool() 与 MCP SDK CallToolResult

核心概念(先读懂这些)

Claude Code 可同时是 MCP client 与 server

REPL 内用户配置 MCP servers → client。claude mcp serve 或嵌入场景 → mcp.ts server。server 名 claude/tengu,capabilities.tools。MCP_COMMANDS 目前仅 [review],TODO 注释提到未来 re-expose MCP tools。CallTool 与 ListTools 必须保持 schema 一致以免 client 调用了列表中不存在的 tool。

权限上下文在 server 模式简化

ListTools/CallTool 使用 getEmptyToolPermissionContext(),不弹出 REPL PermissionRequest。hasPermissionsToUseTool 仍执行,fail 时返回 tool error。readFileStateCache LRU 100 文件 / 25MB 防 MCP 长进程内存泄漏。

建议学习步骤

  1. 阅读 startMCPServer 签名与 Server 构造(源码块 A)
  2. 阅读 ListToolsRequestSchema handler(源码块 B)
  3. 阅读 CallTool 路径(源码块 C)
  4. 对照 agentSdkTypes MCP 类型 import(源码块 D)
  5. 理解 outputSchema 根级 object 限制原因

常见误区

注意

outputSchema 根级 anyOf/oneOf 会被跳过(GitHub issue #8014)

注意

MCP server 不加载 Ink/React,保持 headless 进程

注意

debug/verbose 参数传入但主要用于 tool execution logging

架构位置:server vs client

MCP 在 Claude Code 中有两个正交入口:

Claude Code 作为 CLIENT(常见):
  services/mcp/* → REPL 连接 filesystem/git MCP servers
  skills/mcpSkills.ts → MCP prompts 转为 slash skills

Claude Code 作为 SERVER(本章):
  entrypoints/mcp.ts → startMCPServer(cwd, debug, verbose)
  StdioServerTransport + @modelcontextprotocol/sdk Server

外部 IDE 或 orchestrator 通过 stdio Spawn claude MCP 模式进程,ListTools 获取与 CLI 内 nearly 相同的 tool schema(受 permission context 影响)。

agentSdkTypes.ts 从 MCP SDK 导入 CallToolResult,保证 SDK 用户定义的 tool 与 server 暴露的 tool 共用类型语言。

源码引用: src/entrypoints/mcp.ts · 第 1–28 行(共 197 行)

   1| import { Server } from '@modelcontextprotocol/sdk/server/index.js'
   2| import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
   3| import {
   4|   CallToolRequestSchema,
   5|   type CallToolResult,
   6|   ListToolsRequestSchema,
   7|   type ListToolsResult,
   8|   type Tool,
   9| } from '@modelcontextprotocol/sdk/types.js'
  10| import { getDefaultAppState } from 'src/state/AppStateStore.js'
  11| import review from '../commands/review.js'
  12| import type { Command } from '../commands.js'
  13| import {
  14|   findToolByName,
  15|   getEmptyToolPermissionContext,
  16|   type ToolUseContext,
  17| } from '../Tool.js'
  18| import { getTools } from '../tools.js'
  19| import { createAbortController } from '../utils/abortController.js'
  20| import { createFileStateCacheWithSizeLimit } from '../utils/fileStateCache.js'
  21| import { logError } from '../utils/log.js'
  22| import { createAssistantMessage } from '../utils/messages.js'
  23| import { getMainLoopModel } from '../utils/model/model.js'
  24| import { hasPermissionsToUseTool } from '../utils/permissions/permissions.js'
  25| import { setCwd } from '../utils/Shell.js'
  26| import { jsonStringify } from '../utils/slowOperations.js'
  27| import { getErrorParts } from '../utils/toolErrors.js'
  28| import { zodToJsonSchema } from '../utils/zodToJsonSchema.js'

源码引用: src/entrypoints/agentSdkTypes.ts · 第 12–15 行(共 444 行)

  12| import type {
  13|   CallToolResult,
  14|   ToolAnnotations,
  15| } from '@modelcontextprotocol/sdk/types.js'

startMCPServer 初始化

export async function startMCPServer(cwd, debug, verbose)

启动步骤:

  1. createFileStateCacheWithSizeLimit(100) — LRU readFileState
  2. setCwd(cwd) — 工具路径解析基准
  3. new Server({ name: 'claude/tengu', version: MACRO.VERSION }, { capabilities: { tools: {} } })
  4. 注册 ListTools / CallTool request handlers
  5. StdioServerTransport connect

MCP_COMMANDS = [review] — slash command 也可暴露为 MCP 可调用项(与纯 tool 区分)。

Server 不调用 init() 全量路径时,caller 负责 prior enableConfigs(视 launch 路径而定)。

源码引用: src/entrypoints/mcp.ts · 第 33–57 行(共 197 行)

  33| const MCP_COMMANDS: Command[] = [review]
  34| 
  35| export async function startMCPServer(
  36|   cwd: string,
  37|   debug: boolean,
  38|   verbose: boolean,
  39| ): Promise<void> {
  40|   // Use size-limited LRU cache for readFileState to prevent unbounded memory growth
  41|   // 100 files and 25MB limit should be sufficient for MCP server operations
  42|   const READ_FILE_STATE_CACHE_SIZE = 100
  43|   const readFileStateCache = createFileStateCacheWithSizeLimit(
  44|     READ_FILE_STATE_CACHE_SIZE,
  45|   )
  46|   setCwd(cwd)
  47|   const server = new Server(
  48|     {
  49|       name: 'claude/tengu',
  50|       version: MACRO.VERSION,
  51|     },
  52|     {
  53|       capabilities: {
  54|         tools: {},
  55|       },
  56|     },
  57|   )

源码引用: src/entrypoints/mcp.ts · 第 40–46 行(共 197 行)

  40|   // Use size-limited LRU cache for readFileState to prevent unbounded memory growth
  41|   // 100 files and 25MB limit should be sufficient for MCP server operations
  42|   const READ_FILE_STATE_CACHE_SIZE = 100
  43|   const readFileStateCache = createFileStateCacheWithSizeLimit(
  44|     READ_FILE_STATE_CACHE_SIZE,
  45|   )
  46|   setCwd(cwd)

ListTools:schema 转换与 outputSchema 过滤

ListTools handler:

const toolPermissionContext = getEmptyToolPermissionContext()
const tools = getTools(toolPermissionContext)
return {
  tools: await Promise.all(tools.map(async tool => {
    // inputSchema via zodToJsonSchema
    // outputSchema only if root type === 'object'
  }))
}

关键注释:MCP SDK 要求 outputSchema 根级 type: "object"。z.union / discriminatedUnion 转换后可能出现 anyOf/oneOf 根节点,此类 schema 跳过 outputSchema(GitHub issue #8014)。

这与 REPL 内 tool 列表同源 getTools(),但 permission context 为空——server 模式无 interactive allow rules UI。

源码引用: src/entrypoints/mcp.ts · 第 59–80 行(共 197 行)

  59|   server.setRequestHandler(
  60|     ListToolsRequestSchema,
  61|     async (): Promise<ListToolsResult> => {
  62|       // TODO: Also re-expose any MCP tools
  63|       const toolPermissionContext = getEmptyToolPermissionContext()
  64|       const tools = getTools(toolPermissionContext)
  65|       return {
  66|         tools: await Promise.all(
  67|           tools.map(async tool => {
  68|             let outputSchema: ToolOutput | undefined
  69|             if (tool.outputSchema) {
  70|               const convertedSchema = zodToJsonSchema(tool.outputSchema)
  71|               // MCP SDK requires outputSchema to have type: "object" at root level
  72|               // Skip schemas with anyOf/oneOf at root (from z.union, z.discriminatedUnion, etc.)
  73|               // See: https://github.com/anthropics/claude-code/issues/8014
  74|               if (
  75|                 typeof convertedSchema === 'object' &&
  76|                 convertedSchema !== null &&
  77|                 'type' in convertedSchema &&
  78|                 convertedSchema.type === 'object'
  79|               ) {
  80|                 outputSchema = convertedSchema as ToolOutput

源码引用: src/tools.ts · 第 1–30 行(共 390 行)

   1| // biome-ignore-all assist/source/organizeImports: ANT-ONLY import markers must not be reordered
   2| import { toolMatchesName, type Tool, type Tools } from './Tool.js'
   3| import { AgentTool } from './tools/AgentTool/AgentTool.js'
   4| import { SkillTool } from './tools/SkillTool/SkillTool.js'
   5| import { BashTool } from './tools/BashTool/BashTool.js'
   6| import { FileEditTool } from './tools/FileEditTool/FileEditTool.js'
   7| import { FileReadTool } from './tools/FileReadTool/FileReadTool.js'
   8| import { FileWriteTool } from './tools/FileWriteTool/FileWriteTool.js'
   9| import { GlobTool } from './tools/GlobTool/GlobTool.js'
  10| import { NotebookEditTool } from './tools/NotebookEditTool/NotebookEditTool.js'
  11| import { WebFetchTool } from './tools/WebFetchTool/WebFetchTool.js'
  12| import { TaskStopTool } from './tools/TaskStopTool/TaskStopTool.js'
  13| import { BriefTool } from './tools/BriefTool/BriefTool.js'
  14| // Dead code elimination: conditional import for ant-only tools
  15| /* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */
  16| const REPLTool =
  17|   process.env.USER_TYPE === 'ant'
  18|     ? require('./tools/REPLTool/REPLTool.js').REPLTool
  19|     : null
  20| const SuggestBackgroundPRTool =
  21|   process.env.USER_TYPE === 'ant'
  22|     ? require('./tools/SuggestBackgroundPRTool/SuggestBackgroundPRTool.js')
  23|         .SuggestBackgroundPRTool
  24|     : null
  25| const SleepTool =
  26|   feature('PROACTIVE') || feature('KAIROS')
  27|     ? require('./tools/SleepTool/SleepTool.js').SleepTool
  28|     : null
  29| const cronTools = feature('AGENT_TRIGGERS')
  30|   ? [

CallTool:执行与权限

CallTool handler 流程概要:

  1. findToolByName(name)
  2. parse arguments JSON
  3. createAbortController() — 客户端 disconnect 时 abort
  4. 构造 ToolUseContext(简化 AppState,无 REPL)
  5. hasPermissionsToUseTool — deny 则 structured error
  6. tool.call() → CallToolResult content parts
  7. jsonStringify 结果

getDefaultAppState() 提供 baseline store;与 REPL 的 canUseTool 队列不同,失败直接返回 error content。

createAssistantMessage / getErrorParts 统一错误格式化。

源码引用: src/entrypoints/mcp.ts · 第 80–120 行(共 197 行)

  80|                 outputSchema = convertedSchema as ToolOutput
  81|               }
  82|             }
  83|             return {
  84|               ...tool,
  85|               description: await tool.prompt({
  86|                 getToolPermissionContext: async () => toolPermissionContext,
  87|                 tools,
  88|                 agents: [],
  89|               }),
  90|               inputSchema: zodToJsonSchema(tool.inputSchema) as ToolInput,
  91|               outputSchema,
  92|             }
  93|           }),
  94|         ),
  95|       }
  96|     },
  97|   )
  98| 
  99|   server.setRequestHandler(
 100|     CallToolRequestSchema,
 101|     async ({ params: { name, arguments: args } }): Promise<CallToolResult> => {
 102|       const toolPermissionContext = getEmptyToolPermissionContext()
 103|       // TODO: Also re-expose any MCP tools
 104|       const tools = getTools(toolPermissionContext)
 105|       const tool = findToolByName(tools, name)
 106|       if (!tool) {
 107|         throw new Error(`Tool ${name} not found`)
 108|       }
 109| 
 110|       // Assume MCP servers do not read messages separately from the tool
 111|       // call arguments.
 112|       const toolUseContext: ToolUseContext = {
 113|         abortController: createAbortController(),
 114|         options: {
 115|           commands: MCP_COMMANDS,
 116|           tools,
 117|           mainLoopModel: getMainLoopModel(),
 118|           thinkingConfig: { type: 'disabled' },
 119|           mcpClients: [],
 120|           mcpResources: {},

源码引用: src/entrypoints/mcp.ts · 第 120–160 行(共 197 行)

 120|           mcpResources: {},
 121|           isNonInteractiveSession: true,
 122|           debug,
 123|           verbose,
 124|           agentDefinitions: { activeAgents: [], allAgents: [] },
 125|         },
 126|         getAppState: () => getDefaultAppState(),
 127|         setAppState: () => {},
 128|         messages: [],
 129|         readFileState: readFileStateCache,
 130|         setInProgressToolUseIDs: () => {},
 131|         setResponseLength: () => {},
 132|         updateFileHistoryState: () => {},
 133|         updateAttributionState: () => {},
 134|       }
 135| 
 136|       // TODO: validate input types with zod
 137|       try {
 138|         if (!tool.isEnabled()) {
 139|           throw new Error(`Tool ${name} is not enabled`)
 140|         }
 141|         const validationResult = await tool.validateInput?.(
 142|           (args as never) ?? {},
 143|           toolUseContext,
 144|         )
 145|         if (validationResult && !validationResult.result) {
 146|           throw new Error(
 147|             `Tool ${name} input is invalid: ${validationResult.message}`,
 148|           )
 149|         }
 150|         const finalResult = await tool.call(
 151|           (args ?? {}) as never,
 152|           toolUseContext,
 153|           hasPermissionsToUseTool,
 154|           createAssistantMessage({
 155|             content: [],
 156|           }),
 157|         )
 158| 
 159|         return {
 160|           content: [

agentSdkTypes 与 MCP server 对称

SDK 侧 tool() helper 返回符合 MCP CallToolResult 的 handler;server 侧 ListTools 把内部 Tool 定义转为 MCP Tool JSON schema。

类型导入链:

@modelcontextprotocol/sdk/types.js
  → agentSdkTypes (tool helper)
  → mcp.ts (CallToolResult in handlers)

SdkMcpToolDefinition(runtimeTypes)允许 SDK 进程内嵌 MCP server 实例配置,与 stdio mcp.ts 互补——前者 in-process,后者 subprocess 隔离。

embed 场景 controlTypes permission subtype 可把 tool permission 转发宿主 UI,弥补 server 模式无 REPL PermissionRequest 的缺口。

源码引用: src/entrypoints/agentSdkTypes.ts · 第 73–90 行(共 444 行)

  73| export function tool<Schema extends AnyZodRawShape>(
  74|   _name: string,
  75|   _description: string,
  76|   _inputSchema: Schema,
  77|   _handler: (
  78|     args: InferShape<Schema>,
  79|     extra: unknown,
  80|   ) => Promise<CallToolResult>,
  81|   _extras?: {
  82|     annotations?: ToolAnnotations
  83|     searchHint?: string
  84|     alwaysLoad?: boolean
  85|   },
  86| ): SdkMcpToolDefinition<Schema> {
  87|   throw new Error('not implemented')
  88| }
  89| 
  90| type CreateSdkMcpServerOptions = {

源码引用: src/entrypoints/sdk/runtimeTypes.ts · 第 17–22 行(共 23 行)

  17| export type AnyZodRawShape = Record<string, unknown>
  18| export type InferShape<T> = T
  19| export type SdkMcpToolDefinition<Schema> = {
  20|   schema?: Schema
  21|   [key: string]: unknown
  22| }

与 cli fast-path 的关系

cli.tsx 含 MCP sidecar fast-path:

  • --claude-in-chrome-mcp → runClaudeInChromeMcpServer
  • --computer-use-mcp → runComputerUseMcpServer

这些 不是 entrypoints/mcp.ts,但同属「Claude 子进程作为 MCP server」家族。entrypoints/mcp.ts 通常由 dedicated mcp serve 或测试 harness 调用。

对比 services/mcp-client 章:client 连接外部 server,stdio transport 方向相反。

调试 MCP server:verbose 参数传入 startMCPServer,tool execution 日志经 logError。

源码引用: src/entrypoints/cli.tsx · 第 72–93 行(共 308 行)

  72|     const prompt = await getSystemPrompt([], model)
  73|     // biome-ignore lint/suspicious/noConsole:: intentional console output
  74|     console.log(prompt.join('\n'))
  75|     return
  76|   }
  77| 
  78|   if (process.argv[2] === '--claude-in-chrome-mcp') {
  79|     profileCheckpoint('cli_claude_in_chrome_mcp_path')
  80|     const { runClaudeInChromeMcpServer } = await import(
  81|       '../utils/claudeInChrome/mcpServer.js'
  82|     )
  83|     await runClaudeInChromeMcpServer()
  84|     return
  85|   } else if (process.argv[2] === '--chrome-native-host') {
  86|     profileCheckpoint('cli_chrome_native_host_path')
  87|     const { runChromeNativeHost } = await import(
  88|       '../utils/claudeInChrome/chromeNativeHost.js'
  89|     )
  90|     await runChromeNativeHost()
  91|     return
  92|   } else if (
  93|     feature('CHICAGO_MCP') &&

源码引用: src/entrypoints/mcp.ts · 第 35–39 行(共 197 行)

  35| export async function startMCPServer(
  36|   cwd: string,
  37|   debug: boolean,
  38|   verbose: boolean,
  39| ): Promise<void> {

ToolUseContext 简化

MCP server 的 ToolUseContext 无 REPL 全量 AppState:readFileState 来自 LRU;无 canUseTool 队列;hasPermissionsToUseTool 同步 deny。

setCwd(cwd) 必须在 getTools 前调用。debug/verbose 控制 tool 日志粒度。

client disconnect 应 abort in-flight tool,abortController 与 createAbortController 绑定。

jsonStringify 与错误格式化

CallTool 成功路径用 jsonStringify(slowOperations)序列化 tool result,避免大对象阻塞 event loop。

失败路径 getErrorParts + createAssistantMessage 统一 error content blocks,MCP client 收到 isError: true。

getMainLoopModel 在 MCP server 模式仍影响需要 model 的 tool(如 implicit 默认);与 REPL mainLoopModel 同源函数。

MCP_COMMANDS 与 review

const MCP_COMMANDS: Command[] = [review]

review 命令作为 Command 类型注入 MCP 层,允许外部 client 触发 code review 流程而不仅是 raw Bash/Read tools。

ListTools TODO:Also re-expose any MCP tools — 未来可能把用户连接的 MCP server tools 反向代理到 stdio server,当前未实现。

zodToJsonSchema 位于 utils/zodToJsonSchema.ts,与 API tool schema 转换共用逻辑。

源码引用: src/entrypoints/mcp.ts · 第 30–34 行(共 197 行)

  30| type ToolInput = Tool['inputSchema']
  31| type ToolOutput = Tool['outputSchema']
  32| 
  33| const MCP_COMMANDS: Command[] = [review]
  34| 

源码引用: src/entrypoints/mcp.ts · 第 61–63 行(共 197 行)

  61|     async (): Promise<ListToolsResult> => {
  62|       // TODO: Also re-expose any MCP tools
  63|       const toolPermissionContext = getEmptyToolPermissionContext()

本章小结与延伸

mcp.ts = Claude Code 作为 MCP tool provider。SDK 类型见 agentSdkTypes;client 见 services/mcp-client 章。ListTools 与 CallTool 共用 getTools 但 permission context 为空。review 是唯一 MCP_COMMANDS 斜杠注入项。 继续学习:

  • sdk-types
  • services mcp-client
Prev
sdk-types · core / control / runtime 类型体系
Next
sandbox-types · 沙箱配置单一真相源