@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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DEFAULT_SEARCH_CONTENT_RESULTS, getMaxTextFileSize, MAX_SEARCH_RESULTS, } from './core/util.js';
|
|
2
|
+
import { GET_FILE_INFO, LIST, LIST_ALLOWED_DIRECTORIES, MUTATING_TOOL_NAMES, READ_FILE, SEARCH_CONTENT, SEARCH_FILES, } from './tools/index.js';
|
|
3
|
+
function buildToolsOverview(readOnly) {
|
|
4
|
+
const rows = [
|
|
5
|
+
['Navigate', [LIST_ALLOWED_DIRECTORIES.name, LIST.name, SEARCH_FILES.name]],
|
|
6
|
+
['Inspect', [GET_FILE_INFO.name, SEARCH_CONTENT.name]],
|
|
7
|
+
['Read', [READ_FILE.name]],
|
|
8
|
+
];
|
|
9
|
+
// Under --read-only the mutating tools are never registered, so advertising
|
|
10
|
+
// them here would point the model at tools that are not there. Drop the row
|
|
11
|
+
// rather than emit an empty one.
|
|
12
|
+
if (!readOnly) {
|
|
13
|
+
rows.push(['Write', [...MUTATING_TOOL_NAMES]]);
|
|
14
|
+
}
|
|
15
|
+
const rowLines = rows.map(([cat, names]) => `${cat}: ${names.join(', ')}`);
|
|
16
|
+
return `\`\`\`\n${rowLines.join('\n')}\n\`\`\``;
|
|
17
|
+
}
|
|
18
|
+
export const INSTRUCTIONS_URI = 'internal://instructions';
|
|
19
|
+
export const NO_POSITIONAL_ROOTS_GUIDANCE = 'No positional directories specified. Configure roots with directory arguments, FS_ALLOWED_DIRS, or --allow-cwd. Modern clients with elicitation can also call a tool with a concrete path and approve the requested grant.';
|
|
20
|
+
/**
|
|
21
|
+
* The one statement of what this server is and how to approach it. The server's
|
|
22
|
+
* `instructions`, the `get-help` prompt, and the instructions resource all
|
|
23
|
+
* describe the same document, and three hand-maintained paraphrases of it drift
|
|
24
|
+
* against each other and cost the client the same sentence three times.
|
|
25
|
+
*/
|
|
26
|
+
export const INSTRUCTIONS_SUMMARY = 'Navigation guide for filesystem-mcp tools and constraints. ' +
|
|
27
|
+
'Use list_roots to inspect configured or accepted roots, then list/find_files -> stat -> read. Never guess paths.';
|
|
28
|
+
export function buildSectionsRecord(readOnly) {
|
|
29
|
+
const maxFileMb = Math.floor(getMaxTextFileSize() / 1024 / 1024);
|
|
30
|
+
return {
|
|
31
|
+
guidelines: [
|
|
32
|
+
'Guidelines:',
|
|
33
|
+
'```',
|
|
34
|
+
`root_access: ${LIST_ALLOWED_DIRECTORIES.name} lists configured or accepted roots; every other tool is scoped to them.`,
|
|
35
|
+
'modern_root_grants: Modern clients do not automatically send workspace roots. Call a tool with a concrete path and approve its grant when elicitation is available.',
|
|
36
|
+
`path_resolution: Confirm a path with ${LIST.name} or ${SEARCH_FILES.name} before acting on it.`,
|
|
37
|
+
'```',
|
|
38
|
+
].join('\n'),
|
|
39
|
+
tools_overview: [
|
|
40
|
+
'Tools Overview:',
|
|
41
|
+
buildToolsOverview(readOnly),
|
|
42
|
+
'',
|
|
43
|
+
'Full schemas, descriptions, and annotations are in `tools/list`.',
|
|
44
|
+
].join('\n'),
|
|
45
|
+
constraints: [
|
|
46
|
+
'Constraints:',
|
|
47
|
+
'```',
|
|
48
|
+
`allowed_roots: Startup roots come from CLI paths, FS_ALLOWED_DIRS, or --allow-cwd; accepted modern grants are additive. Call ${LIST_ALLOWED_DIRECTORIES.name} to read the current set.`,
|
|
49
|
+
'legacy_roots: Legacy clients may additionally seed roots through the deprecated roots/list flow.',
|
|
50
|
+
'sensitive_paths: Sensitive file paths (.env, *.pem, *id_rsa*) are denied by default.',
|
|
51
|
+
`enforced_limits: max file size ${maxFileMb} MB, file search cap ${MAX_SEARCH_RESULTS} results, content search cap ${DEFAULT_SEARCH_CONTENT_RESULTS} matches.`,
|
|
52
|
+
'ephemeral_results: When a tool returns resourceUri, call resources/read immediately — cached results are ephemeral and expire after ~60 seconds, eviction, or restart.',
|
|
53
|
+
'pagination: nextCursor is backed by a snapshot on the same ~60s clock. Page through promptly; if a cursor is rejected, start again without one. resourceUri appears on the first page only.',
|
|
54
|
+
'```',
|
|
55
|
+
].join('\n'),
|
|
56
|
+
error_recovery: [
|
|
57
|
+
'Error Recovery:',
|
|
58
|
+
'```',
|
|
59
|
+
`ACCESS_DENIED: Run ${LIST_ALLOWED_DIRECTORIES.name}; configure a missing startup root or retry a concrete path and approve the grant.`,
|
|
60
|
+
`NOT_FOUND: Run ${LIST.name} or ${SEARCH_FILES.name} to verify the path.`,
|
|
61
|
+
`TOO_LARGE: Use ${READ_FILE.name} with head/tail or startLine/endLine, or split across several calls.`,
|
|
62
|
+
'TIMEOUT: Reduce scope, depth, or maxResults.',
|
|
63
|
+
'INVALID_INPUT: Re-read the tool schema in tools/list.',
|
|
64
|
+
'```',
|
|
65
|
+
].join('\n'),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function renderSections(sections) {
|
|
69
|
+
return `\n${Object.values(sections).join('\n\n')}\n`;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=instructions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,SAAS,kBAAkB,CAAC,QAAiB;IAC3C,MAAM,IAAI,GAAyB;QACjC,CAAC,UAAU,EAAE,CAAC,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3E,CAAC,SAAS,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;KAC3B,CAAC;IAEF,4EAA4E;IAC5E,4EAA4E;IAC5E,iCAAiC;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,WAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAC1D,MAAM,CAAC,MAAM,4BAA4B,GACvC,4NAA4N,CAAC;AAE/N;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,6DAA6D;IAC7D,kHAAkH,CAAC;AAErH,MAAM,UAAU,mBAAmB,CAAC,QAAiB;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO;QACL,UAAU,EAAE;YACV,aAAa;YACb,KAAK;YACL,gBAAgB,wBAAwB,CAAC,IAAI,0EAA0E;YACvH,qKAAqK;YACrK,wCAAwC,IAAI,CAAC,IAAI,OAAO,YAAY,CAAC,IAAI,uBAAuB;YAChG,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EAAE;YACd,iBAAiB;YACjB,kBAAkB,CAAC,QAAQ,CAAC;YAC5B,EAAE;YACF,kEAAkE;SACnE,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,cAAc;YACd,KAAK;YACL,gIAAgI,wBAAwB,CAAC,IAAI,2BAA2B;YACxL,kGAAkG;YAClG,sFAAsF;YACtF,kCAAkC,SAAS,wBAAwB,kBAAkB,gCAAgC,8BAA8B,WAAW;YAC9J,wKAAwK;YACxK,6LAA6L;YAC7L,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EAAE;YACd,iBAAiB;YACjB,KAAK;YACL,sBAAsB,wBAAwB,CAAC,IAAI,oFAAoF;YACvI,kBAAkB,IAAI,CAAC,IAAI,OAAO,YAAY,CAAC,IAAI,sBAAsB;YACzE,kBAAkB,SAAS,CAAC,IAAI,sEAAsE;YACtG,8CAA8C;YAC9C,uDAAuD;YACvD,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgC;IAC7D,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AACvD,CAAC","sourcesContent":["import {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n getMaxTextFileSize,\n MAX_SEARCH_RESULTS,\n} from './core/util.js';\nimport {\n GET_FILE_INFO,\n LIST,\n LIST_ALLOWED_DIRECTORIES,\n MUTATING_TOOL_NAMES,\n READ_FILE,\n SEARCH_CONTENT,\n SEARCH_FILES,\n} from './tools/index.js';\n\nfunction buildToolsOverview(readOnly: boolean): string {\n const rows: [string, string[]][] = [\n ['Navigate', [LIST_ALLOWED_DIRECTORIES.name, LIST.name, SEARCH_FILES.name]],\n ['Inspect', [GET_FILE_INFO.name, SEARCH_CONTENT.name]],\n ['Read', [READ_FILE.name]],\n ];\n\n // Under --read-only the mutating tools are never registered, so advertising\n // them here would point the model at tools that are not there. Drop the row\n // rather than emit an empty one.\n if (!readOnly) {\n rows.push(['Write', [...MUTATING_TOOL_NAMES]]);\n }\n\n const rowLines = rows.map(([cat, names]) => `${cat}: ${names.join(', ')}`);\n return `\\`\\`\\`\\n${rowLines.join('\\n')}\\n\\`\\`\\``;\n}\n\nexport const INSTRUCTIONS_URI = 'internal://instructions';\nexport const NO_POSITIONAL_ROOTS_GUIDANCE =\n 'No positional directories specified. Configure roots with directory arguments, FS_ALLOWED_DIRS, or --allow-cwd. Modern clients with elicitation can also call a tool with a concrete path and approve the requested grant.';\n\n/**\n * The one statement of what this server is and how to approach it. The server's\n * `instructions`, the `get-help` prompt, and the instructions resource all\n * describe the same document, and three hand-maintained paraphrases of it drift\n * against each other and cost the client the same sentence three times.\n */\nexport const INSTRUCTIONS_SUMMARY =\n 'Navigation guide for filesystem-mcp tools and constraints. ' +\n 'Use list_roots to inspect configured or accepted roots, then list/find_files -> stat -> read. Never guess paths.';\n\nexport function buildSectionsRecord(readOnly: boolean): Record<string, string> {\n const maxFileMb = Math.floor(getMaxTextFileSize() / 1024 / 1024);\n return {\n guidelines: [\n 'Guidelines:',\n '```',\n `root_access: ${LIST_ALLOWED_DIRECTORIES.name} lists configured or accepted roots; every other tool is scoped to them.`,\n 'modern_root_grants: Modern clients do not automatically send workspace roots. Call a tool with a concrete path and approve its grant when elicitation is available.',\n `path_resolution: Confirm a path with ${LIST.name} or ${SEARCH_FILES.name} before acting on it.`,\n '```',\n ].join('\\n'),\n tools_overview: [\n 'Tools Overview:',\n buildToolsOverview(readOnly),\n '',\n 'Full schemas, descriptions, and annotations are in `tools/list`.',\n ].join('\\n'),\n constraints: [\n 'Constraints:',\n '```',\n `allowed_roots: Startup roots come from CLI paths, FS_ALLOWED_DIRS, or --allow-cwd; accepted modern grants are additive. Call ${LIST_ALLOWED_DIRECTORIES.name} to read the current set.`,\n 'legacy_roots: Legacy clients may additionally seed roots through the deprecated roots/list flow.',\n 'sensitive_paths: Sensitive file paths (.env, *.pem, *id_rsa*) are denied by default.',\n `enforced_limits: max file size ${maxFileMb} MB, file search cap ${MAX_SEARCH_RESULTS} results, content search cap ${DEFAULT_SEARCH_CONTENT_RESULTS} matches.`,\n 'ephemeral_results: When a tool returns resourceUri, call resources/read immediately — cached results are ephemeral and expire after ~60 seconds, eviction, or restart.',\n 'pagination: nextCursor is backed by a snapshot on the same ~60s clock. Page through promptly; if a cursor is rejected, start again without one. resourceUri appears on the first page only.',\n '```',\n ].join('\\n'),\n error_recovery: [\n 'Error Recovery:',\n '```',\n `ACCESS_DENIED: Run ${LIST_ALLOWED_DIRECTORIES.name}; configure a missing startup root or retry a concrete path and approve the grant.`,\n `NOT_FOUND: Run ${LIST.name} or ${SEARCH_FILES.name} to verify the path.`,\n `TOO_LARGE: Use ${READ_FILE.name} with head/tail or startLine/endLine, or split across several calls.`,\n 'TIMEOUT: Reduce scope, depth, or maxResults.',\n 'INVALID_INPUT: Re-read the tool schema in tools/list.',\n '```',\n ].join('\\n'),\n };\n}\n\nexport function renderSections(sections: Record<string, string>): string {\n return `\\n${Object.values(sections).join('\\n\\n')}\\n`;\n}\n"]}
|
package/dist/prompts.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare function
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
interface PromptRegistrarDeps {
|
|
3
|
+
readonly server: McpServer;
|
|
4
|
+
readonly readOnly?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function registerPrompts(deps: PromptRegistrarDeps): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EAGV,MAAM,8BAA8B,CAAC;AAkBtC,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AA+DD,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAoC/D"}
|
package/dist/prompts.js
CHANGED
|
@@ -1,177 +1,83 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return
|
|
21
|
-
const sections = instructions.split(/\n(?=## )/u);
|
|
22
|
-
const match = sections.find((sec) => sec.toLowerCase().startsWith(`## ${normalized}`));
|
|
23
|
-
if (match !== undefined)
|
|
24
|
-
return match;
|
|
25
|
-
const available = sections
|
|
26
|
-
.filter((sec) => sec.startsWith('## '))
|
|
27
|
-
.map((sec) => sec.split('\n')[0]?.replace(/^##\s*/u, '') ?? '')
|
|
28
|
-
.filter(Boolean)
|
|
29
|
-
.join(', ');
|
|
30
|
-
return `Section '${topic}' not found. Available: ${available}\n\n${instructions}`;
|
|
31
|
-
}
|
|
32
|
-
function findKnownToolName(rawName) {
|
|
33
|
-
const normalized = rawName.trim().toLowerCase();
|
|
34
|
-
if (!normalized)
|
|
35
|
-
return undefined;
|
|
36
|
-
return getSortedToolContracts().find((contract) => contract.name.toLowerCase() === normalized)?.name;
|
|
37
|
-
}
|
|
38
|
-
export function registerGetHelpPrompt(server, instructions, iconInfo) {
|
|
39
|
-
const baseConfig = withDefaultIcons({ title: HELP_PROMPT_TITLE, description: HELP_PROMPT_DESCRIPTION }, iconInfo);
|
|
40
|
-
server.registerPrompt(HELP_PROMPT_NAME, {
|
|
41
|
-
...baseConfig,
|
|
42
|
-
argsSchema: z.object({
|
|
43
|
-
topic: z
|
|
44
|
-
.string()
|
|
45
|
-
.optional()
|
|
46
|
-
.describe('Optional section heading prefix (example: "error handling"). Omit to return full instructions.'),
|
|
47
|
-
}),
|
|
48
|
-
}, ({ topic }) => {
|
|
49
|
-
const text = topic
|
|
50
|
-
? filterInstructionsByTopic(instructions, topic)
|
|
51
|
-
: instructions;
|
|
52
|
-
return {
|
|
53
|
-
description: HELP_PROMPT_DESCRIPTION,
|
|
54
|
-
messages: [
|
|
55
|
-
{
|
|
56
|
-
role: 'user',
|
|
57
|
-
content: {
|
|
58
|
-
type: 'text',
|
|
59
|
-
text,
|
|
60
|
-
annotations: {
|
|
61
|
-
audience: ['assistant'],
|
|
62
|
-
priority: 1,
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
};
|
|
1
|
+
import { completable, getDisplayName, ProtocolError } from '@modelcontextprotocol/server';
|
|
2
|
+
import * as z from 'zod/v4';
|
|
3
|
+
import { formatUnknownErrorMessage, fsErrorCode, hasErrorShape } from './core/errors.js';
|
|
4
|
+
import { Logger } from './core/observability.js';
|
|
5
|
+
import { isBlank, SHELL_METACHAR_RE } from './core/schema.js';
|
|
6
|
+
import { buildSectionsRecord, INSTRUCTIONS_SUMMARY, renderSections } from './instructions.js';
|
|
7
|
+
// --- Helpers ---
|
|
8
|
+
function topicArg(topics, description) {
|
|
9
|
+
return completable(z
|
|
10
|
+
.string()
|
|
11
|
+
.min(1, { message: 'Topic required' })
|
|
12
|
+
.refine((val) => !isBlank(val), {
|
|
13
|
+
message: 'Topic cannot be empty or whitespace-only',
|
|
14
|
+
})
|
|
15
|
+
.refine((val) => !SHELL_METACHAR_RE.test(val), {
|
|
16
|
+
message: 'Topic contains prohibited characters (newlines or shell metacharacters)',
|
|
17
|
+
})
|
|
18
|
+
.describe(description), (value) => {
|
|
19
|
+
const lower = value.toLowerCase();
|
|
20
|
+
return lower ? topics.filter((t) => t.startsWith(lower)) : [...topics];
|
|
68
21
|
});
|
|
69
22
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
original: z.string().describe('Path to the original file.'),
|
|
78
|
-
modified: z.string().describe('Path to the modified file.'),
|
|
79
|
-
}),
|
|
80
|
-
}, ({ original, modified }) => ({
|
|
81
|
-
description: COMPARE_FILES_PROMPT_DESCRIPTION,
|
|
82
|
-
messages: [
|
|
83
|
-
{
|
|
84
|
-
role: 'user',
|
|
85
|
-
content: {
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: `Compare files and explain differences.\n\n1. Call \`diff_files\` with:\n - original: ${original}\n - modified: ${modified}\n2. Summarize: additions, deletions, and semantic changes.\n3. Flag any potential issues (conflicts, regressions, breaking changes).`,
|
|
88
|
-
annotations: {
|
|
89
|
-
audience: ['assistant'],
|
|
90
|
-
priority: 1,
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
}));
|
|
23
|
+
function userText(text) {
|
|
24
|
+
const content = {
|
|
25
|
+
type: 'text',
|
|
26
|
+
text,
|
|
27
|
+
annotations: { audience: ['assistant'], priority: 1 },
|
|
28
|
+
};
|
|
29
|
+
return { role: 'user', content };
|
|
96
30
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
priority: 1,
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
}));
|
|
31
|
+
async function wrapHandler(contract, fn) {
|
|
32
|
+
const displayName = getDisplayName(contract);
|
|
33
|
+
try {
|
|
34
|
+
const result = await fn();
|
|
35
|
+
Logger.debug(`prompt resolved`, { name: contract.name, displayName });
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (hasErrorShape(error, 'ProtocolError'))
|
|
40
|
+
throw error;
|
|
41
|
+
const message = formatUnknownErrorMessage(error);
|
|
42
|
+
Logger.error(`Prompt handler failed: ${message}`, {
|
|
43
|
+
promptName: contract.name,
|
|
44
|
+
error,
|
|
45
|
+
});
|
|
46
|
+
const protocolError = new ProtocolError(fsErrorCode(error), message);
|
|
47
|
+
protocolError.cause = error;
|
|
48
|
+
throw protocolError;
|
|
49
|
+
}
|
|
122
50
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
51
|
+
// --- Prompt entries ---
|
|
52
|
+
const GET_HELP = {
|
|
53
|
+
name: 'get-help',
|
|
54
|
+
title: 'Get Help',
|
|
55
|
+
description: INSTRUCTIONS_SUMMARY,
|
|
56
|
+
};
|
|
57
|
+
export function registerPrompts(deps) {
|
|
58
|
+
const sections = buildSectionsRecord(deps.readOnly ?? false);
|
|
59
|
+
const instructions = renderSections(sections);
|
|
60
|
+
const topics = Object.keys(sections);
|
|
61
|
+
deps.server.registerPrompt(GET_HELP.name, {
|
|
62
|
+
title: GET_HELP.title,
|
|
63
|
+
description: GET_HELP.description,
|
|
64
|
+
argsSchema: z.strictObject({
|
|
65
|
+
topic: topicArg(topics, `Section key to filter instructions (one of: ${topics.join(', ')}); omit to return all instructions.`).optional(),
|
|
134
66
|
}),
|
|
135
|
-
}, ({
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const toolInfo = buildToolInfo(toolName);
|
|
141
|
-
if (!toolInfo) {
|
|
142
|
-
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown tool: ${toolName}`);
|
|
67
|
+
}, ({ topic }) => wrapHandler(GET_HELP, () => {
|
|
68
|
+
const lowerTopic = topic?.toLowerCase();
|
|
69
|
+
const section = lowerTopic && Object.hasOwn(sections, lowerTopic) ? sections[lowerTopic] : undefined;
|
|
70
|
+
if (topic && !section) {
|
|
71
|
+
Logger.debug('get-help: unknown topic requested', { topic });
|
|
143
72
|
}
|
|
73
|
+
const text = section ??
|
|
74
|
+
(topic
|
|
75
|
+
? `Section '${topic}' not found. Available: ${topics.join(', ')}\n\n${instructions}`
|
|
76
|
+
: instructions);
|
|
144
77
|
return {
|
|
145
|
-
description:
|
|
146
|
-
messages: [
|
|
147
|
-
{
|
|
148
|
-
role: 'user',
|
|
149
|
-
content: {
|
|
150
|
-
type: 'text',
|
|
151
|
-
text: `Use the embedded contract for \`${toolName}\` as the authoritative reference. ` +
|
|
152
|
-
'Summarize when to use it, its key constraints, and the safest next action.',
|
|
153
|
-
annotations: {
|
|
154
|
-
audience: ['assistant'],
|
|
155
|
-
priority: 1,
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
role: 'user',
|
|
161
|
-
content: {
|
|
162
|
-
type: 'resource',
|
|
163
|
-
resource: {
|
|
164
|
-
uri: `internal://tool-info/${toolName}`,
|
|
165
|
-
mimeType: 'text/markdown',
|
|
166
|
-
text: toolInfo,
|
|
167
|
-
},
|
|
168
|
-
annotations: {
|
|
169
|
-
audience: ['assistant'],
|
|
170
|
-
priority: 1,
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
],
|
|
78
|
+
description: GET_HELP.description,
|
|
79
|
+
messages: [userText(text)],
|
|
175
80
|
};
|
|
176
|
-
});
|
|
81
|
+
}));
|
|
177
82
|
}
|
|
83
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n GetPromptResult,\n McpServer,\n PromptMessage,\n TextContent,\n} from '@modelcontextprotocol/server';\nimport { completable, getDisplayName, ProtocolError } from '@modelcontextprotocol/server';\n\nimport * as z from 'zod/v4';\n\nimport { formatUnknownErrorMessage, fsErrorCode, hasErrorShape } from './core/errors.js';\nimport { Logger } from './core/observability.js';\nimport { isBlank, SHELL_METACHAR_RE } from './core/schema.js';\nimport { buildSectionsRecord, INSTRUCTIONS_SUMMARY, renderSections } from './instructions.js';\n\n// --- Types ---\n\ninterface PromptContract {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n}\n\ninterface PromptRegistrarDeps {\n readonly server: McpServer;\n readonly readOnly?: boolean;\n}\n\n// --- Helpers ---\n\nfunction topicArg(\n topics: readonly string[],\n description: string,\n): ReturnType<typeof completable<z.ZodString>> {\n return completable(\n z\n .string()\n .min(1, { message: 'Topic required' })\n .refine((val) => !isBlank(val), {\n message: 'Topic cannot be empty or whitespace-only',\n })\n .refine((val) => !SHELL_METACHAR_RE.test(val), {\n message: 'Topic contains prohibited characters (newlines or shell metacharacters)',\n })\n .describe(description),\n (value) => {\n const lower = value.toLowerCase();\n return lower ? topics.filter((t) => t.startsWith(lower)) : [...topics];\n },\n );\n}\n\nfunction userText(text: string): PromptMessage {\n const content: TextContent = {\n type: 'text',\n text,\n annotations: { audience: ['assistant'], priority: 1 },\n };\n return { role: 'user', content };\n}\n\nasync function wrapHandler<T>(contract: PromptContract, fn: () => Promise<T> | T): Promise<T> {\n const displayName = getDisplayName(contract);\n\n try {\n const result = await fn();\n Logger.debug(`prompt resolved`, { name: contract.name, displayName });\n return result;\n } catch (error) {\n if (hasErrorShape(error, 'ProtocolError')) throw error;\n const message = formatUnknownErrorMessage(error);\n Logger.error(`Prompt handler failed: ${message}`, {\n promptName: contract.name,\n error,\n });\n const protocolError = new ProtocolError(fsErrorCode(error), message);\n protocolError.cause = error;\n throw protocolError;\n }\n}\n\n// --- Prompt entries ---\n\nconst GET_HELP: PromptContract = {\n name: 'get-help',\n title: 'Get Help',\n description: INSTRUCTIONS_SUMMARY,\n};\n\nexport function registerPrompts(deps: PromptRegistrarDeps): void {\n const sections = buildSectionsRecord(deps.readOnly ?? false);\n const instructions = renderSections(sections);\n const topics = Object.keys(sections);\n\n deps.server.registerPrompt(\n GET_HELP.name,\n {\n title: GET_HELP.title,\n description: GET_HELP.description,\n argsSchema: z.strictObject({\n topic: topicArg(\n topics,\n `Section key to filter instructions (one of: ${topics.join(', ')}); omit to return all instructions.`,\n ).optional(),\n }),\n },\n ({ topic }: { topic?: string | undefined }): GetPromptResult | Promise<GetPromptResult> =>\n wrapHandler(GET_HELP, () => {\n const lowerTopic = topic?.toLowerCase();\n const section =\n lowerTopic && Object.hasOwn(sections, lowerTopic) ? sections[lowerTopic] : undefined;\n if (topic && !section) {\n Logger.debug('get-help: unknown topic requested', { topic });\n }\n const text =\n section ??\n (topic\n ? `Section '${topic}' not found. Available: ${topics.join(', ')}\\n\\n${instructions}`\n : instructions);\n return {\n description: GET_HELP.description,\n messages: [userText(text)],\n };\n }),\n );\n}\n"]}
|
package/dist/resources.d.ts
CHANGED
|
@@ -1,9 +1,73 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import type { CacheHint, McpServer, ReadResourceResult, Resource, Role, ServerContext, ServerNotifier } from '@modelcontextprotocol/server';
|
|
2
|
+
import type { PathGuard } from './core/path.js';
|
|
3
|
+
import type { ResourceStore } from './core/store.js';
|
|
4
|
+
import { type WatcherRegistry } from './core/watcher-registry.js';
|
|
5
|
+
export interface ResourceRegistrationOptions {
|
|
6
|
+
resourceStore: ResourceStore;
|
|
7
|
+
pathGuard?: PathGuard;
|
|
8
|
+
/** Mirrors the `--read-only` gate so the instructions match the tools actually registered. */
|
|
9
|
+
readOnly: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Shared file-watcher registry for the modern (per-request) HTTP leg. When set,
|
|
12
|
+
* the resource uses this handler-scoped registry instead of creating its own
|
|
13
|
+
* per-server one, so file-change watchers persist across requests and publish
|
|
14
|
+
* to the shared ServerEventBus. Omitted (per-server registry) on legacy/stdio.
|
|
15
|
+
*/
|
|
16
|
+
watcherRegistry?: WatcherRegistry;
|
|
17
|
+
/** Modern-leg typed notification publisher. */
|
|
18
|
+
notifier?: ServerNotifier;
|
|
19
|
+
/** The protocol era this instance serves; omitted where the caller does not know. */
|
|
20
|
+
era?: 'legacy' | 'modern';
|
|
21
|
+
/**
|
|
22
|
+
* Scope for shared-content cache hints. 'private' when the endpoint is
|
|
23
|
+
* API-key gated, mirroring the list hints in server.ts — a shared cache must
|
|
24
|
+
* not store an authenticated response body. Defaults to 'public'.
|
|
25
|
+
*/
|
|
26
|
+
cacheScope?: 'public' | 'private';
|
|
27
|
+
}
|
|
28
|
+
type ResourceRegistrarDeps = Omit<ResourceRegistrationOptions, 'pathGuard' | 'readOnly'> & {
|
|
29
|
+
readonly server: McpServer;
|
|
30
|
+
readonly pathGuard: PathGuard;
|
|
31
|
+
readonly readOnly?: boolean;
|
|
32
|
+
};
|
|
33
|
+
interface BaseResourceContract {
|
|
34
|
+
name: string;
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
mimeType?: string;
|
|
38
|
+
cacheHint?: CacheHint;
|
|
39
|
+
annotations?: {
|
|
40
|
+
audience?: Role[];
|
|
41
|
+
priority?: number;
|
|
42
|
+
};
|
|
43
|
+
readonly read: (uri: URL, variables: Record<string, string | string[]>, ctx: ServerContext) => Promise<ReadResourceResult> | ReadResourceResult;
|
|
44
|
+
readonly subscribe?: (uri: string, notify: (uri: string) => void) => Promise<boolean | undefined> | boolean | undefined;
|
|
45
|
+
readonly unsubscribe?: (uri: string) => void;
|
|
46
|
+
readonly destroy?: () => void;
|
|
47
|
+
readonly list?: (ctx: ServerContext) => Promise<{
|
|
48
|
+
resources: Resource[];
|
|
49
|
+
}> | {
|
|
50
|
+
resources: Resource[];
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** A resource with a fixed, enumerable URI (e.g. internal://instructions). */
|
|
54
|
+
interface StaticResourceContract extends BaseResourceContract {
|
|
55
|
+
uri: string;
|
|
56
|
+
uriTemplate?: never;
|
|
57
|
+
complete?: never;
|
|
58
|
+
}
|
|
59
|
+
/** A resource identified by a URI template (FILESYSTEM_FILE_URI_TEMPLATE). */
|
|
60
|
+
interface TemplateResourceContract extends BaseResourceContract {
|
|
61
|
+
uriTemplate: string;
|
|
62
|
+
uri?: never;
|
|
63
|
+
complete?: (variable: string, value: string, ctx?: {
|
|
64
|
+
arguments?: Record<string, string>;
|
|
65
|
+
}) => Promise<string[]> | string[];
|
|
66
|
+
}
|
|
67
|
+
type ResourceContract = StaticResourceContract | TemplateResourceContract;
|
|
68
|
+
export declare function getResourceContracts(options: ResourceRegistrationOptions): ResourceContract[];
|
|
69
|
+
export declare function registerResources(deps: ResourceRegistrarDeps): {
|
|
70
|
+
dispose(): void;
|
|
71
|
+
};
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|