@j0hanz/filesystem-mcp 2.1.4 → 2.1.5

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.
Files changed (115) hide show
  1. package/dist/cli.d.ts +2 -14
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +8 -9
  4. package/dist/cli.js.map +1 -1
  5. package/dist/core/cursor.d.ts +2 -14
  6. package/dist/core/cursor.d.ts.map +1 -1
  7. package/dist/core/cursor.js +25 -39
  8. package/dist/core/cursor.js.map +1 -1
  9. package/dist/core/errors.d.ts +2 -11
  10. package/dist/core/errors.d.ts.map +1 -1
  11. package/dist/core/errors.js +6 -26
  12. package/dist/core/errors.js.map +1 -1
  13. package/dist/core/fmt.js +5 -5
  14. package/dist/core/fmt.js.map +1 -1
  15. package/dist/core/fs.d.ts +3 -11
  16. package/dist/core/fs.d.ts.map +1 -1
  17. package/dist/core/fs.js +3 -21
  18. package/dist/core/fs.js.map +1 -1
  19. package/dist/core/glob.d.ts +0 -1
  20. package/dist/core/glob.d.ts.map +1 -1
  21. package/dist/core/glob.js +1 -2
  22. package/dist/core/glob.js.map +1 -1
  23. package/dist/core/input-required.d.ts +0 -6
  24. package/dist/core/input-required.d.ts.map +1 -1
  25. package/dist/core/input-required.js +0 -8
  26. package/dist/core/input-required.js.map +1 -1
  27. package/dist/core/path-completer.d.ts.map +1 -1
  28. package/dist/core/path-completer.js +2 -1
  29. package/dist/core/path-completer.js.map +1 -1
  30. package/dist/core/path-discovery.js +2 -2
  31. package/dist/core/path-discovery.js.map +1 -1
  32. package/dist/core/path.d.ts +7 -18
  33. package/dist/core/path.d.ts.map +1 -1
  34. package/dist/core/path.js +14 -39
  35. package/dist/core/path.js.map +1 -1
  36. package/dist/core/primitives.d.ts +0 -1
  37. package/dist/core/primitives.d.ts.map +1 -1
  38. package/dist/core/primitives.js +0 -3
  39. package/dist/core/primitives.js.map +1 -1
  40. package/dist/core/read.d.ts +0 -1
  41. package/dist/core/read.d.ts.map +1 -1
  42. package/dist/core/read.js +7 -15
  43. package/dist/core/read.js.map +1 -1
  44. package/dist/core/schema.d.ts +0 -16
  45. package/dist/core/schema.d.ts.map +1 -1
  46. package/dist/core/schema.js +10 -35
  47. package/dist/core/schema.js.map +1 -1
  48. package/dist/core/search.d.ts +6 -2
  49. package/dist/core/search.d.ts.map +1 -1
  50. package/dist/core/search.js +103 -99
  51. package/dist/core/search.js.map +1 -1
  52. package/dist/core/store.d.ts +1 -2
  53. package/dist/core/store.d.ts.map +1 -1
  54. package/dist/core/store.js +1 -4
  55. package/dist/core/store.js.map +1 -1
  56. package/dist/core/watcher-registry.d.ts +1 -8
  57. package/dist/core/watcher-registry.d.ts.map +1 -1
  58. package/dist/core/watcher-registry.js +3 -12
  59. package/dist/core/watcher-registry.js.map +1 -1
  60. package/dist/prompts.d.ts.map +1 -1
  61. package/dist/prompts.js +32 -43
  62. package/dist/prompts.js.map +1 -1
  63. package/dist/resources.d.ts +1 -1
  64. package/dist/resources.d.ts.map +1 -1
  65. package/dist/resources.js +3 -9
  66. package/dist/resources.js.map +1 -1
  67. package/dist/server.d.ts +0 -3
  68. package/dist/server.d.ts.map +1 -1
  69. package/dist/server.js +1 -5
  70. package/dist/server.js.map +1 -1
  71. package/dist/tools/batch.d.ts +11 -2
  72. package/dist/tools/batch.d.ts.map +1 -1
  73. package/dist/tools/batch.js +1 -2
  74. package/dist/tools/batch.js.map +1 -1
  75. package/dist/tools/define.d.ts.map +1 -1
  76. package/dist/tools/define.js +5 -2
  77. package/dist/tools/define.js.map +1 -1
  78. package/dist/tools/edit.d.ts.map +1 -1
  79. package/dist/tools/edit.js +18 -30
  80. package/dist/tools/edit.js.map +1 -1
  81. package/dist/tools/list.js +1 -1
  82. package/dist/tools/list.js.map +1 -1
  83. package/dist/tools/move.d.ts.map +1 -1
  84. package/dist/tools/move.js +7 -3
  85. package/dist/tools/move.js.map +1 -1
  86. package/dist/tools/progress.d.ts +0 -1
  87. package/dist/tools/progress.d.ts.map +1 -1
  88. package/dist/tools/progress.js +2 -8
  89. package/dist/tools/progress.js.map +1 -1
  90. package/dist/tools/read.d.ts.map +1 -1
  91. package/dist/tools/read.js +1 -4
  92. package/dist/tools/read.js.map +1 -1
  93. package/dist/tools/replace-in-files.d.ts.map +1 -1
  94. package/dist/tools/replace-in-files.js +5 -9
  95. package/dist/tools/replace-in-files.js.map +1 -1
  96. package/dist/tools/search-content.d.ts.map +1 -1
  97. package/dist/tools/search-content.js +17 -28
  98. package/dist/tools/search-content.js.map +1 -1
  99. package/dist/tools/stat.d.ts.map +1 -1
  100. package/dist/tools/stat.js +1 -3
  101. package/dist/tools/stat.js.map +1 -1
  102. package/dist/transport/http-policy.d.ts +6 -0
  103. package/dist/transport/http-policy.d.ts.map +1 -1
  104. package/dist/transport/http-policy.js +1 -1
  105. package/dist/transport/http-policy.js.map +1 -1
  106. package/dist/transport/http.d.ts.map +1 -1
  107. package/dist/transport/http.js +4 -11
  108. package/dist/transport/http.js.map +1 -1
  109. package/dist/transport/stdio.js +1 -1
  110. package/dist/transport/stdio.js.map +1 -1
  111. package/dist/transport.d.ts +1 -3
  112. package/dist/transport.d.ts.map +1 -1
  113. package/dist/transport.js +5 -2
  114. package/dist/transport.js.map +1 -1
  115. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/tools/batch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InputRequiredResult } from '@modelcontextprotocol/server';\n\nimport { processInParallel } from '../core/concurrency.js';\nimport { ErrorCode, FsError, Problem, rethrowIfAborted } from '../core/errors.js';\nimport { choiceInput, pendingRoundTrip } from '../core/input-required.js';\nimport { IS_CASE_INSENSITIVE_FS } from '../core/path-utils.js';\nimport type { PairFailureItem } from '../core/schema.js';\nimport { PARALLEL_CONCURRENCY } from '../core/util.js';\nimport type { ToolCtx } from './define.js';\n\ninterface PerPathError {\n code: ErrorCode;\n message: string;\n path?: string;\n suggestion?: string;\n}\n\nexport type PerPathResult<T> = { path: string; value: T } | { path: string; error: PerPathError };\n\nexport interface BatchResult<T> {\n results: PerPathResult<T>[];\n summary: { total: number; succeeded: number; failed: number };\n}\n\ntype BatchInput<TOverride> =\n { path: string } | { paths: string[] } | { files: ({ path: string } & TOverride)[] };\n\ninterface RunOverPathsOptions {\n defaultErrorCode?: ErrorCode;\n concurrency?: number;\n}\n\nfunction normalizeBatchItems<TOverride>(\n args: BatchInput<TOverride>,\n): { path: string; override?: TOverride }[] {\n if ('path' in args) return [{ path: args.path }];\n if ('paths' in args) return args.paths.map((path) => ({ path }));\n if ('files' in args)\n return args.files.map(({ path, ...rest }) => ({\n path,\n override: rest as TOverride,\n }));\n return [];\n}\n\nexport async function runOverPaths<TOverride, TPerPath>(\n args: BatchInput<TOverride>,\n ctx: ToolCtx,\n perPath: (item: { path: string; override?: TOverride }, ctx: ToolCtx) => Promise<TPerPath>,\n options?: RunOverPathsOptions,\n): Promise<BatchResult<TPerPath>> {\n const items = normalizeBatchItems(args);\n if (items.length === 0) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n \"runOverPaths: at least one of 'path', 'paths', or 'files' must be provided\",\n );\n }\n\n const defaultErrorCode = options?.defaultErrorCode ?? ErrorCode.UNKNOWN;\n const concurrency = options?.concurrency ?? PARALLEL_CONCURRENCY;\n\n const total = items.length;\n let completed = 0;\n const results: PerPathResult<TPerPath>[] = new Array<PerPathResult<TPerPath>>(total);\n\n const tick = (): void => {\n completed += 1;\n ctx.onProgress?.({ current: completed, total });\n };\n\n await processInParallel<\n { item: { path: string; override?: TOverride }; index: number },\n undefined\n >(\n items.map((item, index) => ({ item, index })),\n async ({ item, index }) => {\n try {\n const value = await perPath(item, ctx);\n results[index] = { path: item.path, value };\n } catch (error: unknown) {\n results[index] = {\n path: item.path,\n error: Problem.toPerFileError(error, defaultErrorCode, item.path),\n };\n } finally {\n tick();\n }\n return undefined;\n },\n concurrency,\n ctx.signal,\n );\n\n let succeeded = 0;\n for (const result of results) {\n if (!('error' in result)) succeeded += 1;\n }\n\n return {\n results,\n summary: { total, succeeded, failed: total - succeeded },\n };\n}\n\n/** The minimum a pair plan must expose for the shared driver to route it. */\nexport interface PairPlan {\n readonly pair: { source: string; destination: string };\n readonly validDest: string;\n readonly pending: boolean;\n}\n\nexport type PairPlanResult<TPlan extends PairPlan> =\n | { status: 'fail'; failure: PairFailureItem }\n | { status: 'noop' }\n | { status: 'plan'; plan: TPlan };\n\n/** A discriminated union, so the fold below narrows without a generic cast. */\nexport type PairExecResult<TResult> = { readonly skipped: string } | { readonly value: TResult };\n\nexport interface PairBatchOutcome<TResult> {\n results: TResult[];\n skipped: string[];\n failures: PairFailureItem[];\n}\n\n/**\n * A batch where every requested item failed produced no work at all, so it is a\n * failed call — `isError` must say so. Partial failure is deliberately NOT an\n * error: the per-item entries carry which failed, and the succeeded ones really\n * were done. A skipped item is work the caller asked to skip, not work that\n * failed — a self-move that was silently dropped means the call did something.\n * Zero items is not a failure either.\n *\n * Takes either count shape a batch tool holds at its return site: a `summary`\n * (`runOverPaths`, or the hand-built ones in `read`, `delete`, `replace_text`)\n * or a pair outcome (`runOverPairs`).\n */\nexport function isTotalFailure(\n shape:\n | { readonly total: number; readonly failed: number }\n | {\n readonly results: readonly unknown[];\n readonly skipped: readonly unknown[];\n readonly failures: readonly unknown[];\n },\n): boolean {\n if ('total' in shape) return shape.total > 0 && shape.failed === shape.total;\n return shape.failures.length > 0 && shape.results.length + shape.skipped.length === 0;\n}\n\nexport function pairFailure(\n pair: { source: string; destination: string },\n error: unknown,\n): PairFailureItem {\n return {\n source: pair.source,\n destination: pair.destination,\n error: Problem.toPerFileError(error, ErrorCode.UNKNOWN, pair.source),\n };\n}\n\ninterface RunOverPairsOptions<TItem, TPlan extends PairPlan, TResult> {\n readonly op: 'copy' | 'move';\n readonly plan: (item: TItem) => Promise<PairPlanResult<TPlan>>;\n readonly execute: (\n plan: TPlan,\n pendingSorted: readonly string[],\n ) => Promise<PairExecResult<TResult>>;\n}\n\n/**\n * The source→destination sibling of `runOverPaths`: plan every pair, fail closed\n * on a duplicated destination, round-trip the overwrite confirmations as one\n * set, then execute what survived in parallel. `copy` and `move` differ only in\n * their `plan` and `execute` callbacks.\n */\nexport async function runOverPairs<TItem, TPlan extends PairPlan, TResult>(\n items: readonly TItem[],\n ctx: ToolCtx,\n opts: RunOverPairsOptions<TItem, TPlan, TResult>,\n): Promise<PairBatchOutcome<TResult> | InputRequiredResult> {\n const verb = opts.op === 'copy' ? 'Copy' : 'Move';\n\n const { results: planned, errors: planErrors } = await processInParallel(\n items,\n opts.plan,\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n // plan callbacks are fail-closed (they return { status: 'fail' }, never\n // throw), so planErrors should always be empty. Surface the first rather\n // than silently dropping the item if a future plan callback violates that.\n const firstPlanError = planErrors[0];\n if (firstPlanError) throw firstPlanError.error;\n\n const failures: PairFailureItem[] = [];\n const candidates: TPlan[] = [];\n for (const { value } of planned) {\n if (value.status === 'fail') failures.push(value.failure);\n else if (value.status === 'plan') candidates.push(value.plan);\n // 'noop' (self-copy / self-move) is silently skipped.\n }\n\n // Two sources targeting the same destination in one batch would otherwise\n // collapse to a single shared overwrite confirmation and let the second\n // one silently clobber the first's freshly-written content. Fail closed:\n // only the first plan per destination proceeds; later ones targeting the\n // same destination are reported as a per-item failure.\n const seenDest = new Set<string>();\n const ready: TPlan[] = [];\n for (const plan of candidates) {\n const destKey = IS_CASE_INSENSITIVE_FS ? plan.validDest.toLowerCase() : plan.validDest;\n if (seenDest.has(destKey)) {\n failures.push(\n pairFailure(\n plan.pair,\n new FsError(\n ErrorCode.INVALID_INPUT,\n `${verb} cancelled: another entry in this batch already targets destination \"${plan.pair.destination}\"`,\n plan.pair.destination,\n ),\n ),\n );\n continue;\n }\n seenDest.add(destKey);\n ready.push(plan);\n }\n\n const pendingSorted = ready\n .filter((p) => p.pending)\n .map((p) => p.validDest)\n .sort();\n if (pendingSorted.length > 0) {\n // Round 1 returns input_required; a retry whose verified state does not\n // bind this overwrite set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip({\n op: opts.op,\n pending: pendingSorted,\n requestState: ctx.requestState,\n clientCapabilities: ctx.clientCapabilities,\n buildInputs: (dests) =>\n dests.map((dest, i) =>\n choiceInput(\n `confirm_${i}`,\n opts.op === 'move'\n ? `\"${dest}\" already exists. Overwrite it?`\n : `Destination \"${dest}\" already exists. Overwrite it?`,\n [\n { value: 'overwrite', title: 'Overwrite' },\n { value: 'skip', title: 'Skip' },\n ],\n ),\n ),\n });\n if (round !== undefined) return round;\n }\n\n const total = ready.length;\n let completed = 0;\n const tick = (): void => {\n completed += 1;\n ctx.onProgress?.({ current: completed, total });\n };\n const { results: execResults, errors: execErrors } = await processInParallel(\n ready,\n async (plan) => {\n try {\n return await opts.execute(plan, pendingSorted);\n } finally {\n tick();\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n for (const { error, index } of execErrors) {\n rethrowIfAborted(error);\n const plan = ready[index];\n if (plan) failures.push(pairFailure(plan.pair, error));\n }\n\n const results: TResult[] = [];\n const skipped: string[] = [];\n for (const { value } of execResults) {\n if ('skipped' in value) skipped.push(value.skipped);\n else results.push(value.value);\n }\n\n return { results, skipped, failures };\n}\n"]}
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/tools/batch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InputRequiredResult } from '@modelcontextprotocol/server';\n\nimport { processInParallel } from '../core/concurrency.js';\nimport { ErrorCode, FsError, Problem, rethrowIfAborted } from '../core/errors.js';\nimport { choiceInput, pendingRoundTrip } from '../core/input-required.js';\nimport { IS_CASE_INSENSITIVE_FS } from '../core/path-utils.js';\nimport { PARALLEL_CONCURRENCY } from '../core/util.js';\nimport type { ToolCtx } from './define.js';\n\ninterface PerPathError {\n code: ErrorCode;\n message: string;\n path?: string;\n suggestion?: string;\n}\n\n/** One entry of a source→destination tool's `failures[]` — move's failure schema is the wire twin. */\nexport interface PairFailureItem {\n source: string;\n destination: string;\n error: {\n code: string;\n message: string;\n path?: string | undefined;\n suggestion?: string | undefined;\n };\n}\n\nexport type PerPathResult<T> = { path: string; value: T } | { path: string; error: PerPathError };\n\nexport interface BatchResult<T> {\n results: PerPathResult<T>[];\n summary: { total: number; succeeded: number; failed: number };\n}\n\ntype BatchInput<TOverride> =\n { path: string } | { paths: string[] } | { files: ({ path: string } & TOverride)[] };\n\ninterface RunOverPathsOptions {\n defaultErrorCode?: ErrorCode;\n}\n\nfunction normalizeBatchItems<TOverride>(\n args: BatchInput<TOverride>,\n): { path: string; override?: TOverride }[] {\n if ('path' in args) return [{ path: args.path }];\n if ('paths' in args) return args.paths.map((path) => ({ path }));\n if ('files' in args)\n return args.files.map(({ path, ...rest }) => ({\n path,\n override: rest as TOverride,\n }));\n return [];\n}\n\nexport async function runOverPaths<TOverride, TPerPath>(\n args: BatchInput<TOverride>,\n ctx: ToolCtx,\n perPath: (item: { path: string; override?: TOverride }, ctx: ToolCtx) => Promise<TPerPath>,\n options?: RunOverPathsOptions,\n): Promise<BatchResult<TPerPath>> {\n const items = normalizeBatchItems(args);\n if (items.length === 0) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n \"runOverPaths: at least one of 'path', 'paths', or 'files' must be provided\",\n );\n }\n\n const defaultErrorCode = options?.defaultErrorCode ?? ErrorCode.UNKNOWN;\n\n const total = items.length;\n let completed = 0;\n const results: PerPathResult<TPerPath>[] = new Array<PerPathResult<TPerPath>>(total);\n\n const tick = (): void => {\n completed += 1;\n ctx.onProgress?.({ current: completed, total });\n };\n\n await processInParallel<\n { item: { path: string; override?: TOverride }; index: number },\n undefined\n >(\n items.map((item, index) => ({ item, index })),\n async ({ item, index }) => {\n try {\n const value = await perPath(item, ctx);\n results[index] = { path: item.path, value };\n } catch (error: unknown) {\n results[index] = {\n path: item.path,\n error: Problem.toPerFileError(error, defaultErrorCode, item.path),\n };\n } finally {\n tick();\n }\n return undefined;\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n let succeeded = 0;\n for (const result of results) {\n if (!('error' in result)) succeeded += 1;\n }\n\n return {\n results,\n summary: { total, succeeded, failed: total - succeeded },\n };\n}\n\n/** The minimum a pair plan must expose for the shared driver to route it. */\nexport interface PairPlan {\n readonly pair: { source: string; destination: string };\n readonly validDest: string;\n readonly pending: boolean;\n}\n\nexport type PairPlanResult<TPlan extends PairPlan> =\n | { status: 'fail'; failure: PairFailureItem }\n | { status: 'noop' }\n | { status: 'plan'; plan: TPlan };\n\n/** A discriminated union, so the fold below narrows without a generic cast. */\nexport type PairExecResult<TResult> = { readonly skipped: string } | { readonly value: TResult };\n\nexport interface PairBatchOutcome<TResult> {\n results: TResult[];\n skipped: string[];\n failures: PairFailureItem[];\n}\n\n/**\n * A batch where every requested item failed produced no work at all, so it is a\n * failed call — `isError` must say so. Partial failure is deliberately NOT an\n * error: the per-item entries carry which failed, and the succeeded ones really\n * were done. A skipped item is work the caller asked to skip, not work that\n * failed — a self-move that was silently dropped means the call did something.\n * Zero items is not a failure either.\n *\n * Takes either count shape a batch tool holds at its return site: a `summary`\n * (`runOverPaths`, or the hand-built ones in `read`, `delete`, `replace_text`)\n * or a pair outcome (`runOverPairs`).\n */\nexport function isTotalFailure(\n shape:\n | { readonly total: number; readonly failed: number }\n | {\n readonly results: readonly unknown[];\n readonly skipped: readonly unknown[];\n readonly failures: readonly unknown[];\n },\n): boolean {\n if ('total' in shape) return shape.total > 0 && shape.failed === shape.total;\n return shape.failures.length > 0 && shape.results.length + shape.skipped.length === 0;\n}\n\nexport function pairFailure(\n pair: { source: string; destination: string },\n error: unknown,\n): PairFailureItem {\n return {\n source: pair.source,\n destination: pair.destination,\n error: Problem.toPerFileError(error, ErrorCode.UNKNOWN, pair.source),\n };\n}\n\ninterface RunOverPairsOptions<TItem, TPlan extends PairPlan, TResult> {\n readonly op: 'copy' | 'move';\n readonly plan: (item: TItem) => Promise<PairPlanResult<TPlan>>;\n readonly execute: (\n plan: TPlan,\n pendingSorted: readonly string[],\n ) => Promise<PairExecResult<TResult>>;\n}\n\n/**\n * The source→destination sibling of `runOverPaths`: plan every pair, fail closed\n * on a duplicated destination, round-trip the overwrite confirmations as one\n * set, then execute what survived in parallel. `copy` and `move` differ only in\n * their `plan` and `execute` callbacks.\n */\nexport async function runOverPairs<TItem, TPlan extends PairPlan, TResult>(\n items: readonly TItem[],\n ctx: ToolCtx,\n opts: RunOverPairsOptions<TItem, TPlan, TResult>,\n): Promise<PairBatchOutcome<TResult> | InputRequiredResult> {\n const verb = opts.op === 'copy' ? 'Copy' : 'Move';\n\n const { results: planned, errors: planErrors } = await processInParallel(\n items,\n opts.plan,\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n // plan callbacks are fail-closed (they return { status: 'fail' }, never\n // throw), so planErrors should always be empty. Surface the first rather\n // than silently dropping the item if a future plan callback violates that.\n const firstPlanError = planErrors[0];\n if (firstPlanError) throw firstPlanError.error;\n\n const failures: PairFailureItem[] = [];\n const candidates: TPlan[] = [];\n for (const { value } of planned) {\n if (value.status === 'fail') failures.push(value.failure);\n else if (value.status === 'plan') candidates.push(value.plan);\n // 'noop' (self-copy / self-move) is silently skipped.\n }\n\n // Two sources targeting the same destination in one batch would otherwise\n // collapse to a single shared overwrite confirmation and let the second\n // one silently clobber the first's freshly-written content. Fail closed:\n // only the first plan per destination proceeds; later ones targeting the\n // same destination are reported as a per-item failure.\n const seenDest = new Set<string>();\n const ready: TPlan[] = [];\n for (const plan of candidates) {\n const destKey = IS_CASE_INSENSITIVE_FS ? plan.validDest.toLowerCase() : plan.validDest;\n if (seenDest.has(destKey)) {\n failures.push(\n pairFailure(\n plan.pair,\n new FsError(\n ErrorCode.INVALID_INPUT,\n `${verb} cancelled: another entry in this batch already targets destination \"${plan.pair.destination}\"`,\n plan.pair.destination,\n ),\n ),\n );\n continue;\n }\n seenDest.add(destKey);\n ready.push(plan);\n }\n\n const pendingSorted = ready\n .filter((p) => p.pending)\n .map((p) => p.validDest)\n .sort();\n if (pendingSorted.length > 0) {\n // Round 1 returns input_required; a retry whose verified state does not\n // bind this overwrite set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip({\n op: opts.op,\n pending: pendingSorted,\n requestState: ctx.requestState,\n clientCapabilities: ctx.clientCapabilities,\n buildInputs: (dests) =>\n dests.map((dest, i) =>\n choiceInput(\n `confirm_${i}`,\n opts.op === 'move'\n ? `\"${dest}\" already exists. Overwrite it?`\n : `Destination \"${dest}\" already exists. Overwrite it?`,\n [\n { value: 'overwrite', title: 'Overwrite' },\n { value: 'skip', title: 'Skip' },\n ],\n ),\n ),\n });\n if (round !== undefined) return round;\n }\n\n const total = ready.length;\n let completed = 0;\n const tick = (): void => {\n completed += 1;\n ctx.onProgress?.({ current: completed, total });\n };\n const { results: execResults, errors: execErrors } = await processInParallel(\n ready,\n async (plan) => {\n try {\n return await opts.execute(plan, pendingSorted);\n } finally {\n tick();\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n for (const { error, index } of execErrors) {\n rethrowIfAborted(error);\n const plan = ready[index];\n if (plan) failures.push(pairFailure(plan.pair, error));\n }\n\n const results: TResult[] = [];\n const skipped: string[] = [];\n for (const { value } of execResults) {\n if ('skipped' in value) skipped.push(value.skipped);\n else results.push(value.value);\n }\n\n return { results, skipped, failures };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import * as z from 'zod/v4';
3
3
  import { ErrorCode, formatUnknownErrorMessage, Problem } from '../core/errors.js';
4
4
  import { plainMessage } from '../core/fmt.js';
5
5
  import { GuardedFileSystem } from '../core/fs.js';
6
- import { confirmInput, multiSelectInput, pendingRoundTrip, readAcceptedConfirm, readAcceptedMultiChoice, } from '../core/input-required.js';
6
+ import { multiSelectInput, pendingRoundTrip, readAcceptedConfirm, readAcceptedMultiChoice, } from '../core/input-required.js';
7
7
  import { Logger } from '../core/observability.js';
8
8
  import { isSamePath } from '../core/path-utils.js';
9
9
  import { McpProgressSink, ProgressSession } from './progress.js';
@@ -204,7 +204,10 @@ class ToolExecutor {
204
204
  ? [
205
205
  multiSelectInput('grant', 'Grant filesystem access to these directories? Select the ones to allow.', dirs.map((d) => ({ value: d, title: d }))),
206
206
  ]
207
- : dirs.map((dir, i) => confirmInput(`confirm_${i}`, `Grant filesystem access to "${dir}"?`)),
207
+ : dirs.map((dir, i) => ({
208
+ key: `confirm_${i}`,
209
+ message: `Grant filesystem access to "${dir}"?`,
210
+ })),
208
211
  });
