@leo000001/claude-code-mcp 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,486 +1,563 @@
1
- # claude-code-mcp
2
-
3
- [![npm version](https://img.shields.io/npm/v/@leo000001/claude-code-mcp.svg)](https://www.npmjs.com/package/@leo000001/claude-code-mcp)
4
- [![license](https://img.shields.io/npm/l/@leo000001/claude-code-mcp.svg)](https://github.com/xihuai18/claude-code-mcp/blob/HEAD/LICENSE)
5
- [![node](https://img.shields.io/node/v/@leo000001/claude-code-mcp.svg)](https://nodejs.org)
6
-
7
- MCP server that wraps [Claude Code (Claude Agent SDK)](https://docs.anthropic.com/en/docs/claude-code/overview) as tools, enabling any MCP client to invoke Claude Code for autonomous coding tasks.
8
-
9
- Inspired by the [Codex MCP](https://developers.openai.com/codex/guides/agents-sdk/) design philosophy — minimum tools, maximum capability.
10
-
11
- ## Features
12
-
13
- - **4 tools** covering the full agent lifecycle: start, continue, check/poll, manage
14
- - **Session management** with resume and fork support
15
- - **Local settings loaded by default** automatically reads `~/.claude/settings.json`, `.claude/settings.json`, `.claude/settings.local.json`, and `CLAUDE.md` so the agent behaves like your local Claude Code CLI
16
- - **Async permissions** — allow/deny lists + explicit approvals via `claude_code_check`
17
- - **Custom subagents** — define specialized agents per session
18
- - **Cost tracking** — per-session turn and cost accounting
19
- - **Session cancellation** via AbortController
20
- - **Auto-cleanup** 30-minute idle timeout for expired sessions
21
- - **Security** — callers control tool permissions via allow/deny lists + explicit permission decisions
22
-
23
- ## Prerequisites
24
-
25
- - **Node.js >= 18** is required.
26
-
27
- This MCP server uses the [`@anthropic-ai/claude-agent-sdk`](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) package, which **bundles its own Claude Code CLI** (`cli.js`). It does not use the `claude` binary from your system PATH.
28
-
29
- - The SDK's bundled CLI version is determined by the SDK package version (e.g. SDK 0.2.38 = Claude Code 2.1.38)
30
- - **Configuration is shared** — the bundled CLI reads API keys and settings from `~/.claude/`, same as the system-installed `claude`
31
- - **All local settings are loaded by default** — unlike the raw SDK (which defaults to isolation mode), this MCP server loads `user`, `project`, and `local` settings automatically, including `CLAUDE.md` project context. Pass `advanced.settingSources: []` to opt out
32
- - You must have Claude Code configured (API key set up) before using this MCP server: see [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/overview)
33
-
34
- > **Note:** The bundled CLI version may differ from your system-installed `claude`. To check: `claude --version` (system) vs `npm ls @anthropic-ai/claude-agent-sdk` (SDK).
35
-
36
- ## Quick Start
37
-
38
- ### As an MCP server (recommended)
39
-
40
- Install globally or use `npx` (no install needed):
41
-
42
- ```bash
43
- npm install -g @leo000001/claude-code-mcp
44
- ```
45
-
46
- Add to your MCP client configuration (Claude Desktop, Cursor, etc.):
47
-
48
- ```json
49
- {
50
- "mcpServers": {
51
- "claude-code": {
52
- "command": "npx",
53
- "args": ["-y", "@leo000001/claude-code-mcp"]
54
- }
55
- }
56
- }
57
- ```
58
-
59
- ### OpenAI Codex CLI
60
-
61
- ```bash
62
- codex mcp add claude-code -- npx -y @leo000001/claude-code-mcp
63
- ```
64
-
65
- Or manually add to `~/.codex/config.toml`:
66
-
67
- ```toml
68
- [mcp_servers.claude-code]
69
- command = "npx"
70
- args = ["-y", "@leo000001/claude-code-mcp"]
71
- ```
72
-
73
- Codex supports both user-level (`~/.codex/config.toml`) and project-level (`.codex/config.toml`) configuration. See [Codex config reference](https://developers.openai.com/codex/config-reference) for advanced options like `tool_timeout_sec` and `enabled_tools`.
74
-
75
- ### From source
76
-
77
- ```bash
78
- git clone https://github.com/xihuai18/claude-code-mcp.git
79
- cd claude-code-mcp
80
- npm install
81
- npm run build
82
- npm start
83
- ```
84
-
85
- ## Tools
86
-
87
- ### `claude_code` — Start a new session
88
-
89
- Start a new Claude Code session. The agent autonomously performs coding tasks: reading/writing files, running shell commands, searching code, managing git, and interacting with APIs.
90
-
91
- | Parameter | Type | Required | Description |
92
- | ---------------------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
93
- | `prompt` | string | Yes | Task or question for Claude Code |
94
- | `cwd` | string | No | Working directory (defaults to server cwd) |
95
- | `allowedTools` | string[] | No | Auto-approved tool names. Default: `[]` (none). Tools not in `allowedTools`/`disallowedTools` may surface permission requests via `claude_code_check`. Example: `["Bash", "Read", "Write", "Edit"]` |
96
- | `disallowedTools` | string[] | No | Forbidden tool names. Default: `[]` (none). SDK behavior: disallowed tools are removed from the model's context. Takes precedence over `allowedTools` and will be denied even if later approved interactively |
97
- | `maxTurns` | number | No | Maximum number of agent reasoning steps. Each step may involve one or more tool calls. Default: SDK/Claude Code default |
98
- | `model` | string | No | Model to use (e.g. `"claude-sonnet-4-5-20250929"`). Default: SDK/Claude Code default |
99
- | `systemPrompt` | string \| object | No | Override the agent's system prompt. Default: SDK/Claude Code default. Pass a string for full replacement, or `{ type: "preset", preset: "claude_code", append?: "..." }` to extend the default prompt |
100
- | `permissionRequestTimeoutMs` | number | No | Timeout in milliseconds waiting for permission decisions. Default: `60000` |
101
- | `advanced` | object | No | Advanced/low-frequency parameters (see below) |
102
-
103
- <details>
104
- <summary><code>advanced</code> object parameters (22 low-frequency parameters)</summary>
105
-
106
- | Parameter | Type | Description |
107
- | ------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
108
- | `advanced.tools` | string[] \| object | Define the base tool set. Default: SDK/Claude Code default toolset. Array of tool name strings, or `{ type: "preset", preset: "claude_code" }` for the default toolset. `allowedTools`/`disallowedTools` further filter on top of this |
109
- | `advanced.persistSession` | boolean | Persist session history to disk (`~/.claude/projects/`). Default: `true`. Set `false` to disable. |
110
- | `advanced.sessionInitTimeoutMs` | number | Timeout in milliseconds waiting for `system/init`. Default: `10000` |
111
- | `advanced.agents` | object | Define custom sub-agents the main agent can delegate tasks to. Default: none. SDK default: if a sub-agent omits `tools`, it inherits all tools from the parent. |
112
- | `advanced.agent` | string | Name of a custom agent (defined in `agents`) to use as the primary agent. Default: omitted |
113
- | `advanced.maxBudgetUsd` | number | Maximum budget in USD. Default: SDK/Claude Code default |
114
- | `advanced.effort` | string | Effort level: `"low"`, `"medium"`, `"high"`, `"max"`. Default: SDK/Claude Code default |
115
- | `advanced.betas` | string[] | Beta features (e.g. `["context-1m-2025-08-07"]`). Default: none |
116
- | `advanced.additionalDirectories` | string[] | Additional directories the agent can access beyond cwd. Default: none |
117
- | `advanced.outputFormat` | object | Structured output: `{ type: "json_schema", schema: {...} }`. Default: omitted (plain text) |
118
- | `advanced.thinking` | object | Thinking mode: `{ type: "adaptive" }`, `{ type: "enabled", budgetTokens: N }`, or `{ type: "disabled" }`. Default: SDK/Claude Code default |
119
- | `advanced.pathToClaudeCodeExecutable` | string | Path to the Claude Code executable. Default: SDK-bundled Claude Code (cli.js) |
120
- | `advanced.mcpServers` | object | MCP server configurations (key: server name, value: server config). Default: none |
121
- | `advanced.sandbox` | object | Sandbox configuration for isolating shell command execution (e.g., Docker container settings). Default: SDK/Claude Code default |
122
- | `advanced.fallbackModel` | string | Fallback model if the primary model fails or is unavailable. Default: none |
123
- | `advanced.enableFileCheckpointing` | boolean | Enable file checkpointing to track file changes during the session. Default: `false` |
124
- | `advanced.includePartialMessages` | boolean | When true, includes intermediate streaming messages in the response. Useful for real-time progress monitoring. Default: false |
125
- | `advanced.strictMcpConfig` | boolean | Enforce strict validation of MCP server configurations. Default: `false` |
126
- | `advanced.settingSources` | string[] | Which filesystem settings to load. Defaults to `["user", "project", "local"]` (loads all settings and CLAUDE.md). Pass `[]` for SDK isolation mode |
127
- | `advanced.debug` | boolean | Enable debug mode for verbose logging. Default: `false` |
128
- | `advanced.debugFile` | string | Write debug logs to a specific file path (implicitly enables debug mode). Default: omitted |
129
- | `advanced.env` | object | Environment variables to merge with process.env and pass to the Claude Code process (user values take precedence). Default: inherit process.env |
130
-
131
- </details>
132
-
133
- **Returns:** `{ sessionId, status: "running", pollInterval, resumeToken? }`
134
-
135
- Notes:
136
- - `resumeToken` is omitted by default, and is only returned when `CLAUDE_CODE_MCP_RESUME_SECRET` is set on the server.
137
- - On error: `{ sessionId: "", status: "error", error }`
138
-
139
- Use `claude_code_check` to poll events and obtain the final `result`.
140
-
141
- > Notes:
142
- > - **Subagents require the `Task` tool** to be available to the primary agent. If you use `allowedTools`, include `"Task"` or the agent will be unable to invoke subagents.
143
- > - If you configure `advanced.mcpServers` and want the agent to auto-use tools from those servers without approvals, include the exact tool names in `allowedTools` (e.g. `["mcp__my_server__tools/list"]`). Otherwise you will see permission requests via `claude_code_check`.
144
- > - `advanced.includePartialMessages` affects the underlying SDK event stream; intermediate messages are captured as events and returned via `claude_code_check` (the `claude_code` call itself does not stream).
145
-
146
- ### `claude_code_reply` — Continue a session
147
-
148
- Continue an existing session by sending a follow-up message. The agent retains full context from previous turns including files read, code analysis, and conversation history.
149
-
150
- | Parameter | Type | Required | Description |
151
- | ---------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
152
- | `sessionId` | string | Yes | Session ID from a previous `claude_code` call |
153
- | `prompt` | string | Yes | Follow-up prompt |
154
- | `forkSession` | boolean | No | Create a branched copy of this session. Default: `false` |
155
- | `permissionRequestTimeoutMs` | number | No | Timeout in milliseconds waiting for permission decisions. Default: `60000` |
156
- | `sessionInitTimeoutMs` | number | No | Timeout in milliseconds waiting for fork `system/init`. Default: `10000` |
157
- | `diskResumeConfig` | object | No | Disk resume parameters (see below). Used when `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1` and in-memory session is missing |
158
-
159
- <details>
160
- <summary><code>diskResumeConfig</code> object parameters (28 disk-resume-only parameters)</summary>
161
-
162
- | Parameter | Type | Description |
163
- | --------------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------- |
164
- | `diskResumeConfig.resumeToken` | string | Resume token returned by `claude_code` / `claude_code_reply`. Required for disk resume fallback |
165
- | `diskResumeConfig.cwd` | string | Working directory. Required for disk resume. |
166
- | `diskResumeConfig.allowedTools` | string[] | Auto-approved tool names (see `claude_code`). Default: `[]` |
167
- | `diskResumeConfig.disallowedTools` | string[] | Forbidden tool names (see `claude_code`). Default: `[]` |
168
- | `diskResumeConfig.tools` | string[] \| object | Base tool set (see `claude_code`). Default: SDK/Claude Code default |
169
- | `diskResumeConfig.persistSession` | boolean | Persist session history to disk. Default: `true` |
170
- | `diskResumeConfig.maxTurns` | number | Maximum number of agent reasoning steps. Default: SDK/Claude Code default |
171
- | `diskResumeConfig.model` | string | Model to use. Default: SDK/Claude Code default |
172
- | `diskResumeConfig.systemPrompt` | string \| object | Override the agent's system prompt. Default: SDK/Claude Code default |
173
- | `diskResumeConfig.agents` | object | Custom sub-agent definitions (see `claude_code`). Default: none |
174
- | `diskResumeConfig.agent` | string | Primary agent name (see `claude_code` tool). Default: omitted |
175
- | `diskResumeConfig.maxBudgetUsd` | number | Maximum budget in USD. Default: SDK/Claude Code default |
176
- | `diskResumeConfig.effort` | string | Effort level. Default: SDK/Claude Code default |
177
- | `diskResumeConfig.betas` | string[] | Beta features. Default: none |
178
- | `diskResumeConfig.additionalDirectories` | string[] | Additional directories. Default: none |
179
- | `diskResumeConfig.outputFormat` | object | Structured output format. Default: omitted (plain text) |
180
- | `diskResumeConfig.thinking` | object | Thinking mode. Default: SDK/Claude Code default |
181
- | `diskResumeConfig.resumeSessionAt` | string | Resume only up to and including a specific message UUID. Default: omitted |
182
- | `diskResumeConfig.pathToClaudeCodeExecutable` | string | Path to Claude Code executable. Default: SDK-bundled Claude Code (cli.js) |
183
- | `diskResumeConfig.mcpServers` | object | MCP server configurations. Default: none |
184
- | `diskResumeConfig.sandbox` | object | Sandbox config for command isolation. Default: SDK/Claude Code default |
185
- | `diskResumeConfig.fallbackModel` | string | Fallback model. Default: none |
186
- | `diskResumeConfig.enableFileCheckpointing` | boolean | Enable file checkpointing. Default: `false` |
187
- | `diskResumeConfig.includePartialMessages` | boolean | Include intermediate streaming messages. Default: `false` |
188
- | `diskResumeConfig.strictMcpConfig` | boolean | Strict MCP config validation. Default: `false` |
189
- | `diskResumeConfig.settingSources` | string[] | Which filesystem settings to load. Default: `["user", "project", "local"]` |
190
- | `diskResumeConfig.debug` | boolean | Debug mode. Default: `false` |
191
- | `diskResumeConfig.debugFile` | string | Debug log file path. Default: omitted |
192
- | `diskResumeConfig.env` | object | Environment variables. Default: inherit process.env (user values override) |
193
-
194
- </details>
195
-
196
- **Returns:** `{ sessionId, status: "running", pollInterval, resumeToken? }`
197
-
198
- Notes:
199
- - `resumeToken` is omitted by default, and is only returned when `CLAUDE_CODE_MCP_RESUME_SECRET` is set on the server.
200
- - On error: `{ sessionId, status: "error", error }`
201
-
202
- Use `claude_code_check` to poll events and obtain the final `result`.
203
-
204
- **Disk resume (optional):** By default, `claude_code_reply` requires the session to exist in the MCP server's in-memory Session Manager. If you set `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1`, it can attempt to resume using the Claude Code CLI's on-disk transcript even when the in-memory session is missing (e.g. after a restart / TTL cleanup). For safety, disk resume fallback requires `CLAUDE_CODE_MCP_RESUME_SECRET` to be set on the server and requires callers to pass `diskResumeConfig.resumeToken` (returned by `claude_code` / `claude_code_reply` when `CLAUDE_CODE_MCP_RESUME_SECRET` is set).
205
-
206
- ### `claude_code_session` Manage sessions
207
-
208
- List, inspect, or cancel sessions.
209
-
210
- | Parameter | Type | Required | Description |
211
- | ------------------ | ------- | -------------- | ------------------------------------------------------------------------------ |
212
- | `action` | string | Yes | `"list"`, `"get"`, or `"cancel"` |
213
- | `sessionId` | string | For get/cancel | Target session ID |
214
- | `includeSensitive` | boolean | No | Include `cwd`/`systemPrompt`/`agents`/`additionalDirectories` (default: false) |
215
-
216
- **Returns:** `{ sessions, message?, isError? }`
217
-
218
- ### `claude_code_check` Poll events and respond to permission requests
219
-
220
- Poll session events/results and approve/deny pending permission requests.
221
-
222
- | Parameter | Type | Required | Description |
223
- | ------------------- | ------- | ---------------------- | -------------------------------------------------------------------------------------------------------------- |
224
- | `action` | string | Yes | `"poll"` or `"respond_permission"` |
225
- | `sessionId` | string | Yes | Target session ID |
226
- | `cursor` | number | No | Event cursor for incremental polling (`poll` only). Default: omitted (starts from the beginning of the buffer) |
227
- | `responseMode` | string | No | `"minimal"` (default) or `"full"` — controls payload size and redaction behavior |
228
- | `maxEvents` | number | No | Max events per poll (pagination via `nextCursor`). Default: `200` in `"minimal"`; unlimited in `"full"` |
229
- | `requestId` | string | For respond_permission | Permission request ID |
230
- | `decision` | string | For respond_permission | `"allow"` or `"deny"` |
231
- | `denyMessage` | string | No | Deny reason shown to Claude (`deny` only). Default: `"Permission denied by caller"` |
232
- | `interrupt` | boolean | No | When true, denying also interrupts the whole agent (`deny` only). Default: `false` |
233
- | `pollOptions` | object | No | Fine-grained poll control options (see below) |
234
- | `permissionOptions` | object | No | Advanced permission response options (see below) |
235
-
236
- <details>
237
- <summary><code>pollOptions</code> object parameters (9 fine-grained poll controls)</summary>
238
-
239
- | Parameter | Type | Description |
240
- | ------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
241
- | `pollOptions.includeTools` | boolean | When true, includes `availableTools` (`poll` only). Default: `false` (omitted until session init is received) |
242
- | `pollOptions.includeEvents` | boolean | When false, omits `events` (but `nextCursor` still advances). Default: `true` |
243
- | `pollOptions.includeActions` | boolean | When false, omits `actions[]` even if `waiting_permission`. Default: `true` |
244
- | `pollOptions.includeResult` | boolean | When false, omits top-level `result` even when `idle`/`error`. Default: `true` |
245
- | `pollOptions.includeUsage` | boolean | Include `result.usage` (default: true in full mode, false in minimal mode) |
246
- | `pollOptions.includeModelUsage` | boolean | Include `result.modelUsage` (default: true in full mode, false in minimal mode) |
247
- | `pollOptions.includeStructuredOutput` | boolean | Include `result.structuredOutput` (default: true in full mode, false in minimal mode) |
248
- | `pollOptions.includeTerminalEvents` | boolean | When true, keeps terminal `result`/`error` events in `events` even if top-level `result` is included. Default: `false` in `"minimal"`, `true` in `"full"` |
249
- | `pollOptions.includeProgressEvents` | boolean | When true, includes progress events (`tool_progress`, `auth_status`) in the events stream. Default: `false` in `"minimal"`, `true` in `"full"` |
250
-
251
- </details>
252
-
253
- <details>
254
- <summary><code>permissionOptions</code> object parameters (2 advanced permission response options)</summary>
255
-
256
- | Parameter | Type | Description |
257
- | -------------------------------------- | ------ | ----------------------------------------------------------------------- |
258
- | `permissionOptions.updatedInput` | object | Modified tool input to run (`allow` only). Default: none |
259
- | `permissionOptions.updatedPermissions` | array | Permission rule updates suggested/applied (`allow` only). Default: none |
260
-
261
- </details>
262
-
263
- **Returns (poll and respond_permission):** `{ sessionId, status, pollInterval?, cursorResetTo?, truncated?, truncatedFields?, events, nextCursor?, availableTools?, actions?, result?, cancelledAt?, cancelledReason?, cancelledSource?, lastEventId?, lastToolUseId? }`
264
-
265
- Notes:
266
-
267
- - On error (e.g. invalid arguments, missing/expired session): `{ sessionId, isError: true, error }`
268
- - Always treat `cursor` as an incremental position: store `nextCursor` and pass it back on the next poll to avoid replaying old events.
269
- - If `cursorResetTo` is present, your `cursor` was too old (events were evicted); reset your cursor to `cursorResetTo`.
270
- - For safety, de-duplicate events by `event.id` on the client side.
271
- - If `truncated=true`, the server intentionally limited the payload (e.g. `maxEvents`) continue polling with `nextCursor`.
272
- - In `"minimal"` mode (default): assistant message events are slimmed (strips `usage`, `model`, `id`, `cache_control` from content blocks); noisy progress events (`tool_progress`, `auth_status`) are filtered out; `lastEventId`/`lastToolUseId` are omitted; `AgentResult` omits `durationApiMs`/`sessionTotalTurns`/`sessionTotalCostUsd`. Use `responseMode: "full"` or individual `include*` flags to restore any of these.
273
-
274
- ## Usage Example
275
-
276
- ```python
277
- # 1) Start a new session (async start)
278
- start = await mcp.call_tool("claude_code", {
279
- "prompt": "Fix the authentication bug in src/auth.ts",
280
- "cwd": "/path/to/project",
281
- "allowedTools": ["Read", "Edit", "Bash", "Glob", "Grep"],
282
- "advanced": {
283
- "effort": "high",
284
- "maxBudgetUsd": 5.0
285
- }
286
- })
287
- session_id = json.loads(start)["sessionId"]
288
- cursor = None
289
-
290
- # 2) Poll until idle/error/cancelled
291
- while True:
292
- polled = await mcp.call_tool("claude_code_check", {
293
- "action": "poll",
294
- "sessionId": session_id,
295
- "cursor": cursor,
296
- "pollOptions": {
297
- "includeProgressEvents": True
298
- }
299
- })
300
- data = json.loads(polled)
301
- cursor = data.get("nextCursor", cursor)
302
-
303
- # If permission is needed, approve/deny via respond_permission
304
- for action in data.get("actions", []) or []:
305
- if action.get("type") == "permission":
306
- await mcp.call_tool("claude_code_check", {
307
- "action": "respond_permission",
308
- "sessionId": session_id,
309
- "requestId": action["requestId"],
310
- "decision": "allow"
311
- })
312
-
313
- # Final result is available when status becomes idle/error
314
- if data.get("status") in ["idle", "error", "cancelled"]:
315
- final_result = data.get("result")
316
- break
317
-
318
- # 3) Manage sessions (list/get/cancel)
319
- result = await mcp.call_tool("claude_code_session", {"action": "list"})
320
- ```
321
-
322
- ## Windows Support
323
-
324
- The Claude Code CLI bundled in the SDK requires **Git for Windows** (which includes `bash.exe`). If you run this MCP server on Windows and see:
325
-
326
- ```
327
- Claude Code on Windows requires git-bash (https://git-scm.com/downloads/win).
328
- ```
329
-
330
- This means the spawned CLI process cannot locate `bash.exe`. Your locally installed `claude` command may work fine — the issue is that the MCP server's child process may not inherit your shell environment.
331
-
332
- **Fix: set `CLAUDE_CODE_GIT_BASH_PATH` in your MCP server config.**
333
-
334
- For JSON-based MCP clients (Claude Desktop, Cursor, etc.):
335
-
336
- ```json
337
- {
338
- "mcpServers": {
339
- "claude-code": {
340
- "command": "npx",
341
- "args": ["-y", "@leo000001/claude-code-mcp"],
342
- "env": {
343
- "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"
344
- }
345
- }
346
- }
347
- }
348
- ```
349
-
350
- For OpenAI Codex CLI (`~/.codex/config.toml`):
351
-
352
- ```toml
353
- [mcp_servers.claude-code]
354
- command = "npx"
355
- args = ["-y", "@leo000001/claude-code-mcp"]
356
-
357
- [mcp_servers.claude-code.env]
358
- CLAUDE_CODE_GIT_BASH_PATH = "C:\\Program Files\\Git\\bin\\bash.exe"
359
- ```
360
-
361
- > Replace the path with your actual `bash.exe` location. Common paths:
362
- > - `C:\Program Files\Git\bin\bash.exe` (default installer)
363
- >
364
- > To find yours: `where git` in CMD/PowerShell, then look for `bash.exe` under the same Git root's `bin\` folder.
365
-
366
- Alternatively, set the environment variable system-wide so all processes inherit it:
367
-
368
- ```powershell
369
- # PowerShell (permanent, requires new terminal)
370
- setx CLAUDE_CODE_GIT_BASH_PATH "C:\Program Files\Git\bin\bash.exe"
371
- ```
372
-
373
- ## Security
374
-
375
- - **Async permission approvals** — when a tool call needs approval, the session transitions to `waiting_permission` and surfaces requests via `claude_code_check` (`actions[]`).
376
- - **No runtime privilege escalation tool** — permission decisions are per-session (allow/deny lists + explicit approvals), and the server does not expose a `claude_code_configure` bypass switch.
377
- - **Environment variables are inherited** — the spawned Claude Code process inherits all environment variables (including `ANTHROPIC_API_KEY`) from the parent process by default. The `advanced.env` parameter **merges** with `process.env` (user-provided values take precedence), so you can safely add or override individual variables without losing existing ones.
378
- - Tool visibility vs approvals:
379
- - Use `advanced.tools` to restrict which tools the agent can *see* (hidden tools cannot be called).
380
- - Use `allowedTools` to auto-approve specific tools without prompting (the SDK may still prompt for path-based restrictions like `blockedPath`).
381
- - Use `disallowedTools` to hard-block tools; they are denied even if later approved via `claude_code_check`.
382
- - `maxTurns` and `advanced.maxBudgetUsd` prevent runaway execution.
383
- - Sessions auto-expire after 30 minutes of inactivity.
384
-
385
- ## Environment Variables
386
-
387
- All environment variables are optional. They are set on the MCP server process (not on the Claude Code child process — for that, use the `env` tool parameter).
388
-
389
- | Variable | Description | Default |
390
- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------- |
391
- | `CLAUDE_CODE_GIT_BASH_PATH` | Path to `bash.exe` on Windows (see [Windows Support](#windows-support)) | Auto-detected |
392
- | `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME` | Set to `1` to allow `claude_code_reply` to resume from on-disk transcripts when the in-memory session is missing | `0` (disabled) |
393
- | `CLAUDE_CODE_MCP_RESUME_SECRET` | HMAC secret used to validate `resumeToken` for disk resume fallback (recommended if disk resume is enabled) | *(unset)* |
394
-
395
- ### How to configure
396
-
397
- **JSON-based MCP clients** (Claude Desktop, Cursor, etc.) — add an `"env"` block:
398
-
399
- ```json
400
- {
401
- "mcpServers": {
402
- "claude-code": {
403
- "command": "npx",
404
- "args": ["-y", "@leo000001/claude-code-mcp"],
405
- "env": {
406
- "CLAUDE_CODE_MCP_ALLOW_DISK_RESUME": "1",
407
- "CLAUDE_CODE_MCP_RESUME_SECRET": "change-me"
408
- }
409
- }
410
- }
411
- }
412
- ```
413
-
414
- **OpenAI Codex CLI** add an `[mcp_servers.claude-code.env]` section in `~/.codex/config.toml`:
415
-
416
- ```toml
417
- [mcp_servers.claude-code]
418
- command = "npx"
419
- args = ["-y", "@leo000001/claude-code-mcp"]
420
-
421
- [mcp_servers.claude-code.env]
422
- CLAUDE_CODE_MCP_ALLOW_DISK_RESUME = "1"
423
- CLAUDE_CODE_MCP_RESUME_SECRET = "change-me"
424
- ```
425
-
426
- **System-wide** — set via your shell profile or OS settings so all processes inherit them:
427
-
428
- ```bash
429
- # bash / zsh
430
- export CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1
431
- export CLAUDE_CODE_MCP_RESUME_SECRET=change-me
432
-
433
- # PowerShell (permanent, requires new terminal)
434
- setx CLAUDE_CODE_MCP_ALLOW_DISK_RESUME 1
435
- setx CLAUDE_CODE_MCP_RESUME_SECRET change-me
436
- ```
437
-
438
- ## Development
439
-
440
- ```bash
441
- npm install # Install dependencies
442
- npm run build # Build with tsup
443
- npm run typecheck # Type check with tsc
444
- npm test # Run tests with vitest
445
- npm run dev # Watch mode build
446
- ```
447
-
448
- ## Architecture
449
-
450
- ```
451
- MCP Client ←→ (stdio/JSON-RPC) ←→ MCP Server
452
- ├── Session Manager (Map<id, state>)
453
- └── Claude Agent SDK (query())
454
- ```
455
-
456
- **Session persistence:** The MCP server's Session Manager holds **in-memory** session metadata, a snapshot of session options (tool config, limits, `cwd`, allow/deny lists, etc.), and an event buffer used by `claude_code_check`. This metadata is **not** persisted to disk by the MCP server. The actual conversation history is persisted to disk by the Claude Code CLI (under `~/.claude/projects/`) — this is managed by the SDK, not by this MCP server. By default, if the MCP server restarts or the session expires from memory, `claude_code_reply` will return `SESSION_NOT_FOUND` even though the CLI transcript may still exist on disk. You can opt into disk-resume behavior by setting `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1`.
457
-
458
- Sessions are automatically cleaned up after 30 minutes of idle time, or after 4 hours of continuous running.
459
-
460
- **Turn/Cost semantics:** `numTurns` and `totalCostUsd` are per-call increments. For cumulative per-session totals, use `sessionTotalTurns` and `sessionTotalCostUsd`. When `forkSession=true`, the returned `sessionId` (and `sessionTotal*`) refer to the forked session; the original session totals are preserved.
461
-
462
- ## Error Codes
463
-
464
- MCP server validation/policy errors are returned as `Error [CODE]: message` where `CODE` is one of:
465
-
466
- - `INVALID_ARGUMENT` — invalid inputs (e.g. missing sessionId, empty cwd)
467
- - `SESSION_NOT_FOUND`session not found in memory (expired or server restarted)
468
- - `SESSION_BUSY` — session currently running
469
- - `PERMISSION_DENIED` — operation not allowed by server policy
470
- - `PERMISSION_REQUEST_NOT_FOUND` — permission request ID not found (already finished or expired)
471
- - `TIMEOUT` — operation timed out
472
- - `CANCELLED` session was cancelled
473
- - `INTERNAL` — unexpected error or protocol mismatch
474
-
475
- For Claude Agent SDK execution failures, also check `errorSubtype` (e.g. `error_max_turns`, `error_max_budget_usd`, `error_during_execution`) and the returned `result` text.
476
-
477
- ## License
478
-
479
- MITsee [LICENSE](LICENSE)
480
-
481
- ## Contributing
482
-
483
- See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
484
-
485
- - [Security Policy](SECURITY.md)
486
- - [Code of Conduct](CODE_OF_CONDUCT.md)
1
+ # claude-code-mcp
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@leo000001/claude-code-mcp.svg)](https://www.npmjs.com/package/@leo000001/claude-code-mcp)
4
+ [![license](https://img.shields.io/npm/l/@leo000001/claude-code-mcp.svg)](https://github.com/xihuai18/claude-code-mcp/blob/HEAD/LICENSE)
5
+ [![node](https://img.shields.io/node/v/@leo000001/claude-code-mcp.svg)](https://nodejs.org)
6
+
7
+ MCP server that wraps [Claude Code (Claude Agent SDK)](https://docs.anthropic.com/en/docs/claude-code/overview) as tools, enabling any MCP client to invoke Claude Code for autonomous coding tasks. Designed for local use — the MCP server and client are expected to run on the same machine.
8
+
9
+ Inspired by the [Codex MCP](https://developers.openai.com/codex/guides/agents-sdk/) design philosophy — minimum tools, maximum capability.
10
+
11
+ ## Features
12
+
13
+ - **4 tools** covering the full agent lifecycle: start, continue, check/poll, manage
14
+ - **Read-only MCP resources** for server info, internal tool catalog, and compatibility diagnostics
15
+ - **Session management** with resume and fork support
16
+ - **Local settings loaded by default** — automatically reads `~/.claude/settings.json`, `.claude/settings.json`, `.claude/settings.local.json`, and `CLAUDE.md` so the agent behaves like your local Claude Code CLI
17
+ - **Async permissions** — allow/deny lists + explicit approvals via `claude_code_check`
18
+ - **Custom subagents** — define specialized agents per session
19
+ - **Cost tracking** per-session turn and cost accounting
20
+ - **Session cancellation** via AbortController
21
+ - **Auto-cleanup** — 30-minute idle timeout for expired sessions
22
+ - **Security** — callers control tool permissions via allow/deny lists + explicit permission decisions
23
+
24
+ See `CHANGELOG.md` for release history.
25
+
26
+ ## Prerequisites
27
+
28
+ - **Node.js >= 18** is required.
29
+ - **Same-platform deployment** this MCP server is designed to run on the same machine as the MCP client. It communicates via stdio (child process), reads local Claude configuration files from `~/.claude/`, and accesses the local file system directly. Remote deployment is not supported.
30
+
31
+ This MCP server uses the [`@anthropic-ai/claude-agent-sdk`](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) package, which **bundles its own Claude Code CLI** (`cli.js`). It does not use the `claude` binary from your system PATH.
32
+
33
+ - The SDK's bundled CLI version is determined by the SDK package version (e.g. SDK 0.2.38 = Claude Code 2.1.38)
34
+ - **Configuration is shared** — the bundled CLI reads API keys and settings from `~/.claude/`, same as the system-installed `claude`
35
+ - **All local settings are loaded by default** — unlike the raw SDK (which defaults to isolation mode), this MCP server loads `user`, `project`, and `local` settings automatically, including `CLAUDE.md` project context. Pass `advanced.settingSources: []` to opt out
36
+ - You must have Claude Code configured (API key set up) before using this MCP server: see [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/overview)
37
+
38
+ > **Note:** The bundled CLI version may differ from your system-installed `claude`. To check: `claude --version` (system) vs `npm ls @anthropic-ai/claude-agent-sdk` (SDK).
39
+
40
+ ## Quick Start
41
+
42
+ ### As an MCP server (recommended)
43
+
44
+ Install globally or use `npx` (no install needed):
45
+
46
+ ```bash
47
+ npm install -g @leo000001/claude-code-mcp
48
+ ```
49
+
50
+ Add to your MCP client configuration (Claude Desktop, Cursor, etc.):
51
+
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "claude-code": {
56
+ "command": "npx",
57
+ "args": ["-y", "@leo000001/claude-code-mcp"]
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ > Some clients cache tool definitions at connect-time. This server emits `notifications/tools/list_changed` after runtime tool discovery so clients can refresh the `claude_code` tool description.
64
+
65
+ ### Anthropic Claude Code CLI (as an MCP client)
66
+
67
+ ```bash
68
+ claude mcp add --transport stdio claude-code -- npx -y @leo000001/claude-code-mcp
69
+ ```
70
+
71
+ ### OpenAI Codex CLI
72
+
73
+ ```bash
74
+ codex mcp add claude-code -- npx -y @leo000001/claude-code-mcp
75
+ ```
76
+
77
+ Or manually add to `~/.codex/config.toml`:
78
+
79
+ ```toml
80
+ [mcp_servers.claude-code]
81
+ command = "npx"
82
+ args = ["-y", "@leo000001/claude-code-mcp"]
83
+ ```
84
+
85
+ Codex supports both user-level (`~/.codex/config.toml`) and project-level (`.codex/config.toml`) configuration. See [Codex config reference](https://developers.openai.com/codex/config-reference) for advanced options like `tool_timeout_sec` and `enabled_tools`.
86
+
87
+ ### From source
88
+
89
+ ```bash
90
+ git clone https://github.com/xihuai18/claude-code-mcp.git
91
+ cd claude-code-mcp
92
+ npm install
93
+ npm run build
94
+ npm start
95
+ ```
96
+
97
+ ## Tools
98
+
99
+ ### `claude_code` Start a new session
100
+
101
+ Start a new Claude Code session. The agent autonomously performs coding tasks: reading/writing files, running shell commands, searching code, managing git, and interacting with APIs.
102
+
103
+ | Parameter | Type | Required | Description |
104
+ | ---------------------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `prompt` | string | Yes | Task or question for Claude Code |
106
+ | `cwd` | string | No | Working directory (defaults to server cwd) |
107
+ | `allowedTools` | string[] | No | Auto-approved tool names. Default: `[]` (none). Tools not in `allowedTools`/`disallowedTools` may surface permission requests via `claude_code_check`. Example: `["Bash", "Read", "Write", "Edit"]` |
108
+ | `disallowedTools` | string[] | No | Forbidden tool names. Default: `[]` (none). SDK behavior: disallowed tools are removed from the model's context. Takes precedence over `allowedTools` and will be denied even if later approved interactively |
109
+ | `maxTurns` | number | No | Maximum number of agent reasoning steps. Each step may involve one or more tool calls. Default: SDK/Claude Code default |
110
+ | `model` | string | No | Model to use (e.g. `"claude-sonnet-4-5-20250929"`). Default: SDK/Claude Code default |
111
+ | `effort` | string | No | Effort level: `"low"`, `"medium"`, `"high"`, `"max"`. Default: SDK/Claude Code default |
112
+ | `thinking` | object | No | Thinking mode: `{ type: "adaptive" }`, `{ type: "enabled", budgetTokens: N }`, or `{ type: "disabled" }`. Default: SDK/Claude Code default |
113
+ | `systemPrompt` | string \| object | No | Override the agent's system prompt. Default: SDK/Claude Code default. Pass a string for full replacement, or `{ type: "preset", preset: "claude_code", append?: "..." }` to extend the default prompt |
114
+ | `permissionRequestTimeoutMs` | number | No | Timeout in milliseconds waiting for permission decisions, auto-deny on expiry. Default: `60000` (server-clamped to 5min) |
115
+ | `sessionInitTimeoutMs` | number | No | **Compatibility alias** for `advanced.sessionInitTimeoutMs` (deprecated for `claude_code`). Default: `10000`. If both are provided, `advanced.sessionInitTimeoutMs` wins |
116
+ | `advanced` | object | No | Advanced/low-frequency parameters (see below) |
117
+
118
+ <details>
119
+ <summary><code>advanced</code> object parameters (20 low-frequency parameters)</summary>
120
+
121
+ | Parameter | Type | Description |
122
+ | ------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
123
+ | `advanced.tools` | string[] \| object | Define the base tool set. Default: SDK/Claude Code default toolset. Array of tool name strings, or `{ type: "preset", preset: "claude_code" }` for the default toolset. `allowedTools`/`disallowedTools` further filter on top of this |
124
+ | `advanced.persistSession` | boolean | Persist session history to disk (`~/.claude/projects/`). Default: `true`. Set `false` to disable. |
125
+ | `advanced.sessionInitTimeoutMs` | number | Session init timeout in milliseconds waiting for `system/init`. Default: `10000`. **Recommended location for `claude_code` callers.** |
126
+ | `advanced.agents` | object | Define custom sub-agents the main agent can delegate tasks to. Default: none. SDK default: if a sub-agent omits `tools`, it inherits all tools from the parent. |
127
+ | `advanced.agent` | string | Name of a custom agent (defined in `agents`) to use as the primary agent. Default: omitted |
128
+ | `advanced.maxBudgetUsd` | number | Maximum budget in USD. Default: SDK/Claude Code default |
129
+ | `advanced.betas` | string[] | Beta features (e.g. `["context-1m-2025-08-07"]`). Default: none |
130
+ | `advanced.additionalDirectories` | string[] | Additional directories the agent can access beyond cwd. Default: none |
131
+ | `advanced.outputFormat` | object | Structured output: `{ type: "json_schema", schema: {...} }`. Default: omitted (plain text) |
132
+ | `advanced.pathToClaudeCodeExecutable` | string | Path to the Claude Code executable. Default: SDK-bundled Claude Code (cli.js) |
133
+ | `advanced.mcpServers` | object | MCP server configurations (key: server name, value: server config). Default: none |
134
+ | `advanced.sandbox` | object | Sandbox configuration for isolating shell command execution (e.g., Docker container settings). Default: SDK/Claude Code default |
135
+ | `advanced.fallbackModel` | string | Fallback model if the primary model fails or is unavailable. Default: none |
136
+ | `advanced.enableFileCheckpointing` | boolean | Enable file checkpointing to track file changes during the session. Default: `false` |
137
+ | `advanced.includePartialMessages` | boolean | When true, includes intermediate streaming messages in the response. Useful for real-time progress monitoring. Default: false |
138
+ | `advanced.strictMcpConfig` | boolean | Enforce strict validation of MCP server configurations. Default: `false` |
139
+ | `advanced.settingSources` | string[] | Which filesystem settings to load. Defaults to `["user", "project", "local"]` (loads all settings and CLAUDE.md). Pass `[]` for SDK isolation mode |
140
+ | `advanced.debug` | boolean | Enable debug mode for verbose logging. Default: `false` |
141
+ | `advanced.debugFile` | string | Write debug logs to a specific file path (implicitly enables debug mode). Default: omitted |
142
+ | `advanced.env` | object | Environment variables to merge with process.env and pass to the Claude Code process (user values take precedence). Default: inherit process.env |
143
+
144
+ Deprecated aliases: `advanced.effort` and `advanced.thinking` are still accepted for compatibility, but prefer top-level `effort` / `thinking` (top-level wins if both are set).
145
+
146
+ </details>
147
+
148
+ **Returns:** `{ sessionId, status: "running", pollInterval, resumeToken? }`
149
+
150
+ Notes:
151
+
152
+ - `resumeToken` is omitted by default, and is only returned when `CLAUDE_CODE_MCP_RESUME_SECRET` is set on the server.
153
+ - On error: `{ sessionId: "", status: "error", error }`
154
+ - If `sessionInitTimeoutMs` (top-level alias) is used, `claude_code` may return `compatWarnings` to guide migration to `advanced.sessionInitTimeoutMs`.
155
+
156
+ Use `claude_code_check` to poll events and obtain the final `result`.
157
+
158
+ > Notes:
159
+ >
160
+ > - **Subagents require the `Task` tool** to be available to the primary agent. If you use `allowedTools`, include `"Task"` or the agent will be unable to invoke subagents.
161
+ > - If you configure `advanced.mcpServers` and want the agent to auto-use tools from those servers without approvals, include the exact tool names in `allowedTools` (e.g. `["mcp__my_server__tools/list"]`). Otherwise you will see permission requests via `claude_code_check`.
162
+ > - `advanced.includePartialMessages` affects the underlying SDK event stream; intermediate messages are captured as events and returned via `claude_code_check` (the `claude_code` call itself does not stream).
163
+
164
+ > **Security: Configure permissions based on your own scope.** Callers (MCP clients / orchestrating agents) MUST set `allowedTools` and `disallowedTools` according to their own permission boundaries. Only pre-approve tools that you yourself are authorized to perform — do not grant the agent broader permissions than you have. For example, if you lack write access to a directory, do not include `Write`/`Edit` in `allowedTools`. When in doubt, leave both lists empty and review each permission request individually via `claude_code_check`.
165
+
166
+ ### `claude_code_reply` Continue a session
167
+
168
+ Continue an existing session by sending a follow-up message. The agent retains full context from previous turns including files read, code analysis, and conversation history.
169
+
170
+ | Parameter | Type | Required | Description |
171
+ | ---------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
172
+ | `sessionId` | string | Yes | Session ID from a previous `claude_code` call |
173
+ | `prompt` | string | Yes | Follow-up prompt |
174
+ | `forkSession` | boolean | No | Create a branched copy of this session. Default: `false` |
175
+ | `effort` | string | No | Effort level override for this run (and for future replies when not forking). Default: SDK/Claude Code default |
176
+ | `thinking` | object | No | Thinking mode override for this run (and for future replies when not forking). Default: SDK/Claude Code default |
177
+ | `permissionRequestTimeoutMs` | number | No | Timeout in milliseconds waiting for permission decisions, auto-deny on expiry. Default: `60000` |
178
+ | `sessionInitTimeoutMs` | number | No | Fork init timeout in milliseconds (only when `forkSession=true`). Default: `10000` |
179
+ | `diskResumeConfig` | object | No | Disk resume parameters (see below). Used when `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1` and in-memory session is missing |
180
+
181
+ <details>
182
+ <summary><code>diskResumeConfig</code> object parameters (28 disk-resume-only parameters)</summary>
183
+
184
+ | Parameter | Type | Description |
185
+ | --------------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------- |
186
+ | `diskResumeConfig.resumeToken` | string | Resume token returned by `claude_code` / `claude_code_reply`. Required for disk resume fallback |
187
+ | `diskResumeConfig.cwd` | string | Working directory. Required for disk resume. |
188
+ | `diskResumeConfig.allowedTools` | string[] | Auto-approved tool names (see `claude_code`). Default: `[]` |
189
+ | `diskResumeConfig.disallowedTools` | string[] | Forbidden tool names (see `claude_code`). Default: `[]` |
190
+ | `diskResumeConfig.tools` | string[] \| object | Base tool set (see `claude_code`). Default: SDK/Claude Code default |
191
+ | `diskResumeConfig.persistSession` | boolean | Persist session history to disk. Default: `true` |
192
+ | `diskResumeConfig.maxTurns` | number | Maximum number of agent reasoning steps. Default: SDK/Claude Code default |
193
+ | `diskResumeConfig.model` | string | Model to use. Default: SDK/Claude Code default |
194
+ | `diskResumeConfig.systemPrompt` | string \| object | Override the agent's system prompt. Default: SDK/Claude Code default |
195
+ | `diskResumeConfig.agents` | object | Custom sub-agent definitions (see `claude_code`). Default: none |
196
+ | `diskResumeConfig.agent` | string | Primary agent name (see `claude_code` tool). Default: omitted |
197
+ | `diskResumeConfig.maxBudgetUsd` | number | Maximum budget in USD. Default: SDK/Claude Code default |
198
+ | `diskResumeConfig.effort` | string | Effort level. Default: SDK/Claude Code default |
199
+ | `diskResumeConfig.betas` | string[] | Beta features. Default: none |
200
+ | `diskResumeConfig.additionalDirectories` | string[] | Additional directories. Default: none |
201
+ | `diskResumeConfig.outputFormat` | object | Structured output format. Default: omitted (plain text) |
202
+ | `diskResumeConfig.thinking` | object | Thinking mode. Default: SDK/Claude Code default |
203
+ | `diskResumeConfig.resumeSessionAt` | string | Resume only up to and including a specific message UUID. Default: omitted |
204
+ | `diskResumeConfig.pathToClaudeCodeExecutable` | string | Path to Claude Code executable. Default: SDK-bundled Claude Code (cli.js) |
205
+ | `diskResumeConfig.mcpServers` | object | MCP server configurations. Default: none |
206
+ | `diskResumeConfig.sandbox` | object | Sandbox config for command isolation. Default: SDK/Claude Code default |
207
+ | `diskResumeConfig.fallbackModel` | string | Fallback model. Default: none |
208
+ | `diskResumeConfig.enableFileCheckpointing` | boolean | Enable file checkpointing. Default: `false` |
209
+ | `diskResumeConfig.includePartialMessages` | boolean | Include intermediate streaming messages. Default: `false` |
210
+ | `diskResumeConfig.strictMcpConfig` | boolean | Strict MCP config validation. Default: `false` |
211
+ | `diskResumeConfig.settingSources` | string[] | Which filesystem settings to load. Default: `["user", "project", "local"]` |
212
+ | `diskResumeConfig.debug` | boolean | Debug mode. Default: `false` |
213
+ | `diskResumeConfig.debugFile` | string | Debug log file path. Default: omitted |
214
+ | `diskResumeConfig.env` | object | Environment variables. Default: inherit process.env (user values override) |
215
+
216
+ </details>
217
+
218
+ **Returns:** `{ sessionId, status: "running", pollInterval, resumeToken? }`
219
+
220
+ Notes:
221
+
222
+ - `resumeToken` is omitted by default, and is only returned when `CLAUDE_CODE_MCP_RESUME_SECRET` is set on the server.
223
+ - On error: `{ sessionId, status: "error", error }`
224
+
225
+ Use `claude_code_check` to poll events and obtain the final `result`.
226
+
227
+ Gotchas:
228
+
229
+ - Permission approvals have a timeout (default 60s via `permissionRequestTimeoutMs`) and will auto-deny; watch `actions[].expiresAt` / `actions[].remainingMs`.
230
+ - `Read` has a per-call size cap in practice (often ~256KB); for large files use `offset`/`limit` or chunk with `Grep`.
231
+ - `Edit` with `replace_all=true` is substring replacement; if no match is found the tool returns a clear error.
232
+ - On Windows, this server normalizes common MSYS-style paths (e.g. `/d/...`, `/mnt/c/...`, `/cygdrive/c/...`, `//server/share/...`) for `cwd`, `additionalDirectories`, and tool inputs that include `file_path`.
233
+ - On Windows, POSIX home paths like `/home/user/...` are **not** rewritten to drive paths; prefer absolute Windows paths under your current `cwd` to avoid out-of-bounds permission prompts.
234
+ - `TeamDelete` may require members to reach `shutdown_approved` (otherwise you may see "active member" errors); cleanup can be asynchronous during shutdown.
235
+ - Skills may become available later in the same session (early calls may show "Unknown", later succeed after skills are loaded/registered).
236
+ - Some internal features (e.g. ToolSearch) may not appear in `availableTools` (derived from SDK `system/init.tools`).
237
+
238
+ ### Resources
239
+
240
+ If your MCP client supports resources, this server exposes a couple of **read-only** MCP resources:
241
+
242
+ - `claude-code-mcp:///server-info` (JSON): server metadata (version/platform/runtime)
243
+ - `claude-code-mcp:///internal-tools` (JSON): internal tool catalog (runtime-aware)
244
+ - `claude-code-mcp:///gotchas` (Markdown): practical limits/gotchas
245
+ - `claude-code-mcp:///compat-report` (JSON): compatibility report (transport/platform assumptions, runtime warnings, guidance)
246
+
247
+ **Disk resume (optional):** By default, `claude_code_reply` requires the session to exist in the MCP server's in-memory Session Manager. If you set `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1`, it can attempt to resume using the Claude Code CLI's on-disk transcript even when the in-memory session is missing (e.g. after a restart / TTL cleanup). For safety, disk resume fallback requires `CLAUDE_CODE_MCP_RESUME_SECRET` to be set on the server and requires callers to pass `diskResumeConfig.resumeToken` (returned by `claude_code` / `claude_code_reply` when `CLAUDE_CODE_MCP_RESUME_SECRET` is set).
248
+
249
+ ### `claude_code_session` Manage sessions
250
+
251
+ List, inspect, or cancel sessions.
252
+
253
+ | Parameter | Type | Required | Description |
254
+ | ------------------ | ------- | -------------- | ------------------------------------------------------------------------------ |
255
+ | `action` | string | Yes | `"list"`, `"get"`, or `"cancel"` |
256
+ | `sessionId` | string | For get/cancel | Target session ID |
257
+ | `includeSensitive` | boolean | No | Include `cwd`/`systemPrompt`/`agents`/`additionalDirectories` (default: false) |
258
+
259
+ **Returns:** `{ sessions, message?, isError? }`
260
+
261
+ ### `claude_code_check` — Poll events and respond to permission requests
262
+
263
+ Poll session events/results and approve/deny pending permission requests.
264
+
265
+ | Parameter | Type | Required | Description |
266
+ | ------------------- | ------- | ---------------------- | -------------------------------------------------------------------------------------------------------------- |
267
+ | `action` | string | Yes | `"poll"` or `"respond_permission"` |
268
+ | `sessionId` | string | Yes | Target session ID |
269
+ | `cursor` | number | No | Event cursor for incremental polling (`poll` only). Default: omitted (starts from the beginning of the buffer) |
270
+ | `responseMode` | string | No | `"minimal"` (default) or `"full"` controls payload size and redaction behavior |
271
+ | `maxEvents` | number | No | Max events per poll (pagination via `nextCursor`). Default: `200` in `"minimal"`; unlimited in `"full"` |
272
+ | `requestId` | string | For respond_permission | Permission request ID |
273
+ | `decision` | string | For respond_permission | `"allow"` or `"deny"` |
274
+ | `denyMessage` | string | No | Deny reason shown to Claude (`deny` only). Default: `"Permission denied by caller"` |
275
+ | `interrupt` | boolean | No | When true, denying also interrupts the whole agent (`deny` only). Default: `false` |
276
+ | `pollOptions` | object | No | Fine-grained poll control options (see below) |
277
+ | `permissionOptions` | object | No | Advanced permission response options (see below) |
278
+
279
+ <details>
280
+ <summary><code>pollOptions</code> object parameters (10 fine-grained poll controls)</summary>
281
+
282
+ | Parameter | Type | Description |
283
+ | ------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
284
+ | `pollOptions.includeTools` | boolean | When true, includes `availableTools` (`poll` only). Default: `false` (omitted until session init is received). Derived from SDK `system/init.tools` (internal features may not appear). |
285
+ | `pollOptions.includeEvents` | boolean | When false, omits `events` (but `nextCursor` still advances). Default: `true` |
286
+ | `pollOptions.includeActions` | boolean | When false, omits `actions[]` even if `waiting_permission`. Default: `true` |
287
+ | `pollOptions.includeResult` | boolean | When false, omits top-level `result` even when `idle`/`error`. Default: `true` |
288
+ | `pollOptions.includeUsage` | boolean | Include `result.usage` (default: true in full mode, false in minimal mode) |
289
+ | `pollOptions.includeModelUsage` | boolean | Include `result.modelUsage` (default: true in full mode, false in minimal mode) |
290
+ | `pollOptions.includeStructuredOutput` | boolean | Include `result.structuredOutput` (default: true in full mode, false in minimal mode) |
291
+ | `pollOptions.includeTerminalEvents` | boolean | When true, keeps terminal `result`/`error` events in `events` even if top-level `result` is included. Default: `false` in `"minimal"`, `true` in `"full"` |
292
+ | `pollOptions.includeProgressEvents` | boolean | When true, includes progress events (`tool_progress`, `auth_status`) in the events stream. Default: `false` in `"minimal"`, `true` in `"full"` |
293
+ | `pollOptions.maxBytes` | number | Approximate max JSON bytes for `events` in this response. When exceeded, events are truncated and `truncatedFields` includes `"events_bytes"`. Default: unlimited |
294
+
295
+ </details>
296
+
297
+ <details>
298
+ <summary><code>permissionOptions</code> object parameters (2 advanced permission response options)</summary>
299
+
300
+ | Parameter | Type | Description |
301
+ | -------------------------------------- | ------ | ----------------------------------------------------------------------- |
302
+ | `permissionOptions.updatedInput` | object | Modified tool input to run (`allow` only). Default: none |
303
+ | `permissionOptions.updatedPermissions` | array | Permission rule updates suggested/applied (`allow` only). Default: none |
304
+
305
+ </details>
306
+
307
+ **Returns (poll and respond_permission):** `{ sessionId, status, pollInterval?, cursorResetTo?, truncated?, truncatedFields?, events, nextCursor?, availableTools?, toolValidation?, compatWarnings?, actions?, result?, cancelledAt?, cancelledReason?, cancelledSource?, lastEventId?, lastToolUseId? }`
308
+
309
+ Notes:
310
+
311
+ - On error (e.g. invalid arguments, missing/expired session): `{ sessionId, isError: true, error }`
312
+ - Always treat `cursor` as an incremental position: store `nextCursor` and pass it back on the next poll to avoid replaying old events.
313
+ - If `cursorResetTo` is present, your `cursor` was too old (events were evicted); reset your cursor to `cursorResetTo`.
314
+ - For safety, de-duplicate events by `event.id` on the client side.
315
+ - If `truncated=true`, the server intentionally limited the payload (e.g. `maxEvents`) — continue polling with `nextCursor`.
316
+ - `nextCursor` can remain unchanged with `events=[]` during quiet intervals; this is normal transient behavior. Retry a few times (for example up to 3) before treating it as abnormal.
317
+ - `toolValidation` reports whether configured `allowedTools`/`disallowedTools` match runtime-discovered tool names.
318
+ - `compatWarnings` surfaces compatibility hints (for example, unresolved tool names or path/platform mismatch signals) and is **non-blocking**; treat it as advisory unless the session actually fails.
319
+ - Permission `actions[]` include `timeoutMs`, `expiresAt`, and best-effort `remainingMs` to help callers avoid auto-deny timeouts.
320
+ - `permission_result` event data is `{ requestId, toolName, behavior, source, message?, interrupt? }` (denial details only present for `deny`).
321
+ - In `"minimal"` mode (default): assistant message events are slimmed (strips `usage`, `model`, `id`, `cache_control` from content blocks); noisy progress events (`tool_progress`, `auth_status`) are filtered out; `lastEventId`/`lastToolUseId` are omitted; `AgentResult` omits `durationApiMs`/`sessionTotalTurns`/`sessionTotalCostUsd`. Use `responseMode: "full"` or individual `include*` flags to restore any of these.
322
+
323
+ ## Usage Example
324
+
325
+ ```python
326
+ # 1) Start a new session (async start)
327
+ start = await mcp.call_tool("claude_code", {
328
+ "prompt": "Fix the authentication bug in src/auth.ts",
329
+ "cwd": "/path/to/project",
330
+ "allowedTools": ["Read", "Edit", "Bash", "Glob", "Grep"],
331
+ "effort": "high",
332
+ "advanced": {
333
+ "maxBudgetUsd": 5.0
334
+ }
335
+ })
336
+ session_id = json.loads(start)["sessionId"]
337
+ cursor = 0
338
+
339
+ # 2) Poll until idle/error/cancelled
340
+ while True:
341
+ polled = await mcp.call_tool("claude_code_check", {
342
+ "action": "poll",
343
+ "sessionId": session_id,
344
+ "cursor": cursor,
345
+ "pollOptions": {
346
+ "includeProgressEvents": True
347
+ }
348
+ })
349
+ data = json.loads(polled)
350
+ cursor = data.get("nextCursor", cursor)
351
+
352
+ # If permission is needed, approve/deny via respond_permission
353
+ for action in data.get("actions", []) or []:
354
+ if action.get("type") == "permission":
355
+ await mcp.call_tool("claude_code_check", {
356
+ "action": "respond_permission",
357
+ "sessionId": session_id,
358
+ "requestId": action["requestId"],
359
+ "decision": "allow"
360
+ })
361
+
362
+ # Final result is available when status becomes idle/error
363
+ if data.get("status") in ["idle", "error", "cancelled"]:
364
+ final_result = data.get("result")
365
+ break
366
+
367
+ # 3) Manage sessions (list/get/cancel)
368
+ result = await mcp.call_tool("claude_code_session", {"action": "list"})
369
+ ```
370
+
371
+ ## Windows Support
372
+
373
+ The Claude Code CLI bundled in the SDK requires **Git for Windows** (which includes `bash.exe`). If you run this MCP server on Windows and see:
374
+
375
+ ```
376
+ Claude Code on Windows requires git-bash (https://git-scm.com/downloads/win).
377
+ ```
378
+
379
+ This means the spawned CLI process cannot locate `bash.exe`. Your locally installed `claude` command may work fine the issue is that the MCP server's child process may not inherit your shell environment.
380
+
381
+ `claude-code-mcp` will try to auto-detect Git Bash from common install locations and set `CLAUDE_CODE_GIT_BASH_PATH` for child processes. If you still see this error, set `CLAUDE_CODE_GIT_BASH_PATH` explicitly in your MCP server config:
382
+
383
+ For JSON-based MCP clients (Claude Desktop, Cursor, etc.):
384
+
385
+ ```json
386
+ {
387
+ "mcpServers": {
388
+ "claude-code": {
389
+ "command": "npx",
390
+ "args": ["-y", "@leo000001/claude-code-mcp"],
391
+ "env": {
392
+ "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"
393
+ }
394
+ }
395
+ }
396
+ }
397
+ ```
398
+
399
+ For OpenAI Codex CLI (`~/.codex/config.toml`):
400
+
401
+ ```toml
402
+ [mcp_servers.claude-code]
403
+ command = "npx"
404
+ args = ["-y", "@leo000001/claude-code-mcp"]
405
+
406
+ [mcp_servers.claude-code.env]
407
+ CLAUDE_CODE_GIT_BASH_PATH = "C:\\Program Files\\Git\\bin\\bash.exe"
408
+ ```
409
+
410
+ > Replace the path with your actual `bash.exe` location. Common paths:
411
+ >
412
+ > - `C:\Program Files\Git\bin\bash.exe` (default installer)
413
+ >
414
+ > To find yours: `where git` in CMD/PowerShell, then look for `bash.exe` under the same Git root's `bin\` folder.
415
+
416
+ Alternatively, set the environment variable system-wide so all processes inherit it:
417
+
418
+ ```powershell
419
+ # PowerShell (permanent, requires new terminal)
420
+ setx CLAUDE_CODE_GIT_BASH_PATH "C:\Program Files\Git\bin\bash.exe"
421
+ ```
422
+
423
+ ## Security
424
+
425
+ - **Async permission approvals** — when a tool call needs approval, the session transitions to `waiting_permission` and surfaces requests via `claude_code_check` (`actions[]`).
426
+ - **No runtime privilege escalation tool** permission decisions are per-session (allow/deny lists + explicit approvals), and the server does not expose a `claude_code_configure` bypass switch.
427
+ - **Environment variables are inherited** — the spawned Claude Code process inherits all environment variables (including `ANTHROPIC_API_KEY`) from the parent process by default. The `advanced.env` parameter **merges** with `process.env` (user-provided values take precedence), so you can safely add or override individual variables without losing existing ones.
428
+ - Tool visibility vs approvals:
429
+ - Use `advanced.tools` to restrict which tools the agent can _see_ (hidden tools cannot be called).
430
+ - Use `allowedTools` to auto-approve specific tools without prompting (the SDK may still prompt for path-based restrictions like `blockedPath`).
431
+ - Use `disallowedTools` to hard-block tools; they are denied even if later approved via `claude_code_check`.
432
+ - `maxTurns` and `advanced.maxBudgetUsd` prevent runaway execution.
433
+ - Sessions auto-expire after 30 minutes of inactivity.
434
+ - Vulnerability reporting: see `SECURITY.md`.
435
+
436
+ ## Environment Variables
437
+
438
+ All environment variables are optional. They are set on the MCP server process (not on the Claude Code child process — for that, use the `env` tool parameter).
439
+
440
+ | Variable | Description | Default |
441
+ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------- |
442
+ | `CLAUDE_CODE_GIT_BASH_PATH` | Path to `bash.exe` on Windows (see [Windows Support](#windows-support)) | Auto-detected |
443
+ | `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME` | Set to `1` to allow `claude_code_reply` to resume from on-disk transcripts when the in-memory session is missing | `0` (disabled) |
444
+ | `CLAUDE_CODE_MCP_RESUME_SECRET` | HMAC secret used to validate `resumeToken` for disk resume fallback (recommended if disk resume is enabled) | _(unset)_ |
445
+ | `CLAUDE_CODE_MCP_MAX_SESSIONS` | Maximum number of in-memory sessions (set `0` to disable the limit) | `128` |
446
+ | `CLAUDE_CODE_MCP_MAX_PENDING_PERMISSIONS` | Maximum number of outstanding permission requests per session (set `0` to disable the limit) | `64` |
447
+
448
+ ### How to configure
449
+
450
+ **JSON-based MCP clients** (Claude Desktop, Cursor, etc.) — add an `"env"` block:
451
+
452
+ ```json
453
+ {
454
+ "mcpServers": {
455
+ "claude-code": {
456
+ "command": "npx",
457
+ "args": ["-y", "@leo000001/claude-code-mcp"],
458
+ "env": {
459
+ "CLAUDE_CODE_MCP_ALLOW_DISK_RESUME": "1",
460
+ "CLAUDE_CODE_MCP_RESUME_SECRET": "change-me"
461
+ }
462
+ }
463
+ }
464
+ }
465
+ ```
466
+
467
+ **OpenAI Codex CLI** add an `[mcp_servers.claude-code.env]` section in `~/.codex/config.toml`:
468
+
469
+ ```toml
470
+ [mcp_servers.claude-code]
471
+ command = "npx"
472
+ args = ["-y", "@leo000001/claude-code-mcp"]
473
+
474
+ [mcp_servers.claude-code.env]
475
+ CLAUDE_CODE_MCP_ALLOW_DISK_RESUME = "1"
476
+ CLAUDE_CODE_MCP_RESUME_SECRET = "change-me"
477
+ ```
478
+
479
+ **System-wide**set via your shell profile or OS settings so all processes inherit them:
480
+
481
+ ```bash
482
+ # bash / zsh
483
+ export CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1
484
+ export CLAUDE_CODE_MCP_RESUME_SECRET=change-me
485
+
486
+ # PowerShell (permanent, requires new terminal)
487
+ setx CLAUDE_CODE_MCP_ALLOW_DISK_RESUME 1
488
+ setx CLAUDE_CODE_MCP_RESUME_SECRET change-me
489
+ ```
490
+
491
+ ## Development
492
+
493
+ ```bash
494
+ npm install # Install dependencies
495
+ npm run build # Build with tsup
496
+ npm run typecheck # Type check with tsc
497
+ npm test # Run tests with vitest
498
+ npm run dev # Watch mode build
499
+ ```
500
+
501
+ ### E2E regression commands
502
+
503
+ ```bash
504
+ # Run cancel->poll regression loop (single mode)
505
+ npm run e2e:stdio:cancel
506
+
507
+ # Run waiting_permission + cancel regression loop
508
+ npm run e2e:stdio:cancel:wp
509
+
510
+ # Run both modes and output one summary report
511
+ npm run e2e:stdio:runner
512
+ ```
513
+
514
+ ### E2E notes (Codex and other clients)
515
+
516
+ - Some clients do not expose `tools/list` directly in the chat loop. In those clients, treat "tool is callable" as the primary discovery signal, and use `tools/list` only when available.
517
+ - `allowedTools: ["Read", "Write"]` does not guarantee the model will never attempt `Bash`. For deterministic smoke tests, add `disallowedTools: ["Bash"]` and state "do not use Bash" in the prompt.
518
+ - For `claude_code_session(action="get", includeSensitive=true)`, only assert fields that were actually configured. Optional fields that were never set may be omitted.
519
+ - If a client reports `Transport closed` during E2E cleanup, reconnect the MCP server first, then run `claude_code_session(action="list")` and cancel any remaining `running` / `waiting_permission` sessions.
520
+
521
+ For an end-to-end local test plan (third-party CLI/client integration + real coding tasks), see `docs/E2E_LOCAL_TEST_PLAN.md`.
522
+
523
+ ## Architecture
524
+
525
+ ```
526
+ MCP Client ←→ (stdio/JSON-RPC) ←→ MCP Server [same machine]
527
+ ├── Session Manager (Map<id, state>)
528
+ └── Claude Agent SDK (query())
529
+ ```
530
+
531
+ **Session persistence:** The MCP server's Session Manager holds **in-memory** session metadata, a snapshot of session options (tool config, limits, `cwd`, allow/deny lists, etc.), and an event buffer used by `claude_code_check`. This metadata is **not** persisted to disk by the MCP server. The actual conversation history is persisted to disk by the Claude Code CLI (under `~/.claude/projects/`) — this is managed by the SDK, not by this MCP server. By default, if the MCP server restarts or the session expires from memory, `claude_code_reply` will return `SESSION_NOT_FOUND` even though the CLI transcript may still exist on disk. You can opt into disk-resume behavior by setting `CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1`.
532
+
533
+ Sessions are automatically cleaned up after 30 minutes of idle time, or after 4 hours of continuous running.
534
+
535
+ **Turn/Cost semantics:** `numTurns` and `totalCostUsd` are per-call increments. For cumulative per-session totals, use `sessionTotalTurns` and `sessionTotalCostUsd`. When `forkSession=true`, the returned `sessionId` (and `sessionTotal*`) refer to the forked session; the original session totals are preserved.
536
+
537
+ ## Error Codes
538
+
539
+ MCP server validation/policy errors are returned as `Error [CODE]: message` where `CODE` is one of:
540
+
541
+ - `INVALID_ARGUMENT` — invalid inputs (e.g. missing sessionId, empty cwd)
542
+ - `SESSION_NOT_FOUND` — session not found in memory (expired or server restarted)
543
+ - `SESSION_BUSY` — session currently running
544
+ - `PERMISSION_DENIED` — operation not allowed by server policy
545
+ - `PERMISSION_REQUEST_NOT_FOUND` — permission request ID not found (already finished or expired)
546
+ - `RESOURCE_EXHAUSTED` — resource limit reached (e.g. max sessions or max pending permissions)
547
+ - `TIMEOUT` — operation timed out
548
+ - `CANCELLED` — session was cancelled
549
+ - `INTERNAL` — unexpected error or protocol mismatch
550
+
551
+ For Claude Agent SDK execution failures, also check `errorSubtype` (e.g. `error_max_turns`, `error_max_budget_usd`, `error_during_execution`) and the returned `result` text.
552
+
553
+ ## License
554
+
555
+ MIT — see [LICENSE](LICENSE)
556
+
557
+ ## Contributing
558
+
559
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
560
+
561
+ - [Security Policy](SECURITY.md)
562
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
563
+ - [Third-party Notices](NOTICE.md)