@leo000001/claude-code-mcp 2.0.0 → 2.0.3
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/CHANGELOG.md +96 -82
- package/README.md +512 -486
- package/dist/index.js +314 -175
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,47 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
|
+
// src/utils/permission-updated-input.ts
|
|
11
|
+
function normalizePermissionUpdatedInput(input) {
|
|
12
|
+
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
13
|
+
return input;
|
|
14
|
+
}
|
|
15
|
+
return { input };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/utils/normalize-tool-input.ts
|
|
19
|
+
function normalizeMsysToWindowsPath(path2) {
|
|
20
|
+
if (/^[a-zA-Z]:[\\/]/.test(path2) || path2.startsWith("\\\\")) return void 0;
|
|
21
|
+
if (path2.startsWith("//")) {
|
|
22
|
+
const m2 = path2.match(/^\/\/([^/]{2,})\/(.*)$/);
|
|
23
|
+
if (m2) {
|
|
24
|
+
const host = m2[1];
|
|
25
|
+
const rest2 = m2[2] ?? "";
|
|
26
|
+
return `\\\\${host}\\${rest2.replace(/\//g, "\\")}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const cyg = path2.match(/^\/cygdrive\/([a-zA-Z])\/(.*)$/);
|
|
30
|
+
if (cyg) {
|
|
31
|
+
const drive2 = cyg[1].toUpperCase();
|
|
32
|
+
const rest2 = cyg[2] ?? "";
|
|
33
|
+
return `${drive2}:\\${rest2.replace(/\//g, "\\")}`;
|
|
34
|
+
}
|
|
35
|
+
const m = path2.match(/^\/(?:mnt\/)?([a-zA-Z])\/(.*)$/);
|
|
36
|
+
if (!m) return void 0;
|
|
37
|
+
const drive = m[1].toUpperCase();
|
|
38
|
+
const rest = m[2] ?? "";
|
|
39
|
+
return `${drive}:\\${rest.replace(/\//g, "\\")}`;
|
|
40
|
+
}
|
|
41
|
+
function normalizeToolInput(toolName, input, platform = process.platform) {
|
|
42
|
+
if (platform !== "win32") return input;
|
|
43
|
+
if (toolName !== "NotebookEdit") return input;
|
|
44
|
+
const filePath = input.file_path;
|
|
45
|
+
if (typeof filePath !== "string") return input;
|
|
46
|
+
const normalized = normalizeMsysToWindowsPath(filePath);
|
|
47
|
+
if (!normalized) return input;
|
|
48
|
+
return { ...input, file_path: normalized };
|
|
49
|
+
}
|
|
50
|
+
|
|
10
51
|
// src/session/manager.ts
|
|
11
52
|
var DEFAULT_SESSION_TTL_MS = 30 * 60 * 1e3;
|
|
12
53
|
var DEFAULT_RUNNING_SESSION_MAX_MS = 4 * 60 * 60 * 1e3;
|
|
@@ -19,7 +60,9 @@ var SessionManager = class _SessionManager {
|
|
|
19
60
|
cleanupTimer;
|
|
20
61
|
sessionTtlMs = DEFAULT_SESSION_TTL_MS;
|
|
21
62
|
runningSessionMaxMs = DEFAULT_RUNNING_SESSION_MAX_MS;
|
|
22
|
-
|
|
63
|
+
platform;
|
|
64
|
+
constructor(opts) {
|
|
65
|
+
this.platform = opts?.platform ?? process.platform;
|
|
23
66
|
this.cleanupTimer = setInterval(() => this.cleanup(), DEFAULT_CLEANUP_INTERVAL_MS);
|
|
24
67
|
if (this.cleanupTimer.unref) {
|
|
25
68
|
this.cleanupTimer.unref();
|
|
@@ -193,10 +236,16 @@ var SessionManager = class _SessionManager {
|
|
|
193
236
|
const info = this.sessions.get(sessionId);
|
|
194
237
|
if (!state || !info) return false;
|
|
195
238
|
if (!state.pendingPermissions.has(req.requestId)) {
|
|
239
|
+
const inferredExpiresAt = new Date(Date.now() + timeoutMs).toISOString();
|
|
240
|
+
const record = {
|
|
241
|
+
...req,
|
|
242
|
+
timeoutMs,
|
|
243
|
+
expiresAt: inferredExpiresAt
|
|
244
|
+
};
|
|
196
245
|
const timeoutId = setTimeout(() => {
|
|
197
246
|
this.finishRequest(
|
|
198
247
|
sessionId,
|
|
199
|
-
|
|
248
|
+
record.requestId,
|
|
200
249
|
{
|
|
201
250
|
behavior: "deny",
|
|
202
251
|
message: `Permission request timed out after ${timeoutMs}ms.`,
|
|
@@ -205,12 +254,12 @@ var SessionManager = class _SessionManager {
|
|
|
205
254
|
"timeout"
|
|
206
255
|
);
|
|
207
256
|
}, timeoutMs);
|
|
208
|
-
state.pendingPermissions.set(
|
|
257
|
+
state.pendingPermissions.set(record.requestId, { record, finish, timeoutId });
|
|
209
258
|
info.status = "waiting_permission";
|
|
210
259
|
info.lastActiveAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
211
260
|
this.pushEvent(sessionId, {
|
|
212
261
|
type: "permission_request",
|
|
213
|
-
data:
|
|
262
|
+
data: record,
|
|
214
263
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
215
264
|
});
|
|
216
265
|
return true;
|
|
@@ -242,11 +291,40 @@ var SessionManager = class _SessionManager {
|
|
|
242
291
|
};
|
|
243
292
|
}
|
|
244
293
|
}
|
|
294
|
+
if (finalResult.behavior === "allow") {
|
|
295
|
+
const updatedInput = finalResult.updatedInput;
|
|
296
|
+
const validRecord = updatedInput !== null && updatedInput !== void 0 && typeof updatedInput === "object" && !Array.isArray(updatedInput);
|
|
297
|
+
if (!validRecord) {
|
|
298
|
+
finalResult = {
|
|
299
|
+
...finalResult,
|
|
300
|
+
updatedInput: normalizePermissionUpdatedInput(pending.record.input)
|
|
301
|
+
};
|
|
302
|
+
} else {
|
|
303
|
+
finalResult = {
|
|
304
|
+
...finalResult,
|
|
305
|
+
updatedInput: normalizeToolInput(
|
|
306
|
+
pending.record.toolName,
|
|
307
|
+
updatedInput,
|
|
308
|
+
this.platform
|
|
309
|
+
)
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
245
313
|
if (pending.timeoutId) clearTimeout(pending.timeoutId);
|
|
246
314
|
state.pendingPermissions.delete(requestId);
|
|
315
|
+
const eventData = {
|
|
316
|
+
requestId,
|
|
317
|
+
toolName: pending.record.toolName,
|
|
318
|
+
behavior: finalResult.behavior,
|
|
319
|
+
source
|
|
320
|
+
};
|
|
321
|
+
if (finalResult.behavior === "deny") {
|
|
322
|
+
eventData.message = finalResult.message;
|
|
323
|
+
eventData.interrupt = finalResult.interrupt;
|
|
324
|
+
}
|
|
247
325
|
this.pushEvent(sessionId, {
|
|
248
326
|
type: "permission_result",
|
|
249
|
-
data:
|
|
327
|
+
data: eventData,
|
|
250
328
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
251
329
|
});
|
|
252
330
|
try {
|
|
@@ -651,28 +729,37 @@ function consumeQuery(params) {
|
|
|
651
729
|
let initTimeoutId;
|
|
652
730
|
const canUseTool = async (toolName, input, options2) => {
|
|
653
731
|
const sessionId = await getSessionId();
|
|
732
|
+
const normalizedInput = normalizeToolInput(toolName, input, params.platform);
|
|
654
733
|
const sessionInfo = params.sessionManager.get(sessionId);
|
|
655
734
|
if (sessionInfo) {
|
|
656
735
|
if (Array.isArray(sessionInfo.disallowedTools) && sessionInfo.disallowedTools.includes(toolName)) {
|
|
657
736
|
return { behavior: "deny", message: `Tool '${toolName}' is disallowed by session policy.` };
|
|
658
737
|
}
|
|
659
738
|
if (!options2.blockedPath && Array.isArray(sessionInfo.allowedTools) && sessionInfo.allowedTools.includes(toolName)) {
|
|
660
|
-
return {
|
|
739
|
+
return {
|
|
740
|
+
behavior: "allow",
|
|
741
|
+
updatedInput: normalizePermissionUpdatedInput(normalizedInput)
|
|
742
|
+
};
|
|
661
743
|
}
|
|
662
744
|
}
|
|
663
745
|
const requestId = `${options2.toolUseID}:${toolName}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
|
|
746
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
747
|
+
const timeoutMs = params.permissionRequestTimeoutMs;
|
|
748
|
+
const expiresAt = new Date(Date.now() + timeoutMs).toISOString();
|
|
664
749
|
const record = {
|
|
665
750
|
requestId,
|
|
666
751
|
toolName,
|
|
667
|
-
input,
|
|
668
|
-
summary: summarizePermission(toolName,
|
|
752
|
+
input: normalizedInput,
|
|
753
|
+
summary: summarizePermission(toolName, normalizedInput),
|
|
669
754
|
description: describeTool(toolName, params.toolCache),
|
|
670
755
|
decisionReason: options2.decisionReason,
|
|
671
756
|
blockedPath: options2.blockedPath,
|
|
672
757
|
toolUseID: options2.toolUseID,
|
|
673
758
|
agentID: options2.agentID,
|
|
674
759
|
suggestions: options2.suggestions,
|
|
675
|
-
createdAt
|
|
760
|
+
createdAt,
|
|
761
|
+
timeoutMs,
|
|
762
|
+
expiresAt
|
|
676
763
|
};
|
|
677
764
|
return await new Promise((resolve) => {
|
|
678
765
|
let finished = false;
|
|
@@ -1394,13 +1481,16 @@ var TOOL_CATALOG = {
|
|
|
1394
1481
|
description: "Run shell commands (e.g. npm install, git commit, ls) in the project directory.",
|
|
1395
1482
|
category: "execute"
|
|
1396
1483
|
},
|
|
1397
|
-
Read: {
|
|
1484
|
+
Read: {
|
|
1485
|
+
description: "Read the contents of a file given its path (large files may hit per-call size caps; use offset/limit or Grep chunking).",
|
|
1486
|
+
category: "file_read"
|
|
1487
|
+
},
|
|
1398
1488
|
Write: {
|
|
1399
1489
|
description: "Create a new file or completely replace an existing file's contents.",
|
|
1400
1490
|
category: "file_write"
|
|
1401
1491
|
},
|
|
1402
1492
|
Edit: {
|
|
1403
|
-
description: "Make targeted changes to specific parts of an existing file without rewriting the whole file.",
|
|
1493
|
+
description: "Make targeted changes to specific parts of an existing file without rewriting the whole file (replace_all is substring-based).",
|
|
1404
1494
|
category: "file_write"
|
|
1405
1495
|
},
|
|
1406
1496
|
Glob: {
|
|
@@ -1412,7 +1502,7 @@ var TOOL_CATALOG = {
|
|
|
1412
1502
|
category: "file_read"
|
|
1413
1503
|
},
|
|
1414
1504
|
NotebookEdit: {
|
|
1415
|
-
description: "Edit individual cells in Jupyter notebooks (.ipynb files).",
|
|
1505
|
+
description: "Edit individual cells in Jupyter notebooks (.ipynb files) (expects native Windows paths; this server normalizes /d/... when possible).",
|
|
1416
1506
|
category: "file_write"
|
|
1417
1507
|
},
|
|
1418
1508
|
WebFetch: {
|
|
@@ -1433,6 +1523,10 @@ var TOOL_CATALOG = {
|
|
|
1433
1523
|
AskUserQuestion: {
|
|
1434
1524
|
description: "Ask the user a question and wait for their answer before continuing.",
|
|
1435
1525
|
category: "interaction"
|
|
1526
|
+
},
|
|
1527
|
+
TeamDelete: {
|
|
1528
|
+
description: "Delete a team and its resources (may require all active members to shutdown_approved; cleanup may complete asynchronously).",
|
|
1529
|
+
category: "agent"
|
|
1436
1530
|
}
|
|
1437
1531
|
};
|
|
1438
1532
|
function uniq(items) {
|
|
@@ -1487,7 +1581,7 @@ function buildInternalToolsDescription(tools) {
|
|
|
1487
1581
|
const grouped = groupByCategory(tools);
|
|
1488
1582
|
const categories = Object.keys(grouped).sort((a, b) => a.localeCompare(b));
|
|
1489
1583
|
let desc = 'Start a new Claude Code agent session.\n\nLaunches an autonomous coding agent that can read/write files, run shell commands, search code, manage git, access the web, and more. Returns immediately with a sessionId \u2014 the agent runs asynchronously in the background.\n\nWorkflow:\n1. Call claude_code with a prompt \u2192 returns { sessionId, status: "running", pollInterval }\n2. Poll with claude_code_check (action="poll") to receive progress events and the final result\n3. If the agent needs permission for a tool call, approve or deny via claude_code_check (action="respond_permission")\n\n';
|
|
1490
|
-
desc += "Defaults:\n- settingSources: ['user', 'project', 'local'] (loads ~/.claude/settings.json, .claude/settings.json, .claude/settings.local.json, and CLAUDE.md)\n- persistSession: true\n- sessionInitTimeoutMs: 10000\n- permissionRequestTimeoutMs: 60000\n- allowedTools/disallowedTools: [] (none)\n- resumeToken: omitted unless CLAUDE_CODE_MCP_RESUME_SECRET is set on the server\n\n";
|
|
1584
|
+
desc += "Defaults:\n- settingSources: ['user', 'project', 'local'] (loads ~/.claude/settings.json, .claude/settings.json, .claude/settings.local.json, and CLAUDE.md)\n- persistSession: true\n- sessionInitTimeoutMs: 10000\n- permissionRequestTimeoutMs: 60000\n- allowedTools/disallowedTools: [] (none)\n- resumeToken: omitted unless CLAUDE_CODE_MCP_RESUME_SECRET is set on the server\n- Permission prompts auto-deny on timeout; use claude_code_check actions[].expiresAt/remainingMs\n\n";
|
|
1491
1585
|
desc += "Internal tools available to the agent (use allowedTools/disallowedTools to control approval policy; authoritative list returned by claude_code_check with includeTools=true):\n";
|
|
1492
1586
|
for (const category of categories) {
|
|
1493
1587
|
desc += `
|
|
@@ -1498,7 +1592,8 @@ function buildInternalToolsDescription(tools) {
|
|
|
1498
1592
|
`;
|
|
1499
1593
|
}
|
|
1500
1594
|
}
|
|
1501
|
-
desc +=
|
|
1595
|
+
desc += "\nSecurity: You MUST configure allowedTools/disallowedTools based on your own permission scope. Only allow tools that you yourself are authorized to perform \u2014 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.\n\n";
|
|
1596
|
+
desc += 'Use `allowedTools` to pre-approve tools (no permission prompts). Use `disallowedTools` to permanently block specific tools. Any tool not in either list will pause the session (status: "waiting_permission") until approved or denied via claude_code_check.\n';
|
|
1502
1597
|
return desc;
|
|
1503
1598
|
}
|
|
1504
1599
|
|
|
@@ -1621,20 +1716,27 @@ function buildResult(sessionManager, toolCache, input) {
|
|
|
1621
1716
|
}),
|
|
1622
1717
|
nextCursor,
|
|
1623
1718
|
availableTools,
|
|
1624
|
-
actions: includeActions && status === "waiting_permission" ? pending.map((req) =>
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1719
|
+
actions: includeActions && status === "waiting_permission" ? pending.map((req) => {
|
|
1720
|
+
const expiresMs = req.expiresAt ? Date.parse(req.expiresAt) : Number.NaN;
|
|
1721
|
+
const remainingMs = Number.isFinite(expiresMs) ? Math.max(0, expiresMs - Date.now()) : void 0;
|
|
1722
|
+
return {
|
|
1723
|
+
type: "permission",
|
|
1724
|
+
requestId: req.requestId,
|
|
1725
|
+
toolName: req.toolName,
|
|
1726
|
+
input: req.input,
|
|
1727
|
+
summary: req.summary,
|
|
1728
|
+
decisionReason: req.decisionReason,
|
|
1729
|
+
blockedPath: req.blockedPath,
|
|
1730
|
+
toolUseID: req.toolUseID,
|
|
1731
|
+
agentID: req.agentID,
|
|
1732
|
+
suggestions: req.suggestions,
|
|
1733
|
+
description: req.description,
|
|
1734
|
+
createdAt: req.createdAt,
|
|
1735
|
+
timeoutMs: req.timeoutMs,
|
|
1736
|
+
expiresAt: req.expiresAt,
|
|
1737
|
+
remainingMs
|
|
1738
|
+
};
|
|
1739
|
+
}) : void 0,
|
|
1638
1740
|
result: includeResult && stored?.result ? redactAgentResult(stored.result, {
|
|
1639
1741
|
includeUsage,
|
|
1640
1742
|
includeModelUsage,
|
|
@@ -1796,8 +1898,96 @@ function executeClaudeCodeSession(input, sessionManager) {
|
|
|
1796
1898
|
}
|
|
1797
1899
|
}
|
|
1798
1900
|
|
|
1901
|
+
// src/resources/register-resources.ts
|
|
1902
|
+
var RESOURCE_SCHEME = "claude-code-mcp";
|
|
1903
|
+
var RESOURCE_URIS = {
|
|
1904
|
+
serverInfo: `${RESOURCE_SCHEME}:///server-info`,
|
|
1905
|
+
internalTools: `${RESOURCE_SCHEME}:///internal-tools`,
|
|
1906
|
+
gotchas: `${RESOURCE_SCHEME}:///gotchas`
|
|
1907
|
+
};
|
|
1908
|
+
function asTextResource(uri, text, mimeType) {
|
|
1909
|
+
return {
|
|
1910
|
+
contents: [
|
|
1911
|
+
{
|
|
1912
|
+
uri: uri.toString(),
|
|
1913
|
+
text,
|
|
1914
|
+
mimeType
|
|
1915
|
+
}
|
|
1916
|
+
]
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
function registerResources(server, deps) {
|
|
1920
|
+
const serverInfoUri = new URL(RESOURCE_URIS.serverInfo);
|
|
1921
|
+
server.registerResource(
|
|
1922
|
+
"server_info",
|
|
1923
|
+
serverInfoUri.toString(),
|
|
1924
|
+
{
|
|
1925
|
+
title: "Server Info",
|
|
1926
|
+
description: "Static server metadata (version/platform/runtime).",
|
|
1927
|
+
mimeType: "application/json"
|
|
1928
|
+
},
|
|
1929
|
+
() => asTextResource(
|
|
1930
|
+
serverInfoUri,
|
|
1931
|
+
JSON.stringify(
|
|
1932
|
+
{
|
|
1933
|
+
name: "claude-code-mcp",
|
|
1934
|
+
node: process.version,
|
|
1935
|
+
platform: process.platform,
|
|
1936
|
+
arch: process.arch,
|
|
1937
|
+
resources: Object.values(RESOURCE_URIS),
|
|
1938
|
+
toolCatalogCount: deps.toolCache.getTools().length
|
|
1939
|
+
},
|
|
1940
|
+
null,
|
|
1941
|
+
2
|
|
1942
|
+
),
|
|
1943
|
+
"application/json"
|
|
1944
|
+
)
|
|
1945
|
+
);
|
|
1946
|
+
const toolsUri = new URL(RESOURCE_URIS.internalTools);
|
|
1947
|
+
server.registerResource(
|
|
1948
|
+
"internal_tools",
|
|
1949
|
+
toolsUri.toString(),
|
|
1950
|
+
{
|
|
1951
|
+
title: "Internal Tools",
|
|
1952
|
+
description: "Claude Code internal tool catalog (static + runtime-discovered).",
|
|
1953
|
+
mimeType: "application/json"
|
|
1954
|
+
},
|
|
1955
|
+
() => asTextResource(
|
|
1956
|
+
toolsUri,
|
|
1957
|
+
JSON.stringify({ tools: deps.toolCache.getTools() }, null, 2),
|
|
1958
|
+
"application/json"
|
|
1959
|
+
)
|
|
1960
|
+
);
|
|
1961
|
+
const gotchasUri = new URL(RESOURCE_URIS.gotchas);
|
|
1962
|
+
server.registerResource(
|
|
1963
|
+
"gotchas",
|
|
1964
|
+
gotchasUri.toString(),
|
|
1965
|
+
{
|
|
1966
|
+
title: "Gotchas",
|
|
1967
|
+
description: "Practical limits and gotchas when using Claude Code via this MCP server.",
|
|
1968
|
+
mimeType: "text/markdown"
|
|
1969
|
+
},
|
|
1970
|
+
() => asTextResource(
|
|
1971
|
+
gotchasUri,
|
|
1972
|
+
[
|
|
1973
|
+
"# claude-code-mcp: gotchas",
|
|
1974
|
+
"",
|
|
1975
|
+
"- Permission approvals have a timeout (default 60s) and auto-deny (`actions[].expiresAt`/`remainingMs`).",
|
|
1976
|
+
"- `Read` has a per-call size cap in practice (often ~256KB); for large files use `offset`/`limit` or chunk with `Grep`.",
|
|
1977
|
+
"- `Edit` with `replace_all=true` is substring replacement; if no match is found the tool returns an error.",
|
|
1978
|
+
"- `NotebookEdit` expects native Windows paths; this server normalizes MSYS paths like `/d/...` when possible.",
|
|
1979
|
+
"- `TeamDelete` may require members to reach `shutdown_approved`; cleanup can be asynchronous during shutdown.",
|
|
1980
|
+
'- Skills may become available later in the same session (early calls may show "Unknown").',
|
|
1981
|
+
"- Some internal features (e.g. ToolSearch) may not appear in `availableTools` because it is derived from SDK `system/init.tools`.",
|
|
1982
|
+
""
|
|
1983
|
+
].join("\n"),
|
|
1984
|
+
"text/markdown"
|
|
1985
|
+
)
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1799
1989
|
// src/server.ts
|
|
1800
|
-
var SERVER_VERSION = true ? "2.0.
|
|
1990
|
+
var SERVER_VERSION = true ? "2.0.3" : "0.0.0-dev";
|
|
1801
1991
|
function createServer(serverCwd) {
|
|
1802
1992
|
const sessionManager = new SessionManager();
|
|
1803
1993
|
const toolCache = new ToolDiscoveryCache();
|
|
@@ -1821,7 +2011,7 @@ function createServer(serverCwd) {
|
|
|
1821
2011
|
z.object({
|
|
1822
2012
|
type: z.literal("preset"),
|
|
1823
2013
|
preset: z.literal("claude_code"),
|
|
1824
|
-
append: z.string().optional().describe("
|
|
2014
|
+
append: z.string().optional().describe("Appended to preset prompt")
|
|
1825
2015
|
})
|
|
1826
2016
|
]);
|
|
1827
2017
|
const toolsConfigSchema = z.union([
|
|
@@ -1835,66 +2025,50 @@ function createServer(serverCwd) {
|
|
|
1835
2025
|
z.object({ type: z.literal("adaptive") }),
|
|
1836
2026
|
z.object({
|
|
1837
2027
|
type: z.literal("enabled"),
|
|
1838
|
-
budgetTokens: z.number().int().positive()
|
|
2028
|
+
budgetTokens: z.number().int().positive()
|
|
1839
2029
|
}),
|
|
1840
2030
|
z.object({ type: z.literal("disabled") })
|
|
1841
2031
|
]);
|
|
1842
2032
|
const outputFormatSchema = z.object({
|
|
1843
2033
|
type: z.literal("json_schema"),
|
|
1844
|
-
schema: z.record(z.string(), z.unknown())
|
|
2034
|
+
schema: z.record(z.string(), z.unknown())
|
|
1845
2035
|
});
|
|
1846
2036
|
const advancedOptionsSchema = z.object({
|
|
1847
|
-
tools: toolsConfigSchema.optional().describe(
|
|
1848
|
-
|
|
1849
|
-
),
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
),
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
"Which local config files to load. Default: ['user', 'project', 'local']. Pass [] to disable all."
|
|
1871
|
-
),
|
|
1872
|
-
debug: z.boolean().optional().describe("Enable debug mode. Default: false."),
|
|
1873
|
-
debugFile: z.string().optional().describe("Write debug logs to a file path (implicitly enables debug mode)."),
|
|
1874
|
-
env: z.record(z.string(), z.string().optional()).optional().describe("Environment variables to merge with process.env.")
|
|
1875
|
-
}).optional().describe(
|
|
1876
|
-
"Low-frequency SDK options. All fields are optional with sensible defaults. Most callers can omit this entirely."
|
|
1877
|
-
);
|
|
2037
|
+
tools: toolsConfigSchema.optional().describe("Visible tool set. Default: SDK"),
|
|
2038
|
+
persistSession: z.boolean().optional().describe("Default: true"),
|
|
2039
|
+
sessionInitTimeoutMs: z.number().int().positive().optional().describe("Default: 10000"),
|
|
2040
|
+
agents: z.record(z.string(), agentDefinitionSchema).optional().describe("Sub-agent definitions. Default: none"),
|
|
2041
|
+
agent: z.string().optional().describe("Primary agent name (from 'agents'). Default: none"),
|
|
2042
|
+
maxBudgetUsd: z.number().positive().optional().describe("Default: none"),
|
|
2043
|
+
effort: z.enum(EFFORT_LEVELS).optional().describe("Default: SDK"),
|
|
2044
|
+
betas: z.array(z.string()).optional().describe("Default: none"),
|
|
2045
|
+
additionalDirectories: z.array(z.string()).optional().describe("Default: none"),
|
|
2046
|
+
outputFormat: outputFormatSchema.optional().describe("Default: none (plain text)"),
|
|
2047
|
+
thinking: thinkingSchema.optional().describe("Default: SDK"),
|
|
2048
|
+
pathToClaudeCodeExecutable: z.string().optional().describe("Default: SDK-bundled"),
|
|
2049
|
+
mcpServers: z.record(z.string(), z.record(z.string(), z.unknown())).optional().describe("Default: none"),
|
|
2050
|
+
sandbox: z.record(z.string(), z.unknown()).optional().describe("Default: none"),
|
|
2051
|
+
fallbackModel: z.string().optional().describe("Default: none"),
|
|
2052
|
+
enableFileCheckpointing: z.boolean().optional().describe("Default: false"),
|
|
2053
|
+
includePartialMessages: z.boolean().optional().describe("Stream events to claude_code_check. Default: false"),
|
|
2054
|
+
strictMcpConfig: z.boolean().optional().describe("Default: false"),
|
|
2055
|
+
settingSources: z.array(z.enum(["user", "project", "local"])).optional().describe("Default: ['user','project','local']. [] = isolation mode"),
|
|
2056
|
+
debug: z.boolean().optional().describe("Default: false"),
|
|
2057
|
+
debugFile: z.string().optional().describe("Enables debug. Default: none"),
|
|
2058
|
+
env: z.record(z.string(), z.string().optional()).optional().describe("Merged with process.env. Default: none")
|
|
2059
|
+
}).optional().describe("Low-frequency SDK options (all optional)");
|
|
1878
2060
|
server.tool(
|
|
1879
2061
|
"claude_code",
|
|
1880
2062
|
buildInternalToolsDescription(toolCache.getTools()),
|
|
1881
2063
|
{
|
|
1882
|
-
prompt: z.string().describe("
|
|
1883
|
-
cwd: z.string().optional().describe("Working directory. Default: server cwd
|
|
1884
|
-
allowedTools: z.array(z.string()).optional().describe(
|
|
1885
|
-
|
|
1886
|
-
),
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
),
|
|
1890
|
-
maxTurns: z.number().int().positive().optional().describe("Maximum number of reasoning steps the agent can take."),
|
|
1891
|
-
model: z.string().optional().describe("Model to use, e.g. 'claude-sonnet-4-5-20250929'."),
|
|
1892
|
-
systemPrompt: systemPromptSchema.optional().describe(
|
|
1893
|
-
"Override the agent's system prompt. Pass a string for full replacement, or use {type: 'preset', preset: 'claude_code', append: '...'} to extend the default."
|
|
1894
|
-
),
|
|
1895
|
-
permissionRequestTimeoutMs: z.number().int().positive().optional().describe(
|
|
1896
|
-
"How long to wait (in ms) for a permission decision via claude_code_check before auto-denying. Default: 60000."
|
|
1897
|
-
),
|
|
2064
|
+
prompt: z.string().describe("Task or question"),
|
|
2065
|
+
cwd: z.string().optional().describe("Working directory. Default: server cwd"),
|
|
2066
|
+
allowedTools: z.array(z.string()).optional().describe("Auto-approved tools, e.g. ['Bash','Read','Write','Edit']. Default: []"),
|
|
2067
|
+
disallowedTools: z.array(z.string()).optional().describe("Forbidden tools (priority over allowedTools). Default: []"),
|
|
2068
|
+
maxTurns: z.number().int().positive().optional().describe("Default: SDK"),
|
|
2069
|
+
model: z.string().optional().describe("e.g. 'opus'. Default: SDK"),
|
|
2070
|
+
systemPrompt: systemPromptSchema.optional().describe("Default: SDK"),
|
|
2071
|
+
permissionRequestTimeoutMs: z.number().int().positive().optional().describe("Auto-deny timeout (ms). Default: 60000"),
|
|
1898
2072
|
advanced: advancedOptionsSchema
|
|
1899
2073
|
},
|
|
1900
2074
|
async (args, extra) => {
|
|
@@ -1946,49 +2120,43 @@ Defaults:
|
|
|
1946
2120
|
|
|
1947
2121
|
Disk resume: If the server restarted and the session is no longer in memory, set CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1 to let the agent resume from its on-disk transcript. Pass diskResumeConfig with resumeToken and session parameters.`,
|
|
1948
2122
|
{
|
|
1949
|
-
sessionId: z.string().describe("
|
|
1950
|
-
prompt: z.string().describe("Follow-up
|
|
1951
|
-
forkSession: z.boolean().optional().describe(
|
|
1952
|
-
|
|
1953
|
-
),
|
|
1954
|
-
sessionInitTimeoutMs: z.number().int().positive().optional().describe("How long to wait (in ms) for a forked session to initialize. Default: 10000."),
|
|
1955
|
-
permissionRequestTimeoutMs: z.number().int().positive().optional().describe(
|
|
1956
|
-
"How long to wait (in ms) for a permission decision via claude_code_check before auto-denying. Default: 60000."
|
|
1957
|
-
),
|
|
2123
|
+
sessionId: z.string().describe("Session ID from claude_code"),
|
|
2124
|
+
prompt: z.string().describe("Follow-up message"),
|
|
2125
|
+
forkSession: z.boolean().optional().describe("Branch into new session copy. Default: false"),
|
|
2126
|
+
sessionInitTimeoutMs: z.number().int().positive().optional().describe("Fork init timeout (ms). Default: 10000"),
|
|
2127
|
+
permissionRequestTimeoutMs: z.number().int().positive().optional().describe("Auto-deny timeout (ms). Default: 60000"),
|
|
1958
2128
|
diskResumeConfig: z.object({
|
|
1959
|
-
resumeToken: z.string().optional().describe(
|
|
1960
|
-
|
|
1961
|
-
),
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
debugFile: z.string().optional().describe("Write debug logs to a file path."),
|
|
1989
|
-
env: z.record(z.string(), z.string().optional()).optional().describe("Environment variables to merge with process.env.")
|
|
2129
|
+
resumeToken: z.string().optional().describe("Required"),
|
|
2130
|
+
cwd: z.string().optional().describe("Required"),
|
|
2131
|
+
allowedTools: z.array(z.string()).optional().describe("Default: []"),
|
|
2132
|
+
disallowedTools: z.array(z.string()).optional().describe("Default: []"),
|
|
2133
|
+
tools: toolsConfigSchema.optional().describe("Default: SDK"),
|
|
2134
|
+
persistSession: z.boolean().optional().describe("Default: true"),
|
|
2135
|
+
maxTurns: z.number().int().positive().optional().describe("Default: SDK"),
|
|
2136
|
+
model: z.string().optional().describe("Default: SDK"),
|
|
2137
|
+
systemPrompt: systemPromptSchema.optional().describe("Default: SDK"),
|
|
2138
|
+
agents: z.record(z.string(), agentDefinitionSchema).optional().describe("Default: none"),
|
|
2139
|
+
agent: z.string().optional().describe("Default: none"),
|
|
2140
|
+
maxBudgetUsd: z.number().positive().optional().describe("Default: none"),
|
|
2141
|
+
effort: z.enum(EFFORT_LEVELS).optional().describe("Default: SDK"),
|
|
2142
|
+
betas: z.array(z.string()).optional().describe("Default: none"),
|
|
2143
|
+
additionalDirectories: z.array(z.string()).optional().describe("Default: none"),
|
|
2144
|
+
outputFormat: outputFormatSchema.optional().describe("Default: none"),
|
|
2145
|
+
thinking: thinkingSchema.optional().describe("Default: SDK"),
|
|
2146
|
+
resumeSessionAt: z.string().optional().describe("Resume to specific message UUID. Default: none"),
|
|
2147
|
+
pathToClaudeCodeExecutable: z.string().optional().describe("Default: SDK-bundled"),
|
|
2148
|
+
mcpServers: z.record(z.string(), z.record(z.string(), z.unknown())).optional().describe("Default: none"),
|
|
2149
|
+
sandbox: z.record(z.string(), z.unknown()).optional().describe("Default: none"),
|
|
2150
|
+
fallbackModel: z.string().optional().describe("Default: none"),
|
|
2151
|
+
enableFileCheckpointing: z.boolean().optional().describe("Default: false"),
|
|
2152
|
+
includePartialMessages: z.boolean().optional().describe("Stream events to claude_code_check. Default: false"),
|
|
2153
|
+
strictMcpConfig: z.boolean().optional().describe("Default: false"),
|
|
2154
|
+
settingSources: z.array(z.enum(["user", "project", "local"])).optional().describe("Default: ['user','project','local']. [] = isolation mode"),
|
|
2155
|
+
debug: z.boolean().optional().describe("Default: false"),
|
|
2156
|
+
debugFile: z.string().optional().describe("Enables debug. Default: none"),
|
|
2157
|
+
env: z.record(z.string(), z.string().optional()).optional().describe("Default: none")
|
|
1990
2158
|
}).optional().describe(
|
|
1991
|
-
"Disk resume
|
|
2159
|
+
"Disk resume config (needs CLAUDE_CODE_MCP_ALLOW_DISK_RESUME=1). Requires resumeToken + cwd."
|
|
1992
2160
|
)
|
|
1993
2161
|
},
|
|
1994
2162
|
async (args, extra) => {
|
|
@@ -2026,11 +2194,9 @@ Disk resume: If the server restarted and the session is no longer in memory, set
|
|
|
2026
2194
|
- action="get": Get full details for one session (pass sessionId). Add includeSensitive=true to also see cwd, systemPrompt, agents, and additionalDirectories.
|
|
2027
2195
|
- action="cancel": Stop a running session immediately (pass sessionId).`,
|
|
2028
2196
|
{
|
|
2029
|
-
action: z.enum(SESSION_ACTIONS)
|
|
2030
|
-
sessionId: z.string().optional().describe("
|
|
2031
|
-
includeSensitive: z.boolean().optional().describe(
|
|
2032
|
-
"When true, includes sensitive fields (cwd, systemPrompt, agents, additionalDirectories) in the response. Default: false."
|
|
2033
|
-
)
|
|
2197
|
+
action: z.enum(SESSION_ACTIONS),
|
|
2198
|
+
sessionId: z.string().optional().describe("Required for 'get' and 'cancel'"),
|
|
2199
|
+
includeSensitive: z.boolean().optional().describe("Include cwd/systemPrompt/agents/additionalDirectories. Default: false")
|
|
2034
2200
|
},
|
|
2035
2201
|
async (args) => {
|
|
2036
2202
|
const result = executeClaudeCodeSession(args, sessionManager);
|
|
@@ -2066,58 +2232,30 @@ action="respond_permission" \u2014 Approve or deny a pending permission request.
|
|
|
2066
2232
|
Approving resumes agent execution. Denying (with optional interrupt=true) can halt the entire session.
|
|
2067
2233
|
The response also includes the latest poll state (events, status, etc.), so a separate poll call is not needed.`,
|
|
2068
2234
|
{
|
|
2069
|
-
action: z.enum(CHECK_ACTIONS)
|
|
2070
|
-
sessionId: z.string().describe("
|
|
2071
|
-
cursor: z.number().int().nonnegative().optional().describe(
|
|
2072
|
-
|
|
2073
|
-
),
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
),
|
|
2078
|
-
requestId: z.string().optional().describe(
|
|
2079
|
-
"The permission request ID to respond to (from the actions array). Required for respond_permission."
|
|
2080
|
-
),
|
|
2081
|
-
decision: z.enum(["allow", "deny"]).optional().describe(
|
|
2082
|
-
"Whether to approve or reject the permission request. Required for respond_permission."
|
|
2083
|
-
),
|
|
2084
|
-
denyMessage: z.string().optional().describe(
|
|
2085
|
-
"Reason for denying, shown to the agent. Only used with decision='deny'. Default: 'Permission denied by caller'."
|
|
2086
|
-
),
|
|
2087
|
-
interrupt: z.boolean().optional().describe(
|
|
2088
|
-
"When true with decision='deny', stops the entire agent session. Default: false."
|
|
2089
|
-
),
|
|
2235
|
+
action: z.enum(CHECK_ACTIONS),
|
|
2236
|
+
sessionId: z.string().describe("Target session ID"),
|
|
2237
|
+
cursor: z.number().int().nonnegative().optional().describe("Event offset for incremental poll. Default: 0"),
|
|
2238
|
+
responseMode: z.enum(CHECK_RESPONSE_MODES).optional().describe("Default: 'minimal'"),
|
|
2239
|
+
maxEvents: z.number().int().positive().optional().describe("Events per poll. Default: 200 (minimal)"),
|
|
2240
|
+
requestId: z.string().optional().describe("Permission request ID (from actions[])"),
|
|
2241
|
+
decision: z.enum(["allow", "deny"]).optional().describe("For respond_permission"),
|
|
2242
|
+
denyMessage: z.string().optional().describe("Reason shown to agent on deny. Default: 'Permission denied by caller'"),
|
|
2243
|
+
interrupt: z.boolean().optional().describe("Stop session on deny. Default: false"),
|
|
2090
2244
|
pollOptions: z.object({
|
|
2091
|
-
includeTools: z.boolean().optional().describe("
|
|
2092
|
-
includeEvents: z.boolean().optional().describe(
|
|
2093
|
-
|
|
2094
|
-
),
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
includeStructuredOutput: z.boolean().optional().describe(
|
|
2102
|
-
"Include AgentResult.structuredOutput. Default: true in full mode, false in minimal."
|
|
2103
|
-
),
|
|
2104
|
-
includeTerminalEvents: z.boolean().optional().describe(
|
|
2105
|
-
"Include terminal result/error events in events stream. Default: true in full, false in minimal."
|
|
2106
|
-
),
|
|
2107
|
-
includeProgressEvents: z.boolean().optional().describe(
|
|
2108
|
-
"Include progress events (tool_progress, auth_status). Default: true in full, false in minimal."
|
|
2109
|
-
)
|
|
2110
|
-
}).optional().describe(
|
|
2111
|
-
"Fine-grained poll control. Overrides responseMode defaults for individual fields. Most callers can omit this."
|
|
2112
|
-
),
|
|
2245
|
+
includeTools: z.boolean().optional().describe("Default: false"),
|
|
2246
|
+
includeEvents: z.boolean().optional().describe("Default: true"),
|
|
2247
|
+
includeActions: z.boolean().optional().describe("Default: true"),
|
|
2248
|
+
includeResult: z.boolean().optional().describe("Default: true"),
|
|
2249
|
+
includeUsage: z.boolean().optional().describe("Default: full=true, minimal=false"),
|
|
2250
|
+
includeModelUsage: z.boolean().optional().describe("Default: full=true, minimal=false"),
|
|
2251
|
+
includeStructuredOutput: z.boolean().optional().describe("Default: full=true, minimal=false"),
|
|
2252
|
+
includeTerminalEvents: z.boolean().optional().describe("Default: full=true, minimal=false"),
|
|
2253
|
+
includeProgressEvents: z.boolean().optional().describe("Default: full=true, minimal=false")
|
|
2254
|
+
}).optional().describe("Override responseMode defaults"),
|
|
2113
2255
|
permissionOptions: z.object({
|
|
2114
|
-
updatedInput: z.record(z.string(), z.unknown()).optional().describe(
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
updatedPermissions: z.array(z.record(z.string(), z.unknown())).optional().describe("Permission rule updates to apply. Only with decision='allow'.")
|
|
2118
|
-
}).optional().describe(
|
|
2119
|
-
"Advanced permission response options. Only used with respond_permission + decision='allow'."
|
|
2120
|
-
)
|
|
2256
|
+
updatedInput: z.record(z.string(), z.unknown()).optional().describe("Replace tool input on allow. Default: none"),
|
|
2257
|
+
updatedPermissions: z.array(z.record(z.string(), z.unknown())).optional().describe("Update permission rules on allow. Default: none")
|
|
2258
|
+
}).optional().describe("Allow-only: modify tool input or update rules")
|
|
2121
2259
|
},
|
|
2122
2260
|
async (args) => {
|
|
2123
2261
|
const result = executeClaudeCodeCheck(args, sessionManager, toolCache);
|
|
@@ -2133,6 +2271,7 @@ action="respond_permission" \u2014 Approve or deny a pending permission request.
|
|
|
2133
2271
|
};
|
|
2134
2272
|
}
|
|
2135
2273
|
);
|
|
2274
|
+
registerResources(server, { toolCache });
|
|
2136
2275
|
const originalClose = server.close.bind(server);
|
|
2137
2276
|
server.close = async () => {
|
|
2138
2277
|
sessionManager.destroy();
|