209
212
  if (round !== undefined)
210
213
  return round;
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AuthInfo,\n CallToolResult,\n ClientCapabilities,\n ContentBlock,\n InputRequiredResult,\n JsonSchemaType,\n JsonSchemaValidator,\n jsonSchemaValidator,\n McpServer,\n Notification,\n RegisteredTool,\n RequestMeta,\n RequestStateAccessor,\n ServerContext,\n ToolAnnotations,\n} from '@modelcontextprotocol/server';\nimport {\n CLIENT_CAPABILITIES_META_KEY,\n fromJsonSchema,\n isInputRequiredResult,\n} from '@modelcontextprotocol/server';\n\nimport * as z from 'zod/v4';\n\nimport { ErrorCode, formatUnknownErrorMessage, Problem } from '../core/errors.js';\nimport type { ProgressCtx } from '../core/fmt.js';\nimport { plainMessage } from '../core/fmt.js';\nimport { GuardedFileSystem } from '../core/fs.js';\nimport {\n confirmInput,\n multiSelectInput,\n pendingRoundTrip,\n readAcceptedConfirm,\n readAcceptedMultiChoice,\n} from '../core/input-required.js';\nimport { Logger } from '../core/observability.js';\nimport type { LoggingLevel } from '../core/observability.js';\nimport type { PageSnapshotStore } from '../core/page-store.js';\nimport { isSamePath } from '../core/path-utils.js';\nimport type { PathGuard } from '../core/path.js';\nimport type { ResourceStore } from '../core/store.js';\nimport { McpProgressSink, ProgressSession } from './progress.js';\n\nexport interface ToolCtx {\n readonly signal: AbortSignal;\n readonly sessionId?: string;\n readonly authInfo?: AuthInfo;\n readonly _meta?: RequestMeta | undefined;\n readonly fs: GuardedFileSystem;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n /** Emits a log line to stderr via `Logger.emit`, gated by `LOG_LEVEL`. */\n readonly log?: (level: LoggingLevel, data: unknown, logger?: string) => void;\n readonly sendNotification?: (notification: Notification) => Promise<void>;\n readonly onProgress?: (params: { current: number; total?: number }) => void;\n /**\n * Multi-round-trip `inputResponses` carried by a retried `tools/call`\n * (protocol revision 2026-07-28); `undefined` on the first round. Bare,\n * unvalidated client values — handlers read them through\n * `readAcceptedConfirm`.\n */\n readonly inputResponses?: Record<string, unknown> | undefined;\n /**\n * Reads the verified multi-round-trip `requestState` for the current round:\n * the decoded `PendingState` the `requestStateCodec` verified, or `undefined`\n * when the round carried no state (the first round). `undefined` when no\n * live request context is available.\n */\n readonly requestState?: RequestStateAccessor | undefined;\n /**\n * What the connected client declared it can do, or `undefined` when this\n * connection cannot say. Read by the `input_required` flows: an embedded\n * elicitation sent to a client that never declared `elicitation` is rejected\n * by the SDK with `-32021` before it reaches the wire, so the handlers check\n * first and answer with an actionable tool error instead.\n *\n * Two sources, because the eras differ: a legacy connection negotiated them\n * at `initialize` (`Server.getClientCapabilities()`), a modern one carries\n * them per request in the `_meta` envelope and never runs `initialize` at\n * all. `undefined` means \"cannot tell\" — never \"no capabilities\".\n */\n readonly clientCapabilities?: ClientCapabilities | undefined;\n readonly server?: McpServer;\n}\n\ninterface ToolDeps {\n readonly server: McpServer;\n readonly pathGuard: PathGuard;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n}\n\ninterface RunResult<T> {\n readonly structured: T;\n readonly text?: string;\n readonly resources?: ContentBlock[];\n /**\n * The call as a whole failed. Batch tools set it from `isTotalFailure` in\n * `batch.ts` — every requested item failed — so the executor never has to\n * know a tool's output shape. Absent or `false` means the call did work.\n */\n readonly isError?: boolean;\n}\n\n/**\n * `ToolAnnotations` with `readOnlyHint` required. It is optional in the SDK, but\n * MUTATING_TOOL_NAMES derives the `--read-only` gate from it, so a tool that\n * forgets it must be a compile error rather than a silent reclassification.\n */\ntype DeclaredAnnotations = ToolAnnotations & { readonly readOnlyHint: boolean };\n\nexport interface ToolDef<I extends z.ZodType, O extends z.ZodType> {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n readonly input: I;\n readonly output: O;\n readonly annotations: DeclaredAnnotations;\n readonly timeoutMs?: number;\n readonly progress?: (args: z.infer<I>) => ProgressCtx;\n readonly progressDone?: (args: z.infer<I>, result: z.infer<O>) => Partial<ProgressCtx>;\n readonly defaultErrorCode?: ErrorCode;\n /**\n * The filesystem paths this tool will operate on, extracted from its parsed\n * args. The executor runs an access-grant pre-check over these BEFORE `run`\n * (R7): any path outside the granted roots yields an `input_required`\n * round-trip requesting a grant, and nothing is touched until the client\n * retries with an accepted grant (R8). Omit for tools that do not operate on\n * caller-supplied filesystem paths.\n */\n readonly accessPaths?: (args: z.infer<I>) => readonly string[];\n readonly run: (\n args: z.infer<I>,\n ctx: ToolCtx,\n ) => Promise<RunResult<z.infer<O>> | InputRequiredResult>;\n}\n\nexport interface DefinedTool {\n readonly name: string;\n readonly annotations: DeclaredAnnotations;\n\n register(deps: ToolDeps): RegisteredTool;\n}\n\nfunction toToolCtx(\n ctx: ServerContext | undefined,\n deps: Pick<ToolDeps, 'pathGuard' | 'pageStore' | 'resourceStore' | 'server'>,\n): ToolCtx {\n if (!ctx) {\n const signal = new AbortController().signal;\n return {\n signal,\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n server: deps.server,\n };\n }\n // Envelope first, accessor second — the two eras carry this differently.\n // A modern request states the capabilities in its own `_meta` envelope; a\n // legacy connection fixed them at `initialize` and has no envelope at all.\n // The deprecated accessor still answers for both today (the SDK backfills it\n // per request from the validated envelope on modern instances), but reading\n // the envelope directly is the supported path, so it leads: when the accessor\n // goes, legacy degrades to \"cannot tell\", which fails open to the behavior\n // that predates this check.\n //\n // The cast is the SDK's shipped `RequestMetaEnvelope` declaration collapsing\n // to `{}` — the reserved keys survive at runtime but not in the .d.ts, so the\n // key constant cannot index the declared type.\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined;\n const clientCapabilities =\n (envelope?.[CLIENT_CAPABILITIES_META_KEY] as ClientCapabilities | undefined) ??\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- the only source of client capabilities on a legacy connection, where no envelope exists.\n deps.server.server.getClientCapabilities();\n\n return {\n signal: ctx.mcpReq.signal,\n ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),\n ...(ctx.http?.authInfo ? { authInfo: ctx.http.authInfo } : {}),\n ...(ctx.mcpReq._meta ? { _meta: ctx.mcpReq._meta } : {}),\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n sendNotification: async (notification) => ctx.mcpReq.notify(notification),\n inputResponses: ctx.mcpReq.inputResponses,\n requestState: ctx.mcpReq.requestState,\n ...(clientCapabilities ? { clientCapabilities } : {}),\n server: deps.server,\n };\n}\n\nfunction resolveProgressCtx<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n args: z.infer<I>,\n): ProgressCtx {\n if (!def.progress) return { label: def.title };\n try {\n return def.progress(args);\n } catch (err: unknown) {\n Logger.warn(`resolveProgressCtx: ${def.name}.progress threw: ${String(err)}`);\n return { label: def.title };\n }\n}\n\nfunction composeSignal(base: AbortSignal, timeoutMs?: number): AbortSignal {\n if (!timeoutMs) return base;\n return AbortSignal.any([base, AbortSignal.timeout(timeoutMs)]);\n}\n\n/**\n * Claude Code — and any client that treats `structuredContent` as the canonical\n * model view — discards the `text` blocks when `structuredContent` is present,\n * showing the model `JSON.stringify(structuredContent)` instead. A tool that\n * authored a text result (list's ASCII tree, read's file) meant that text for\n * the model, so it ships its metadata under `_meta`, which no client renders in\n * place of the content. Tools with no `text` keep `structuredContent`: the JSON\n * *is* their model-facing view.\n */\nfunction buildSuccessResponse<O>(result: RunResult<O>): CallToolResult {\n const hasText = result.text !== undefined;\n const text = result.text ?? JSON.stringify(result.structured);\n const content: ContentBlock[] = [{ type: 'text' as const, text }, ...(result.resources ?? [])];\n return {\n content,\n ...(hasText\n ? // Safe because every `ToolDef.output` is a Zod object schema, so\n // `structured` is always a plain object. Constraining `O` to prove it\n // is not worth the cost: the bound has to thread through five generic\n // sites and still loses to `exactOptionalPropertyTypes` variance on\n // `RunResult`'s optional fields.\n { _meta: result.structured as Record<string, unknown> }\n : { structuredContent: result.structured }),\n ...(result.isError ? { isError: true } : {}),\n };\n}\n\nclass ToolExecutor<I extends z.ZodType, O extends z.ZodType> {\n readonly signal: AbortSignal;\n private readonly def: ToolDef<I, O>;\n private readonly parsedArgs: z.infer<I>;\n private readonly toolCtx: ToolCtx;\n\n #progressClosed = false;\n readonly #progressCtx: ProgressCtx;\n readonly #mcpSink?: McpProgressSink;\n readonly #progressSession: ProgressSession;\n\n constructor(toolName: string, ctx: ToolCtx, def: ToolDef<I, O>, parsedArgs: z.infer<I>) {\n this.def = def;\n this.parsedArgs = parsedArgs;\n this.signal = composeSignal(ctx.signal, def.timeoutMs);\n this.#progressCtx = resolveProgressCtx(def, parsedArgs);\n const token = ctx._meta?.progressToken;\n if (token !== undefined && ctx.sendNotification !== undefined) {\n this.#mcpSink = new McpProgressSink(toolName, token, ctx.sendNotification);\n }\n const isTest = process.env['NODE_ENV'] === 'test' || process.execArgv.includes('--test');\n this.#progressSession = new ProgressSession({\n label: this.#progressCtx.label,\n ...(this.#mcpSink ? { sink: this.#mcpSink } : {}),\n ...(isTest ? { rateLimitMs: 0 } : {}),\n });\n this.toolCtx = {\n ...ctx,\n signal: this.signal,\n log: (level: LoggingLevel, data: unknown, logger?: string) => {\n const msg = typeof data === 'string' ? data : String(data);\n const prefix = logger ? `[${logger}] ` : '';\n Logger.emit(level, `${prefix}${msg}`);\n },\n onProgress: (p) => {\n this.#tick(p);\n },\n };\n }\n\n #tick(p: { current: number; total?: number }): void {\n if (this.#progressClosed) return;\n const tickCtx: ProgressCtx = {\n ...this.#progressCtx,\n current: p.current,\n ...(p.total !== undefined ? { total: p.total } : {}),\n };\n this.#progressSession.set({ ...p, message: plainMessage('tick', tickCtx) });\n }\n\n async #closeWithDone(message: string): Promise<void> {\n this.#progressClosed = true;\n this.#progressSession.complete(message);\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n async #closeWithFail(error: unknown, message: string): Promise<void> {\n this.#progressClosed = true;\n this.#progressSession.fail(error, message);\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n async #flushProgress(): Promise<void> {\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n private async completeProgress(result: z.infer<O>): Promise<void> {\n const doneCtx: ProgressCtx = this.def.progressDone\n ? { ...this.#progressCtx, ...this.def.progressDone(this.parsedArgs, result) }\n : this.#progressCtx;\n await this.#closeWithDone(plainMessage('done', doneCtx));\n }\n\n private async failProgress(error: unknown): Promise<{ isError: true; content: ContentBlock[] }> {\n const errMsg = formatUnknownErrorMessage(error);\n const message = plainMessage('fail', { ...this.#progressCtx, error: errMsg });\n await this.#closeWithFail(error, message);\n const { text: errorText } = Problem.toText(\n error,\n this.def.defaultErrorCode ?? ErrorCode.UNKNOWN,\n );\n return {\n content: [{ type: 'text' as const, text: errorText }],\n isError: true,\n };\n }\n\n /**\n * Access-grant pre-check (R7/R8/R9). Before `run` touches the filesystem,\n * ask PathGuard which of the tool's declared paths are out-of-root and\n * grantable. If any are and this round carries no verified `requestState`,\n * return `input_required` (nothing is read or written — R7). On retry, the\n * verified state must bind this grant set (R9); apply each accepted grant for\n * the session (R8) and proceed. A declined or ungrantable path is left for\n * `validateAccess` to fail closed during the operation. Returns `undefined`\n * when no round-trip is needed and any applicable grants have been applied.\n */\n private async precheckGrant(): Promise<InputRequiredResult | undefined> {\n const extract = this.def.accessPaths;\n if (!extract) return undefined;\n const paths = extract(this.parsedArgs);\n if (paths.length === 0) return undefined;\n const grantDirs = await this.toolCtx.fs.pathGuard.precheckAccess(paths);\n if (grantDirs.length === 0) return undefined;\n\n // One grant dir: a single boolean confirm. Multiple: one multi-select\n // elicitation so the client picks the subset to allow in one round-trip\n // (N dirs → 1 round-trip, not N). `pendingRoundTrip` still binds\n // `paths: grantDirs` sorted, so R9 path-binding is unaffected.\n const multi = grantDirs.length > 1;\n const round = await pendingRoundTrip({\n op: 'grant',\n pending: grantDirs,\n requestState: this.toolCtx.requestState,\n clientCapabilities: this.toolCtx.clientCapabilities,\n buildInputs: (dirs) =>\n multi\n ? [\n multiSelectInput(\n 'grant',\n 'Grant filesystem access to these directories? Select the ones to allow.',\n dirs.map((d) => ({ value: d, title: d })),\n ),\n ]\n : dirs.map((dir, i) =>\n confirmInput(`confirm_${i}`, `Grant filesystem access to \"${dir}\"?`),\n ),\n });\n if (round !== undefined) return round;\n // Apply accepted grants for the session (R8). Declined/missing dirs are\n // skipped here; their paths fail with ACCESS_DENIED during the operation.\n //\n // No list-changed notification follows: a grant widens the allowed roots,\n // and no resource list reads them. The instructions resource has a fixed\n // URI, the result template lists the ResourceStore, and the file template\n // lists nothing at all (see resources.ts). Notifying here only bought the\n // client a round trip to re-fetch a list that could not have changed.\n //\n // `readAcceptedMultiChoice` does NOT validate against the offered choices\n // (attacker-controlled inputResponses on re-entry). Only grant dirs that\n // were actually offered by precheckAccess — a value outside grantDirs is\n // ignored and fails closed in validateAccess. The single-select path reads\n // `confirm_${i}` for `grantDirs[i]`, so the isSamePath filter is a no-op\n // there; it only bites for the multi-select array.\n const accepted = multi\n ? (readAcceptedMultiChoice(this.toolCtx.inputResponses, 'grant') ?? [])\n : grantDirs.filter((_dir, i) =>\n readAcceptedConfirm(this.toolCtx.inputResponses, `confirm_${i}`),\n );\n for (const dir of accepted) {\n if (!grantDirs.some((g) => isSamePath(g, dir))) continue;\n await this.toolCtx.fs.pathGuard.applyGrant(dir);\n }\n return undefined;\n }\n\n async execute(): Promise<CallToolResult | InputRequiredResult> {\n const runTool = async (): Promise<CallToolResult | InputRequiredResult> => {\n try {\n // Access-grant pre-check before any filesystem touch (R7/R8/R9). A\n // grant input_required short-circuits here (progress paused, not\n // finished); an R9 mismatch throws, which this catch surfaces as an\n // isError tool result like every other handler failure — not a raw\n // JSON-RPC error (GRANT-1 impact #2).\n const grantRequired = await this.precheckGrant();\n if (grantRequired !== undefined) return grantRequired;\n const result = await this.def.run(this.parsedArgs, this.toolCtx);\n // input_required is a return value, not a completed call: the client\n // retries the same tools/call carrying inputResponses, and this\n // handler re-enters from the top. Skip the progress \"done\" close and\n // return it verbatim — progress is paused, not finished.\n if (isInputRequiredResult(result)) {\n return result;\n }\n await this.completeProgress(result.structured);\n return buildSuccessResponse(result);\n } catch (error) {\n return await this.failProgress(error);\n } finally {\n await this.#flushProgress();\n }\n };\n\n return runTool();\n }\n}\n\nfunction createServerToolHandler<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n deps: ToolDeps,\n): (args: z.infer<I>, ctx: ServerContext) => Promise<CallToolResult | InputRequiredResult> {\n return async (args, ctx) =>\n new ToolExecutor<I, O>(def.name, toToolCtx(ctx, deps), def, args).execute();\n}\n\n/**\n * Validate with Zod while publishing the precomputed JSON Schema: clients get\n * draft-2020-12, handlers get Zod's coercions, defaults and error messages.\n *\n * Each validator instance is built for exactly one schema and handed straight\n * to `fromJsonSchema(thatSchema, ...)`, which calls `getValidator` once with\n * the same schema — so the argument is redundant here and deliberately ignored.\n * Reusing one instance across schemas would silently validate against `schema`.\n */\nfunction zodJsonSchemaValidator(schema: z.ZodType): jsonSchemaValidator {\n return {\n getValidator<U>(): JsonSchemaValidator<U> {\n return (input: unknown) => {\n const result = schema.safeParse(input);\n if (result.success) {\n return {\n valid: true as const,\n data: result.data as U,\n errorMessage: undefined,\n };\n }\n return {\n valid: false as const,\n data: undefined,\n errorMessage: z.prettifyError(result.error),\n };\n };\n },\n };\n}\n\n/**\n * Generate the wire copy of a schema for `tools/list`. The Zod schema keeps\n * every constraint for runtime validation; the `override` pass only trims what\n * the wire copy costs every client at session start:\n *\n * - `$schema` and `title` carry no information the host uses.\n * - `maximum: Number.MAX_SAFE_INTEGER` is zod's int() artifact, not a bound.\n * - `examples` is dropped in both directions: on output it describes a field the\n * server itself fills in, and on input every description that carried one\n * already spells the same example out inline, so the keyword paid twice.\n *\n * Output `description`s are NOT dropped. They were, and the result was a wire\n * contract the model had to guess at: `delete` returns `path` XOR `paths`,\n * `edit.diff` appears only under dryRun, `read.value` has no required field at\n * all. None of that is inferable from types alone.\n *\n * No shared subschema carries a `.meta({ id })`, so zod inlines every one of\n * them and the emitted document has no `$defs`/`$ref` to dereference.\n */\nfunction toDraft202012(schema: z.ZodType, io: 'input' | 'output'): JsonSchemaType {\n const generated = z.toJSONSchema(schema, {\n target: 'draft-2020-12',\n io,\n override: ({ jsonSchema }) => {\n const node = jsonSchema as Record<string, unknown>;\n delete node['title'];\n if (node['maximum'] === Number.MAX_SAFE_INTEGER) delete node['maximum'];\n delete node['examples'];\n },\n }) as Record<string, unknown>;\n delete generated['$schema'];\n return generated;\n}\n\nexport function defineTool<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n): DefinedTool {\n const inputJsonSchema = toDraft202012(def.input, 'input');\n\n // Nothing here depends on `deps`, so it is built once per tool definition\n // rather than once per `register` — the HTTP leg registers every tool afresh\n // on each request.\n // Published annotations are derived, not passed through. `readOnlyHint` is\n // load-bearing (MUTATING_TOOL_NAMES derives the --read-only gate from it) and\n // `openWorldHint: false` is a real claim for a filesystem server. The other\n // two describe behavior a read-only tool cannot have, and restate the default\n // for a mutating one — 29 tokens per tool for nothing a client acts on.\n const publishedAnnotations: ToolAnnotations = {\n readOnlyHint: def.annotations.readOnlyHint,\n openWorldHint: def.annotations.openWorldHint ?? false,\n ...(def.annotations.readOnlyHint\n ? {}\n : { destructiveHint: def.annotations.destructiveHint ?? true }),\n };\n\n const toolDefShape = {\n title: def.title,\n description: def.description,\n inputSchema: fromJsonSchema<z.infer<I>>(inputJsonSchema, zodJsonSchemaValidator(def.input)),\n // No `outputSchema`, ever. Publishing one obliges the result to carry\n // `structuredContent` (clients enforce it), and every tool that authors its\n // own text ships its metadata under `_meta` instead — see\n // `buildSuccessResponse`. The two cannot both hold, and the text is what\n // the model reads. `TOOL-SURFACE-001` pins this for the whole surface.\n //\n // `def.output` stays: it types `RunResult<z.infer<O>>`, which is what makes\n // a tool returning the wrong shape a compile error.\n annotations: publishedAnnotations,\n };\n\n const tool: DefinedTool = {\n name: def.name,\n annotations: def.annotations,\n\n register(deps: ToolDeps): RegisteredTool {\n return deps.server.registerTool(def.name, toolDefShape, createServerToolHandler(def, deps));\n },\n };\n\n return tool;\n}\n"]}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,yBAAyB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAElF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAuGjE,SAAS,SAAS,CAChB,GAA8B,EAC9B,IAA4E;IAE5E,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC,MAAM,CAAC;QAC5C,OAAO;YACL,MAAM;YACN,EAAE,EAAE,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC;YACzC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IACD,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,8EAA8E;IAC9E,2EAA2E;IAC3E,4BAA4B;IAC5B,EAAE;IACF,6EAA6E;IAC7E,8EAA8E;IAC9E,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,QAA+C,CAAC;IAC5E,MAAM,kBAAkB,GACrB,QAAQ,EAAE,CAAC,4BAA4B,CAAoC;QAC5E,wJAAwJ;QACxJ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;IAE7C,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM;QACzB,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,EAAE,EAAE,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC;QACzC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,gBAAgB,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;QACzE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,cAAc;QACzC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY;QACrC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,GAAkB,EAClB,IAAgB;IAEhB,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,uBAAuB,GAAG,CAAC,IAAI,oBAAoB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9E,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAiB,EAAE,SAAkB;IAC1D,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,oBAAoB,CAAI,MAAoB;IACnD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAmB,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/F,OAAO;QACL,OAAO;QACP,GAAG,CAAC,OAAO;YACT,CAAC,CAAC,iEAAiE;gBACjE,sEAAsE;gBACtE,sEAAsE;gBACtE,oEAAoE;gBACpE,iCAAiC;gBACjC,EAAE,KAAK,EAAE,MAAM,CAAC,UAAqC,EAAE;YACzD,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;QAC7C,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,YAAY;IACP,MAAM,CAAc;IACZ,GAAG,CAAgB;IACnB,UAAU,CAAa;IACvB,OAAO,CAAU;IAElC,eAAe,GAAG,KAAK,CAAC;IACf,YAAY,CAAc;IAC1B,QAAQ,CAAmB;IAC3B,gBAAgB,CAAkB;IAE3C,YAAY,QAAgB,EAAE,GAAY,EAAE,GAAkB,EAAE,UAAsB;QACpF,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,YAAY,GAAG,kBAAkB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC;QACvC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC9D,IAAI,CAAC,QAAQ,GAAG,IAAI,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzF,IAAI,CAAC,gBAAgB,GAAG,IAAI,eAAe,CAAC;YAC1C,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK;YAC9B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG;YACb,GAAG,GAAG;YACN,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,CAAC,KAAmB,EAAE,IAAa,EAAE,MAAe,EAAE,EAAE;gBAC3D,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;YACxC,CAAC;YACD,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE;gBAChB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAChB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,CAAsC;QAC1C,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACjC,MAAM,OAAO,GAAgB;YAC3B,GAAG,IAAI,CAAC,YAAY;YACpB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrD,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAe;QAClC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAc,EAAE,OAAe;QAClD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjD,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,MAAkB;QAC/C,MAAM,OAAO,GAAgB,IAAI,CAAC,GAAG,CAAC,YAAY;YAChD,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE;YAC7E,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;QACtB,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,KAAc;QACvC,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9E,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CACxC,KAAK,EACL,IAAI,CAAC,GAAG,CAAC,gBAAgB,IAAI,SAAS,CAAC,OAAO,CAC/C,CAAC;QACF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;YACrD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,aAAa;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QACrC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACxE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAE7C,sEAAsE;QACtE,wEAAwE;QACxE,iEAAiE;QACjE,+DAA+D;QAC/D,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC;YACnC,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,SAAS;YAClB,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;YACvC,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,kBAAkB;YACnD,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CACpB,KAAK;gBACH,CAAC,CAAC;oBACE,gBAAgB,CACd,OAAO,EACP,yEAAyE,EACzE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAC1C;iBACF;gBACH,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;oBACpB,GAAG,EAAE,WAAW,CAAC,EAAE;oBACnB,OAAO,EAAE,+BAA+B,GAAG,IAAI;iBAChD,CAAC,CAAC;SACV,CAAC,CAAC;QACH,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,wEAAwE;QACxE,0EAA0E;QAC1E,EAAE;QACF,0EAA0E;QAC1E,yEAAyE;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,sEAAsE;QACtE,EAAE;QACF,0EAA0E;QAC1E,yEAAyE;QACzE,yEAAyE;QACzE,2EAA2E;QAC3E,yEAAyE;QACzE,mDAAmD;QACnD,MAAM,QAAQ,GAAG,KAAK;YACpB,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;YACvE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAC3B,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,WAAW,CAAC,EAAE,CAAC,CACjE,CAAC;QACN,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAAE,SAAS;YACzD,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,GAAG,KAAK,IAAmD,EAAE;YACxE,IAAI,CAAC;gBACH,mEAAmE;gBACnE,iEAAiE;gBACjE,oEAAoE;gBACpE,mEAAmE;gBACnE,sCAAsC;gBACtC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjD,IAAI,aAAa,KAAK,SAAS;oBAAE,OAAO,aAAa,CAAC;gBACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACjE,qEAAqE;gBACrE,gEAAgE;gBAChE,qEAAqE;gBACrE,yDAAyD;gBACzD,IAAI,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;oBAClC,OAAO,MAAM,CAAC;gBAChB,CAAC;gBACD,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAC/C,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACxC,CAAC;oBAAS,CAAC;gBACT,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,OAAO,OAAO,EAAE,CAAC;IACnB,CAAC;CACF;AAED,SAAS,uBAAuB,CAC9B,GAAkB,EAClB,IAAc;IAEd,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CACzB,IAAI,YAAY,CAAO,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AAChF,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,sBAAsB,CAAC,MAAiB;IAC/C,OAAO;QACL,YAAY;YACV,OAAO,CAAC,KAAc,EAAE,EAAE;gBACxB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACvC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,OAAO;wBACL,KAAK,EAAE,IAAa;wBACpB,IAAI,EAAE,MAAM,CAAC,IAAS;wBACtB,YAAY,EAAE,SAAS;qBACxB,CAAC;gBACJ,CAAC;gBACD,OAAO;oBACL,KAAK,EAAE,KAAc;oBACrB,IAAI,EAAE,SAAS;oBACf,YAAY,EAAE,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC5C,CAAC;YACJ,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,aAAa,CAAC,MAAiB,EAAE,EAAsB;IAC9D,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE;QACvC,MAAM,EAAE,eAAe;QACvB,EAAE;QACF,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,UAAqC,CAAC;YACnD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,gBAAgB;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;YACxE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;KACF,CAA4B,CAAC;IAC9B,OAAO,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,GAAkB;IAElB,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1D,0EAA0E;IAC1E,6EAA6E;IAC7E,mBAAmB;IACnB,2EAA2E;IAC3E,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,wEAAwE;IACxE,MAAM,oBAAoB,GAAoB;QAC5C,YAAY,EAAE,GAAG,CAAC,WAAW,CAAC,YAAY;QAC1C,aAAa,EAAE,GAAG,CAAC,WAAW,CAAC,aAAa,IAAI,KAAK;QACrD,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY;YAC9B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,WAAW,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;KAClE,CAAC;IAEF,MAAM,YAAY,GAAG;QACnB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,cAAc,CAAa,eAAe,EAAE,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3F,sEAAsE;QACtE,4EAA4E;QAC5E,0DAA0D;QAC1D,yEAAyE;QACzE,uEAAuE;QACvE,EAAE;QACF,4EAA4E;QAC5E,oDAAoD;QACpD,WAAW,EAAE,oBAAoB;KAClC,CAAC;IAEF,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAE5B,QAAQ,CAAC,IAAc;YACrB,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9F,CAAC;KACF,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import type {\n AuthInfo,\n CallToolResult,\n ClientCapabilities,\n ContentBlock,\n InputRequiredResult,\n JsonSchemaType,\n JsonSchemaValidator,\n jsonSchemaValidator,\n McpServer,\n Notification,\n RegisteredTool,\n RequestMeta,\n RequestStateAccessor,\n ServerContext,\n ToolAnnotations,\n} from '@modelcontextprotocol/server';\nimport {\n CLIENT_CAPABILITIES_META_KEY,\n fromJsonSchema,\n isInputRequiredResult,\n} from '@modelcontextprotocol/server';\n\nimport * as z from 'zod/v4';\n\nimport { ErrorCode, formatUnknownErrorMessage, Problem } from '../core/errors.js';\nimport type { ProgressCtx } from '../core/fmt.js';\nimport { plainMessage } from '../core/fmt.js';\nimport { GuardedFileSystem } from '../core/fs.js';\nimport {\n multiSelectInput,\n pendingRoundTrip,\n readAcceptedConfirm,\n readAcceptedMultiChoice,\n} from '../core/input-required.js';\nimport { Logger } from '../core/observability.js';\nimport type { LoggingLevel } from '../core/observability.js';\nimport type { PageSnapshotStore } from '../core/page-store.js';\nimport { isSamePath } from '../core/path-utils.js';\nimport type { PathGuard } from '../core/path.js';\nimport type { ResourceStore } from '../core/store.js';\nimport { McpProgressSink, ProgressSession } from './progress.js';\n\nexport interface ToolCtx {\n readonly signal: AbortSignal;\n readonly sessionId?: string;\n readonly authInfo?: AuthInfo;\n readonly _meta?: RequestMeta | undefined;\n readonly fs: GuardedFileSystem;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n /** Emits a log line to stderr via `Logger.emit`, gated by `LOG_LEVEL`. */\n readonly log?: (level: LoggingLevel, data: unknown, logger?: string) => void;\n readonly sendNotification?: (notification: Notification) => Promise<void>;\n readonly onProgress?: (params: { current: number; total?: number }) => void;\n /**\n * Multi-round-trip `inputResponses` carried by a retried `tools/call`\n * (protocol revision 2026-07-28); `undefined` on the first round. Bare,\n * unvalidated client values — handlers read them through\n * `readAcceptedConfirm`.\n */\n readonly inputResponses?: Record<string, unknown> | undefined;\n /**\n * Reads the verified multi-round-trip `requestState` for the current round:\n * the decoded `PendingState` the `requestStateCodec` verified, or `undefined`\n * when the round carried no state (the first round). `undefined` when no\n * live request context is available.\n */\n readonly requestState?: RequestStateAccessor | undefined;\n /**\n * What the connected client declared it can do, or `undefined` when this\n * connection cannot say. Read by the `input_required` flows: an embedded\n * elicitation sent to a client that never declared `elicitation` is rejected\n * by the SDK with `-32021` before it reaches the wire, so the handlers check\n * first and answer with an actionable tool error instead.\n *\n * Two sources, because the eras differ: a legacy connection negotiated them\n * at `initialize` (`Server.getClientCapabilities()`), a modern one carries\n * them per request in the `_meta` envelope and never runs `initialize` at\n * all. `undefined` means \"cannot tell\" — never \"no capabilities\".\n */\n readonly clientCapabilities?: ClientCapabilities | undefined;\n readonly server?: McpServer;\n}\n\ninterface ToolDeps {\n readonly server: McpServer;\n readonly pathGuard: PathGuard;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n}\n\ninterface RunResult<T> {\n readonly structured: T;\n readonly text?: string;\n readonly resources?: ContentBlock[];\n /**\n * The call as a whole failed. Batch tools set it from `isTotalFailure` in\n * `batch.ts` — every requested item failed — so the executor never has to\n * know a tool's output shape. Absent or `false` means the call did work.\n */\n readonly isError?: boolean;\n}\n\n/**\n * `ToolAnnotations` with `readOnlyHint` required. It is optional in the SDK, but\n * MUTATING_TOOL_NAMES derives the `--read-only` gate from it, so a tool that\n * forgets it must be a compile error rather than a silent reclassification.\n */\ntype DeclaredAnnotations = ToolAnnotations & { readonly readOnlyHint: boolean };\n\nexport interface ToolDef<I extends z.ZodType, O extends z.ZodType> {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n readonly input: I;\n readonly output: O;\n readonly annotations: DeclaredAnnotations;\n readonly timeoutMs?: number;\n readonly progress?: (args: z.infer<I>) => ProgressCtx;\n readonly progressDone?: (args: z.infer<I>, result: z.infer<O>) => Partial<ProgressCtx>;\n readonly defaultErrorCode?: ErrorCode;\n /**\n * The filesystem paths this tool will operate on, extracted from its parsed\n * args. The executor runs an access-grant pre-check over these BEFORE `run`\n * (R7): any path outside the granted roots yields an `input_required`\n * round-trip requesting a grant, and nothing is touched until the client\n * retries with an accepted grant (R8). Omit for tools that do not operate on\n * caller-supplied filesystem paths.\n */\n readonly accessPaths?: (args: z.infer<I>) => readonly string[];\n readonly run: (\n args: z.infer<I>,\n ctx: ToolCtx,\n ) => Promise<RunResult<z.infer<O>> | InputRequiredResult>;\n}\n\nexport interface DefinedTool {\n readonly name: string;\n readonly annotations: DeclaredAnnotations;\n\n register(deps: ToolDeps): RegisteredTool;\n}\n\nfunction toToolCtx(\n ctx: ServerContext | undefined,\n deps: Pick<ToolDeps, 'pathGuard' | 'pageStore' | 'resourceStore' | 'server'>,\n): ToolCtx {\n if (!ctx) {\n const signal = new AbortController().signal;\n return {\n signal,\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n server: deps.server,\n };\n }\n // Envelope first, accessor second — the two eras carry this differently.\n // A modern request states the capabilities in its own `_meta` envelope; a\n // legacy connection fixed them at `initialize` and has no envelope at all.\n // The deprecated accessor still answers for both today (the SDK backfills it\n // per request from the validated envelope on modern instances), but reading\n // the envelope directly is the supported path, so it leads: when the accessor\n // goes, legacy degrades to \"cannot tell\", which fails open to the behavior\n // that predates this check.\n //\n // The cast is the SDK's shipped `RequestMetaEnvelope` declaration collapsing\n // to `{}` — the reserved keys survive at runtime but not in the .d.ts, so the\n // key constant cannot index the declared type.\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined;\n const clientCapabilities =\n (envelope?.[CLIENT_CAPABILITIES_META_KEY] as ClientCapabilities | undefined) ??\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- the only source of client capabilities on a legacy connection, where no envelope exists.\n deps.server.server.getClientCapabilities();\n\n return {\n signal: ctx.mcpReq.signal,\n ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),\n ...(ctx.http?.authInfo ? { authInfo: ctx.http.authInfo } : {}),\n ...(ctx.mcpReq._meta ? { _meta: ctx.mcpReq._meta } : {}),\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n sendNotification: async (notification) => ctx.mcpReq.notify(notification),\n inputResponses: ctx.mcpReq.inputResponses,\n requestState: ctx.mcpReq.requestState,\n ...(clientCapabilities ? { clientCapabilities } : {}),\n server: deps.server,\n };\n}\n\nfunction resolveProgressCtx<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n args: z.infer<I>,\n): ProgressCtx {\n if (!def.progress) return { label: def.title };\n try {\n return def.progress(args);\n } catch (err: unknown) {\n Logger.warn(`resolveProgressCtx: ${def.name}.progress threw: ${String(err)}`);\n return { label: def.title };\n }\n}\n\nfunction composeSignal(base: AbortSignal, timeoutMs?: number): AbortSignal {\n if (!timeoutMs) return base;\n return AbortSignal.any([base, AbortSignal.timeout(timeoutMs)]);\n}\n\n/**\n * Claude Code — and any client that treats `structuredContent` as the canonical\n * model view — discards the `text` blocks when `structuredContent` is present,\n * showing the model `JSON.stringify(structuredContent)` instead. A tool that\n * authored a text result (list's ASCII tree, read's file) meant that text for\n * the model, so it ships its metadata under `_meta`, which no client renders in\n * place of the content. Tools with no `text` keep `structuredContent`: the JSON\n * *is* their model-facing view.\n */\nfunction buildSuccessResponse<O>(result: RunResult<O>): CallToolResult {\n const hasText = result.text !== undefined;\n const text = result.text ?? JSON.stringify(result.structured);\n const content: ContentBlock[] = [{ type: 'text' as const, text }, ...(result.resources ?? [])];\n return {\n content,\n ...(hasText\n ? // Safe because every `ToolDef.output` is a Zod object schema, so\n // `structured` is always a plain object. Constraining `O` to prove it\n // is not worth the cost: the bound has to thread through five generic\n // sites and still loses to `exactOptionalPropertyTypes` variance on\n // `RunResult`'s optional fields.\n { _meta: result.structured as Record<string, unknown> }\n : { structuredContent: result.structured }),\n ...(result.isError ? { isError: true } : {}),\n };\n}\n\nclass ToolExecutor<I extends z.ZodType, O extends z.ZodType> {\n readonly signal: AbortSignal;\n private readonly def: ToolDef<I, O>;\n private readonly parsedArgs: z.infer<I>;\n private readonly toolCtx: ToolCtx;\n\n #progressClosed = false;\n readonly #progressCtx: ProgressCtx;\n readonly #mcpSink?: McpProgressSink;\n readonly #progressSession: ProgressSession;\n\n constructor(toolName: string, ctx: ToolCtx, def: ToolDef<I, O>, parsedArgs: z.infer<I>) {\n this.def = def;\n this.parsedArgs = parsedArgs;\n this.signal = composeSignal(ctx.signal, def.timeoutMs);\n this.#progressCtx = resolveProgressCtx(def, parsedArgs);\n const token = ctx._meta?.progressToken;\n if (token !== undefined && ctx.sendNotification !== undefined) {\n this.#mcpSink = new McpProgressSink(toolName, token, ctx.sendNotification);\n }\n const isTest = process.env['NODE_ENV'] === 'test' || process.execArgv.includes('--test');\n this.#progressSession = new ProgressSession({\n label: this.#progressCtx.label,\n ...(this.#mcpSink ? { sink: this.#mcpSink } : {}),\n ...(isTest ? { rateLimitMs: 0 } : {}),\n });\n this.toolCtx = {\n ...ctx,\n signal: this.signal,\n log: (level: LoggingLevel, data: unknown, logger?: string) => {\n const msg = typeof data === 'string' ? data : String(data);\n const prefix = logger ? `[${logger}] ` : '';\n Logger.emit(level, `${prefix}${msg}`);\n },\n onProgress: (p) => {\n this.#tick(p);\n },\n };\n }\n\n #tick(p: { current: number; total?: number }): void {\n if (this.#progressClosed) return;\n const tickCtx: ProgressCtx = {\n ...this.#progressCtx,\n current: p.current,\n ...(p.total !== undefined ? { total: p.total } : {}),\n };\n this.#progressSession.set({ ...p, message: plainMessage('tick', tickCtx) });\n }\n\n async #closeWithDone(message: string): Promise<void> {\n this.#progressClosed = true;\n this.#progressSession.complete(message);\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n async #closeWithFail(error: unknown, message: string): Promise<void> {\n this.#progressClosed = true;\n this.#progressSession.fail(error, message);\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n async #flushProgress(): Promise<void> {\n if (this.#mcpSink) await this.#mcpSink.flush();\n }\n\n private async completeProgress(result: z.infer<O>): Promise<void> {\n const doneCtx: ProgressCtx = this.def.progressDone\n ? { ...this.#progressCtx, ...this.def.progressDone(this.parsedArgs, result) }\n : this.#progressCtx;\n await this.#closeWithDone(plainMessage('done', doneCtx));\n }\n\n private async failProgress(error: unknown): Promise<{ isError: true; content: ContentBlock[] }> {\n const errMsg = formatUnknownErrorMessage(error);\n const message = plainMessage('fail', { ...this.#progressCtx, error: errMsg });\n await this.#closeWithFail(error, message);\n const { text: errorText } = Problem.toText(\n error,\n this.def.defaultErrorCode ?? ErrorCode.UNKNOWN,\n );\n return {\n content: [{ type: 'text' as const, text: errorText }],\n isError: true,\n };\n }\n\n /**\n * Access-grant pre-check (R7/R8/R9). Before `run` touches the filesystem,\n * ask PathGuard which of the tool's declared paths are out-of-root and\n * grantable. If any are and this round carries no verified `requestState`,\n * return `input_required` (nothing is read or written — R7). On retry, the\n * verified state must bind this grant set (R9); apply each accepted grant for\n * the session (R8) and proceed. A declined or ungrantable path is left for\n * `validateAccess` to fail closed during the operation. Returns `undefined`\n * when no round-trip is needed and any applicable grants have been applied.\n */\n private async precheckGrant(): Promise<InputRequiredResult | undefined> {\n const extract = this.def.accessPaths;\n if (!extract) return undefined;\n const paths = extract(this.parsedArgs);\n if (paths.length === 0) return undefined;\n const grantDirs = await this.toolCtx.fs.pathGuard.precheckAccess(paths);\n if (grantDirs.length === 0) return undefined;\n\n // One grant dir: a single boolean confirm. Multiple: one multi-select\n // elicitation so the client picks the subset to allow in one round-trip\n // (N dirs → 1 round-trip, not N). `pendingRoundTrip` still binds\n // `paths: grantDirs` sorted, so R9 path-binding is unaffected.\n const multi = grantDirs.length > 1;\n const round = await pendingRoundTrip({\n op: 'grant',\n pending: grantDirs,\n requestState: this.toolCtx.requestState,\n clientCapabilities: this.toolCtx.clientCapabilities,\n buildInputs: (dirs) =>\n multi\n ? [\n multiSelectInput(\n 'grant',\n 'Grant filesystem access to these directories? Select the ones to allow.',\n dirs.map((d) => ({ value: d, title: d })),\n ),\n ]\n : dirs.map((dir, i) => ({\n key: `confirm_${i}`,\n message: `Grant filesystem access to \"${dir}\"?`,\n })),\n });\n if (round !== undefined) return round;\n // Apply accepted grants for the session (R8). Declined/missing dirs are\n // skipped here; their paths fail with ACCESS_DENIED during the operation.\n //\n // No list-changed notification follows: a grant widens the allowed roots,\n // and no resource list reads them. The instructions resource has a fixed\n // URI, the result template lists the ResourceStore, and the file template\n // lists nothing at all (see resources.ts). Notifying here only bought the\n // client a round trip to re-fetch a list that could not have changed.\n //\n // `readAcceptedMultiChoice` does NOT validate against the offered choices\n // (attacker-controlled inputResponses on re-entry). Only grant dirs that\n // were actually offered by precheckAccess — a value outside grantDirs is\n // ignored and fails closed in validateAccess. The single-select path reads\n // `confirm_${i}` for `grantDirs[i]`, so the isSamePath filter is a no-op\n // there; it only bites for the multi-select array.\n const accepted = multi\n ? (readAcceptedMultiChoice(this.toolCtx.inputResponses, 'grant') ?? [])\n : grantDirs.filter((_dir, i) =>\n readAcceptedConfirm(this.toolCtx.inputResponses, `confirm_${i}`),\n );\n for (const dir of accepted) {\n if (!grantDirs.some((g) => isSamePath(g, dir))) continue;\n await this.toolCtx.fs.pathGuard.applyGrant(dir);\n }\n return undefined;\n }\n\n async execute(): Promise<CallToolResult | InputRequiredResult> {\n const runTool = async (): Promise<CallToolResult | InputRequiredResult> => {\n try {\n // Access-grant pre-check before any filesystem touch (R7/R8/R9). A\n // grant input_required short-circuits here (progress paused, not\n // finished); an R9 mismatch throws, which this catch surfaces as an\n // isError tool result like every other handler failure — not a raw\n // JSON-RPC error (GRANT-1 impact #2).\n const grantRequired = await this.precheckGrant();\n if (grantRequired !== undefined) return grantRequired;\n const result = await this.def.run(this.parsedArgs, this.toolCtx);\n // input_required is a return value, not a completed call: the client\n // retries the same tools/call carrying inputResponses, and this\n // handler re-enters from the top. Skip the progress \"done\" close and\n // return it verbatim — progress is paused, not finished.\n if (isInputRequiredResult(result)) {\n return result;\n }\n await this.completeProgress(result.structured);\n return buildSuccessResponse(result);\n } catch (error) {\n return await this.failProgress(error);\n } finally {\n await this.#flushProgress();\n }\n };\n\n return runTool();\n }\n}\n\nfunction createServerToolHandler<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n deps: ToolDeps,\n): (args: z.infer<I>, ctx: ServerContext) => Promise<CallToolResult | InputRequiredResult> {\n return async (args, ctx) =>\n new ToolExecutor<I, O>(def.name, toToolCtx(ctx, deps), def, args).execute();\n}\n\n/**\n * Validate with Zod while publishing the precomputed JSON Schema: clients get\n * draft-2020-12, handlers get Zod's coercions, defaults and error messages.\n *\n * Each validator instance is built for exactly one schema and handed straight\n * to `fromJsonSchema(thatSchema, ...)`, which calls `getValidator` once with\n * the same schema — so the argument is redundant here and deliberately ignored.\n * Reusing one instance across schemas would silently validate against `schema`.\n */\nfunction zodJsonSchemaValidator(schema: z.ZodType): jsonSchemaValidator {\n return {\n getValidator<U>(): JsonSchemaValidator<U> {\n return (input: unknown) => {\n const result = schema.safeParse(input);\n if (result.success) {\n return {\n valid: true as const,\n data: result.data as U,\n errorMessage: undefined,\n };\n }\n return {\n valid: false as const,\n data: undefined,\n errorMessage: z.prettifyError(result.error),\n };\n };\n },\n };\n}\n\n/**\n * Generate the wire copy of a schema for `tools/list`. The Zod schema keeps\n * every constraint for runtime validation; the `override` pass only trims what\n * the wire copy costs every client at session start:\n *\n * - `$schema` and `title` carry no information the host uses.\n * - `maximum: Number.MAX_SAFE_INTEGER` is zod's int() artifact, not a bound.\n * - `examples` is dropped in both directions: on output it describes a field the\n * server itself fills in, and on input every description that carried one\n * already spells the same example out inline, so the keyword paid twice.\n *\n * Output `description`s are NOT dropped. They were, and the result was a wire\n * contract the model had to guess at: `delete` returns `path` XOR `paths`,\n * `edit.diff` appears only under dryRun, `read.value` has no required field at\n * all. None of that is inferable from types alone.\n *\n * No shared subschema carries a `.meta({ id })`, so zod inlines every one of\n * them and the emitted document has no `$defs`/`$ref` to dereference.\n */\nfunction toDraft202012(schema: z.ZodType, io: 'input' | 'output'): JsonSchemaType {\n const generated = z.toJSONSchema(schema, {\n target: 'draft-2020-12',\n io,\n override: ({ jsonSchema }) => {\n const node = jsonSchema as Record<string, unknown>;\n delete node['title'];\n if (node['maximum'] === Number.MAX_SAFE_INTEGER) delete node['maximum'];\n delete node['examples'];\n },\n }) as Record<string, unknown>;\n delete generated['$schema'];\n return generated;\n}\n\nexport function defineTool<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n): DefinedTool {\n const inputJsonSchema = toDraft202012(def.input, 'input');\n\n // Nothing here depends on `deps`, so it is built once per tool definition\n // rather than once per `register` — the HTTP leg registers every tool afresh\n // on each request.\n // Published annotations are derived, not passed through. `readOnlyHint` is\n // load-bearing (MUTATING_TOOL_NAMES derives the --read-only gate from it) and\n // `openWorldHint: false` is a real claim for a filesystem server. The other\n // two describe behavior a read-only tool cannot have, and restate the default\n // for a mutating one — 29 tokens per tool for nothing a client acts on.\n const publishedAnnotations: ToolAnnotations = {\n readOnlyHint: def.annotations.readOnlyHint,\n openWorldHint: def.annotations.openWorldHint ?? false,\n ...(def.annotations.readOnlyHint\n ? {}\n : { destructiveHint: def.annotations.destructiveHint ?? true }),\n };\n\n const toolDefShape = {\n title: def.title,\n description: def.description,\n inputSchema: fromJsonSchema<z.infer<I>>(inputJsonSchema, zodJsonSchemaValidator(def.input)),\n // No `outputSchema`, ever. Publishing one obliges the result to carry\n // `structuredContent` (clients enforce it), and every tool that authors its\n // own text ships its metadata under `_meta` instead — see\n // `buildSuccessResponse`. The two cannot both hold, and the text is what\n // the model reads. `TOOL-SURFACE-001` pins this for the whole surface.\n //\n // `def.output` stays: it types `RunResult<z.infer<O>>`, which is what makes\n // a tool returning the wrong shape a compile error.\n annotations: publishedAnnotations,\n };\n\n const tool: DefinedTool = {\n name: def.name,\n annotations: def.annotations,\n\n register(deps: ToolDeps): RegisteredTool {\n return deps.server.registerTool(def.name, toolDefShape, createServerToolHandler(def, deps));\n },\n };\n\n return tool;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAogBA,eAAO,MAAM,IAAI,mCAwEf,CAAC"}
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AA+fA,eAAO,MAAM,IAAI,mCAwEf,CAAC"}
@@ -125,25 +125,17 @@ const EditFileOutputSchema = z.strictObject({
125
125
  .describe('Per-path edit results ordered to match the input paths'),
126
126
  summary: OperationSummarySchema,
127
127
  });
128
- async function computeDiffStats(original, modified) {
129
- return new Promise((resolve) => {
130
- // Yield to the event loop so we don't completely block
131
- setImmediate(() => {
132
- diffLines(original, modified, {
133
- callback: (changes) => {
134
- let linesAdded = 0;
135
- let linesRemoved = 0;
136
- for (const part of changes) {
137
- if (part.added)
138
- linesAdded += part.count;
139
- else if (part.removed)
140
- linesRemoved += part.count;
141
- }
142
- resolve({ linesAdded, linesRemoved });
143
- },
144
- });
145
- });
146
- });
128
+ function computeDiffStats(original, modified) {
129
+ // diffLines returns the change list synchronously on diff v9.
130
+ let linesAdded = 0;
131
+ let linesRemoved = 0;
132
+ for (const part of diffLines(original, modified)) {
133
+ if (part.added)
134
+ linesAdded += part.count;
135
+ else if (part.removed)
136
+ linesRemoved += part.count;
137
+ }
138
+ return { linesAdded, linesRemoved };
147
139
  }
148
140
  function findEditMatch(content, oldText, ignoreWhitespace, regexCache) {
149
141
  if (ignoreWhitespace) {
@@ -243,9 +235,9 @@ function buildEditFileValue(validPath, meta, modified, result) {
243
235
  ...(result.lineRange ? { lineRange: result.lineRange } : {}),
244
236
  };
245
237
  }
246
- async function finalizeEditResult(originalContent, updatedContent, appliedEdits, unmatchedEdits, lineRange) {
238
+ function finalizeEditResult(originalContent, updatedContent, appliedEdits, unmatchedEdits, lineRange) {
247
239
  const { linesAdded, linesRemoved } = appliedEdits > 0
248
- ? await computeDiffStats(originalContent, updatedContent)
240
+ ? computeDiffStats(originalContent, updatedContent)
249
241
  : { linesAdded: 0, linesRemoved: 0 };
250
242
  return {
251
243
  content: updatedContent,
@@ -275,7 +267,7 @@ function buildEditFileMetadata(content, validPath, appliedEdits, resourceStore)
275
267
  resourceLink,
276
268
  };
277
269
  }
278
- async function applyEdits(content, edits, ignoreWhitespace) {
270
+ function applyEdits(content, edits, ignoreWhitespace) {
279
271
  let newContent = content;
280
272
  let appliedEdits = 0;
281
273
  const unmatchedEdits = [];
@@ -307,17 +299,13 @@ async function handleEditFile(filePath, edits, options, ctx) {
307
299
  const { validPath, content } = await ctx.fs.readEditableText(filePath, {
308
300
  signal: ctx.signal,
309
301
  });
310
- const editResult = await applyEdits(content, edits, options.ignoreWhitespace);
302
+ const editResult = applyEdits(content, edits, options.ignoreWhitespace);
311
303
  if (options.dryRun) {
312
304
  if (editResult.appliedEdits > 0) {
313
305
  const label = basename(validPath);
314
- editResult.diff = await new Promise((resolve) => {
315
- createTwoFilesPatch(label, label, content, editResult.content, 'Original', 'Modified', {
316
- callback: (res) => {
317
- resolve(res ?? '');
318
- },
319
- });
320
- });
306
+ // createTwoFilesPatch returns the unified diff string synchronously on
307
+ // diff v9 (the { callback } option fires via setTimeout and returns undefined).
308
+ editResult.diff = createTwoFilesPatch(label, label, content, editResult.content, 'Original', 'Modified');
321
309
  }
322
310
  // Nothing was written, so there is no updated content to point a
323
311
  // resourceUri or a resource_link at — the file on disk is still the one the
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\nimport { createTwoFilesPatch, diffLines } from 'diff';\n\nimport { ErrorCode, FsError } from '../core/errors.js';\nimport { buildFileResourceLink, buildFileResourceUri } from '../core/file-uri.js';\nimport { detectMimeFromContent } from '../core/mime.js';\nimport { escapeRegexLiteral } from '../core/primitives.js';\nimport { countLines } from '../core/read.js';\nimport {\n defaultFalseBoolean,\n FileKind,\n isBlank,\n IsoDateTime,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n PositiveInt,\n RequiredPath,\n singleOrBatchAccessPaths,\n} from '../core/schema.js';\nimport type { Regex } from '../core/search.js';\nimport { compileRegex, freeRegex } from '../core/search.js';\nimport type { ResourceStore } from '../core/store.js';\nimport { isTotalFailure, runOverPaths } from './batch.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\nconst EditSpecSchema = z\n .strictObject({\n oldText: z\n .string()\n .min(1, 'oldText required')\n .refine((val) => !isBlank(val), {\n message: 'oldText cannot be empty or whitespace-only',\n })\n .describe(\n 'Exact literal text to locate in the file. Must include 3-5 lines of context to ensure uniqueness and avoid matching the wrong block.',\n )\n .meta({ examples: ['const x = 1;', 'function oldName('] }),\n newText: z\n .string()\n .describe('Replacement text. Use an empty string to delete the matched oldText.')\n .meta({ examples: ['const x = 2;', 'function newName(', ''] }),\n })\n // The one document in this server where a `$ref` pays: this subschema is used\n // at both `edits` and `files[].edits`, so an `id` hoists it into `$defs` once\n // instead of inlining ~1.3 kB twice. Shared schemas used once per document\n // deliberately carry no `id` — there a `$ref` costs more than it saves.\n .meta({ id: 'EditSpec' });\n\nconst MAX_MULTI_FILES = 5;\nconst MAX_EDITS_PER_FILE = 100;\n\nconst EditFileInputSchema = z\n .strictObject({\n path: RequiredPath.optional().describe('Single file path; mutually exclusive with files'),\n edits: z\n .array(EditSpecSchema)\n .min(1)\n .max(MAX_EDITS_PER_FILE)\n .optional()\n .describe('Replacements applied to path; not allowed when using files'),\n files: z\n .array(\n z.strictObject({\n path: RequiredPath,\n edits: z\n .array(EditSpecSchema)\n .min(1)\n .max(MAX_EDITS_PER_FILE)\n .describe('Replacements to apply to this specific file'),\n }),\n )\n .min(1)\n .max(MAX_MULTI_FILES)\n .optional()\n .describe('Per-file entries (batch mode)'),\n dryRun: defaultFalseBoolean(\n 'Preview diffs without writing to disk (default: false = apply edits)',\n ),\n ignoreWhitespace: defaultFalseBoolean(\n 'Ignore leading/trailing whitespace differences when matching oldText',\n ),\n })\n .superRefine((value, ctx) => {\n const hasPath = value.path !== undefined;\n const hasFiles = value.files !== undefined;\n if (hasPath === hasFiles) {\n ctx.addIssue({\n code: 'custom',\n path: ['path'],\n message: \"Provide exactly one of 'path' or 'files'\",\n input: value,\n });\n }\n if (hasPath && value.edits === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['edits'],\n message: \"'edits' required when using 'path'\",\n input: value,\n });\n }\n if (hasFiles && value.edits !== undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['edits'],\n message: \"'edits' not allowed with 'files'; each file carries its own edits\",\n input: value,\n });\n }\n })\n // Mirror the superRefine on the wire: exactly one input mode, and single-file\n // mode carries its own `edits`. Without `edits` in the first branch, `{ path }`\n // alone validated against the published schema and was then rejected at\n // runtime — the model had no way to see that coming.\n .meta({ oneOf: [{ required: ['path', 'edits'] }, { required: ['files'] }] });\n\nconst PerFileResultSchema = z.strictObject({\n path: z.string().describe('Resolved absolute path of the edited file'),\n size: NonNegInt.describe('File size in bytes after edits'),\n lineCount: NonNegInt.describe('Number of lines in the file after edits'),\n mimeType: z.string().describe('Detected MIME type of the file'),\n kind: FileKind.describe('Broad file kind: text, binary, image, audio, or pdf'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'Resource URI pointing to the updated file content; omitted when no edit matched (appliedEdits is 0) and the file was left untouched',\n ),\n modified: IsoDateTime.describe('Last modification timestamp after edits (ISO 8601 UTC)'),\n appliedEdits: NonNegInt.describe('Number of edits successfully applied'),\n linesAdded: NonNegInt.optional().describe('Net lines added by all applied edits'),\n linesRemoved: NonNegInt.optional().describe('Net lines removed by all applied edits'),\n diff: z.string().optional().describe('Unified diff of all changes (present only in dryRun mode)'),\n unmatchedEdits: z\n .array(z.string())\n .optional()\n .describe('oldText values that did not match any content in the file'),\n lineRange: z\n .tuple([PositiveInt, PositiveInt])\n .optional()\n .describe('Line range [firstLine, lastLine] covering all applied edits'),\n});\n\nconst EditPerPathSchema = z.strictObject({\n path: z.string().describe('Requested file path'),\n value: PerFileResultSchema.optional().describe('Edit result; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst EditFileOutputSchema = z.strictObject({\n results: z\n .array(EditPerPathSchema)\n .describe('Per-path edit results ordered to match the input paths'),\n summary: OperationSummarySchema,\n});\n\ntype EditFileValue = z.infer<typeof PerFileResultSchema>;\n\ninterface TextRange {\n startIndex: number;\n length: number;\n}\n\ninterface EditResult {\n content: string;\n appliedEdits: number;\n unmatchedEdits: string[];\n linesAdded: number;\n linesRemoved: number;\n diff?: string;\n lineRange?: [number, number];\n}\n\nasync function computeDiffStats(\n original: string,\n modified: string,\n): Promise<{ linesAdded: number; linesRemoved: number }> {\n return new Promise((resolve) => {\n // Yield to the event loop so we don't completely block\n setImmediate(() => {\n diffLines(original, modified, {\n callback: (changes) => {\n let linesAdded = 0;\n let linesRemoved = 0;\n for (const part of changes) {\n if (part.added) linesAdded += part.count;\n else if (part.removed) linesRemoved += part.count;\n }\n resolve({ linesAdded, linesRemoved });\n },\n });\n });\n });\n}\n\nfunction findEditMatch(\n content: string,\n oldText: string,\n ignoreWhitespace: boolean,\n regexCache?: Map<string, Regex>,\n): TextRange | undefined {\n if (ignoreWhitespace) {\n // Make whitespace flexible (tolerate indentation/spacing differences)\n // without letting it cross line boundaries: a whitespace run that contains\n // a newline keeps at least one newline, so a single-line oldText cannot\n // match across a newline and a multi-line oldText cannot collapse onto one\n // line. Horizontal whitespace stays mandatory between word characters so\n // adjacent identifiers are not merged.\n const pattern = escapeRegexLiteral(oldText)\n .replace(/[^\\S\\n]*\\n\\s*/g, '[^\\\\S\\\\n]*\\\\n+[^\\\\S\\\\n]*')\n .replace(/(\\w)[^\\S\\n]+(\\w)/g, '$1[^\\\\S\\\\n]+$2')\n .replace(/[^\\S\\n]+/g, '[^\\\\S\\\\n]*');\n let regex = regexCache?.get(pattern);\n if (!regex) {\n regex = compileRegex(pattern, { caseSensitive: true });\n regexCache?.set(pattern, regex);\n }\n // The compiled regex is global and may come from the cache, so lastIndex\n // still points past the previous edit's match — reset before searching.\n regex.lastIndex = 0;\n const match = regex.exec(content);\n\n if (match === null) return undefined;\n // RE2ExecArray types group 0 as optional. A successful match always has it;\n // an empty one would name a zero-length span, which cannot be replaced.\n const matched = match[0];\n if (matched === undefined || matched.length === 0) return undefined;\n\n return {\n startIndex: match.index,\n length: matched.length,\n };\n }\n\n const index = content.indexOf(oldText);\n if (index === -1) {\n return undefined;\n }\n\n return {\n startIndex: index,\n length: oldText.length,\n };\n}\n\nfunction replaceEditMatch(content: string, match: TextRange, newText: string): string {\n return (\n content.slice(0, match.startIndex) + newText + content.slice(match.startIndex + match.length)\n );\n}\n\n/**\n * Compute the 1-indexed line range of changed lines in `modified` relative to\n * `original`, using a common-prefix/suffix line scan. This is a conservative\n * bound (it widens to cover independent changes between matching bookends), but\n * it is computed against the FINAL content so it is not skewed by earlier edits\n * inserting or removing lines — which the per-edit merge could not account for.\n */\nfunction computeChangedLineRange(original: string, modified: string): [number, number] | undefined {\n const origLines = original.split('\\n');\n const modLines = modified.split('\\n');\n const minLen = Math.min(origLines.length, modLines.length);\n\n let firstChanged = -1;\n for (let i = 0; i < minLen; i++) {\n if (origLines[i] !== modLines[i]) {\n firstChanged = i;\n break;\n }\n }\n if (firstChanged === -1 && origLines.length === modLines.length) return undefined;\n if (firstChanged === -1) firstChanged = minLen; // pure append/trim at the tail\n\n let lastChangedMod = modLines.length - 1;\n let lastChangedOrig = origLines.length - 1;\n while (\n lastChangedMod > firstChanged &&\n lastChangedOrig >= 0 &&\n modLines[lastChangedMod] === origLines[lastChangedOrig]\n ) {\n lastChangedMod--;\n lastChangedOrig--;\n }\n\n // When the modified content is a strict prefix of the original (a tail trim on\n // a file with no final newline), the loop above never runs and lastChangedMod\n // lands one below firstChanged. Clamp so the range is never inverted.\n return [firstChanged + 1, Math.max(firstChanged, lastChangedMod) + 1];\n}\n\nfunction buildEditFileValue(\n validPath: string,\n meta: EditFileMetadata,\n modified: string,\n result: EditResult,\n): EditFileValue {\n return {\n path: validPath,\n size: meta.bytesWritten,\n lineCount: meta.lineCount,\n mimeType: meta.mimeType,\n kind: meta.kind,\n ...(meta.resourceUri !== undefined ? { resourceUri: meta.resourceUri } : {}),\n modified,\n appliedEdits: result.appliedEdits,\n ...(result.appliedEdits > 0\n ? { linesAdded: result.linesAdded, linesRemoved: result.linesRemoved }\n : {}),\n ...(result.unmatchedEdits.length > 0 ? { unmatchedEdits: result.unmatchedEdits } : {}),\n ...(result.diff ? { diff: result.diff } : {}),\n ...(result.lineRange ? { lineRange: result.lineRange } : {}),\n };\n}\n\nasync function finalizeEditResult(\n originalContent: string,\n updatedContent: string,\n appliedEdits: number,\n unmatchedEdits: string[],\n lineRange: EditResult['lineRange'],\n): Promise<EditResult> {\n const { linesAdded, linesRemoved } =\n appliedEdits > 0\n ? await computeDiffStats(originalContent, updatedContent)\n : { linesAdded: 0, linesRemoved: 0 };\n\n return {\n content: updatedContent,\n appliedEdits,\n unmatchedEdits,\n linesAdded,\n linesRemoved,\n ...(lineRange ? { lineRange } : {}),\n };\n}\n\ninterface EditFileMetadata {\n bytesWritten: number;\n lineCount: number;\n mimeType: string;\n kind: FileKind;\n /** Undefined when no edit matched: there is no updated content to point at. */\n resourceUri: string | undefined;\n resourceLink: ContentBlock | undefined;\n}\n\nfunction buildEditFileMetadata(\n content: string,\n validPath: string,\n appliedEdits: number,\n resourceStore: ResourceStore | undefined,\n): EditFileMetadata {\n const bytesWritten = Buffer.byteLength(content, 'utf-8');\n const lineCount = countLines(content);\n const mimeInfo = detectMimeFromContent(validPath, content);\n // Omitted rather than empty-stringed when nothing matched: `\"\"` satisfied the\n // schema's `string` and then failed every resources/read a client tried it on.\n const resourceUri = appliedEdits > 0 ? buildFileResourceUri(validPath) : undefined;\n const resourceLink =\n appliedEdits > 0 && resourceStore\n ? buildFileResourceLink(validPath, mimeInfo.mimeType, bytesWritten)\n : undefined;\n return {\n bytesWritten,\n lineCount,\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n resourceUri,\n resourceLink,\n };\n}\n\nasync function applyEdits(\n content: string,\n edits: z.infer<typeof EditSpecSchema>[],\n ignoreWhitespace: boolean,\n): Promise<EditResult> {\n let newContent = content;\n let appliedEdits = 0;\n const unmatchedEdits: string[] = [];\n const regexCache = ignoreWhitespace ? new Map<string, Regex>() : undefined;\n\n try {\n for (const edit of edits) {\n const match = findEditMatch(newContent, edit.oldText, ignoreWhitespace, regexCache);\n\n if (!match) {\n unmatchedEdits.push(edit.oldText);\n continue;\n }\n\n newContent = replaceEditMatch(newContent, match, edit.newText);\n appliedEdits += 1;\n }\n } finally {\n // Every cached pattern owns wasm memory re2-wasm never reclaims on its own,\n // and the cache does not outlive this call.\n for (const cached of regexCache?.values() ?? []) freeRegex(cached);\n regexCache?.clear();\n }\n\n // Compute the line range against the final content so earlier edits whose\n // lines were shifted by later edits are still covered.\n const lineRange = appliedEdits > 0 ? computeChangedLineRange(content, newContent) : undefined;\n\n return finalizeEditResult(content, newContent, appliedEdits, unmatchedEdits, lineRange);\n}\n\ninterface EditFileOptions {\n dryRun: boolean;\n ignoreWhitespace: boolean;\n}\n\nasync function handleEditFile(\n filePath: string,\n edits: z.infer<typeof EditSpecSchema>[],\n options: EditFileOptions,\n ctx: ToolCtx,\n): Promise<{ file: EditFileValue; resourceLink?: ContentBlock }> {\n const { validPath, content } = await ctx.fs.readEditableText(filePath, {\n signal: ctx.signal,\n });\n const editResult = await applyEdits(content, edits, options.ignoreWhitespace);\n\n if (options.dryRun) {\n if (editResult.appliedEdits > 0) {\n const label = basename(validPath);\n editResult.diff = await new Promise<string>((resolve) => {\n createTwoFilesPatch(label, label, content, editResult.content, 'Original', 'Modified', {\n callback: (res: string | undefined) => {\n resolve(res ?? '');\n },\n });\n });\n }\n\n // Nothing was written, so there is no updated content to point a\n // resourceUri or a resource_link at — the file on disk is still the one the\n // caller already has. Same rule the appliedEdits-is-0 case follows: no\n // write, no link.\n const meta = buildEditFileMetadata(editResult.content, validPath, 0, ctx.resourceStore);\n return {\n file: buildEditFileValue(validPath, meta, new Date().toISOString(), editResult),\n ...(meta.resourceLink ? { resourceLink: meta.resourceLink } : {}),\n };\n }\n\n if (editResult.unmatchedEdits.length > 0) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n `${editResult.unmatchedEdits.length} edit(s) failed to match. Verify oldText matches exact file content.`,\n filePath,\n );\n }\n\n if (editResult.appliedEdits > 0) {\n await ctx.fs.writeFile(filePath, editResult.content, {\n encoding: 'utf-8',\n signal: ctx.signal,\n });\n ctx.log?.(\n 'info',\n `edit: ${filePath} (${editResult.appliedEdits} edits, +${editResult.linesAdded}/-${editResult.linesRemoved})`,\n 'edit',\n );\n }\n\n // `modified` is read from a post-write stat and is advisory: under a concurrent\n // writer it may reflect that writer's mtime while `size`/content below come from\n // this edit's atomic write. The file content itself is always consistent.\n const { stats: fileStats } = await ctx.fs.stat(filePath, { signal: ctx.signal });\n const meta = buildEditFileMetadata(\n editResult.content,\n validPath,\n editResult.appliedEdits,\n ctx.resourceStore,\n );\n return {\n file: buildEditFileValue(validPath, meta, fileStats.mtime.toISOString(), editResult),\n ...(meta.resourceLink ? { resourceLink: meta.resourceLink } : {}),\n };\n}\n\nfunction formatEditSummary(\n results: readonly z.infer<typeof EditPerPathSchema>[],\n dryRun: boolean,\n): string {\n const tag = dryRun ? ' [dry run]' : '';\n // Single-file failure: say why here rather than making the caller read\n // structuredContent for the one message that can apply.\n const [only] = results;\n if (results.length === 1 && only?.error) {\n return `edit: ${only.path} FAILED — ${only.error.message}${tag}`;\n }\n const tokens = results.map((r) => {\n if (r.error) return `${basename(r.path)} FAILED`;\n const v = r.value;\n if (!v) return `${basename(r.path)} (no result)`;\n if (v.unmatchedEdits && v.unmatchedEdits.length > 0) return `${basename(v.path)} NO MATCH`;\n const added = v.linesAdded ?? 0;\n const removed = v.linesRemoved ?? 0;\n if (added === 0 && removed === 0) return `${basename(v.path)} (no change)`;\n return `${basename(v.path)} +${String(added)} -${String(removed)}`;\n });\n\n const failed = results.filter((r) => r.error !== undefined).length;\n const ok = results.length - failed;\n const ratio = failed > 0 ? ` (${String(ok)}/${String(results.length)} ok)` : '';\n return `edit: ${tokens.join(' · ')}${ratio}${tag}`;\n}\n\nexport const EDIT = defineTool({\n name: 'edit',\n title: 'Edit Files',\n description:\n 'Apply sequential literal string replacements to one or more files (max 5 files per call). ' +\n 'Modes: single-file { path, edits } or per-file { files: [{ path, edits }] }. ' +\n 'oldText must match file content exactly; include 3-5 lines of surrounding context to ensure uniqueness. ' +\n 'Set dryRun=true to preview diffs without writing. ' +\n 'For glob-based bulk regex replacement across many files, use replace_text instead.',\n input: EditFileInputSchema,\n output: EditFileOutputSchema,\n annotations: {\n readOnlyHint: false,\n idempotentHint: false,\n destructiveHint: true,\n openWorldHint: false,\n },\n progress: (args) => {\n const dryLabel = args.dryRun ? ' [dry run]' : '';\n let subject: string;\n if (args.path !== undefined) {\n subject = basename(args.path);\n } else if (args.files !== undefined) {\n subject = `${args.files.length} files`;\n } else {\n subject = 'files';\n }\n return { label: `Edit${dryLabel}`, subject };\n },\n accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n const sharedEdits = args.edits ?? [];\n const batchInput = args.path !== undefined ? { path: args.path } : { files: args.files ?? [] };\n\n const options: EditFileOptions = {\n dryRun: args.dryRun,\n ignoreWhitespace: args.ignoreWhitespace,\n };\n\n const batch = await runOverPaths<\n { edits: z.infer<typeof EditSpecSchema>[] },\n { file: EditFileValue; resourceLink?: ContentBlock }\n >(\n batchInput,\n ctx,\n ({ path, override }) => handleEditFile(path, override?.edits ?? sharedEdits, options, ctx),\n { defaultErrorCode: ErrorCode.UNKNOWN },\n );\n\n const perPathResults: z.infer<typeof EditPerPathSchema>[] = [];\n const resourceLinks: ContentBlock[] = [];\n for (const r of batch.results) {\n if ('error' in r) {\n perPathResults.push({ path: r.path, error: r.error });\n continue;\n }\n perPathResults.push({ path: r.path, value: r.value.file });\n if (r.value.resourceLink) resourceLinks.push(r.value.resourceLink);\n }\n\n const summaryText = formatEditSummary(perPathResults, args.dryRun);\n\n return {\n structured: {\n results: perPathResults,\n summary: batch.summary,\n },\n text: summaryText,\n isError: isTotalFailure(batch.summary),\n ...(resourceLinks.length > 0 ? { resources: resourceLinks } : {}),\n };\n },\n});\n"]}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\nimport { createTwoFilesPatch, diffLines } from 'diff';\n\nimport { ErrorCode, FsError } from '../core/errors.js';\nimport { buildFileResourceLink, buildFileResourceUri } from '../core/file-uri.js';\nimport { detectMimeFromContent } from '../core/mime.js';\nimport { escapeRegexLiteral } from '../core/primitives.js';\nimport { countLines } from '../core/read.js';\nimport {\n defaultFalseBoolean,\n FileKind,\n isBlank,\n IsoDateTime,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n PositiveInt,\n RequiredPath,\n singleOrBatchAccessPaths,\n} from '../core/schema.js';\nimport type { Regex } from '../core/search.js';\nimport { compileRegex, freeRegex } from '../core/search.js';\nimport type { ResourceStore } from '../core/store.js';\nimport { isTotalFailure, runOverPaths } from './batch.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\nconst EditSpecSchema = z\n .strictObject({\n oldText: z\n .string()\n .min(1, 'oldText required')\n .refine((val) => !isBlank(val), {\n message: 'oldText cannot be empty or whitespace-only',\n })\n .describe(\n 'Exact literal text to locate in the file. Must include 3-5 lines of context to ensure uniqueness and avoid matching the wrong block.',\n )\n .meta({ examples: ['const x = 1;', 'function oldName('] }),\n newText: z\n .string()\n .describe('Replacement text. Use an empty string to delete the matched oldText.')\n .meta({ examples: ['const x = 2;', 'function newName(', ''] }),\n })\n // The one document in this server where a `$ref` pays: this subschema is used\n // at both `edits` and `files[].edits`, so an `id` hoists it into `$defs` once\n // instead of inlining ~1.3 kB twice. Shared schemas used once per document\n // deliberately carry no `id` — there a `$ref` costs more than it saves.\n .meta({ id: 'EditSpec' });\n\nconst MAX_MULTI_FILES = 5;\nconst MAX_EDITS_PER_FILE = 100;\n\nconst EditFileInputSchema = z\n .strictObject({\n path: RequiredPath.optional().describe('Single file path; mutually exclusive with files'),\n edits: z\n .array(EditSpecSchema)\n .min(1)\n .max(MAX_EDITS_PER_FILE)\n .optional()\n .describe('Replacements applied to path; not allowed when using files'),\n files: z\n .array(\n z.strictObject({\n path: RequiredPath,\n edits: z\n .array(EditSpecSchema)\n .min(1)\n .max(MAX_EDITS_PER_FILE)\n .describe('Replacements to apply to this specific file'),\n }),\n )\n .min(1)\n .max(MAX_MULTI_FILES)\n .optional()\n .describe('Per-file entries (batch mode)'),\n dryRun: defaultFalseBoolean(\n 'Preview diffs without writing to disk (default: false = apply edits)',\n ),\n ignoreWhitespace: defaultFalseBoolean(\n 'Ignore leading/trailing whitespace differences when matching oldText',\n ),\n })\n .superRefine((value, ctx) => {\n const hasPath = value.path !== undefined;\n const hasFiles = value.files !== undefined;\n if (hasPath === hasFiles) {\n ctx.addIssue({\n code: 'custom',\n path: ['path'],\n message: \"Provide exactly one of 'path' or 'files'\",\n input: value,\n });\n }\n if (hasPath && value.edits === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['edits'],\n message: \"'edits' required when using 'path'\",\n input: value,\n });\n }\n if (hasFiles && value.edits !== undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['edits'],\n message: \"'edits' not allowed with 'files'; each file carries its own edits\",\n input: value,\n });\n }\n })\n // Mirror the superRefine on the wire: exactly one input mode, and single-file\n // mode carries its own `edits`. Without `edits` in the first branch, `{ path }`\n // alone validated against the published schema and was then rejected at\n // runtime — the model had no way to see that coming.\n .meta({ oneOf: [{ required: ['path', 'edits'] }, { required: ['files'] }] });\n\nconst PerFileResultSchema = z.strictObject({\n path: z.string().describe('Resolved absolute path of the edited file'),\n size: NonNegInt.describe('File size in bytes after edits'),\n lineCount: NonNegInt.describe('Number of lines in the file after edits'),\n mimeType: z.string().describe('Detected MIME type of the file'),\n kind: FileKind.describe('Broad file kind: text, binary, image, audio, or pdf'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'Resource URI pointing to the updated file content; omitted when no edit matched (appliedEdits is 0) and the file was left untouched',\n ),\n modified: IsoDateTime.describe('Last modification timestamp after edits (ISO 8601 UTC)'),\n appliedEdits: NonNegInt.describe('Number of edits successfully applied'),\n linesAdded: NonNegInt.optional().describe('Net lines added by all applied edits'),\n linesRemoved: NonNegInt.optional().describe('Net lines removed by all applied edits'),\n diff: z.string().optional().describe('Unified diff of all changes (present only in dryRun mode)'),\n unmatchedEdits: z\n .array(z.string())\n .optional()\n .describe('oldText values that did not match any content in the file'),\n lineRange: z\n .tuple([PositiveInt, PositiveInt])\n .optional()\n .describe('Line range [firstLine, lastLine] covering all applied edits'),\n});\n\nconst EditPerPathSchema = z.strictObject({\n path: z.string().describe('Requested file path'),\n value: PerFileResultSchema.optional().describe('Edit result; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst EditFileOutputSchema = z.strictObject({\n results: z\n .array(EditPerPathSchema)\n .describe('Per-path edit results ordered to match the input paths'),\n summary: OperationSummarySchema,\n});\n\ntype EditFileValue = z.infer<typeof PerFileResultSchema>;\n\ninterface TextRange {\n startIndex: number;\n length: number;\n}\n\ninterface EditResult {\n content: string;\n appliedEdits: number;\n unmatchedEdits: string[];\n linesAdded: number;\n linesRemoved: number;\n diff?: string;\n lineRange?: [number, number];\n}\n\nfunction computeDiffStats(\n original: string,\n modified: string,\n): { linesAdded: number; linesRemoved: number } {\n // diffLines returns the change list synchronously on diff v9.\n let linesAdded = 0;\n let linesRemoved = 0;\n for (const part of diffLines(original, modified)) {\n if (part.added) linesAdded += part.count;\n else if (part.removed) linesRemoved += part.count;\n }\n return { linesAdded, linesRemoved };\n}\n\nfunction findEditMatch(\n content: string,\n oldText: string,\n ignoreWhitespace: boolean,\n regexCache?: Map<string, Regex>,\n): TextRange | undefined {\n if (ignoreWhitespace) {\n // Make whitespace flexible (tolerate indentation/spacing differences)\n // without letting it cross line boundaries: a whitespace run that contains\n // a newline keeps at least one newline, so a single-line oldText cannot\n // match across a newline and a multi-line oldText cannot collapse onto one\n // line. Horizontal whitespace stays mandatory between word characters so\n // adjacent identifiers are not merged.\n const pattern = escapeRegexLiteral(oldText)\n .replace(/[^\\S\\n]*\\n\\s*/g, '[^\\\\S\\\\n]*\\\\n+[^\\\\S\\\\n]*')\n .replace(/(\\w)[^\\S\\n]+(\\w)/g, '$1[^\\\\S\\\\n]+$2')\n .replace(/[^\\S\\n]+/g, '[^\\\\S\\\\n]*');\n let regex = regexCache?.get(pattern);\n if (!regex) {\n regex = compileRegex(pattern, { caseSensitive: true });\n regexCache?.set(pattern, regex);\n }\n // The compiled regex is global and may come from the cache, so lastIndex\n // still points past the previous edit's match — reset before searching.\n regex.lastIndex = 0;\n const match = regex.exec(content);\n\n if (match === null) return undefined;\n // RE2ExecArray types group 0 as optional. A successful match always has it;\n // an empty one would name a zero-length span, which cannot be replaced.\n const matched = match[0];\n if (matched === undefined || matched.length === 0) return undefined;\n\n return {\n startIndex: match.index,\n length: matched.length,\n };\n }\n\n const index = content.indexOf(oldText);\n if (index === -1) {\n return undefined;\n }\n\n return {\n startIndex: index,\n length: oldText.length,\n };\n}\n\nfunction replaceEditMatch(content: string, match: TextRange, newText: string): string {\n return (\n content.slice(0, match.startIndex) + newText + content.slice(match.startIndex + match.length)\n );\n}\n\n/**\n * Compute the 1-indexed line range of changed lines in `modified` relative to\n * `original`, using a common-prefix/suffix line scan. This is a conservative\n * bound (it widens to cover independent changes between matching bookends), but\n * it is computed against the FINAL content so it is not skewed by earlier edits\n * inserting or removing lines — which the per-edit merge could not account for.\n */\nfunction computeChangedLineRange(original: string, modified: string): [number, number] | undefined {\n const origLines = original.split('\\n');\n const modLines = modified.split('\\n');\n const minLen = Math.min(origLines.length, modLines.length);\n\n let firstChanged = -1;\n for (let i = 0; i < minLen; i++) {\n if (origLines[i] !== modLines[i]) {\n firstChanged = i;\n break;\n }\n }\n if (firstChanged === -1 && origLines.length === modLines.length) return undefined;\n if (firstChanged === -1) firstChanged = minLen; // pure append/trim at the tail\n\n let lastChangedMod = modLines.length - 1;\n let lastChangedOrig = origLines.length - 1;\n while (\n lastChangedMod > firstChanged &&\n lastChangedOrig >= 0 &&\n modLines[lastChangedMod] === origLines[lastChangedOrig]\n ) {\n lastChangedMod--;\n lastChangedOrig--;\n }\n\n // When the modified content is a strict prefix of the original (a tail trim on\n // a file with no final newline), the loop above never runs and lastChangedMod\n // lands one below firstChanged. Clamp so the range is never inverted.\n return [firstChanged + 1, Math.max(firstChanged, lastChangedMod) + 1];\n}\n\nfunction buildEditFileValue(\n validPath: string,\n meta: EditFileMetadata,\n modified: string,\n result: EditResult,\n): EditFileValue {\n return {\n path: validPath,\n size: meta.bytesWritten,\n lineCount: meta.lineCount,\n mimeType: meta.mimeType,\n kind: meta.kind,\n ...(meta.resourceUri !== undefined ? { resourceUri: meta.resourceUri } : {}),\n modified,\n appliedEdits: result.appliedEdits,\n ...(result.appliedEdits > 0\n ? { linesAdded: result.linesAdded, linesRemoved: result.linesRemoved }\n : {}),\n ...(result.unmatchedEdits.length > 0 ? { unmatchedEdits: result.unmatchedEdits } : {}),\n ...(result.diff ? { diff: result.diff } : {}),\n ...(result.lineRange ? { lineRange: result.lineRange } : {}),\n };\n}\n\nfunction finalizeEditResult(\n originalContent: string,\n updatedContent: string,\n appliedEdits: number,\n unmatchedEdits: string[],\n lineRange: EditResult['lineRange'],\n): EditResult {\n const { linesAdded, linesRemoved } =\n appliedEdits > 0\n ? computeDiffStats(originalContent, updatedContent)\n : { linesAdded: 0, linesRemoved: 0 };\n\n return {\n content: updatedContent,\n appliedEdits,\n unmatchedEdits,\n linesAdded,\n linesRemoved,\n ...(lineRange ? { lineRange } : {}),\n };\n}\n\ninterface EditFileMetadata {\n bytesWritten: number;\n lineCount: number;\n mimeType: string;\n kind: FileKind;\n /** Undefined when no edit matched: there is no updated content to point at. */\n resourceUri: string | undefined;\n resourceLink: ContentBlock | undefined;\n}\n\nfunction buildEditFileMetadata(\n content: string,\n validPath: string,\n appliedEdits: number,\n resourceStore: ResourceStore | undefined,\n): EditFileMetadata {\n const bytesWritten = Buffer.byteLength(content, 'utf-8');\n const lineCount = countLines(content);\n const mimeInfo = detectMimeFromContent(validPath, content);\n // Omitted rather than empty-stringed when nothing matched: `\"\"` satisfied the\n // schema's `string` and then failed every resources/read a client tried it on.\n const resourceUri = appliedEdits > 0 ? buildFileResourceUri(validPath) : undefined;\n const resourceLink =\n appliedEdits > 0 && resourceStore\n ? buildFileResourceLink(validPath, mimeInfo.mimeType, bytesWritten)\n : undefined;\n return {\n bytesWritten,\n lineCount,\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n resourceUri,\n resourceLink,\n };\n}\n\nfunction applyEdits(\n content: string,\n edits: z.infer<typeof EditSpecSchema>[],\n ignoreWhitespace: boolean,\n): EditResult {\n let newContent = content;\n let appliedEdits = 0;\n const unmatchedEdits: string[] = [];\n const regexCache = ignoreWhitespace ? new Map<string, Regex>() : undefined;\n\n try {\n for (const edit of edits) {\n const match = findEditMatch(newContent, edit.oldText, ignoreWhitespace, regexCache);\n\n if (!match) {\n unmatchedEdits.push(edit.oldText);\n continue;\n }\n\n newContent = replaceEditMatch(newContent, match, edit.newText);\n appliedEdits += 1;\n }\n } finally {\n // Every cached pattern owns wasm memory re2-wasm never reclaims on its own,\n // and the cache does not outlive this call.\n for (const cached of regexCache?.values() ?? []) freeRegex(cached);\n regexCache?.clear();\n }\n\n // Compute the line range against the final content so earlier edits whose\n // lines were shifted by later edits are still covered.\n const lineRange = appliedEdits > 0 ? computeChangedLineRange(content, newContent) : undefined;\n\n return finalizeEditResult(content, newContent, appliedEdits, unmatchedEdits, lineRange);\n}\n\ninterface EditFileOptions {\n dryRun: boolean;\n ignoreWhitespace: boolean;\n}\n\nasync function handleEditFile(\n filePath: string,\n edits: z.infer<typeof EditSpecSchema>[],\n options: EditFileOptions,\n ctx: ToolCtx,\n): Promise<{ file: EditFileValue; resourceLink?: ContentBlock }> {\n const { validPath, content } = await ctx.fs.readEditableText(filePath, {\n signal: ctx.signal,\n });\n const editResult = applyEdits(content, edits, options.ignoreWhitespace);\n\n if (options.dryRun) {\n if (editResult.appliedEdits > 0) {\n const label = basename(validPath);\n // createTwoFilesPatch returns the unified diff string synchronously on\n // diff v9 (the { callback } option fires via setTimeout and returns undefined).\n editResult.diff = createTwoFilesPatch(\n label,\n label,\n content,\n editResult.content,\n 'Original',\n 'Modified',\n );\n }\n\n // Nothing was written, so there is no updated content to point a\n // resourceUri or a resource_link at — the file on disk is still the one the\n // caller already has. Same rule the appliedEdits-is-0 case follows: no\n // write, no link.\n const meta = buildEditFileMetadata(editResult.content, validPath, 0, ctx.resourceStore);\n return {\n file: buildEditFileValue(validPath, meta, new Date().toISOString(), editResult),\n ...(meta.resourceLink ? { resourceLink: meta.resourceLink } : {}),\n };\n }\n\n if (editResult.unmatchedEdits.length > 0) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n `${editResult.unmatchedEdits.length} edit(s) failed to match. Verify oldText matches exact file content.`,\n filePath,\n );\n }\n\n if (editResult.appliedEdits > 0) {\n await ctx.fs.writeFile(filePath, editResult.content, {\n encoding: 'utf-8',\n signal: ctx.signal,\n });\n ctx.log?.(\n 'info',\n `edit: ${filePath} (${editResult.appliedEdits} edits, +${editResult.linesAdded}/-${editResult.linesRemoved})`,\n 'edit',\n );\n }\n\n // `modified` is read from a post-write stat and is advisory: under a concurrent\n // writer it may reflect that writer's mtime while `size`/content below come from\n // this edit's atomic write. The file content itself is always consistent.\n const { stats: fileStats } = await ctx.fs.stat(filePath, { signal: ctx.signal });\n const meta = buildEditFileMetadata(\n editResult.content,\n validPath,\n editResult.appliedEdits,\n ctx.resourceStore,\n );\n return {\n file: buildEditFileValue(validPath, meta, fileStats.mtime.toISOString(), editResult),\n ...(meta.resourceLink ? { resourceLink: meta.resourceLink } : {}),\n };\n}\n\nfunction formatEditSummary(\n results: readonly z.infer<typeof EditPerPathSchema>[],\n dryRun: boolean,\n): string {\n const tag = dryRun ? ' [dry run]' : '';\n // Single-file failure: say why here rather than making the caller read\n // structuredContent for the one message that can apply.\n const [only] = results;\n if (results.length === 1 && only?.error) {\n return `edit: ${only.path} FAILED — ${only.error.message}${tag}`;\n }\n const tokens = results.map((r) => {\n if (r.error) return `${basename(r.path)} FAILED`;\n const v = r.value;\n if (!v) return `${basename(r.path)} (no result)`;\n if (v.unmatchedEdits && v.unmatchedEdits.length > 0) return `${basename(v.path)} NO MATCH`;\n const added = v.linesAdded ?? 0;\n const removed = v.linesRemoved ?? 0;\n if (added === 0 && removed === 0) return `${basename(v.path)} (no change)`;\n return `${basename(v.path)} +${String(added)} -${String(removed)}`;\n });\n\n const failed = results.filter((r) => r.error !== undefined).length;\n const ok = results.length - failed;\n const ratio = failed > 0 ? ` (${String(ok)}/${String(results.length)} ok)` : '';\n return `edit: ${tokens.join(' · ')}${ratio}${tag}`;\n}\n\nexport const EDIT = defineTool({\n name: 'edit',\n title: 'Edit Files',\n description:\n 'Apply sequential literal string replacements to one or more files (max 5 files per call). ' +\n 'Modes: single-file { path, edits } or per-file { files: [{ path, edits }] }. ' +\n 'oldText must match file content exactly; include 3-5 lines of surrounding context to ensure uniqueness. ' +\n 'Set dryRun=true to preview diffs without writing. ' +\n 'For glob-based bulk regex replacement across many files, use replace_text instead.',\n input: EditFileInputSchema,\n output: EditFileOutputSchema,\n annotations: {\n readOnlyHint: false,\n idempotentHint: false,\n destructiveHint: true,\n openWorldHint: false,\n },\n progress: (args) => {\n const dryLabel = args.dryRun ? ' [dry run]' : '';\n let subject: string;\n if (args.path !== undefined) {\n subject = basename(args.path);\n } else if (args.files !== undefined) {\n subject = `${args.files.length} files`;\n } else {\n subject = 'files';\n }\n return { label: `Edit${dryLabel}`, subject };\n },\n accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n const sharedEdits = args.edits ?? [];\n const batchInput = args.path !== undefined ? { path: args.path } : { files: args.files ?? [] };\n\n const options: EditFileOptions = {\n dryRun: args.dryRun,\n ignoreWhitespace: args.ignoreWhitespace,\n };\n\n const batch = await runOverPaths<\n { edits: z.infer<typeof EditSpecSchema>[] },\n { file: EditFileValue; resourceLink?: ContentBlock }\n >(\n batchInput,\n ctx,\n ({ path, override }) => handleEditFile(path, override?.edits ?? sharedEdits, options, ctx),\n { defaultErrorCode: ErrorCode.UNKNOWN },\n );\n\n const perPathResults: z.infer<typeof EditPerPathSchema>[] = [];\n const resourceLinks: ContentBlock[] = [];\n for (const r of batch.results) {\n if ('error' in r) {\n perPathResults.push({ path: r.path, error: r.error });\n continue;\n }\n perPathResults.push({ path: r.path, value: r.value.file });\n if (r.value.resourceLink) resourceLinks.push(r.value.resourceLink);\n }\n\n const summaryText = formatEditSummary(perPathResults, args.dryRun);\n\n return {\n structured: {\n results: perPathResults,\n summary: batch.summary,\n },\n text: summaryText,\n isError: isTotalFailure(batch.summary),\n ...(resourceLinks.length > 0 ? { resources: resourceLinks } : {}),\n };\n },\n});\n"]}
@@ -62,7 +62,7 @@ async function collect(rootPath, options) {
62
62
  })) {
63
63
  continue;
64
64
  }
65
- const accessible = await options.pathGuard.isEntryAccessible(entry.path, entryType, [rootPath]);
65
+ const accessible = await options.pathGuard.isEntryAccessible(entry.path);
66
66
  if (!accessible)
67
67
  continue;
68
68
  totalEntries++;