@j0hanz/filesystem-mcp 1.19.0 → 2.0.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 +333 -838
- package/dist/cli-help.d.ts +3 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +169 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli.d.ts +28 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +168 -123
- package/dist/cli.js.map +1 -0
- package/dist/core/concurrency.d.ts +70 -0
- package/dist/core/concurrency.d.ts.map +1 -0
- package/dist/core/concurrency.js +173 -0
- package/dist/core/concurrency.js.map +1 -0
- package/dist/core/config.d.ts +19 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +11 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/cursor.d.ts +23 -0
- package/dist/core/cursor.d.ts.map +1 -0
- package/dist/core/cursor.js +62 -0
- package/dist/core/cursor.js.map +1 -0
- package/dist/core/errors.d.ts +96 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +356 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/file-uri.d.ts +24 -0
- package/dist/core/file-uri.d.ts.map +1 -0
- package/dist/core/file-uri.js +52 -0
- package/dist/core/file-uri.js.map +1 -0
- package/dist/core/fmt.d.ts +38 -0
- package/dist/core/fmt.d.ts.map +1 -0
- package/dist/core/fmt.js +109 -0
- package/dist/core/fmt.js.map +1 -0
- package/dist/core/fs.d.ts +108 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +243 -0
- package/dist/core/fs.js.map +1 -0
- package/dist/core/glob.d.ts +41 -0
- package/dist/core/glob.d.ts.map +1 -0
- package/dist/core/glob.js +399 -0
- package/dist/core/glob.js.map +1 -0
- package/dist/core/input-required.d.ts +147 -0
- package/dist/core/input-required.d.ts.map +1 -0
- package/dist/core/input-required.js +261 -0
- package/dist/core/input-required.js.map +1 -0
- package/dist/core/mime.d.ts +15 -0
- package/dist/core/mime.d.ts.map +1 -0
- package/dist/core/mime.js +188 -0
- package/dist/core/mime.js.map +1 -0
- package/dist/core/observability.d.ts +10 -0
- package/dist/core/observability.d.ts.map +1 -0
- package/dist/core/observability.js +76 -0
- package/dist/core/observability.js.map +1 -0
- package/dist/core/page-store.d.ts +41 -0
- package/dist/core/page-store.d.ts.map +1 -0
- package/dist/core/page-store.js +74 -0
- package/dist/core/page-store.js.map +1 -0
- package/dist/core/path-completer.d.ts +10 -0
- package/dist/core/path-completer.d.ts.map +1 -0
- package/dist/core/path-completer.js +227 -0
- package/dist/core/path-completer.js.map +1 -0
- package/dist/core/path-discovery.d.ts +8 -0
- package/dist/core/path-discovery.d.ts.map +1 -0
- package/dist/core/path-discovery.js +105 -0
- package/dist/core/path-discovery.js.map +1 -0
- package/dist/core/path-utils.d.ts +9 -0
- package/dist/core/path-utils.d.ts.map +1 -0
- package/dist/core/path-utils.js +121 -0
- package/dist/core/path-utils.js.map +1 -0
- package/dist/core/path.d.ts +148 -0
- package/dist/core/path.d.ts.map +1 -0
- package/dist/core/path.js +674 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/primitives.d.ts +23 -0
- package/dist/core/primitives.d.ts.map +1 -0
- package/dist/core/primitives.js +54 -0
- package/dist/core/primitives.js.map +1 -0
- package/dist/core/read.d.ts +74 -0
- package/dist/core/read.d.ts.map +1 -0
- package/dist/core/read.js +562 -0
- package/dist/core/read.js.map +1 -0
- package/dist/core/schema.d.ts +139 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +345 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/search.d.ts +100 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +248 -0
- package/dist/core/search.js.map +1 -0
- package/dist/core/sensitive.d.ts +6 -0
- package/dist/core/sensitive.d.ts.map +1 -0
- package/dist/core/sensitive.js +142 -0
- package/dist/core/sensitive.js.map +1 -0
- package/dist/core/store.d.ts +57 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +162 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/util.d.ts +26 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/core/util.js +66 -0
- package/dist/core/util.js.map +1 -0
- package/dist/core/watcher-registry.d.ts +68 -0
- package/dist/core/watcher-registry.d.ts.map +1 -0
- package/dist/core/watcher-registry.js +312 -0
- package/dist/core/watcher-registry.js.map +1 -0
- package/dist/http-policy.d.ts +121 -0
- package/dist/http-policy.d.ts.map +1 -0
- package/dist/http-policy.js +340 -0
- package/dist/http-policy.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -41
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +12 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +71 -0
- package/dist/instructions.js.map +1 -0
- package/dist/prompts.d.ts +8 -6
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +74 -168
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +73 -9
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +392 -163
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +62 -1
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +139 -1
- package/dist/server.js.map +1 -0
- package/dist/tools/batch.d.ts +89 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +157 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/create.d.ts +2 -0
- package/dist/tools/create.d.ts.map +1 -0
- package/dist/tools/create.js +142 -0
- package/dist/tools/create.js.map +1 -0
- package/dist/tools/define.d.ts +110 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +394 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/delete-file.d.ts +2 -4
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +330 -87
- package/dist/tools/delete-file.js.map +1 -0
- package/dist/tools/diff.d.ts +2 -0
- package/dist/tools/diff.d.ts.map +1 -0
- package/dist/tools/diff.js +94 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +442 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/index.d.ts +26 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +52 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list.d.ts +2 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +291 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/move.d.ts +2 -0
- package/dist/tools/move.d.ts.map +1 -0
- package/dist/tools/move.js +321 -0
- package/dist/tools/move.js.map +1 -0
- package/dist/tools/patch.d.ts +2 -0
- package/dist/tools/patch.d.ts.map +1 -0
- package/dist/tools/patch.js +155 -0
- package/dist/tools/patch.js.map +1 -0
- package/dist/tools/progress.d.ts +52 -0
- package/dist/tools/progress.d.ts.map +1 -0
- package/dist/tools/progress.js +172 -0
- package/dist/tools/progress.js.map +1 -0
- package/dist/tools/read.d.ts +2 -4
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +398 -152
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/replace-in-files.d.ts +2 -4
- package/dist/tools/replace-in-files.d.ts.map +1 -0
- package/dist/tools/replace-in-files.js +435 -264
- package/dist/tools/replace-in-files.js.map +1 -0
- package/dist/tools/roots.d.ts +2 -4
- package/dist/tools/roots.d.ts.map +1 -0
- package/dist/tools/roots.js +29 -52
- package/dist/tools/roots.js.map +1 -0
- package/dist/tools/search-content.d.ts +2 -4
- package/dist/tools/search-content.d.ts.map +1 -0
- package/dist/tools/search-content.js +262 -228
- package/dist/tools/search-content.js.map +1 -0
- package/dist/tools/search-files.d.ts +2 -4
- package/dist/tools/search-files.d.ts.map +1 -0
- package/dist/tools/search-files.js +162 -161
- package/dist/tools/search-files.js.map +1 -0
- package/dist/tools/stat.d.ts +2 -4
- package/dist/tools/stat.d.ts.map +1 -0
- package/dist/tools/stat.js +202 -62
- package/dist/tools/stat.js.map +1 -0
- package/dist/transport/http.d.ts +5 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +276 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/shared.d.ts +45 -0
- package/dist/transport/shared.d.ts.map +1 -0
- package/dist/transport/shared.js +65 -0
- package/dist/transport/shared.js.map +1 -0
- package/dist/transport/stdio.d.ts +32 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +279 -0
- package/dist/transport/stdio.js.map +1 -0
- package/dist/transport.d.ts +5 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +4 -0
- package/dist/transport.js.map +1 -0
- package/package.json +37 -46
- package/dist/assets/logo.svg +0 -35
- package/dist/completions.d.ts +0 -2
- package/dist/completions.js +0 -572
- package/dist/config.d.ts +0 -119
- package/dist/config.js +0 -31
- package/dist/lib/abort.d.ts +0 -7
- package/dist/lib/abort.js +0 -81
- package/dist/lib/constants.d.ts +0 -42
- package/dist/lib/constants.js +0 -313
- package/dist/lib/errors.d.ts +0 -28
- package/dist/lib/errors.js +0 -301
- package/dist/lib/file-operations/core.d.ts +0 -53
- package/dist/lib/file-operations/core.js +0 -144
- package/dist/lib/file-operations/metadata.d.ts +0 -77
- package/dist/lib/file-operations/metadata.js +0 -878
- package/dist/lib/file-operations/search.d.ts +0 -46
- package/dist/lib/file-operations/search.js +0 -1194
- package/dist/lib/file-operations/traversal.d.ts +0 -40
- package/dist/lib/file-operations/traversal.js +0 -310
- package/dist/lib/fs-helpers.d.ts +0 -46
- package/dist/lib/fs-helpers.js +0 -606
- package/dist/lib/globs.d.ts +0 -2
- package/dist/lib/globs.js +0 -19
- package/dist/lib/logger.d.ts +0 -27
- package/dist/lib/logger.js +0 -91
- package/dist/lib/observability.d.ts +0 -33
- package/dist/lib/observability.js +0 -373
- package/dist/lib/paths.d.ts +0 -35
- package/dist/lib/paths.js +0 -634
- package/dist/lib/resource-store.d.ts +0 -28
- package/dist/lib/resource-store.js +0 -195
- package/dist/lib/utils.d.ts +0 -7
- package/dist/lib/utils.js +0 -37
- package/dist/lib/zod-codecs.d.ts +0 -2
- package/dist/lib/zod-codecs.js +0 -18
- package/dist/pkg-info.d.ts +0 -7
- package/dist/pkg-info.js +0 -9
- package/dist/resources/generated-instructions.d.ts +0 -1
- package/dist/resources/generated-instructions.js +0 -105
- package/dist/resources/tool-catalog.d.ts +0 -2
- package/dist/resources/tool-catalog.js +0 -78
- package/dist/resources/tool-info.d.ts +0 -9
- package/dist/resources/tool-info.js +0 -206
- package/dist/resources/workflows.d.ts +0 -1
- package/dist/resources/workflows.js +0 -72
- package/dist/schemas.d.ts +0 -505
- package/dist/schemas.js +0 -676
- package/dist/server/bootstrap.d.ts +0 -6
- package/dist/server/bootstrap.js +0 -563
- package/dist/server/event-store.d.ts +0 -18
- package/dist/server/event-store.js +0 -71
- package/dist/server/roots-manager.d.ts +0 -28
- package/dist/server/roots-manager.js +0 -227
- package/dist/server/task-store.d.ts +0 -10
- package/dist/server/task-store.js +0 -91
- package/dist/tools/apply-patch.d.ts +0 -4
- package/dist/tools/apply-patch.js +0 -235
- package/dist/tools/calculate-hash.d.ts +0 -4
- package/dist/tools/calculate-hash.js +0 -187
- package/dist/tools/contract.d.ts +0 -50
- package/dist/tools/contract.js +0 -1
- package/dist/tools/create-directory.d.ts +0 -4
- package/dist/tools/create-directory.js +0 -68
- package/dist/tools/diff-files.d.ts +0 -4
- package/dist/tools/diff-files.js +0 -136
- package/dist/tools/edit-file.d.ts +0 -4
- package/dist/tools/edit-file.js +0 -256
- package/dist/tools/icons.d.ts +0 -15
- package/dist/tools/icons.js +0 -24
- package/dist/tools/list-directory.d.ts +0 -4
- package/dist/tools/list-directory.js +0 -218
- package/dist/tools/move-file.d.ts +0 -4
- package/dist/tools/move-file.js +0 -178
- package/dist/tools/read-multiple.d.ts +0 -4
- package/dist/tools/read-multiple.js +0 -207
- package/dist/tools/shared.d.ts +0 -172
- package/dist/tools/shared.js +0 -599
- package/dist/tools/stat-many.d.ts +0 -4
- package/dist/tools/stat-many.js +0 -104
- package/dist/tools/task-support.d.ts +0 -29
- package/dist/tools/task-support.js +0 -472
- package/dist/tools/tree.d.ts +0 -4
- package/dist/tools/tree.js +0 -102
- package/dist/tools/write-file.d.ts +0 -4
- package/dist/tools/write-file.js +0 -60
- package/dist/tools.d.ts +0 -5
- package/dist/tools.js +0 -54
package/dist/tools/stat-many.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_SEARCH_TIMEOUT_MS } from '../lib/constants.js';
|
|
2
|
-
import { classifyError, ErrorCode } from '../lib/errors.js';
|
|
3
|
-
import { getMultipleFileInfo } from '../lib/file-operations/metadata.js';
|
|
4
|
-
import { formatBytes, joinLines } from '../config.js';
|
|
5
|
-
import { GetMultipleFileInfoInputSchema, GetMultipleFileInfoOutputSchema, } from '../schemas.js';
|
|
6
|
-
import { FILE_READ_ICONS } from './icons.js';
|
|
7
|
-
import { buildBatchPathContext, buildFileInfoPayload, buildStructuredError, buildToolErrorResponse, buildToolResponse, createBatchProgressCallbacks, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, } from './shared.js';
|
|
8
|
-
import { registerStandardTool } from './task-support.js';
|
|
9
|
-
export const GET_MULTIPLE_FILE_INFO_TOOL = {
|
|
10
|
-
name: 'stat_many',
|
|
11
|
-
title: 'Get Multiple File Info',
|
|
12
|
-
description: 'Get metadata for multiple files/directories in one request. ' +
|
|
13
|
-
'Use `tokenEstimate` (size\u00f74) to pre-screen token cost before reading.',
|
|
14
|
-
inputSchema: GetMultipleFileInfoInputSchema,
|
|
15
|
-
outputSchema: GetMultipleFileInfoOutputSchema,
|
|
16
|
-
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
17
|
-
icons: FILE_READ_ICONS,
|
|
18
|
-
taskSupport: 'optional',
|
|
19
|
-
};
|
|
20
|
-
function formatFileInfoDetail(info) {
|
|
21
|
-
const lines = [
|
|
22
|
-
`${info.name} (${info.type})`,
|
|
23
|
-
` Path: ${info.path}`,
|
|
24
|
-
` Size: ${formatBytes(info.size)}`,
|
|
25
|
-
` Modified: ${info.modified.toISOString()}`,
|
|
26
|
-
];
|
|
27
|
-
if (info.mimeType)
|
|
28
|
-
lines.push(` Type: ${info.mimeType}`);
|
|
29
|
-
if (info.symlinkTarget)
|
|
30
|
-
lines.push(` Target: ${info.symlinkTarget}`);
|
|
31
|
-
return joinLines(lines);
|
|
32
|
-
}
|
|
33
|
-
async function handleGetMultipleFileInfo(args, signal, onProgress) {
|
|
34
|
-
const result = await getMultipleFileInfo(args.paths, {
|
|
35
|
-
includeMimeType: true,
|
|
36
|
-
...(signal ? { signal } : {}),
|
|
37
|
-
...(onProgress ? { onProgress } : {}),
|
|
38
|
-
});
|
|
39
|
-
const structuredResults = result.results.map((entry) => ({
|
|
40
|
-
path: entry.path,
|
|
41
|
-
info: entry.info ? buildFileInfoPayload(entry.info) : undefined,
|
|
42
|
-
error: entry.error
|
|
43
|
-
? buildStructuredError(entry.error, ErrorCode.NOT_FOUND, entry.path)
|
|
44
|
-
: undefined,
|
|
45
|
-
}));
|
|
46
|
-
const text = result.results
|
|
47
|
-
.map((entry) => {
|
|
48
|
-
if (entry.error) {
|
|
49
|
-
return `${entry.path}: ${buildStructuredError(entry.error, ErrorCode.NOT_FOUND, entry.path).message}`;
|
|
50
|
-
}
|
|
51
|
-
if (entry.info) {
|
|
52
|
-
return formatFileInfoDetail(entry.info);
|
|
53
|
-
}
|
|
54
|
-
return entry.path;
|
|
55
|
-
})
|
|
56
|
-
.join('\n\n');
|
|
57
|
-
const structured = {
|
|
58
|
-
ok: true,
|
|
59
|
-
results: structuredResults,
|
|
60
|
-
summary: {
|
|
61
|
-
total: result.summary.total,
|
|
62
|
-
succeeded: result.summary.succeeded,
|
|
63
|
-
failed: result.summary.failed,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
return buildToolResponse(text, structured);
|
|
67
|
-
}
|
|
68
|
-
export function registerGetMultipleFileInfoTool(server, options = {}) {
|
|
69
|
-
const handler = (args, ctx) => {
|
|
70
|
-
const primaryPath = args.paths[0] ?? '';
|
|
71
|
-
return executeToolWithDiagnostics({
|
|
72
|
-
toolName: 'stat_many',
|
|
73
|
-
ctx,
|
|
74
|
-
outputSchema: GetMultipleFileInfoOutputSchema,
|
|
75
|
-
timedSignal: { timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS },
|
|
76
|
-
context: { path: primaryPath },
|
|
77
|
-
run: async (signal) => {
|
|
78
|
-
const context = buildBatchPathContext(args.paths);
|
|
79
|
-
const { progress, onItemComplete } = createBatchProgressCallbacks(ctx, {
|
|
80
|
-
toolLabel: GET_MULTIPLE_FILE_INFO_TOOL.title,
|
|
81
|
-
context,
|
|
82
|
-
totalItems: args.paths.length,
|
|
83
|
-
itemVerb: 'done',
|
|
84
|
-
});
|
|
85
|
-
try {
|
|
86
|
-
const result = await handleGetMultipleFileInfo(args, signal, onItemComplete);
|
|
87
|
-
const sc = result.structuredContent;
|
|
88
|
-
const total = sc.summary?.total ?? 0;
|
|
89
|
-
const failed = sc.summary?.failed ?? 0;
|
|
90
|
-
const suffix = failed ? `${failed} failed` : 'done';
|
|
91
|
-
const finalCurrent = resolveFinalProgressCurrent(progress, total);
|
|
92
|
-
progress.complete(`${GET_MULTIPLE_FILE_INFO_TOOL.title}: ${context} • ${suffix}`, finalCurrent);
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
progress.fail(`${GET_MULTIPLE_FILE_INFO_TOOL.title}: ${context} • ${classifyError(error)}`);
|
|
97
|
-
throw error;
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
onError: (error) => buildToolErrorResponse(error, ErrorCode.NOT_FOUND, primaryPath),
|
|
101
|
-
});
|
|
102
|
-
};
|
|
103
|
-
registerStandardTool(server, GET_MULTIPLE_FILE_INFO_TOOL, handler, options);
|
|
104
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type McpServer, type RequestTaskStore, type StandardSchemaWithJSON, type ToolTaskHandler } from '@modelcontextprotocol/server';
|
|
2
|
-
import { type IconInfo, type ToolContext, type ToolContract, type ToolRegistrationOptions, type ToolResult } from './shared.js';
|
|
3
|
-
/**
|
|
4
|
-
* Report an intermediate 'working' status update for the current task.
|
|
5
|
-
* No-op when called outside of a task context.
|
|
6
|
-
*/
|
|
7
|
-
export declare function reportTaskStatus(statusMessage: string): Promise<void>;
|
|
8
|
-
type TaskToolContext = ToolContext & {
|
|
9
|
-
taskId?: string;
|
|
10
|
-
taskStore?: RequestTaskStore;
|
|
11
|
-
taskRequestedTtl?: number;
|
|
12
|
-
};
|
|
13
|
-
type ToolSchema = StandardSchemaWithJSON | undefined;
|
|
14
|
-
type ToolArgs<Args extends ToolSchema> = Args extends StandardSchemaWithJSON ? StandardSchemaWithJSON.InferOutput<Args> : undefined;
|
|
15
|
-
export declare function registerToolTaskIfAvailable<Args extends ToolSchema, Result>(server: McpServer, toolName: string, toolDef: object, run: (args: ToolArgs<Args>, ctx: TaskToolContext) => Promise<ToolResult<Result>>, iconInfo: IconInfo | undefined, guard?: () => boolean): boolean;
|
|
16
|
-
export declare function registerStandardTool<Args, Result extends Record<string, unknown>>(server: McpServer, toolDef: ToolContract, handler: (args: Args, ctx: ToolContext) => Promise<ToolResult<Result>>, options?: ToolRegistrationOptions, wrapOptions?: {
|
|
17
|
-
guard?: (() => boolean) | undefined;
|
|
18
|
-
progressMessage?: (args: Args) => string;
|
|
19
|
-
completionMessage?: (args: Args, result: ToolResult<Result>) => string | undefined;
|
|
20
|
-
}): void;
|
|
21
|
-
interface TaskHandlerOptions {
|
|
22
|
-
guard?: () => boolean;
|
|
23
|
-
toolName?: string;
|
|
24
|
-
cancelPollMs?: number;
|
|
25
|
-
pollIntervalMs?: number;
|
|
26
|
-
}
|
|
27
|
-
export declare function createToolTaskHandler<Result>(run: (args: undefined, ctx: TaskToolContext) => Promise<ToolResult<Result>>, options?: TaskHandlerOptions): ToolTaskHandler;
|
|
28
|
-
export declare function createToolTaskHandler<Args extends StandardSchemaWithJSON, Result>(run: (args: ToolArgs<Args>, ctx: TaskToolContext) => Promise<ToolResult<Result>>, options?: TaskHandlerOptions): ToolTaskHandler<Args>;
|
|
29
|
-
export {};
|
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
import { isTerminal, RELATED_TASK_META_KEY, } from '@modelcontextprotocol/server';
|
|
2
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
-
import { channel } from 'node:diagnostics_channel';
|
|
4
|
-
import { performance } from 'node:perf_hooks';
|
|
5
|
-
import { format } from 'node:util';
|
|
6
|
-
import { DEFAULT_TASK_TTL_MS, MAX_CONCURRENT_TASKS, MAX_TASK_TTL_MS, TASK_CANCEL_POLL_MS, TASK_POLL_INTERVAL_MS, } from '../lib/constants.js';
|
|
7
|
-
import { ErrorCode, McpError } from '../lib/errors.js';
|
|
8
|
-
import { Logger } from '../lib/logger.js';
|
|
9
|
-
import { isRecord } from '../lib/utils.js';
|
|
10
|
-
import { buildToolErrorResponse, maybeStripStructuredContentFromResult, resolveToolTaskSupportLevel, toToolContext, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
11
|
-
const taskContext = new AsyncLocalStorage();
|
|
12
|
-
/**
|
|
13
|
-
* Report an intermediate 'working' status update for the current task.
|
|
14
|
-
* No-op when called outside of a task context.
|
|
15
|
-
*/
|
|
16
|
-
export async function reportTaskStatus(statusMessage) {
|
|
17
|
-
const store = taskContext.getStore();
|
|
18
|
-
if (!store)
|
|
19
|
-
return;
|
|
20
|
-
const { taskId, taskStore, ctx, toolName } = store;
|
|
21
|
-
try {
|
|
22
|
-
await taskStore.updateTaskStatus(taskId, 'working', statusMessage);
|
|
23
|
-
await notifyTaskStatusIfPossible(ctx, taskStore, taskId, toolName);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Best-effort: never fail tool execution for status updates.
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const TASK_DIAGNOSTICS_CHANNEL = channel('filesystem-mcp:tasks');
|
|
30
|
-
function publishTaskDiagnostics(event) {
|
|
31
|
-
if (TASK_DIAGNOSTICS_CHANNEL.hasSubscribers) {
|
|
32
|
-
TASK_DIAGNOSTICS_CHANNEL.publish(event);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// --- Type Guards & Helpers ---
|
|
36
|
-
function hasTaskToolCapability(server) {
|
|
37
|
-
try {
|
|
38
|
-
const capabilities = server.server.getCapabilities();
|
|
39
|
-
return capabilities.tasks?.requests?.tools?.call !== undefined;
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const TASK_STATUS_NOTIFICATION_METHOD = 'notifications/tasks/status';
|
|
46
|
-
const TASK_CREATED_NOTIFICATION_METHOD = 'notifications/tasks/created';
|
|
47
|
-
function assertCreateTaskContext(value) {
|
|
48
|
-
if (!isRecord(value.task) || typeof value.task.store !== 'object') {
|
|
49
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task store not configured.');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function assertTaskRequestContext(value) {
|
|
53
|
-
if (!isRecord(value.task) ||
|
|
54
|
-
typeof value.task.store !== 'object' ||
|
|
55
|
-
typeof value.task.id !== 'string' ||
|
|
56
|
-
value.task.id.length === 0) {
|
|
57
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task id or store missing.');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function toTaskToolContext(ctx) {
|
|
61
|
-
return {
|
|
62
|
-
...toToolContext(ctx),
|
|
63
|
-
taskStore: ctx.task.store,
|
|
64
|
-
...(typeof ctx.task.id === 'string' && ctx.task.id.length > 0
|
|
65
|
-
? { taskId: ctx.task.id }
|
|
66
|
-
: {}),
|
|
67
|
-
...(ctx.task.requestedTtl !== undefined
|
|
68
|
-
? { taskRequestedTtl: ctx.task.requestedTtl }
|
|
69
|
-
: {}),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function toGetTaskResult(task) {
|
|
73
|
-
return task;
|
|
74
|
-
}
|
|
75
|
-
function toCallToolResult(value) {
|
|
76
|
-
return value;
|
|
77
|
-
}
|
|
78
|
-
function getToolResultErrorCode(result) {
|
|
79
|
-
if (!isRecord(result) || result.isError !== true)
|
|
80
|
-
return undefined;
|
|
81
|
-
if (typeof result.errorCode === 'string')
|
|
82
|
-
return result.errorCode;
|
|
83
|
-
const { content } = result;
|
|
84
|
-
if (!Array.isArray(content) || content.length === 0)
|
|
85
|
-
return undefined;
|
|
86
|
-
const first = content[0];
|
|
87
|
-
if (!isRecord(first) || first.type !== 'text')
|
|
88
|
-
return undefined;
|
|
89
|
-
const { text } = first;
|
|
90
|
-
if (typeof text !== 'string')
|
|
91
|
-
return undefined;
|
|
92
|
-
const match = /^Error \[([A-Z0-9_]+)\]:/.exec(text);
|
|
93
|
-
return match ? match[1] : undefined;
|
|
94
|
-
}
|
|
95
|
-
function isCancelledToolResult(result) {
|
|
96
|
-
return getToolResultErrorCode(result) === ErrorCode.CANCELLED;
|
|
97
|
-
}
|
|
98
|
-
function resolveTaskResultStatuses(result) {
|
|
99
|
-
if (isCancelledToolResult(result)) {
|
|
100
|
-
return { storedStatus: 'failed', reportedStatus: 'cancelled' };
|
|
101
|
-
}
|
|
102
|
-
if (isRecord(result) && result.isError === true) {
|
|
103
|
-
return { storedStatus: 'failed', reportedStatus: 'failed' };
|
|
104
|
-
}
|
|
105
|
-
return { storedStatus: 'completed', reportedStatus: 'completed' };
|
|
106
|
-
}
|
|
107
|
-
function attachRelatedTaskMeta(result, taskId) {
|
|
108
|
-
const existingMeta = isRecord(result._meta) ? result._meta : {};
|
|
109
|
-
return {
|
|
110
|
-
...result,
|
|
111
|
-
_meta: {
|
|
112
|
-
...existingMeta,
|
|
113
|
-
[RELATED_TASK_META_KEY]: { taskId },
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
async function projectCancelledTaskStatus(taskStore, task) {
|
|
118
|
-
if (task.status !== 'failed')
|
|
119
|
-
return task;
|
|
120
|
-
try {
|
|
121
|
-
const result = await taskStore.getTaskResult(task.taskId);
|
|
122
|
-
if (isCancelledToolResult(result)) {
|
|
123
|
-
return { ...task, status: 'cancelled' };
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
// Best effort only: task result may not be available yet.
|
|
128
|
-
}
|
|
129
|
-
return task;
|
|
130
|
-
}
|
|
131
|
-
function buildTaskStatusNotificationParams(task) {
|
|
132
|
-
const params = {
|
|
133
|
-
taskId: task.taskId,
|
|
134
|
-
status: task.status,
|
|
135
|
-
ttl: task.ttl,
|
|
136
|
-
createdAt: task.createdAt,
|
|
137
|
-
lastUpdatedAt: task.lastUpdatedAt,
|
|
138
|
-
};
|
|
139
|
-
if (task.pollInterval !== undefined)
|
|
140
|
-
params.pollInterval = task.pollInterval;
|
|
141
|
-
if (task.statusMessage !== undefined)
|
|
142
|
-
params.statusMessage = task.statusMessage;
|
|
143
|
-
return params;
|
|
144
|
-
}
|
|
145
|
-
async function notifyTaskCreatedIfPossible(ctx, taskId, toolName) {
|
|
146
|
-
if (!ctx.sendNotification)
|
|
147
|
-
return;
|
|
148
|
-
try {
|
|
149
|
-
await ctx.sendNotification({
|
|
150
|
-
method: TASK_CREATED_NOTIFICATION_METHOD,
|
|
151
|
-
params: {
|
|
152
|
-
_meta: {
|
|
153
|
-
[RELATED_TASK_META_KEY]: {
|
|
154
|
-
taskId,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
publishTaskDiagnostics({
|
|
162
|
-
phase: 'task_status_notify_failed',
|
|
163
|
-
taskId,
|
|
164
|
-
...(toolName ? { toolName } : {}),
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
async function notifyTaskStatusIfPossible(ctx, taskStore, taskId, toolName) {
|
|
169
|
-
if (!ctx.sendNotification)
|
|
170
|
-
return;
|
|
171
|
-
try {
|
|
172
|
-
const task = await taskStore.getTask(taskId);
|
|
173
|
-
const normalized = await projectCancelledTaskStatus(taskStore, toGetTaskResult(task));
|
|
174
|
-
await ctx.sendNotification({
|
|
175
|
-
method: TASK_STATUS_NOTIFICATION_METHOD,
|
|
176
|
-
params: buildTaskStatusNotificationParams(normalized),
|
|
177
|
-
});
|
|
178
|
-
publishTaskDiagnostics({
|
|
179
|
-
phase: 'task_status_notified',
|
|
180
|
-
taskId,
|
|
181
|
-
status: normalized.status,
|
|
182
|
-
...(toolName ? { toolName } : {}),
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
publishTaskDiagnostics({
|
|
187
|
-
phase: 'task_status_notify_failed',
|
|
188
|
-
taskId,
|
|
189
|
-
...(toolName ? { toolName } : {}),
|
|
190
|
-
});
|
|
191
|
-
// Never fail task execution because status notifications are optional.
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function getTaskStore(ctx) {
|
|
195
|
-
if (!ctx.taskStore) {
|
|
196
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task store not configured.');
|
|
197
|
-
}
|
|
198
|
-
return ctx.taskStore;
|
|
199
|
-
}
|
|
200
|
-
function getTaskId(ctx) {
|
|
201
|
-
if (!ctx.taskId) {
|
|
202
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task id missing.');
|
|
203
|
-
}
|
|
204
|
-
return ctx.taskId;
|
|
205
|
-
}
|
|
206
|
-
function isErrorResult(result) {
|
|
207
|
-
return 'isError' in result && result.isError;
|
|
208
|
-
}
|
|
209
|
-
// Strips structuredContent from a tool result if present, without modifying the original object.
|
|
210
|
-
function withoutStructuredContent(result) {
|
|
211
|
-
if (!Object.hasOwn(result, 'structuredContent'))
|
|
212
|
-
return result;
|
|
213
|
-
const stripped = { ...result };
|
|
214
|
-
delete stripped['structuredContent'];
|
|
215
|
-
return stripped;
|
|
216
|
-
}
|
|
217
|
-
const taskCreationLocks = new WeakMap();
|
|
218
|
-
async function acquireTaskCreationLock(taskStore) {
|
|
219
|
-
const previous = taskCreationLocks.get(taskStore) ?? Promise.resolve();
|
|
220
|
-
let release;
|
|
221
|
-
const next = new Promise((resolve) => {
|
|
222
|
-
release = resolve;
|
|
223
|
-
});
|
|
224
|
-
taskCreationLocks.set(taskStore, previous.catch(() => { }).then(() => next));
|
|
225
|
-
await previous.catch(() => { });
|
|
226
|
-
return () => {
|
|
227
|
-
release();
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
async function isTaskAlreadyTerminal(taskStore, taskId) {
|
|
231
|
-
try {
|
|
232
|
-
const task = await taskStore.getTask(taskId);
|
|
233
|
-
if (!isRecord(task))
|
|
234
|
-
return false;
|
|
235
|
-
const { status } = task;
|
|
236
|
-
return typeof status === 'string' && isTerminal(status);
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
function isMissingTaskStoreError(error) {
|
|
243
|
-
return (error instanceof Error &&
|
|
244
|
-
/Task .*not found|not found after cancellation/iu.test(error.message));
|
|
245
|
-
}
|
|
246
|
-
async function countActiveTasks(taskStore) {
|
|
247
|
-
if (typeof taskStore.listTasks !== 'function')
|
|
248
|
-
return 0;
|
|
249
|
-
const listed = await taskStore.listTasks();
|
|
250
|
-
const tasks = Array.isArray(listed.tasks) ? listed.tasks : [];
|
|
251
|
-
let active = 0;
|
|
252
|
-
for (const task of tasks) {
|
|
253
|
-
if (!isRecord(task) || typeof task.status !== 'string')
|
|
254
|
-
continue;
|
|
255
|
-
if (!isTerminal(task.status)) {
|
|
256
|
-
active += 1;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return active;
|
|
260
|
-
}
|
|
261
|
-
function resolveRequestedTaskTtl(requestedTtl) {
|
|
262
|
-
if (requestedTtl === undefined)
|
|
263
|
-
return DEFAULT_TASK_TTL_MS;
|
|
264
|
-
if (!Number.isFinite(requestedTtl)) {
|
|
265
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task TTL must be finite.');
|
|
266
|
-
}
|
|
267
|
-
const normalized = Math.trunc(requestedTtl);
|
|
268
|
-
if (normalized <= 0) {
|
|
269
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Task TTL must be > 0.');
|
|
270
|
-
}
|
|
271
|
-
return Math.min(normalized, MAX_TASK_TTL_MS);
|
|
272
|
-
}
|
|
273
|
-
async function safelyStoreTaskResult(taskStore, taskId, storedStatus, result) {
|
|
274
|
-
try {
|
|
275
|
-
await taskStore.storeTaskResult(taskId, storedStatus, result);
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
if (isMissingTaskStoreError(error))
|
|
279
|
-
return;
|
|
280
|
-
// If task was already cancelled/failed by another process, ignore the write error
|
|
281
|
-
if (await isTaskAlreadyTerminal(taskStore, taskId))
|
|
282
|
-
return;
|
|
283
|
-
throw error;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
async function isTaskCancelled(taskStore, taskId) {
|
|
287
|
-
try {
|
|
288
|
-
const task = await taskStore.getTask(taskId);
|
|
289
|
-
return isRecord(task) && task.status === 'cancelled';
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
async function runTaskInBackground(run, args, ctx, taskStore, taskId, toolName, cancelPollMs) {
|
|
296
|
-
// Create a dedicated AbortController for background execution.
|
|
297
|
-
// The original request signal is stale once createTask returns.
|
|
298
|
-
const taskAbort = new AbortController();
|
|
299
|
-
const taskExtra = { ...ctx, signal: taskAbort.signal };
|
|
300
|
-
// Poll the task store for client-initiated cancellation.
|
|
301
|
-
const cancelPoller = setInterval(() => {
|
|
302
|
-
void isTaskCancelled(taskStore, taskId).then((cancelled) => {
|
|
303
|
-
if (cancelled)
|
|
304
|
-
taskAbort.abort(new Error('Task cancelled by client'));
|
|
305
|
-
});
|
|
306
|
-
}, cancelPollMs ?? TASK_CANCEL_POLL_MS);
|
|
307
|
-
const start = performance.now();
|
|
308
|
-
let taskStatuses;
|
|
309
|
-
let result;
|
|
310
|
-
try {
|
|
311
|
-
const rawResult = await taskContext.run({ taskId, toolName, startTime: start, taskStore, ctx: taskExtra }, () => run(args, taskExtra));
|
|
312
|
-
taskStatuses = resolveTaskResultStatuses(rawResult);
|
|
313
|
-
result = isErrorResult(rawResult)
|
|
314
|
-
? withoutStructuredContent(rawResult)
|
|
315
|
-
: maybeStripStructuredContentFromResult(rawResult);
|
|
316
|
-
}
|
|
317
|
-
catch (error) {
|
|
318
|
-
taskStatuses = { storedStatus: 'failed', reportedStatus: 'failed' };
|
|
319
|
-
result = maybeStripStructuredContentFromResult(buildToolErrorResponse(error, ErrorCode.UNKNOWN));
|
|
320
|
-
}
|
|
321
|
-
finally {
|
|
322
|
-
clearInterval(cancelPoller);
|
|
323
|
-
}
|
|
324
|
-
const durationMs = performance.now() - start;
|
|
325
|
-
try {
|
|
326
|
-
await safelyStoreTaskResult(taskStore, taskId, taskStatuses.storedStatus, result);
|
|
327
|
-
publishTaskDiagnostics({
|
|
328
|
-
phase: 'task_result_stored',
|
|
329
|
-
taskId,
|
|
330
|
-
status: taskStatuses.reportedStatus,
|
|
331
|
-
toolName,
|
|
332
|
-
durationMs,
|
|
333
|
-
});
|
|
334
|
-
await notifyTaskStatusIfPossible(ctx, taskStore, taskId, toolName);
|
|
335
|
-
}
|
|
336
|
-
catch (innerError) {
|
|
337
|
-
Logger.error(format('Failed to store task result for task %s:', taskId), innerError);
|
|
338
|
-
const syntheticTask = {
|
|
339
|
-
taskId,
|
|
340
|
-
status: taskStatuses.reportedStatus === 'cancelled' ? 'cancelled' : 'failed',
|
|
341
|
-
ttl: null,
|
|
342
|
-
createdAt: new Date().toISOString(),
|
|
343
|
-
lastUpdatedAt: new Date().toISOString(),
|
|
344
|
-
statusMessage: 'Internal system error while storing result',
|
|
345
|
-
};
|
|
346
|
-
if (ctx.sendNotification) {
|
|
347
|
-
try {
|
|
348
|
-
await ctx.sendNotification({
|
|
349
|
-
method: TASK_STATUS_NOTIFICATION_METHOD,
|
|
350
|
-
params: buildTaskStatusNotificationParams(syntheticTask),
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
catch {
|
|
354
|
-
// Best effort only: transport may already be closed while a cancelled
|
|
355
|
-
// task is still unwinding in the background.
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Registers a tool preferring task-capable registration when available, and
|
|
362
|
-
* returns `true`. Returns `false` so the caller can fall through to standard
|
|
363
|
-
* `server.registerTool`.
|
|
364
|
-
*/
|
|
365
|
-
function tryRegisterToolTask(server, toolName, toolDef, taskHandler, iconInfo) {
|
|
366
|
-
if (!hasTaskToolCapability(server))
|
|
367
|
-
return false;
|
|
368
|
-
const def = toolDef;
|
|
369
|
-
const existingExecution = def.execution ?? {};
|
|
370
|
-
const taskSupport = resolveToolTaskSupportLevel(def.taskSupport, existingExecution.taskSupport);
|
|
371
|
-
if (!taskSupport || taskSupport === 'forbidden')
|
|
372
|
-
return false;
|
|
373
|
-
server.experimental.tasks.registerToolTask(toolName, withDefaultIcons({ ...toolDef, execution: { ...existingExecution, taskSupport } }, iconInfo), taskHandler);
|
|
374
|
-
return true;
|
|
375
|
-
}
|
|
376
|
-
export function registerToolTaskIfAvailable(server, toolName, toolDef, run, iconInfo, guard) {
|
|
377
|
-
const taskOptions = {
|
|
378
|
-
...(guard ? { guard } : {}),
|
|
379
|
-
toolName,
|
|
380
|
-
};
|
|
381
|
-
return tryRegisterToolTask(server, toolName, toolDef, createToolTaskHandler(run, taskOptions), iconInfo);
|
|
382
|
-
}
|
|
383
|
-
export function registerStandardTool(server, toolDef, handler, options = {}, wrapOptions = {}) {
|
|
384
|
-
const wrappedHandler = wrapToolHandler(handler, {
|
|
385
|
-
guard: options.isInitialized,
|
|
386
|
-
...wrapOptions,
|
|
387
|
-
});
|
|
388
|
-
const validatedHandler = withValidatedArgs(toolDef.inputSchema, wrappedHandler);
|
|
389
|
-
if (registerToolTaskIfAvailable(server, toolDef.name, toolDef, validatedHandler, options.iconInfo, options.isInitialized)) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
server.registerTool(toolDef.name, withDefaultIcons({ ...toolDef }, options.iconInfo), validatedHandler);
|
|
393
|
-
}
|
|
394
|
-
export function createToolTaskHandler(run, options) {
|
|
395
|
-
const createTask = (async (...params) => {
|
|
396
|
-
let args;
|
|
397
|
-
let serverCtx;
|
|
398
|
-
if (params.length === 1) {
|
|
399
|
-
serverCtx = params[0];
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
[args, serverCtx] = params;
|
|
403
|
-
}
|
|
404
|
-
assertCreateTaskContext(serverCtx);
|
|
405
|
-
const ctx = toTaskToolContext(serverCtx);
|
|
406
|
-
if (options?.guard && !options.guard()) {
|
|
407
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Client not initialized; wait for notifications/initialized');
|
|
408
|
-
}
|
|
409
|
-
const taskStore = getTaskStore(ctx);
|
|
410
|
-
const releaseCreationLock = await acquireTaskCreationLock(taskStore);
|
|
411
|
-
let task;
|
|
412
|
-
try {
|
|
413
|
-
if ((await countActiveTasks(taskStore)) >= MAX_CONCURRENT_TASKS) {
|
|
414
|
-
throw new McpError(ErrorCode.INVALID_INPUT, `Too many active tasks (limit: ${String(MAX_CONCURRENT_TASKS)}).`);
|
|
415
|
-
}
|
|
416
|
-
task = await taskStore.createTask({
|
|
417
|
-
ttl: resolveRequestedTaskTtl(ctx.taskRequestedTtl),
|
|
418
|
-
pollInterval: options?.pollIntervalMs ?? TASK_POLL_INTERVAL_MS,
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
finally {
|
|
422
|
-
releaseCreationLock();
|
|
423
|
-
}
|
|
424
|
-
const toolLabel = options?.toolName ?? 'tool';
|
|
425
|
-
try {
|
|
426
|
-
await taskStore.updateTaskStatus(task.taskId, 'working', `${toolLabel}: starting`);
|
|
427
|
-
}
|
|
428
|
-
catch {
|
|
429
|
-
// Best effort — status message is informational.
|
|
430
|
-
}
|
|
431
|
-
publishTaskDiagnostics({
|
|
432
|
-
phase: 'task_created',
|
|
433
|
-
taskId: task.taskId,
|
|
434
|
-
status: task.status,
|
|
435
|
-
...(options?.toolName ? { toolName: options.toolName } : {}),
|
|
436
|
-
});
|
|
437
|
-
const taskExtra = {
|
|
438
|
-
...ctx,
|
|
439
|
-
taskStore,
|
|
440
|
-
taskId: task.taskId,
|
|
441
|
-
};
|
|
442
|
-
void notifyTaskCreatedIfPossible(taskExtra, task.taskId, options?.toolName);
|
|
443
|
-
void notifyTaskStatusIfPossible(taskExtra, taskStore, task.taskId, options?.toolName);
|
|
444
|
-
void runTaskInBackground(run, args, taskExtra, taskStore, task.taskId, options?.toolName, options?.cancelPollMs);
|
|
445
|
-
return {
|
|
446
|
-
task,
|
|
447
|
-
};
|
|
448
|
-
});
|
|
449
|
-
const getTask = (async (...params) => {
|
|
450
|
-
const serverCtx = params.length === 1 ? params[0] : params[1];
|
|
451
|
-
assertTaskRequestContext(serverCtx);
|
|
452
|
-
const ctx = toTaskToolContext(serverCtx);
|
|
453
|
-
const taskStore = getTaskStore(ctx);
|
|
454
|
-
const taskId = getTaskId(ctx);
|
|
455
|
-
const task = await taskStore.getTask(taskId);
|
|
456
|
-
return projectCancelledTaskStatus(taskStore, toGetTaskResult(task));
|
|
457
|
-
});
|
|
458
|
-
const getTaskResult = (async (...params) => {
|
|
459
|
-
const serverCtx = params.length === 1 ? params[0] : params[1];
|
|
460
|
-
assertTaskRequestContext(serverCtx);
|
|
461
|
-
const ctx = toTaskToolContext(serverCtx);
|
|
462
|
-
const taskStore = getTaskStore(ctx);
|
|
463
|
-
const taskId = getTaskId(ctx);
|
|
464
|
-
const result = await taskStore.getTaskResult(taskId);
|
|
465
|
-
return attachRelatedTaskMeta(toCallToolResult(result), taskId);
|
|
466
|
-
});
|
|
467
|
-
return {
|
|
468
|
-
createTask,
|
|
469
|
-
getTask,
|
|
470
|
-
getTaskResult,
|
|
471
|
-
};
|
|
472
|
-
}
|
package/dist/tools/tree.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
-
import { type ToolContract, type ToolRegistrationOptions } from './shared.js';
|
|
3
|
-
export declare const TREE_TOOL: ToolContract;
|
|
4
|
-
export declare function registerTreeTool(server: McpServer, options?: ToolRegistrationOptions): void;
|