@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/shared.js
DELETED
|
@@ -1,599 +0,0 @@
|
|
|
1
|
-
import { channel } from 'node:diagnostics_channel';
|
|
2
|
-
import { basename } from 'node:path';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import { createTimedAbortSignal } from '../lib/abort.js';
|
|
5
|
-
import { parseTrueEnvFlag } from '../lib/constants.js';
|
|
6
|
-
import { classifyError, createDetailedError, ErrorCode, formatDetailedError, getSuggestion, McpError, } from '../lib/errors.js';
|
|
7
|
-
import { Logger } from '../lib/logger.js';
|
|
8
|
-
import { withToolDiagnostics, } from '../lib/observability.js';
|
|
9
|
-
import { getAllowedDirectories } from '../lib/paths.js';
|
|
10
|
-
import { createBase64JsonCodec } from '../lib/zod-codecs.js';
|
|
11
|
-
export {} from './contract.js';
|
|
12
|
-
const MAX_INLINE_CONTENT_CHARS = parseInt(process.env['FS_CONTEXT_MAX_INLINE_CHARS'] ?? '', 10) || 20_000;
|
|
13
|
-
const MAX_INLINE_PREVIEW_CHARS = 4_000;
|
|
14
|
-
const PROGRESS_RATE_LIMIT_MS = 50;
|
|
15
|
-
const CONTEXT_DIAGNOSTICS_CHANNEL = channel('filesystem-mcp:context');
|
|
16
|
-
// W3C Trace Context: version-traceid-parentid-traceflags
|
|
17
|
-
const TRACEPARENT_RE = /^[\da-f]{2}-[\da-f]{32}-[\da-f]{16}-[\da-f]{2}$/i;
|
|
18
|
-
function extractTraceContext(meta) {
|
|
19
|
-
const tp = meta?.traceparent;
|
|
20
|
-
if (typeof tp !== 'string' || !TRACEPARENT_RE.test(tp))
|
|
21
|
-
return undefined;
|
|
22
|
-
return {
|
|
23
|
-
traceparent: tp,
|
|
24
|
-
...(typeof meta?.tracestate === 'string'
|
|
25
|
-
? { tracestate: meta.tracestate }
|
|
26
|
-
: {}),
|
|
27
|
-
...(typeof meta?.baggage === 'string' ? { baggage: meta.baggage } : {}),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function publishContextDiagnostics(event) {
|
|
31
|
-
if (!CONTEXT_DIAGNOSTICS_CHANNEL.hasSubscribers)
|
|
32
|
-
return;
|
|
33
|
-
CONTEXT_DIAGNOSTICS_CHANNEL.publish(event);
|
|
34
|
-
}
|
|
35
|
-
export const READ_ONLY_TOOL_ANNOTATIONS = {
|
|
36
|
-
readOnlyHint: true,
|
|
37
|
-
idempotentHint: true,
|
|
38
|
-
destructiveHint: false,
|
|
39
|
-
openWorldHint: false,
|
|
40
|
-
};
|
|
41
|
-
export const DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS = {
|
|
42
|
-
readOnlyHint: false,
|
|
43
|
-
idempotentHint: false,
|
|
44
|
-
destructiveHint: true,
|
|
45
|
-
openWorldHint: false,
|
|
46
|
-
};
|
|
47
|
-
export const IDEMPOTENT_WRITE_TOOL_ANNOTATIONS = {
|
|
48
|
-
readOnlyHint: false,
|
|
49
|
-
idempotentHint: true,
|
|
50
|
-
destructiveHint: false,
|
|
51
|
-
openWorldHint: false,
|
|
52
|
-
};
|
|
53
|
-
function isTaskSupportLevel(value) {
|
|
54
|
-
return value === 'optional' || value === 'required' || value === 'forbidden';
|
|
55
|
-
}
|
|
56
|
-
function getExecutionConfig(candidate) {
|
|
57
|
-
const { execution } = candidate;
|
|
58
|
-
return execution && typeof execution === 'object'
|
|
59
|
-
? execution
|
|
60
|
-
: undefined;
|
|
61
|
-
}
|
|
62
|
-
export function resolveToolTaskSupportLevel(topLevelTaskSupport, executionTaskSupport) {
|
|
63
|
-
if (isTaskSupportLevel(topLevelTaskSupport)) {
|
|
64
|
-
return topLevelTaskSupport;
|
|
65
|
-
}
|
|
66
|
-
if (isTaskSupportLevel(executionTaskSupport)) {
|
|
67
|
-
return executionTaskSupport;
|
|
68
|
-
}
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
function buildNormalizedExecution(existingExecution, taskSupport) {
|
|
72
|
-
if (taskSupport === undefined && existingExecution === undefined) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
...(existingExecution ?? {}),
|
|
77
|
-
...(taskSupport !== undefined ? { taskSupport } : {}),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function normalizeToolExecution(tool) {
|
|
81
|
-
const candidate = tool;
|
|
82
|
-
const topLevelTaskSupport = candidate['taskSupport'];
|
|
83
|
-
const existingExecution = getExecutionConfig(candidate);
|
|
84
|
-
const resolvedTaskSupport = resolveToolTaskSupportLevel(topLevelTaskSupport, existingExecution?.['taskSupport']);
|
|
85
|
-
if (resolvedTaskSupport === undefined && topLevelTaskSupport === undefined) {
|
|
86
|
-
return tool;
|
|
87
|
-
}
|
|
88
|
-
const normalized = { ...candidate };
|
|
89
|
-
delete normalized['taskSupport'];
|
|
90
|
-
const execution = buildNormalizedExecution(existingExecution, resolvedTaskSupport);
|
|
91
|
-
if (execution !== undefined) {
|
|
92
|
-
normalized['execution'] = execution;
|
|
93
|
-
}
|
|
94
|
-
return normalized;
|
|
95
|
-
}
|
|
96
|
-
function shouldStripStructuredOutput() {
|
|
97
|
-
return parseTrueEnvFlag(process.env['FS_CONTEXT_STRIP_STRUCTURED']);
|
|
98
|
-
}
|
|
99
|
-
export function maybeStripStructuredContentFromResult(result) {
|
|
100
|
-
if (!shouldStripStructuredOutput())
|
|
101
|
-
return result;
|
|
102
|
-
if (!Object.hasOwn(result, 'structuredContent'))
|
|
103
|
-
return result;
|
|
104
|
-
const stripped = Object.fromEntries(Object.entries(result).filter(([key]) => key !== 'structuredContent'));
|
|
105
|
-
return stripped;
|
|
106
|
-
}
|
|
107
|
-
function maybeStripOutputSchema(tool) {
|
|
108
|
-
if (!shouldStripStructuredOutput())
|
|
109
|
-
return tool;
|
|
110
|
-
if (!Object.hasOwn(tool, 'outputSchema'))
|
|
111
|
-
return tool;
|
|
112
|
-
const stripped = Object.fromEntries(Object.entries(tool).filter(([key]) => key !== 'outputSchema'));
|
|
113
|
-
return stripped;
|
|
114
|
-
}
|
|
115
|
-
function buildTextPreview(text) {
|
|
116
|
-
if (text.length <= MAX_INLINE_PREVIEW_CHARS)
|
|
117
|
-
return text;
|
|
118
|
-
return `${text.slice(0, MAX_INLINE_PREVIEW_CHARS)}\n… [truncated preview]`;
|
|
119
|
-
}
|
|
120
|
-
export function maybeExternalizeTextContent(resourceStore, content, params) {
|
|
121
|
-
if (!resourceStore)
|
|
122
|
-
return undefined;
|
|
123
|
-
if (content.length <= MAX_INLINE_CONTENT_CHARS)
|
|
124
|
-
return undefined;
|
|
125
|
-
const entry = resourceStore.putText({
|
|
126
|
-
name: params.name,
|
|
127
|
-
...(params.mimeType !== undefined ? { mimeType: params.mimeType } : {}),
|
|
128
|
-
text: content,
|
|
129
|
-
});
|
|
130
|
-
publishContextDiagnostics({
|
|
131
|
-
phase: 'externalize_text',
|
|
132
|
-
name: params.name,
|
|
133
|
-
...(params.mimeType !== undefined ? { mimeType: params.mimeType } : {}),
|
|
134
|
-
chars: content.length,
|
|
135
|
-
uri: entry.uri,
|
|
136
|
-
});
|
|
137
|
-
Logger.debug(`Content externalized: ${params.name} (${content.length} chars) → ${entry.uri}`);
|
|
138
|
-
return {
|
|
139
|
-
entry,
|
|
140
|
-
preview: buildTextPreview(content),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
export function buildResourceLink(params) {
|
|
144
|
-
const descParts = [];
|
|
145
|
-
if (params.description)
|
|
146
|
-
descParts.push(params.description);
|
|
147
|
-
if (params.expiresAt)
|
|
148
|
-
descParts.push(`Expires: ${params.expiresAt}`);
|
|
149
|
-
const description = descParts.length > 0 ? descParts.join(' · ') : undefined;
|
|
150
|
-
return {
|
|
151
|
-
type: 'resource_link',
|
|
152
|
-
uri: params.uri,
|
|
153
|
-
name: params.name,
|
|
154
|
-
...(description ? { description } : {}),
|
|
155
|
-
...(params.mimeType ? { mimeType: params.mimeType } : {}),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
function resolveDetailedError(error, defaultCode, path) {
|
|
159
|
-
const detailed = createDetailedError(error, path);
|
|
160
|
-
if (detailed.code === ErrorCode.UNKNOWN) {
|
|
161
|
-
detailed.code = defaultCode;
|
|
162
|
-
const suggestion = getSuggestion(defaultCode);
|
|
163
|
-
if (suggestion) {
|
|
164
|
-
detailed.suggestion = suggestion;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return detailed;
|
|
168
|
-
}
|
|
169
|
-
export function buildStructuredError(error, defaultCode, path) {
|
|
170
|
-
const detailed = resolveDetailedError(error, defaultCode, path);
|
|
171
|
-
return {
|
|
172
|
-
code: detailed.code,
|
|
173
|
-
message: detailed.message,
|
|
174
|
-
...(detailed.path !== undefined ? { path: detailed.path } : {}),
|
|
175
|
-
...(detailed.suggestion !== undefined
|
|
176
|
-
? { suggestion: detailed.suggestion }
|
|
177
|
-
: {}),
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
export function buildToolResponse(text, structuredContent, extraContent = []) {
|
|
181
|
-
return {
|
|
182
|
-
content: [{ type: 'text', text }, ...extraContent],
|
|
183
|
-
structuredContent,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function validateStructuredContent(toolName, outputSchema, structuredContent) {
|
|
187
|
-
const parsed = outputSchema.safeParse(structuredContent);
|
|
188
|
-
if (parsed.success) {
|
|
189
|
-
return parsed.data;
|
|
190
|
-
}
|
|
191
|
-
throw new McpError(ErrorCode.UNKNOWN, `Tool "${toolName}" returned invalid structuredContent.`, undefined, { errors: z.treeifyError(parsed.error) });
|
|
192
|
-
}
|
|
193
|
-
function validateToolResponse(toolName, result, outputSchema) {
|
|
194
|
-
if (!outputSchema)
|
|
195
|
-
return result;
|
|
196
|
-
if (!Object.hasOwn(result, 'structuredContent')) {
|
|
197
|
-
throw new McpError(ErrorCode.UNKNOWN, `Tool "${toolName}" returned success without structuredContent.`);
|
|
198
|
-
}
|
|
199
|
-
return {
|
|
200
|
-
...result,
|
|
201
|
-
structuredContent: validateStructuredContent(toolName, outputSchema, result.structuredContent),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function parseToolArgs(schema, args) {
|
|
205
|
-
const candidate = args === undefined ? {} : args;
|
|
206
|
-
const parsed = schema.safeParse(candidate);
|
|
207
|
-
if (parsed.success) {
|
|
208
|
-
return parsed.data;
|
|
209
|
-
}
|
|
210
|
-
throw new McpError(ErrorCode.INVALID_INPUT, `Invalid tool arguments:\n${z.prettifyError(parsed.error)}`);
|
|
211
|
-
}
|
|
212
|
-
export function withValidatedArgs(schema, handler) {
|
|
213
|
-
return async (args, ctx) => {
|
|
214
|
-
try {
|
|
215
|
-
const normalizedArgs = parseToolArgs(schema, args);
|
|
216
|
-
return await handler(normalizedArgs, toToolContext(ctx));
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
219
|
-
if (error instanceof McpError && error.code === ErrorCode.INVALID_INPUT) {
|
|
220
|
-
return buildToolErrorResponse(error, ErrorCode.INVALID_INPUT);
|
|
221
|
-
}
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
export function toToolContext(ctx) {
|
|
227
|
-
if (!ctx)
|
|
228
|
-
return {};
|
|
229
|
-
if ('mcpReq' in ctx) {
|
|
230
|
-
return {
|
|
231
|
-
signal: ctx.mcpReq.signal,
|
|
232
|
-
...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),
|
|
233
|
-
...(ctx.mcpReq._meta
|
|
234
|
-
? { _meta: ctx.mcpReq._meta }
|
|
235
|
-
: {}),
|
|
236
|
-
sendNotification: async (notification) => ctx.mcpReq.notify(notification),
|
|
237
|
-
log: async (level, data, logger) => ctx.mcpReq.log(level, data, logger),
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
return ctx;
|
|
241
|
-
}
|
|
242
|
-
function canSendProgress(ctx) {
|
|
243
|
-
return (ctx._meta?.progressToken !== undefined && ctx.sendNotification !== undefined);
|
|
244
|
-
}
|
|
245
|
-
function canReportProgress(ctx) {
|
|
246
|
-
const taskExtra = ctx;
|
|
247
|
-
const hasTask = taskExtra.taskId !== undefined && taskExtra.taskStore !== undefined;
|
|
248
|
-
return canSendProgress(ctx) || hasTask;
|
|
249
|
-
}
|
|
250
|
-
export function withDefaultIcons(tool, iconInfo) {
|
|
251
|
-
const normalizedTool = normalizeToolExecution(tool);
|
|
252
|
-
if (!iconInfo) {
|
|
253
|
-
return maybeStripOutputSchema(normalizedTool);
|
|
254
|
-
}
|
|
255
|
-
const existingIcons = normalizedTool.icons;
|
|
256
|
-
if (existingIcons && existingIcons.length > 0) {
|
|
257
|
-
return maybeStripOutputSchema(normalizedTool);
|
|
258
|
-
}
|
|
259
|
-
const withIcons = {
|
|
260
|
-
...normalizedTool,
|
|
261
|
-
icons: [
|
|
262
|
-
{
|
|
263
|
-
src: iconInfo.src,
|
|
264
|
-
mimeType: iconInfo.mimeType,
|
|
265
|
-
},
|
|
266
|
-
],
|
|
267
|
-
};
|
|
268
|
-
return maybeStripOutputSchema(withIcons);
|
|
269
|
-
}
|
|
270
|
-
export function buildFileInfoPayload(info) {
|
|
271
|
-
return {
|
|
272
|
-
name: info.name,
|
|
273
|
-
path: info.path,
|
|
274
|
-
type: info.type,
|
|
275
|
-
size: info.size,
|
|
276
|
-
...(info.tokenEstimate !== undefined
|
|
277
|
-
? { tokenEstimate: info.tokenEstimate }
|
|
278
|
-
: {}),
|
|
279
|
-
created: info.created.toISOString(),
|
|
280
|
-
modified: info.modified.toISOString(),
|
|
281
|
-
accessed: info.accessed.toISOString(),
|
|
282
|
-
permissions: info.permissions,
|
|
283
|
-
isHidden: info.isHidden,
|
|
284
|
-
...(info.mimeType !== undefined ? { mimeType: info.mimeType } : {}),
|
|
285
|
-
...(info.symlinkTarget !== undefined
|
|
286
|
-
? { symlinkTarget: info.symlinkTarget }
|
|
287
|
-
: {}),
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
const NOT_INITIALIZED_ERROR = new McpError(ErrorCode.INVALID_INPUT, 'Client not initialized; wait for notifications/initialized');
|
|
291
|
-
async function withToolErrorHandling(run, onError) {
|
|
292
|
-
try {
|
|
293
|
-
return await run();
|
|
294
|
-
}
|
|
295
|
-
catch (error) {
|
|
296
|
-
return onError(error);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
function getToolSignal(extraSignal, timedSignal) {
|
|
300
|
-
if (!timedSignal) {
|
|
301
|
-
return { signal: extraSignal, cleanup: () => { } };
|
|
302
|
-
}
|
|
303
|
-
const { signal, cleanup } = createTimedAbortSignal(extraSignal, timedSignal.timeoutMs);
|
|
304
|
-
return { signal, cleanup };
|
|
305
|
-
}
|
|
306
|
-
export async function executeToolWithDiagnostics(options) {
|
|
307
|
-
const traceContext = extractTraceContext(options.ctx._meta);
|
|
308
|
-
return withToolDiagnostics(options.toolName, () => withToolErrorHandling(async () => {
|
|
309
|
-
const { signal, cleanup } = getToolSignal(options.ctx.signal, options.timedSignal);
|
|
310
|
-
try {
|
|
311
|
-
return validateToolResponse(options.toolName, await options.run(signal), options.outputSchema);
|
|
312
|
-
}
|
|
313
|
-
finally {
|
|
314
|
-
cleanup();
|
|
315
|
-
}
|
|
316
|
-
}, options.onError), {
|
|
317
|
-
...options.context,
|
|
318
|
-
...(traceContext ? { traceContext } : {}),
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
export function buildToolErrorResponse(error, defaultCode, path) {
|
|
322
|
-
const detailed = resolveDetailedError(error, defaultCode, path);
|
|
323
|
-
const text = formatDetailedError(detailed);
|
|
324
|
-
return {
|
|
325
|
-
content: [{ type: 'text', text }],
|
|
326
|
-
isError: true,
|
|
327
|
-
errorCode: detailed.code,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
function buildNotInitializedResult() {
|
|
331
|
-
return buildToolErrorResponse(NOT_INITIALIZED_ERROR, ErrorCode.INVALID_INPUT);
|
|
332
|
-
}
|
|
333
|
-
async function reportProgress(ctx, progress) {
|
|
334
|
-
await updateTaskStoreProgress(ctx, progress);
|
|
335
|
-
await sendMcpProgressNotification(ctx, progress);
|
|
336
|
-
}
|
|
337
|
-
function formatTaskStatusMessage(progress) {
|
|
338
|
-
if (progress.total !== undefined) {
|
|
339
|
-
return progress.message
|
|
340
|
-
? `${progress.message} (${progress.current}/${progress.total})`
|
|
341
|
-
: `${progress.current}/${progress.total}`;
|
|
342
|
-
}
|
|
343
|
-
return progress.message ?? `${progress.current}`;
|
|
344
|
-
}
|
|
345
|
-
function isBenignTaskStatusUpdateError(error) {
|
|
346
|
-
return (error instanceof Error &&
|
|
347
|
-
/Task .*not found|terminal status/iu.test(error.message));
|
|
348
|
-
}
|
|
349
|
-
async function updateTaskStoreProgress(ctx, progress) {
|
|
350
|
-
const taskExtra = ctx;
|
|
351
|
-
if (typeof taskExtra.taskId === 'string' &&
|
|
352
|
-
taskExtra.taskStore !== undefined &&
|
|
353
|
-
taskExtra.taskStore !== null) {
|
|
354
|
-
const store = taskExtra.taskStore;
|
|
355
|
-
if (typeof store.updateTaskStatus === 'function') {
|
|
356
|
-
try {
|
|
357
|
-
await store.updateTaskStatus(taskExtra.taskId, 'working', formatTaskStatusMessage(progress));
|
|
358
|
-
}
|
|
359
|
-
catch (error) {
|
|
360
|
-
if (isBenignTaskStatusUpdateError(error))
|
|
361
|
-
return;
|
|
362
|
-
Logger.error('Failed to update task status message:', error);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async function sendMcpProgressNotification(ctx, progress) {
|
|
368
|
-
if (canSendProgress(ctx)) {
|
|
369
|
-
try {
|
|
370
|
-
await ctx.sendNotification({
|
|
371
|
-
method: 'notifications/progress',
|
|
372
|
-
params: {
|
|
373
|
-
progressToken: ctx._meta.progressToken,
|
|
374
|
-
progress: progress.current,
|
|
375
|
-
...(progress.total !== undefined ? { total: progress.total } : {}),
|
|
376
|
-
...(progress.message !== undefined
|
|
377
|
-
? { message: progress.message }
|
|
378
|
-
: {}),
|
|
379
|
-
},
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
Logger.error('Failed to send progress notification:', error);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
export function createProgressReporter(ctx) {
|
|
388
|
-
if (!canReportProgress(ctx)) {
|
|
389
|
-
return () => { };
|
|
390
|
-
}
|
|
391
|
-
// State for monotonic enforcement and rate-limiting.
|
|
392
|
-
let lastProgress = -1;
|
|
393
|
-
let lastSentMs = 0;
|
|
394
|
-
return (progress) => {
|
|
395
|
-
const { current, total, message } = progress;
|
|
396
|
-
// Enforce monotonic progress to prevent client confusion. Client behavior on
|
|
397
|
-
// out-of-order progress is undefined in the MCP spec.
|
|
398
|
-
if (current <= lastProgress)
|
|
399
|
-
return;
|
|
400
|
-
// Terminal notifications always bypass the rate limit so clients reliably
|
|
401
|
-
// receive the final state even when updates arrive in quick succession.
|
|
402
|
-
const isTerminal = total !== undefined && current >= total;
|
|
403
|
-
const now = Date.now();
|
|
404
|
-
if (!isTerminal && now - lastSentMs < PROGRESS_RATE_LIMIT_MS)
|
|
405
|
-
return;
|
|
406
|
-
lastProgress = current;
|
|
407
|
-
lastSentMs = now;
|
|
408
|
-
void reportProgress(ctx, {
|
|
409
|
-
current,
|
|
410
|
-
...(total !== undefined ? { total } : {}),
|
|
411
|
-
...(message !== undefined ? { message } : {}),
|
|
412
|
-
});
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
export function notifyProgress(ctx, progress) {
|
|
416
|
-
if (!canReportProgress(ctx))
|
|
417
|
-
return;
|
|
418
|
-
void reportProgress(ctx, progress);
|
|
419
|
-
}
|
|
420
|
-
export function createToolProgressSession(ctx, startMessage, initialTotal) {
|
|
421
|
-
notifyProgress(ctx, {
|
|
422
|
-
current: 0,
|
|
423
|
-
...(initialTotal !== undefined ? { total: initialTotal } : {}),
|
|
424
|
-
message: startMessage,
|
|
425
|
-
});
|
|
426
|
-
let cursor = 0;
|
|
427
|
-
const baseReporter = createProgressReporter(ctx);
|
|
428
|
-
const setCursor = (value) => {
|
|
429
|
-
if (value > cursor)
|
|
430
|
-
cursor = value;
|
|
431
|
-
return cursor;
|
|
432
|
-
};
|
|
433
|
-
const finishProgress = (message, minimumCurrent) => {
|
|
434
|
-
const finalCurrent = Math.max(cursor + 1, minimumCurrent ?? 1, 1);
|
|
435
|
-
notifyProgress(ctx, {
|
|
436
|
-
current: finalCurrent,
|
|
437
|
-
total: finalCurrent,
|
|
438
|
-
...(message !== undefined ? { message } : {}),
|
|
439
|
-
});
|
|
440
|
-
cursor = finalCurrent;
|
|
441
|
-
};
|
|
442
|
-
return {
|
|
443
|
-
update: ({ current, total, message }) => {
|
|
444
|
-
const normalized = setCursor(current);
|
|
445
|
-
baseReporter({
|
|
446
|
-
current: normalized,
|
|
447
|
-
...(total !== undefined ? { total } : {}),
|
|
448
|
-
message,
|
|
449
|
-
});
|
|
450
|
-
},
|
|
451
|
-
increment: (messageForCurrent) => {
|
|
452
|
-
const next = setCursor(cursor + 1);
|
|
453
|
-
baseReporter({
|
|
454
|
-
current: next,
|
|
455
|
-
message: messageForCurrent(next),
|
|
456
|
-
});
|
|
457
|
-
},
|
|
458
|
-
complete: finishProgress,
|
|
459
|
-
fail: finishProgress,
|
|
460
|
-
getCurrent: () => cursor,
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
export function createBatchProgressCallbacks(ctx, params) {
|
|
464
|
-
const progress = createToolProgressSession(ctx, `${params.toolLabel}: ${params.context}`, params.totalItems);
|
|
465
|
-
let itemsDone = 0;
|
|
466
|
-
const onItemComplete = () => {
|
|
467
|
-
itemsDone++;
|
|
468
|
-
progress.update({
|
|
469
|
-
current: itemsDone,
|
|
470
|
-
total: params.totalItems,
|
|
471
|
-
message: `${params.toolLabel}: ${params.context} [${itemsDone}/${params.totalItems} ${params.itemVerb}]`,
|
|
472
|
-
});
|
|
473
|
-
};
|
|
474
|
-
return { progress, onItemComplete };
|
|
475
|
-
}
|
|
476
|
-
export function resolveFinalProgressCurrent(progress, ...candidates) {
|
|
477
|
-
let finalCurrent = progress.getCurrent() + 1;
|
|
478
|
-
for (const candidate of candidates) {
|
|
479
|
-
if (candidate > finalCurrent) {
|
|
480
|
-
finalCurrent = candidate;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
return finalCurrent;
|
|
484
|
-
}
|
|
485
|
-
async function withProgress(message, ctx, run, getCompletionMessage) {
|
|
486
|
-
if (!canReportProgress(ctx)) {
|
|
487
|
-
return run();
|
|
488
|
-
}
|
|
489
|
-
const total = 1;
|
|
490
|
-
// Emit the start notification only when a progressToken is present; for
|
|
491
|
-
// task-only mode the task status is already 'working' — a zero-progress
|
|
492
|
-
// notification would add unnecessary overhead without client value.
|
|
493
|
-
if (canSendProgress(ctx)) {
|
|
494
|
-
await reportProgress(ctx, { current: 0, total, message });
|
|
495
|
-
}
|
|
496
|
-
try {
|
|
497
|
-
const result = await run();
|
|
498
|
-
const endMessage = getCompletionMessage?.(result) ?? message;
|
|
499
|
-
await reportProgress(ctx, {
|
|
500
|
-
current: total,
|
|
501
|
-
total,
|
|
502
|
-
message: endMessage,
|
|
503
|
-
});
|
|
504
|
-
return result;
|
|
505
|
-
}
|
|
506
|
-
catch (error) {
|
|
507
|
-
void reportProgress(ctx, {
|
|
508
|
-
current: total,
|
|
509
|
-
total,
|
|
510
|
-
message: `${message} • ${classifyError(error)}`,
|
|
511
|
-
});
|
|
512
|
-
throw error;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
export function wrapToolHandler(handler, options) {
|
|
516
|
-
return async (args, ctx) => {
|
|
517
|
-
const resolvedExtra = toToolContext(ctx);
|
|
518
|
-
if (options.guard && !options.guard()) {
|
|
519
|
-
return maybeStripStructuredContentFromResult(buildNotInitializedResult());
|
|
520
|
-
}
|
|
521
|
-
if (options.progressMessage) {
|
|
522
|
-
const message = options.progressMessage(args);
|
|
523
|
-
const { completionMessage } = options;
|
|
524
|
-
const completionFn = completionMessage
|
|
525
|
-
? (result) => completionMessage(args, result)
|
|
526
|
-
: undefined;
|
|
527
|
-
const result = await withProgress(message, resolvedExtra, () => handler(args, resolvedExtra), completionFn);
|
|
528
|
-
return maybeStripStructuredContentFromResult(result);
|
|
529
|
-
}
|
|
530
|
-
const result = await handler(args, resolvedExtra);
|
|
531
|
-
return maybeStripStructuredContentFromResult(result);
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* Returns `pathValue` if non-empty; otherwise resolves to the single allowed
|
|
536
|
-
* directory from module-level state managed by `RootsManager`. Throws when the
|
|
537
|
-
* path is ambiguous (multiple roots) or when no roots are configured.
|
|
538
|
-
*
|
|
539
|
-
* NOTE: Depends on `getAllowedDirectories()` which reads module-level state
|
|
540
|
-
* updated by `RootsManager`. Ensure the server is initialized before calling.
|
|
541
|
-
* See `src/server/roots-manager.ts` for the update lifecycle.
|
|
542
|
-
*/
|
|
543
|
-
export function resolvePathOrRoot(pathValue) {
|
|
544
|
-
if (pathValue && pathValue.trim().length > 0)
|
|
545
|
-
return pathValue;
|
|
546
|
-
const roots = getAllowedDirectories();
|
|
547
|
-
if (roots.length === 0) {
|
|
548
|
-
throw new McpError(ErrorCode.ACCESS_DENIED, 'No roots configured. Use roots tool, --allow-cwd, or MCP Roots protocol.');
|
|
549
|
-
}
|
|
550
|
-
if (roots.length > 1) {
|
|
551
|
-
throw new McpError(ErrorCode.INVALID_INPUT, 'Multiple roots configured. Provide an explicit path.');
|
|
552
|
-
}
|
|
553
|
-
const root = roots[0];
|
|
554
|
-
if (!root) {
|
|
555
|
-
throw new McpError(ErrorCode.ACCESS_DENIED, 'Workspace root is unexpectedly undefined');
|
|
556
|
-
}
|
|
557
|
-
return root;
|
|
558
|
-
}
|
|
559
|
-
const OffsetCursorSchema = z.strictObject({
|
|
560
|
-
offset: z.int().min(0),
|
|
561
|
-
});
|
|
562
|
-
const OffsetCursorCodec = createBase64JsonCodec(OffsetCursorSchema);
|
|
563
|
-
export function encodeOffsetCursor(offset) {
|
|
564
|
-
return z.encode(OffsetCursorCodec, { offset });
|
|
565
|
-
}
|
|
566
|
-
export function decodeOffsetCursor(cursor) {
|
|
567
|
-
try {
|
|
568
|
-
return OffsetCursorCodec.parse(cursor).offset;
|
|
569
|
-
}
|
|
570
|
-
catch {
|
|
571
|
-
// fall through to throw
|
|
572
|
-
}
|
|
573
|
-
throw new McpError(ErrorCode.INVALID_INPUT, `Invalid cursor. Request the first page without a cursor.`);
|
|
574
|
-
}
|
|
575
|
-
export function buildBatchPathContext(paths, unitLabel = 'paths') {
|
|
576
|
-
const normalizedLabel = paths.length === 1 ? unitLabel.replace(/s$/i, '') : unitLabel;
|
|
577
|
-
const first = basename(paths[0] ?? '');
|
|
578
|
-
let extraPaths = '';
|
|
579
|
-
if (paths.length > 1) {
|
|
580
|
-
const secondPath = basename(paths[1] ?? '');
|
|
581
|
-
const ellipsis = paths.length > 2 ? '…' : '';
|
|
582
|
-
extraPaths = `, ${secondPath}${ellipsis}`;
|
|
583
|
-
}
|
|
584
|
-
return `${paths.length} ${normalizedLabel} [${first}${extraPaths}]`;
|
|
585
|
-
}
|
|
586
|
-
export function truncateProgressPattern(pattern, maxLength = 40) {
|
|
587
|
-
if (pattern.length <= maxLength)
|
|
588
|
-
return pattern;
|
|
589
|
-
if (pattern.includes('|')) {
|
|
590
|
-
const segments = pattern.split('|');
|
|
591
|
-
const first = segments[0] ?? '';
|
|
592
|
-
const second = segments[1];
|
|
593
|
-
const preview = second !== undefined ? `${first}|${second}` : first;
|
|
594
|
-
return preview.length <= maxLength
|
|
595
|
-
? `${preview}…`
|
|
596
|
-
: `${preview.slice(0, maxLength)}…`;
|
|
597
|
-
}
|
|
598
|
-
return `${pattern.slice(0, maxLength)}…`;
|
|
599
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
-
import { type ToolContract, type ToolRegistrationOptions } from './shared.js';
|
|
3
|
-
export declare const GET_MULTIPLE_FILE_INFO_TOOL: ToolContract;
|
|
4
|
-
export declare function registerGetMultipleFileInfoTool(server: McpServer, options?: ToolRegistrationOptions): void;
|