@descryy/mcp 0.11.4 → 0.11.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.
- package/package.json +7 -7
- package/dist/action-handshake.d.ts +0 -38
- package/dist/action-handshake.d.ts.map +0 -1
- package/dist/action-handshake.js +0 -127
- package/dist/action-handshake.js.map +0 -1
- package/dist/bin/descry-mcp.d.ts +0 -7
- package/dist/bin/descry-mcp.d.ts.map +0 -1
- package/dist/bin/descry-mcp.js +0 -72
- package/dist/bin/descry-mcp.js.map +0 -1
- package/dist/browser/auth.d.ts +0 -84
- package/dist/browser/auth.d.ts.map +0 -1
- package/dist/browser/auth.js +0 -233
- package/dist/browser/auth.js.map +0 -1
- package/dist/browser/capability-probe.d.ts +0 -109
- package/dist/browser/capability-probe.d.ts.map +0 -1
- package/dist/browser/capability-probe.js +0 -201
- package/dist/browser/capability-probe.js.map +0 -1
- package/dist/browser/driver.d.ts +0 -591
- package/dist/browser/driver.d.ts.map +0 -1
- package/dist/browser/driver.js +0 -116
- package/dist/browser/driver.js.map +0 -1
- package/dist/browser/evidence.d.ts +0 -28
- package/dist/browser/evidence.d.ts.map +0 -1
- package/dist/browser/evidence.js +0 -82
- package/dist/browser/evidence.js.map +0 -1
- package/dist/browser/fake-driver.d.ts +0 -116
- package/dist/browser/fake-driver.d.ts.map +0 -1
- package/dist/browser/fake-driver.js +0 -416
- package/dist/browser/fake-driver.js.map +0 -1
- package/dist/browser/fault-attribution.d.ts +0 -178
- package/dist/browser/fault-attribution.d.ts.map +0 -1
- package/dist/browser/fault-attribution.js +0 -266
- package/dist/browser/fault-attribution.js.map +0 -1
- package/dist/browser/graph-write.d.ts +0 -45
- package/dist/browser/graph-write.d.ts.map +0 -1
- package/dist/browser/graph-write.js +0 -103
- package/dist/browser/graph-write.js.map +0 -1
- package/dist/browser/identity-graph-write.d.ts +0 -55
- package/dist/browser/identity-graph-write.d.ts.map +0 -1
- package/dist/browser/identity-graph-write.js +0 -45
- package/dist/browser/identity-graph-write.js.map +0 -1
- package/dist/browser/page-probe.d.ts +0 -81
- package/dist/browser/page-probe.d.ts.map +0 -1
- package/dist/browser/page-probe.js +0 -202
- package/dist/browser/page-probe.js.map +0 -1
- package/dist/browser/playwright-driver.d.ts +0 -114
- package/dist/browser/playwright-driver.d.ts.map +0 -1
- package/dist/browser/playwright-driver.js +0 -1518
- package/dist/browser/playwright-driver.js.map +0 -1
- package/dist/browser/provider.d.ts +0 -26
- package/dist/browser/provider.d.ts.map +0 -1
- package/dist/browser/provider.js +0 -14
- package/dist/browser/provider.js.map +0 -1
- package/dist/browser/reach-recording-session.d.ts +0 -44
- package/dist/browser/reach-recording-session.d.ts.map +0 -1
- package/dist/browser/reach-recording-session.js +0 -151
- package/dist/browser/reach-recording-session.js.map +0 -1
- package/dist/browser/reachability.d.ts +0 -168
- package/dist/browser/reachability.d.ts.map +0 -1
- package/dist/browser/reachability.js +0 -294
- package/dist/browser/reachability.js.map +0 -1
- package/dist/browser/registry.d.ts +0 -126
- package/dist/browser/registry.d.ts.map +0 -1
- package/dist/browser/registry.js +0 -177
- package/dist/browser/registry.js.map +0 -1
- package/dist/browser/scenario-provenance.d.ts +0 -23
- package/dist/browser/scenario-provenance.d.ts.map +0 -1
- package/dist/browser/scenario-provenance.js +0 -73
- package/dist/browser/scenario-provenance.js.map +0 -1
- package/dist/browser/scenario-resolve.d.ts +0 -28
- package/dist/browser/scenario-resolve.d.ts.map +0 -1
- package/dist/browser/scenario-resolve.js +0 -96
- package/dist/browser/scenario-resolve.js.map +0 -1
- package/dist/browser/scenario-runner.d.ts +0 -72
- package/dist/browser/scenario-runner.d.ts.map +0 -1
- package/dist/browser/scenario-runner.js +0 -353
- package/dist/browser/scenario-runner.js.map +0 -1
- package/dist/browser/stack-parser.d.ts +0 -19
- package/dist/browser/stack-parser.d.ts.map +0 -1
- package/dist/browser/stack-parser.js +0 -85
- package/dist/browser/stack-parser.js.map +0 -1
- package/dist/browser/tool-support.d.ts +0 -71
- package/dist/browser/tool-support.d.ts.map +0 -1
- package/dist/browser/tool-support.js +0 -216
- package/dist/browser/tool-support.js.map +0 -1
- package/dist/browser/url-scheme.d.ts +0 -14
- package/dist/browser/url-scheme.d.ts.map +0 -1
- package/dist/browser/url-scheme.js +0 -38
- package/dist/browser/url-scheme.js.map +0 -1
- package/dist/browser/wait-target.d.ts +0 -37
- package/dist/browser/wait-target.d.ts.map +0 -1
- package/dist/browser/wait-target.js +0 -54
- package/dist/browser/wait-target.js.map +0 -1
- package/dist/cancellation.d.ts +0 -20
- package/dist/cancellation.d.ts.map +0 -1
- package/dist/cancellation.js +0 -41
- package/dist/cancellation.js.map +0 -1
- package/dist/capped.d.ts +0 -39
- package/dist/capped.d.ts.map +0 -1
- package/dist/capped.js +0 -43
- package/dist/capped.js.map +0 -1
- package/dist/credential-store.d.ts +0 -22
- package/dist/credential-store.d.ts.map +0 -1
- package/dist/credential-store.js +0 -33
- package/dist/credential-store.js.map +0 -1
- package/dist/disclosure-ledger.d.ts +0 -14
- package/dist/disclosure-ledger.d.ts.map +0 -1
- package/dist/disclosure-ledger.js +0 -18
- package/dist/disclosure-ledger.js.map +0 -1
- package/dist/evidence/observed-route-evidence.d.ts +0 -25
- package/dist/evidence/observed-route-evidence.d.ts.map +0 -1
- package/dist/evidence/observed-route-evidence.js +0 -76
- package/dist/evidence/observed-route-evidence.js.map +0 -1
- package/dist/heap.d.ts +0 -61
- package/dist/heap.d.ts.map +0 -1
- package/dist/heap.js +0 -82
- package/dist/heap.js.map +0 -1
- package/dist/heartbeat.d.ts +0 -46
- package/dist/heartbeat.d.ts.map +0 -1
- package/dist/heartbeat.js +0 -66
- package/dist/heartbeat.js.map +0 -1
- package/dist/index.d.ts +0 -32
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -19
- package/dist/index.js.map +0 -1
- package/dist/module-trust.d.ts +0 -37
- package/dist/module-trust.d.ts.map +0 -1
- package/dist/module-trust.js +0 -77
- package/dist/module-trust.js.map +0 -1
- package/dist/path-confinement.d.ts +0 -31
- package/dist/path-confinement.d.ts.map +0 -1
- package/dist/path-confinement.js +0 -44
- package/dist/path-confinement.js.map +0 -1
- package/dist/planner/predict-then-propose.d.ts +0 -134
- package/dist/planner/predict-then-propose.d.ts.map +0 -1
- package/dist/planner/predict-then-propose.js +0 -138
- package/dist/planner/predict-then-propose.js.map +0 -1
- package/dist/planner/propose-journey.d.ts +0 -75
- package/dist/planner/propose-journey.d.ts.map +0 -1
- package/dist/planner/propose-journey.js +0 -96
- package/dist/planner/propose-journey.js.map +0 -1
- package/dist/protocol.d.ts +0 -57
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js +0 -90
- package/dist/protocol.js.map +0 -1
- package/dist/registry.d.ts +0 -103
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -327
- package/dist/registry.js.map +0 -1
- package/dist/render.d.ts +0 -623
- package/dist/render.d.ts.map +0 -1
- package/dist/render.js +0 -968
- package/dist/render.js.map +0 -1
- package/dist/runtime-registry.d.ts +0 -22
- package/dist/runtime-registry.d.ts.map +0 -1
- package/dist/runtime-registry.js +0 -142
- package/dist/runtime-registry.js.map +0 -1
- package/dist/sandbox-defaults.d.ts +0 -41
- package/dist/sandbox-defaults.d.ts.map +0 -1
- package/dist/sandbox-defaults.js +0 -14
- package/dist/sandbox-defaults.js.map +0 -1
- package/dist/scenarios/browser-run-plan-projection.d.ts +0 -161
- package/dist/scenarios/browser-run-plan-projection.d.ts.map +0 -1
- package/dist/scenarios/browser-run-plan-projection.js +0 -264
- package/dist/scenarios/browser-run-plan-projection.js.map +0 -1
- package/dist/scenarios/credential-ref.d.ts +0 -102
- package/dist/scenarios/credential-ref.d.ts.map +0 -1
- package/dist/scenarios/credential-ref.js +0 -148
- package/dist/scenarios/credential-ref.js.map +0 -1
- package/dist/scenarios/index.d.ts +0 -7
- package/dist/scenarios/index.d.ts.map +0 -1
- package/dist/scenarios/index.js +0 -7
- package/dist/scenarios/index.js.map +0 -1
- package/dist/scenarios/parse.d.ts +0 -18
- package/dist/scenarios/parse.d.ts.map +0 -1
- package/dist/scenarios/parse.js +0 -212
- package/dist/scenarios/parse.js.map +0 -1
- package/dist/scenarios/scenario.d.ts +0 -93
- package/dist/scenarios/scenario.d.ts.map +0 -1
- package/dist/scenarios/scenario.js +0 -27
- package/dist/scenarios/scenario.js.map +0 -1
- package/dist/scenarios/secret-ref.d.ts +0 -86
- package/dist/scenarios/secret-ref.d.ts.map +0 -1
- package/dist/scenarios/secret-ref.js +0 -125
- package/dist/scenarios/secret-ref.js.map +0 -1
- package/dist/scenarios/storage.d.ts +0 -21
- package/dist/scenarios/storage.d.ts.map +0 -1
- package/dist/scenarios/storage.js +0 -103
- package/dist/scenarios/storage.js.map +0 -1
- package/dist/server.d.ts +0 -61
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -651
- package/dist/server.js.map +0 -1
- package/dist/session.d.ts +0 -356
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -779
- package/dist/session.js.map +0 -1
- package/dist/tools/alias-kit.d.ts +0 -29
- package/dist/tools/alias-kit.d.ts.map +0 -1
- package/dist/tools/alias-kit.js +0 -21
- package/dist/tools/alias-kit.js.map +0 -1
- package/dist/tools/aliases.d.ts +0 -42
- package/dist/tools/aliases.d.ts.map +0 -1
- package/dist/tools/aliases.js +0 -52
- package/dist/tools/aliases.js.map +0 -1
- package/dist/tools/analyze-workspace.d.ts +0 -52
- package/dist/tools/analyze-workspace.d.ts.map +0 -1
- package/dist/tools/analyze-workspace.js +0 -207
- package/dist/tools/analyze-workspace.js.map +0 -1
- package/dist/tools/analyze.d.ts +0 -163
- package/dist/tools/analyze.d.ts.map +0 -1
- package/dist/tools/analyze.js +0 -724
- package/dist/tools/analyze.js.map +0 -1
- package/dist/tools/browser-click.d.ts +0 -18
- package/dist/tools/browser-click.d.ts.map +0 -1
- package/dist/tools/browser-click.js +0 -110
- package/dist/tools/browser-click.js.map +0 -1
- package/dist/tools/browser-close-session.d.ts +0 -39
- package/dist/tools/browser-close-session.d.ts.map +0 -1
- package/dist/tools/browser-close-session.js +0 -120
- package/dist/tools/browser-close-session.js.map +0 -1
- package/dist/tools/browser-fill.d.ts +0 -18
- package/dist/tools/browser-fill.d.ts.map +0 -1
- package/dist/tools/browser-fill.js +0 -117
- package/dist/tools/browser-fill.js.map +0 -1
- package/dist/tools/browser-navigate.d.ts +0 -15
- package/dist/tools/browser-navigate.d.ts.map +0 -1
- package/dist/tools/browser-navigate.js +0 -104
- package/dist/tools/browser-navigate.js.map +0 -1
- package/dist/tools/browser-read.d.ts +0 -33
- package/dist/tools/browser-read.d.ts.map +0 -1
- package/dist/tools/browser-read.js +0 -113
- package/dist/tools/browser-read.js.map +0 -1
- package/dist/tools/browser-run-scenario.d.ts +0 -28
- package/dist/tools/browser-run-scenario.d.ts.map +0 -1
- package/dist/tools/browser-run-scenario.js +0 -225
- package/dist/tools/browser-run-scenario.js.map +0 -1
- package/dist/tools/browser-save-scenario.d.ts +0 -19
- package/dist/tools/browser-save-scenario.d.ts.map +0 -1
- package/dist/tools/browser-save-scenario.js +0 -447
- package/dist/tools/browser-save-scenario.js.map +0 -1
- package/dist/tools/browser-select.d.ts +0 -20
- package/dist/tools/browser-select.d.ts.map +0 -1
- package/dist/tools/browser-select.js +0 -120
- package/dist/tools/browser-select.js.map +0 -1
- package/dist/tools/browser-snapshot.d.ts +0 -46
- package/dist/tools/browser-snapshot.d.ts.map +0 -1
- package/dist/tools/browser-snapshot.js +0 -127
- package/dist/tools/browser-snapshot.js.map +0 -1
- package/dist/tools/browser-start-session.d.ts +0 -24
- package/dist/tools/browser-start-session.d.ts.map +0 -1
- package/dist/tools/browser-start-session.js +0 -640
- package/dist/tools/browser-start-session.js.map +0 -1
- package/dist/tools/browser-submit.d.ts +0 -18
- package/dist/tools/browser-submit.d.ts.map +0 -1
- package/dist/tools/browser-submit.js +0 -106
- package/dist/tools/browser-submit.js.map +0 -1
- package/dist/tools/browser-type.d.ts +0 -18
- package/dist/tools/browser-type.d.ts.map +0 -1
- package/dist/tools/browser-type.js +0 -115
- package/dist/tools/browser-type.js.map +0 -1
- package/dist/tools/browser-wait-for.d.ts +0 -45
- package/dist/tools/browser-wait-for.d.ts.map +0 -1
- package/dist/tools/browser-wait-for.js +0 -150
- package/dist/tools/browser-wait-for.js.map +0 -1
- package/dist/tools/browser.d.ts +0 -69
- package/dist/tools/browser.d.ts.map +0 -1
- package/dist/tools/browser.js +0 -386
- package/dist/tools/browser.js.map +0 -1
- package/dist/tools/chain.d.ts +0 -41
- package/dist/tools/chain.d.ts.map +0 -1
- package/dist/tools/chain.js +0 -105
- package/dist/tools/chain.js.map +0 -1
- package/dist/tools/change-scope.d.ts +0 -25
- package/dist/tools/change-scope.d.ts.map +0 -1
- package/dist/tools/change-scope.js +0 -110
- package/dist/tools/change-scope.js.map +0 -1
- package/dist/tools/code-context.d.ts +0 -83
- package/dist/tools/code-context.d.ts.map +0 -1
- package/dist/tools/code-context.js +0 -444
- package/dist/tools/code-context.js.map +0 -1
- package/dist/tools/contracts.d.ts +0 -74
- package/dist/tools/contracts.d.ts.map +0 -1
- package/dist/tools/contracts.js +0 -196
- package/dist/tools/contracts.js.map +0 -1
- package/dist/tools/cross-pr.d.ts +0 -178
- package/dist/tools/cross-pr.d.ts.map +0 -1
- package/dist/tools/cross-pr.js +0 -370
- package/dist/tools/cross-pr.js.map +0 -1
- package/dist/tools/disclosure.d.ts +0 -75
- package/dist/tools/disclosure.d.ts.map +0 -1
- package/dist/tools/disclosure.js +0 -307
- package/dist/tools/disclosure.js.map +0 -1
- package/dist/tools/draw-conclusion.d.ts +0 -55
- package/dist/tools/draw-conclusion.d.ts.map +0 -1
- package/dist/tools/draw-conclusion.js +0 -259
- package/dist/tools/draw-conclusion.js.map +0 -1
- package/dist/tools/git-context.d.ts +0 -39
- package/dist/tools/git-context.d.ts.map +0 -1
- package/dist/tools/git-context.js +0 -385
- package/dist/tools/git-context.js.map +0 -1
- package/dist/tools/git-diff.d.ts +0 -45
- package/dist/tools/git-diff.d.ts.map +0 -1
- package/dist/tools/git-diff.js +0 -338
- package/dist/tools/git-diff.js.map +0 -1
- package/dist/tools/git-history.d.ts +0 -16
- package/dist/tools/git-history.d.ts.map +0 -1
- package/dist/tools/git-history.js +0 -106
- package/dist/tools/git-history.js.map +0 -1
- package/dist/tools/history.d.ts +0 -34
- package/dist/tools/history.d.ts.map +0 -1
- package/dist/tools/history.js +0 -121
- package/dist/tools/history.js.map +0 -1
- package/dist/tools/impact.d.ts +0 -46
- package/dist/tools/impact.d.ts.map +0 -1
- package/dist/tools/impact.js +0 -225
- package/dist/tools/impact.js.map +0 -1
- package/dist/tools/index.d.ts +0 -59
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -70
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/kit.d.ts +0 -165
- package/dist/tools/kit.d.ts.map +0 -1
- package/dist/tools/kit.js +0 -153
- package/dist/tools/kit.js.map +0 -1
- package/dist/tools/link-workspace.d.ts +0 -24
- package/dist/tools/link-workspace.d.ts.map +0 -1
- package/dist/tools/link-workspace.js +0 -131
- package/dist/tools/link-workspace.js.map +0 -1
- package/dist/tools/lookup.d.ts +0 -19
- package/dist/tools/lookup.d.ts.map +0 -1
- package/dist/tools/lookup.js +0 -63
- package/dist/tools/lookup.js.map +0 -1
- package/dist/tools/mark-incident.d.ts +0 -28
- package/dist/tools/mark-incident.d.ts.map +0 -1
- package/dist/tools/mark-incident.js +0 -188
- package/dist/tools/mark-incident.js.map +0 -1
- package/dist/tools/merged-browser.d.ts +0 -11
- package/dist/tools/merged-browser.d.ts.map +0 -1
- package/dist/tools/merged-browser.js +0 -20
- package/dist/tools/merged-browser.js.map +0 -1
- package/dist/tools/merged-context.d.ts +0 -11
- package/dist/tools/merged-context.d.ts.map +0 -1
- package/dist/tools/merged-context.js +0 -21
- package/dist/tools/merged-context.js.map +0 -1
- package/dist/tools/merged-observe.d.ts +0 -13
- package/dist/tools/merged-observe.d.ts.map +0 -1
- package/dist/tools/merged-observe.js +0 -21
- package/dist/tools/merged-observe.js.map +0 -1
- package/dist/tools/merged-workspace.d.ts +0 -14
- package/dist/tools/merged-workspace.d.ts.map +0 -1
- package/dist/tools/merged-workspace.js +0 -21
- package/dist/tools/merged-workspace.js.map +0 -1
- package/dist/tools/observe-runtime.d.ts +0 -262
- package/dist/tools/observe-runtime.d.ts.map +0 -1
- package/dist/tools/observe-runtime.js +0 -1901
- package/dist/tools/observe-runtime.js.map +0 -1
- package/dist/tools/observe-tests.d.ts +0 -57
- package/dist/tools/observe-tests.d.ts.map +0 -1
- package/dist/tools/observe-tests.js +0 -368
- package/dist/tools/observe-tests.js.map +0 -1
- package/dist/tools/observe.d.ts +0 -28
- package/dist/tools/observe.d.ts.map +0 -1
- package/dist/tools/observe.js +0 -330
- package/dist/tools/observe.js.map +0 -1
- package/dist/tools/pr-analysis.d.ts +0 -189
- package/dist/tools/pr-analysis.d.ts.map +0 -1
- package/dist/tools/pr-analysis.js +0 -374
- package/dist/tools/pr-analysis.js.map +0 -1
- package/dist/tools/pre-push.d.ts +0 -168
- package/dist/tools/pre-push.d.ts.map +0 -1
- package/dist/tools/pre-push.js +0 -416
- package/dist/tools/pre-push.js.map +0 -1
- package/dist/tools/predict-reach.d.ts +0 -57
- package/dist/tools/predict-reach.d.ts.map +0 -1
- package/dist/tools/predict-reach.js +0 -159
- package/dist/tools/predict-reach.js.map +0 -1
- package/dist/tools/propagation.d.ts +0 -37
- package/dist/tools/propagation.d.ts.map +0 -1
- package/dist/tools/propagation.js +0 -162
- package/dist/tools/propagation.js.map +0 -1
- package/dist/tools/propose-journey.d.ts +0 -16
- package/dist/tools/propose-journey.d.ts.map +0 -1
- package/dist/tools/propose-journey.js +0 -121
- package/dist/tools/propose-journey.js.map +0 -1
- package/dist/tools/prove-reach.d.ts +0 -74
- package/dist/tools/prove-reach.d.ts.map +0 -1
- package/dist/tools/prove-reach.js +0 -286
- package/dist/tools/prove-reach.js.map +0 -1
- package/dist/tools/questions.d.ts +0 -30
- package/dist/tools/questions.d.ts.map +0 -1
- package/dist/tools/questions.js +0 -232
- package/dist/tools/questions.js.map +0 -1
- package/dist/tools/refusal-fetch.d.ts +0 -35
- package/dist/tools/refusal-fetch.d.ts.map +0 -1
- package/dist/tools/refusal-fetch.js +0 -123
- package/dist/tools/refusal-fetch.js.map +0 -1
- package/dist/tools/runtime-incident.d.ts +0 -33
- package/dist/tools/runtime-incident.d.ts.map +0 -1
- package/dist/tools/runtime-incident.js +0 -67
- package/dist/tools/runtime-incident.js.map +0 -1
- package/dist/tools/runtime-journey-drive.d.ts +0 -102
- package/dist/tools/runtime-journey-drive.d.ts.map +0 -1
- package/dist/tools/runtime-journey-drive.js +0 -247
- package/dist/tools/runtime-journey-drive.js.map +0 -1
- package/dist/tools/scope.d.ts +0 -45
- package/dist/tools/scope.d.ts.map +0 -1
- package/dist/tools/scope.js +0 -217
- package/dist/tools/scope.js.map +0 -1
- package/dist/tools/similar-incidents.d.ts +0 -43
- package/dist/tools/similar-incidents.d.ts.map +0 -1
- package/dist/tools/similar-incidents.js +0 -203
- package/dist/tools/similar-incidents.js.map +0 -1
- package/dist/tools/validate.d.ts +0 -133
- package/dist/tools/validate.d.ts.map +0 -1
- package/dist/tools/validate.js +0 -520
- package/dist/tools/validate.js.map +0 -1
- package/dist/tools/verb.d.ts +0 -46
- package/dist/tools/verb.d.ts.map +0 -1
- package/dist/tools/verb.js +0 -78
- package/dist/tools/verb.js.map +0 -1
- package/dist/tools/verification-status.d.ts +0 -38
- package/dist/tools/verification-status.d.ts.map +0 -1
- package/dist/tools/verification-status.js +0 -203
- package/dist/tools/verification-status.js.map +0 -1
- package/dist/tools/verify-claim.d.ts +0 -29
- package/dist/tools/verify-claim.d.ts.map +0 -1
- package/dist/tools/verify-claim.js +0 -220
- package/dist/tools/verify-claim.js.map +0 -1
- package/dist/tools/workspace.d.ts +0 -28
- package/dist/tools/workspace.d.ts.map +0 -1
- package/dist/tools/workspace.js +0 -101
- package/dist/tools/workspace.js.map +0 -1
- package/dist/transport.d.ts +0 -32
- package/dist/transport.d.ts.map +0 -1
- package/dist/transport.js +0 -85
- package/dist/transport.js.map +0 -1
- package/dist/workspace-index.d.ts +0 -164
- package/dist/workspace-index.d.ts.map +0 -1
- package/dist/workspace-index.js +0 -381
- package/dist/workspace-index.js.map +0 -1
package/dist/server.js
DELETED
|
@@ -1,651 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The MCP server: handshake, tool listing, tool calls, streaming narration.
|
|
3
|
-
*
|
|
4
|
-
* ## The layering that makes this testable without a pipe
|
|
5
|
-
*
|
|
6
|
-
* `dispatch` takes a line of text and a `send`, and that is the whole surface.
|
|
7
|
-
* The stdio transport is a loop around it; a test is a call to it. So the
|
|
8
|
-
* handshake, the error frames and the progress notifications are all covered by
|
|
9
|
-
* ordinary unit tests rather than by spawning a process and hoping.
|
|
10
|
-
*
|
|
11
|
-
* ## Streaming narration — §22.2's primary UX, at the protocol level
|
|
12
|
-
*
|
|
13
|
-
* A developer asking a question in their editor and watching the work happen is
|
|
14
|
-
* the most-used delivery path in the architecture. MCP's mechanism is
|
|
15
|
-
* `notifications/progress`, sent only when the request carried a
|
|
16
|
-
* `_meta.progressToken`. Tools call `ctx.progress(...)` unconditionally and this
|
|
17
|
-
* layer decides whether anyone is listening — the alternative, tools checking
|
|
18
|
-
* first, is how narration ends up in some code paths and not others.
|
|
19
|
-
*
|
|
20
|
-
* ## Every tool failure is a *tool* result, not a protocol error
|
|
21
|
-
*
|
|
22
|
-
* The spec is explicit and the reason is practical: a JSON-RPC error is for a
|
|
23
|
-
* malformed request, and an agent that receives one has nothing to reason about.
|
|
24
|
-
* A bad argument, a missing graph, an unreadable repository — those come back as
|
|
25
|
-
* content with `isError`, which the model can read and act on. Only genuinely
|
|
26
|
-
* broken protocol produces an error frame.
|
|
27
|
-
*/
|
|
28
|
-
import { randomUUID } from "node:crypto";
|
|
29
|
-
import { resolveActionDispatch } from "./action-handshake.js";
|
|
30
|
-
import { TOOL_ALIASES } from "./tools/aliases.js";
|
|
31
|
-
import { fail, isRequest, negotiateVersion, ok, parseMessage, ProtocolError, RPC_INTERNAL_ERROR, RPC_INVALID_PARAMS, RPC_METHOD_NOT_FOUND, } from "./protocol.js";
|
|
32
|
-
import { renderAnswer, renderFailed, renderHandshake, renderRefusedInput, renderTimedOut, renderToolError, TOOL_OUTPUT_SCHEMA, } from "./render.js";
|
|
33
|
-
import { createDisclosureLedger } from "./disclosure-ledger.js";
|
|
34
|
-
import { AUTO_REFRESH_BUDGET_MS, checkConfigDrift, checkFreshness, ConfigError } from "./session.js";
|
|
35
|
-
import { TOOLS, TOOLS_BY_NAME, ToolInputError, } from "./tools/index.js";
|
|
36
|
-
import { analyzeTool } from "./tools/analyze.js";
|
|
37
|
-
/** Every call's declared budget (§6). Fixed today; per-trigger budgets are P26/P28 work. */
|
|
38
|
-
const CALL_BUDGET_MS = 15 * 60 * 1000;
|
|
39
|
-
function isAbort(error) {
|
|
40
|
-
return ((error instanceof Error && error.name === "AbortError") ||
|
|
41
|
-
(typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "TimeoutError"));
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* The stored graph's stamp, for a caller that has no `result` to read it from
|
|
45
|
-
* — a refusal, a failure, a timeout, or a handshake mint (F3, UAT Phase 5).
|
|
46
|
-
*
|
|
47
|
-
* Read defensively, never folded into `renderOptions()` unconditionally: a
|
|
48
|
-
* graph in a state `baseStamp()` cannot read (a stale schema version, MK-4)
|
|
49
|
-
* must not turn a graceful refusal into a thrown error. `try`/`catch` to
|
|
50
|
-
* `undefined` here, exactly as `renderHandshake`'s call site already did
|
|
51
|
-
* before this helper existed, so `renderRefusedInput`/`renderFailed`/
|
|
52
|
-
* `renderTimedOut` can stop hardcoding "no graph" regardless of what is
|
|
53
|
-
* actually stored, without reopening that already-reverted failure mode.
|
|
54
|
-
*/
|
|
55
|
-
function readGraphStampSafely(session) {
|
|
56
|
-
try {
|
|
57
|
-
return session.provider().baseStamp();
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const NO_FRESHNESS_OUTCOME = { freshness: undefined, autoNotes: [] };
|
|
64
|
-
function elapsedSeconds(startedAt) {
|
|
65
|
-
return ((Date.now() - startedAt) / 1000).toFixed(1);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Lane "map-freshness" items 1-3, run once per call, ahead of `tool.run` —
|
|
69
|
-
* the one shared place this happens, rather than 29 separate tools each
|
|
70
|
-
* growing their own copy (the lane's own instruction). Builds the graph when
|
|
71
|
-
* it is empty, refreshes it (within a budget) when it is `behind`, and
|
|
72
|
-
* either way reads the freshness this call should report.
|
|
73
|
-
*
|
|
74
|
-
* Skipped entirely for `workspace`: its `analyze`/`index` verbs already are
|
|
75
|
-
* the build/refresh mechanism (so running this ahead of them would be a
|
|
76
|
-
* second, redundant build) and `link` only declares repositories. The retired
|
|
77
|
-
* `analyze`/`analyze_workspace` names are aliases that resolve to `workspace`
|
|
78
|
-
* before this runs, so they are covered by the same check. `analyzeTool` is
|
|
79
|
-
* imported directly: it is not registered in `TOOLS_BY_NAME` under its own
|
|
80
|
-
* name any more, so a by-name lookup finds nothing.
|
|
81
|
-
*
|
|
82
|
-
* Never throws: an auto-build/refresh that fails (a `ConfigError` needing
|
|
83
|
-
* input this call can't default, an aborted refresh, anything else) is
|
|
84
|
-
* caught and treated as "did not run" — the real tool call proceeds exactly
|
|
85
|
-
* as it would have if this had never been attempted, per the lane's own
|
|
86
|
-
* "keep today's named refusal" instruction. An empty graph that stays empty
|
|
87
|
-
* after a failed auto-build still reports `freshness: null` (never `unknown`
|
|
88
|
-
* or a fabricated `current`) via `freshnessField` in `render.ts`, from the
|
|
89
|
-
* real `commitSha` this function reads again after the attempt.
|
|
90
|
-
*/
|
|
91
|
-
async function ensureFreshGraph(session, tool, ctx) {
|
|
92
|
-
if (tool.name === "workspace")
|
|
93
|
-
return NO_FRESHNESS_OUTCOME;
|
|
94
|
-
let stamp;
|
|
95
|
-
try {
|
|
96
|
-
stamp = session.provider().baseStamp();
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return NO_FRESHNESS_OUTCOME;
|
|
100
|
-
}
|
|
101
|
-
// Item 2: an empty graph is built with defaults before this call answers.
|
|
102
|
-
// `analyzeTool.run` already calls `ctx.progress(...)` as it works, so
|
|
103
|
-
// reusing this call's real `ctx` (rather than a stand-in) is what "sends
|
|
104
|
-
// progress notifications" means here — nothing extra to wire.
|
|
105
|
-
if (stamp.commitSha === null) {
|
|
106
|
-
const startedAt = Date.now();
|
|
107
|
-
try {
|
|
108
|
-
await analyzeTool.run({}, ctx);
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
// Needs input `analyze`'s own defaults can't supply (not a git
|
|
112
|
-
// repository, for instance) — leave the graph empty and let the real
|
|
113
|
-
// tool call's own "graph is empty" refusal stand, unchanged.
|
|
114
|
-
}
|
|
115
|
-
const rebuilt = readGraphStampSafely(session);
|
|
116
|
-
if (rebuilt === undefined || rebuilt.commitSha === null)
|
|
117
|
-
return NO_FRESHNESS_OUTCOME;
|
|
118
|
-
return {
|
|
119
|
-
freshness: await checkFreshness(session),
|
|
120
|
-
autoNotes: [`Code map built automatically for this answer (took ${elapsedSeconds(startedAt)}s).`],
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
const freshness = await checkFreshness(session);
|
|
124
|
-
if (freshness === undefined || freshness.status !== "behind")
|
|
125
|
-
return { freshness, autoNotes: [] };
|
|
126
|
-
// Item 3: refresh within a budget. `AbortSignal.any` combines the caller's
|
|
127
|
-
// signal with a timeout for this attempt, and `analyze` hands it to every
|
|
128
|
-
// source's `prepare()`. That is the whole reach of the budget: a source
|
|
129
|
-
// that checks the signal abandons the refresh, one that does not (git
|
|
130
|
-
// history does not) runs to completion, so the budget bounds a slow
|
|
131
|
-
// adapter, not the refresh as a whole. It is not raced against a timer:
|
|
132
|
-
// an abandoned refresh left running would write the graph while the real
|
|
133
|
-
// tool reads it. A budget of 0 or less skips the refresh outright.
|
|
134
|
-
const budgetMs = session.autoRefreshBudgetMs ?? AUTO_REFRESH_BUDGET_MS;
|
|
135
|
-
if (budgetMs <= 0)
|
|
136
|
-
return { freshness, autoNotes: [] };
|
|
137
|
-
const refreshCtx = { ...ctx, signal: AbortSignal.any([ctx.signal, AbortSignal.timeout(budgetMs)]) };
|
|
138
|
-
const startedAt = Date.now();
|
|
139
|
-
try {
|
|
140
|
-
await analyzeTool.run({}, refreshCtx);
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
// Timed out, or failed outright — answer from the graph as it stood
|
|
144
|
-
// before this attempt. `freshness` (still `behind`) already carries its
|
|
145
|
-
// own disclosure downstream (`freshnessDisclosure` in `render.ts`), so
|
|
146
|
-
// the caller learns the map is stale even though the refresh did not run.
|
|
147
|
-
return { freshness, autoNotes: [] };
|
|
148
|
-
}
|
|
149
|
-
return {
|
|
150
|
-
freshness: await checkFreshness(session),
|
|
151
|
-
autoNotes: [`Code map refreshed automatically for this answer (took ${elapsedSeconds(startedAt)}s).`],
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
/** A schema's own declared top-level argument names — empty when it has none, or when the
|
|
155
|
-
* schema isn't the `{ properties: {...} }` shape every tool's `inputSchema` actually is. */
|
|
156
|
-
function declaredTopLevelProperties(schema) {
|
|
157
|
-
const props = schema["properties"];
|
|
158
|
-
return typeof props === "object" && props !== null ? Object.keys(props) : [];
|
|
159
|
-
}
|
|
160
|
-
/** UAT phase 5, F12: which top-level keys in `args` this schema does not declare. Only meaningful
|
|
161
|
-
* when the schema opts into `additionalProperties: false` — the promise every tool's `SCHEMA`
|
|
162
|
-
* already makes (asserted across the registry by `tool-input-schema-gate.test.ts`) and that
|
|
163
|
-
* nothing enforced before this check existed. Shape only: whether a key exists, never what it
|
|
164
|
-
* means — a tool's own `requiredString`/`optionalEnum`/etc. still reads and validates the value. */
|
|
165
|
-
function unknownArgumentKeys(schema, args) {
|
|
166
|
-
if (schema["additionalProperties"] !== false)
|
|
167
|
-
return [];
|
|
168
|
-
const known = new Set(declaredTopLevelProperties(schema));
|
|
169
|
-
return Object.keys(args).filter((key) => !known.has(key));
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Does this frame have to jump the transport's ordering queue?
|
|
173
|
-
*
|
|
174
|
-
* True for `notifications/cancelled` and nothing else. Exported because the
|
|
175
|
-
* stdio runner needs the answer and the knowledge of what MCP methods mean
|
|
176
|
-
* belongs here, not in a module that otherwise only knows about bytes. Never
|
|
177
|
-
* throws — a line that will not parse is the dispatcher's to reject, with the
|
|
178
|
-
* error frame it already knows how to build.
|
|
179
|
-
*/
|
|
180
|
-
export function isOutOfBand(line) {
|
|
181
|
-
try {
|
|
182
|
-
const message = JSON.parse(line);
|
|
183
|
-
if (typeof message !== "object" || message === null || Array.isArray(message))
|
|
184
|
-
return false;
|
|
185
|
-
const frame = message;
|
|
186
|
-
// A *request* named `notifications/cancelled` is malformed, not a
|
|
187
|
-
// cancellation. Letting it jump the queue would answer it out of order,
|
|
188
|
-
// which is the exact hazard the ordering exists to prevent.
|
|
189
|
-
return frame["method"] === "notifications/cancelled" && frame["id"] === undefined;
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
const SERVER_INSTRUCTIONS = "Descry reads the repository's source into a code graph and answers questions about it.\n\n" +
|
|
196
|
-
"Call `workspace` (`{verb: \"analyze\"}`) first — every other tool queries the graph it builds, " +
|
|
197
|
-
"and a stale graph answers about code that has changed.\n\n" +
|
|
198
|
-
"Every reply has a `state`, one of five, and they are different claims: `ok` (found " +
|
|
199
|
-
"something), `empty` (looked completely, found nothing — a fact about your code), `refused` " +
|
|
200
|
-
"(could not look — a fact about Descry, never about your code), `failed` (something broke) " +
|
|
201
|
-
"and `timed_out` (ran out of its time budget, partial answer). A tool that answered `[]` for " +
|
|
202
|
-
"both \"nothing matched\" and \"I could not look\" would teach a false fact with no way to " +
|
|
203
|
-
"detect it — that is why these are distinct. Never read `refused` as \"clean\" or `empty` as " +
|
|
204
|
-
"\"broken\".\n\n" +
|
|
205
|
-
"**One case is not an answer at all and has its own shape**: a call naming no tool this " +
|
|
206
|
-
"server has — `name` is not a string, or names nothing in the registry — comes back with " +
|
|
207
|
-
"`isError: true` and `{ tool, status: \"error\", message }`, carrying no `state`, no `graph` " +
|
|
208
|
-
"and no `disclosures`. There is no `state` because there is no tool to say `state` about. " +
|
|
209
|
-
"This is narrower than it once was: a *resolved* tool given bad input — a missing required " +
|
|
210
|
-
"field, a value of the wrong type — is a fact about that tool's call and comes back as a " +
|
|
211
|
-
"real `state: \"refused\"` reply instead, with `disclosures` naming what was wrong. Branch " +
|
|
212
|
-
"on `isError` before reading `state` regardless — a caller that only ever sees the second, " +
|
|
213
|
-
"unresolved-tool shape in testing will still be surprised by it in production.\n\n" +
|
|
214
|
-
"Every reply also carries a `disclosures` list, a `resolutionFloor` and a `reliabilityCap` " +
|
|
215
|
-
"(A, B or C) inside `graph`. `resolutionFloor` is how much tooling actually ran under the " +
|
|
216
|
-
"weakest evidence behind the answer, R0 through R4: R0 is syntax only, nothing resolved; R1 " +
|
|
217
|
-
"adds module/import resolution; R2 adds cross-file reference resolution (which symbol a name " +
|
|
218
|
-
"refers to, but no type checker); R3 adds a type checker, so claims about shapes are provable; " +
|
|
219
|
-
"R4 means the fact was observed at runtime rather than inferred. `reliabilityCap` is what that " +
|
|
220
|
-
"floor permits the claim to be relayed as: C means the claim is a behavioural prediction that " +
|
|
221
|
-
"has not been confirmed by running anything, and must not be relayed as fact. B means the " +
|
|
222
|
-
"claim rests on structural or reference resolution — a name, an import, a call target — real " +
|
|
223
|
-
"evidence, but not yet a confirmed behaviour. A means the claim is as strong as this graph can " +
|
|
224
|
-
"make it: a name-level fact resolved at R2 or better, a shape-level fact backed by a type " +
|
|
225
|
-
"checker (R3), or anything witnessed at runtime (R4, unconditional). Read the disclosures " +
|
|
226
|
-
"before summarising — they say what the answer does *not* cover.\n\n" +
|
|
227
|
-
"Coverage is a separate question from confidence: call `disclosure` with `{verb: \"coverage\", " +
|
|
228
|
-
"refs: [...]}` and a list of node ids or file paths from an earlier reply to learn which of " +
|
|
229
|
-
"them the graph actually reached, and at what resolution, rather than assuming silence means " +
|
|
230
|
-
"untested. `disclosure`'s `{verb: \"unresolved\"}` gives the graph's full ledger of things an " +
|
|
231
|
-
"adapter could not resolve — call it with no `handle` for a one-line summary and a handle, " +
|
|
232
|
-
"then again with that handle to page through every row; never assume the summary's one " +
|
|
233
|
-
"exemplar is the only refusal.\n\n" +
|
|
234
|
-
"`class` on each tool (`read`, `stateful-read` or `action`) says whether it is safe to retry. " +
|
|
235
|
-
"The one `action`-class tool (`questions`, when answering) takes a two-call handshake: the " +
|
|
236
|
-
"first call performs nothing and returns a confirmation token; only a second call presenting " +
|
|
237
|
-
"that exact token performs the write.\n\n" +
|
|
238
|
-
"`tier` on each tool is `conclusion` for the tools that already state a verdict about your " +
|
|
239
|
-
"code (`validate`, `contracts`, `cross_pr` — quote their `headline` verbatim rather than " +
|
|
240
|
-
"rephrasing it) or `evidence` for every other tool, which returns graph facts for you to " +
|
|
241
|
-
"reason over yourself. Every reply also carries `reportCategory` — one of `confirmed`, " +
|
|
242
|
-
"`strongly supported`, `unconfirmed`, `not analysable`, `unsupported`, or `null` where no " +
|
|
243
|
-
"claim applies. It is `null` on every `conclusion`-tier reply (the `headline` already states " +
|
|
244
|
-
"the verdict in plain words). On an `evidence`-tier reply it follows that reply's own " +
|
|
245
|
-
"`resolutionFloor`: `unconfirmed` below R4, where nothing was observed, and `strongly " +
|
|
246
|
-
"supported` at R4, where every hop behind the answer was witnessed in a real run — " +
|
|
247
|
-
"`observe`'s `runtime` and `tests` verbs are what write those edges. `confirmed` never appears " +
|
|
248
|
-
"here — that word is reserved for results that passed the full governance pipeline, and its " +
|
|
249
|
-
"absence is honest, not a bug.\n\n" +
|
|
250
|
-
"Beside it, `existenceCategory` answers a different question, and the two are not " +
|
|
251
|
-
"interchangeable. `reportCategory` says how strongly the *cause* may be stated and is capped " +
|
|
252
|
-
"by how well the code resolved; `existenceCategory` says how strongly the evidence shows the " +
|
|
253
|
-
"failure is *real*, and never reads the resolution at all. They separate exactly where it " +
|
|
254
|
-
"matters: a reply that witnessed a failure on three channels but resolved no code path " +
|
|
255
|
-
"reports `unconfirmed` for the cause and `strongly supported` for the failure. Read that as " +
|
|
256
|
-
"*something is wrong and we could not tell you where* — not as *nothing is wrong*. It is " +
|
|
257
|
-
"`null` wherever no evidence reading was taken at all: conclusion-tier replies, faults, and " +
|
|
258
|
-
"refusals, since a refusal is a fact about Descry rather than about your code. `provenance` names " +
|
|
259
|
-
"this surface explicitly (`adjudicatedBy: \"descry\"`, `presentedBy: \"host-agent\"`) so a " +
|
|
260
|
-
"reply from here is never mistaken for one the app itself adjudicated and presented.\n\n" +
|
|
261
|
-
"In agent mode, Descry gives you high-reliability facts about your code. It does not give you " +
|
|
262
|
-
"confirmed behaviour, because it did not run your application — `descry-runtime`'s live loop " +
|
|
263
|
-
"does not execute inside an MCP call, at any resolution level or however careful the static " +
|
|
264
|
-
"analysis was. `confirmed` and `strongly supported` are the desktop app's differentiator, not " +
|
|
265
|
-
"this surface's; treat every reply here as a strong lead to verify, never as a closed case.\n\n" +
|
|
266
|
-
"Descry cannot enforce any of this once you leave this server: nothing stops you from adding " +
|
|
267
|
-
"your own claims on top of what a tool returned (the fact boundary), and nothing stops you " +
|
|
268
|
-
"from investigating paths no tool surfaced or suggested (the candidate boundary) — this text " +
|
|
269
|
-
"cannot make you not do either. The fields above exist so you do not have to guess.";
|
|
270
|
-
export function createMcpServer(options) {
|
|
271
|
-
const session = options.session;
|
|
272
|
-
const serverName = options.name ?? "descry";
|
|
273
|
-
const serverVersion = options.version ?? "0.0.0";
|
|
274
|
-
// One per connection, living exactly as long as this server — see
|
|
275
|
-
// `disclosure-ledger.ts` for why it is not shared across connections.
|
|
276
|
-
const disclosureLedger = createDisclosureLedger();
|
|
277
|
-
let initialized = false;
|
|
278
|
-
const tools = options.tools ?? TOOLS;
|
|
279
|
-
const toolsByName = options.tools === undefined
|
|
280
|
-
? TOOLS_BY_NAME
|
|
281
|
-
: new Map(options.tools.map((tool) => [tool.name, tool]));
|
|
282
|
-
/**
|
|
283
|
-
* In-flight `tools/call`s, by request id, so `notifications/cancelled` has
|
|
284
|
-
* something to act on. Entries live exactly as long as the call: added
|
|
285
|
-
* before `tool.run`, removed in the `finally` that also drops the call's
|
|
286
|
-
* progress tick.
|
|
287
|
-
*/
|
|
288
|
-
const pending = new Map();
|
|
289
|
-
async function handleRequest(request, transport) {
|
|
290
|
-
const { id, method } = request;
|
|
291
|
-
const params = request.params ?? {};
|
|
292
|
-
switch (method) {
|
|
293
|
-
case "initialize": {
|
|
294
|
-
transport.send(ok(id, {
|
|
295
|
-
protocolVersion: negotiateVersion(params["protocolVersion"]),
|
|
296
|
-
// `listChanged: false` is honest: the tool set is fixed at startup,
|
|
297
|
-
// so the server will never send a list-changed notification and
|
|
298
|
-
// should not claim it might.
|
|
299
|
-
capabilities: { tools: { listChanged: false } },
|
|
300
|
-
serverInfo: { name: serverName, version: serverVersion },
|
|
301
|
-
instructions: SERVER_INSTRUCTIONS,
|
|
302
|
-
}));
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
case "ping": {
|
|
306
|
-
transport.send(ok(id, {}));
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
case "tools/list": {
|
|
310
|
-
transport.send(ok(id, {
|
|
311
|
-
tools: tools.map((tool) => ({
|
|
312
|
-
name: tool.name,
|
|
313
|
-
title: tool.title,
|
|
314
|
-
description: tool.description,
|
|
315
|
-
inputSchema: tool.inputSchema,
|
|
316
|
-
// ai-tool-contract.md §8: every endpoint declares a class, and an
|
|
317
|
-
// external client has no other way to read it — §6's retry table
|
|
318
|
-
// (read=retryable, stateful-read=idempotent-retryable,
|
|
319
|
-
// action=no-retry+handshake-required) is meaningless without this
|
|
320
|
-
// on the wire.
|
|
321
|
-
class: tool.class,
|
|
322
|
-
// MK-5: whether this tool's output is a conclusion about the
|
|
323
|
-
// user's code or a fact about the graph — same "no other way to
|
|
324
|
-
// read it" reasoning as `class`, one line up.
|
|
325
|
-
tier: tool.tier,
|
|
326
|
-
toolVersion: tool.version,
|
|
327
|
-
// Every reply this server sends carries a `structuredContent`
|
|
328
|
-
// envelope, and without this a host has no way to validate one.
|
|
329
|
-
// Shared across all tools because the envelope is: see
|
|
330
|
-
// `TOOL_OUTPUT_SCHEMA`, including why `data` is left open.
|
|
331
|
-
outputSchema: TOOL_OUTPUT_SCHEMA,
|
|
332
|
-
})),
|
|
333
|
-
}));
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
case "tools/call": {
|
|
337
|
-
const result = await callTool(id, params, transport);
|
|
338
|
-
// `null` means the call was cancelled while it ran. MCP forbids a
|
|
339
|
-
// response to a cancelled request, so the only correct frame here is
|
|
340
|
-
// no frame at all.
|
|
341
|
-
if (result !== null)
|
|
342
|
-
transport.send(ok(id, result));
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
default:
|
|
346
|
-
transport.send(fail(id, RPC_METHOD_NOT_FOUND, `unknown method: ${method}`));
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
async function callTool(id, params, transport) {
|
|
350
|
-
const name = params["name"];
|
|
351
|
-
if (typeof name !== "string") {
|
|
352
|
-
return renderToolError("tools/call", '"name" must be a string');
|
|
353
|
-
}
|
|
354
|
-
// A retired name is resolved here and nowhere else: `tools/list` never
|
|
355
|
-
// offered it (see `tools/aliases.ts`), so only a caller holding an old
|
|
356
|
-
// name in a config or a script can arrive with one. `aliasedTo` is
|
|
357
|
-
// threaded into `renderOptions` so the reply says which name answered.
|
|
358
|
-
const direct = toolsByName.get(name);
|
|
359
|
-
const alias = direct === undefined ? TOOL_ALIASES.get(name) : undefined;
|
|
360
|
-
const tool = direct ?? (alias === undefined ? undefined : toolsByName.get(alias.to));
|
|
361
|
-
if (tool === undefined) {
|
|
362
|
-
return renderToolError(name, `no such tool. Available: ${tools.map((t) => t.name).join(", ")}.`);
|
|
363
|
-
}
|
|
364
|
-
// `tool` is resolved from here on, so any input failure below has a real
|
|
365
|
-
// `ToolDefinition` to render a `state: "refused"` envelope from
|
|
366
|
-
// (`renderRefusedInput`) rather than `renderToolError`'s bare shape —
|
|
367
|
-
// minted here, ahead of the args check, so both that check and a
|
|
368
|
-
// `ToolInputError` thrown later out of `tool.run` share the one
|
|
369
|
-
// `renderOptions()`. Same precedent as B10's `callId`: a call that never
|
|
370
|
-
// reaches `tool.run` still gets one minted (`renderFailed`/`renderTimedOut`
|
|
371
|
-
// already do this for every call but `verify_claim`), and is never passed
|
|
372
|
-
// to `session.recordCallWithId` below, so no gap opens in what a citation
|
|
373
|
-
// can resolve.
|
|
374
|
-
const started = Date.now();
|
|
375
|
-
const callId = name === "verify_claim" ? randomUUID() : session.allocateCallId();
|
|
376
|
-
// 13.3.16 (N2) steps 2-3: checked once per call, ahead of dispatch, so every
|
|
377
|
-
// reply this call produces — ok, refused, failed or timed out — carries the
|
|
378
|
-
// same disclosure and the same `configStale` flag, not only `analyze`'s.
|
|
379
|
-
const configDrift = await checkConfigDrift(session);
|
|
380
|
-
// Lane "map-freshness": set for real just before `tool.run` (once `ctx`
|
|
381
|
-
// exists), by `ensureFreshGraph`. Declared here, ahead of every early
|
|
382
|
-
// `renderOptions()` call below (an `"arguments"`-shape refusal, an
|
|
383
|
-
// unknown-argument refusal), so those calls see the same
|
|
384
|
-
// `NO_FRESHNESS_OUTCOME` default `configDrift` above already reads —
|
|
385
|
-
// never a "used before declaration" on a call site that runs before
|
|
386
|
-
// `ctx` does.
|
|
387
|
-
let freshnessOutcome = NO_FRESHNESS_OUTCOME;
|
|
388
|
-
const renderOptions = () => ({
|
|
389
|
-
toolVersion: tool.version,
|
|
390
|
-
toolClass: tool.class,
|
|
391
|
-
toolTier: tool.tier,
|
|
392
|
-
elapsedMs: Date.now() - started,
|
|
393
|
-
limitMs: CALL_BUDGET_MS,
|
|
394
|
-
disclosureLedger,
|
|
395
|
-
callId,
|
|
396
|
-
configDrift,
|
|
397
|
-
...(freshnessOutcome.freshness === undefined ? {} : { freshness: freshnessOutcome.freshness }),
|
|
398
|
-
...(freshnessOutcome.autoNotes.length === 0 ? {} : { autoNotes: freshnessOutcome.autoNotes }),
|
|
399
|
-
...(alias === undefined ? {} : { aliasedFrom: name, aliasedTo: tool.name }),
|
|
400
|
-
});
|
|
401
|
-
const rawArgs = params["arguments"];
|
|
402
|
-
if (rawArgs !== undefined && (typeof rawArgs !== "object" || rawArgs === null || Array.isArray(rawArgs))) {
|
|
403
|
-
const graphStamp = readGraphStampSafely(session);
|
|
404
|
-
return renderRefusedInput(name, '"arguments" must be an object', {
|
|
405
|
-
...renderOptions(),
|
|
406
|
-
...(graphStamp === undefined ? {} : { graphStamp }),
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
const rewritten = (rawArgs ?? {});
|
|
410
|
-
// The old call shape becomes the new one before any gate reads it, so the
|
|
411
|
-
// schema check below is run against the tool that will actually answer.
|
|
412
|
-
const args = alias?.args === undefined ? rewritten : alias.args(rewritten);
|
|
413
|
-
// UAT phase 5, F12: `inputSchema` is advertised in `tools/list` and never read
|
|
414
|
-
// again — every tool hand-reads the keys it knows, so an unknown argument was
|
|
415
|
-
// silently ignored rather than refused (`contracts({ symbol: ... })` returning
|
|
416
|
-
// the whole-repo report; `browser_start_session({ profile: ... })` issuing the
|
|
417
|
-
// wrong consent because the tool reads `environment`). Checked here, once, for
|
|
418
|
-
// every tool that declares `additionalProperties: false` — which is all of
|
|
419
|
-
// them (asserted by tool-input-schema-gate.test.ts) — before dispatch, so a
|
|
420
|
-
// typo'd or misremembered key refuses loudly instead of vanishing. This is
|
|
421
|
-
// shape only: which keys exist, not what they mean — each tool's own
|
|
422
|
-
// `requiredString`/`optionalEnum`/etc. still checks that.
|
|
423
|
-
const unknownArgs = unknownArgumentKeys(tool.inputSchema, args);
|
|
424
|
-
if (unknownArgs.length > 0) {
|
|
425
|
-
const known = declaredTopLevelProperties(tool.inputSchema);
|
|
426
|
-
return renderRefusedInput(name, `unknown argument(s): ${unknownArgs.map((k) => `"${k}"`).join(", ")}. ` +
|
|
427
|
-
(known.length > 0 ? `${name} accepts: ${known.join(", ")}.` : `${name} takes no arguments.`), renderOptions());
|
|
428
|
-
}
|
|
429
|
-
const meta = params["_meta"];
|
|
430
|
-
const token = typeof meta === "object" && meta !== null
|
|
431
|
-
? meta["progressToken"]
|
|
432
|
-
: undefined;
|
|
433
|
-
const progress = typeof token === "string" || typeof token === "number"
|
|
434
|
-
? (message, current, total) => {
|
|
435
|
-
transport.send({
|
|
436
|
-
jsonrpc: "2.0",
|
|
437
|
-
method: "notifications/progress",
|
|
438
|
-
params: {
|
|
439
|
-
progressToken: token,
|
|
440
|
-
// `progress` is required by the spec and must increase. When a
|
|
441
|
-
// tool narrates without a count, the message is the payload and
|
|
442
|
-
// the number is a monotonic tick rather than a fake percentage.
|
|
443
|
-
progress: current ?? nextTick(id),
|
|
444
|
-
...(total === undefined ? {} : { total }),
|
|
445
|
-
message,
|
|
446
|
-
},
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
: () => { };
|
|
450
|
-
// Two ways a call ends early, composed into the one signal the tool sees:
|
|
451
|
-
// its own budget running out, and the client asking for it to stop.
|
|
452
|
-
//
|
|
453
|
-
// **What this does and does not buy.** Aborting here stops the *server*
|
|
454
|
-
// waiting and suppresses the response the client is no longer listening
|
|
455
|
-
// for, which is the protocol's requirement and is met. It stops the actual
|
|
456
|
-
// work only in a tool that reads the signal it is handed, and today that is
|
|
457
|
-
// exactly one of thirty-three — `analyze`, which passes `ctx.signal` down. The
|
|
458
|
-
// other thirty-two, `browser_run_scenario` and `observe_runtime` among
|
|
459
|
-
// them, take the signal and never look at it, so a cancelled call there
|
|
460
|
-
// leaves a real browser or a real application process running until it
|
|
461
|
-
// finishes on its own. That is a disclosed gap, filed as
|
|
462
|
-
// `DEC-NEXT-cancellation-reaches-one-tool-in-thirty.md`, not something this
|
|
463
|
-
// layer can fix from here — threading the signal is each tool's own work.
|
|
464
|
-
const controller = new AbortController();
|
|
465
|
-
pending.set(id, controller);
|
|
466
|
-
const ctx = {
|
|
467
|
-
session,
|
|
468
|
-
progress,
|
|
469
|
-
signal: AbortSignal.any([controller.signal, AbortSignal.timeout(CALL_BUDGET_MS)]),
|
|
470
|
-
};
|
|
471
|
-
// B10: `started`/`callId`/`renderOptions` are minted above, ahead of the
|
|
472
|
-
// `arguments` shape check, so every envelope this call can produce
|
|
473
|
-
// (refused, handshake, failed, timed-out, or a real answer) carries the
|
|
474
|
-
// exact id `recordCallWithId` will file the record under below — a
|
|
475
|
-
// caller reading `callId` off the reply and citing it in `verify_claim`
|
|
476
|
-
// is citing the id that call is actually recorded as.
|
|
477
|
-
//
|
|
478
|
-
// `verify_claim` itself is the one exception, on the same reasoning as
|
|
479
|
-
// its exclusion from recording just below: it produces no fact for a
|
|
480
|
-
// later claim to cite, so its own `callId` is not drawn from the
|
|
481
|
-
// session's call-id sequence at all — `session.allocateCallId()` is
|
|
482
|
-
// reserved for calls that will actually be recorded under the id it
|
|
483
|
-
// returns. Reusing it here would consume a real id `verify_claim` never
|
|
484
|
-
// gets recorded under, opening a gap in the sequence a caller relies on
|
|
485
|
-
// corresponding exactly to recorded calls.
|
|
486
|
-
try {
|
|
487
|
-
// §7's two-call handshake. Decided before any real work starts — a mint
|
|
488
|
-
// has no I/O to time out on — so this sits outside the try/catch's
|
|
489
|
-
// failure/timeout handling below, which is for `tool.run` alone.
|
|
490
|
-
const dispatch = await resolveActionDispatch(tool, args, ctx);
|
|
491
|
-
if (dispatch.kind === "handshake") {
|
|
492
|
-
// A handshake mint has done no I/O yet, so falling back to "no stamp
|
|
493
|
-
// known" on a read failure is exactly `renderHandshake`'s original,
|
|
494
|
-
// already-correct behaviour, not a new silent failure — see
|
|
495
|
-
// `readGraphStampSafely`'s own doc for why this is never folded into
|
|
496
|
-
// `renderOptions()` unconditionally.
|
|
497
|
-
const graphStamp = readGraphStampSafely(session);
|
|
498
|
-
return renderHandshake(name, dispatch.token, dispatch.willDo, {
|
|
499
|
-
...renderOptions(),
|
|
500
|
-
...(graphStamp === undefined ? {} : { graphStamp }),
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
// Lane "map-freshness" items 1-3: build an empty graph, refresh a
|
|
504
|
-
// `behind` one within budget, and read the freshness this call should
|
|
505
|
-
// report — once, here, ahead of the real work, not inside `tool.run`
|
|
506
|
-
// itself. After the handshake check (a mint does no I/O, so nothing to
|
|
507
|
-
// ensure yet) and before `tool.run` (which is what needs a fresh graph
|
|
508
|
-
// to answer from).
|
|
509
|
-
freshnessOutcome = await ensureFreshGraph(session, tool, ctx);
|
|
510
|
-
const outcome = await tool.run(dispatch.args, ctx);
|
|
511
|
-
// Cancelled while it was running, and it finished anyway — the client
|
|
512
|
-
// stopped listening for this id, so the answer is dropped rather than
|
|
513
|
-
// sent late. Not recorded on the session either: a fact the caller never
|
|
514
|
-
// received must not become one a later `verify_claim` can cite.
|
|
515
|
-
if (controller.signal.aborted)
|
|
516
|
-
return null;
|
|
517
|
-
// Re-checked here, not reused from the `configDrift` captured before
|
|
518
|
-
// dispatch: `tool.run` is the one place `session.reloadConfig()` can be
|
|
519
|
-
// called (§0 gap 2's `analyze({ reload: true })`), and a call that just
|
|
520
|
-
// reloaded must not still report itself as stale — the drift it would
|
|
521
|
-
// be reporting no longer exists by the time this line runs.
|
|
522
|
-
const rendered = renderAnswer(name, outcome, {
|
|
523
|
-
...renderOptions(),
|
|
524
|
-
configDrift: await checkConfigDrift(session),
|
|
525
|
-
// Rule 7 on the redemption path: the handshake decided which arguments ran, so it is the
|
|
526
|
-
// only thing that knows which of the caller's were dropped. Omitted entirely when nothing
|
|
527
|
-
// was, so a correct two-call redemption reads exactly as it did before.
|
|
528
|
-
...(dispatch.discardedArgs === undefined ? {} : { discardedArgs: dispatch.discardedArgs }),
|
|
529
|
-
});
|
|
530
|
-
// MK-12: recorded after rendering, from the exact structuredContent the
|
|
531
|
-
// host receives — not the pre-render outcome, which the host never
|
|
532
|
-
// sees. `verify_claim` itself is excluded: it produces no fact for a
|
|
533
|
-
// later claim to cite, only a verdict about other calls' facts.
|
|
534
|
-
//
|
|
535
|
-
// Recorded under `callId` — the same id `rendered.structuredContent`
|
|
536
|
-
// already carries as `callId` — rather than a freshly minted one
|
|
537
|
-
// (B10): the two must be the same value for a citation read off this
|
|
538
|
-
// reply to resolve.
|
|
539
|
-
if (name !== "verify_claim") {
|
|
540
|
-
// B1: a tool that can be handed a credential says how it wants to be
|
|
541
|
-
// remembered (`ToolDefinition.redactArgs`). Every other tool is
|
|
542
|
-
// recorded exactly as it was called, as before.
|
|
543
|
-
session.recordCallWithId(callId, name, tool.redactArgs === undefined ? args : tool.redactArgs(args), rendered.structuredContent);
|
|
544
|
-
}
|
|
545
|
-
return rendered;
|
|
546
|
-
}
|
|
547
|
-
catch (error) {
|
|
548
|
-
// Cancellation is checked before anything else, including
|
|
549
|
-
// `ToolInputError`: whatever the tool threw on its way out, the client
|
|
550
|
-
// has told us it is not listening, and the spec is explicit that a
|
|
551
|
-
// cancelled request gets no response at all.
|
|
552
|
-
if (controller.signal.aborted)
|
|
553
|
-
return null;
|
|
554
|
-
const graphStamp = readGraphStampSafely(session);
|
|
555
|
-
const optionsWithStamp = () => ({
|
|
556
|
-
...renderOptions(),
|
|
557
|
-
...(graphStamp === undefined ? {} : { graphStamp }),
|
|
558
|
-
});
|
|
559
|
-
if (error instanceof ToolInputError)
|
|
560
|
-
return renderRefusedInput(name, error.message, optionsWithStamp());
|
|
561
|
-
if (isAbort(error) || ctx.signal.aborted)
|
|
562
|
-
return renderTimedOut(name, optionsWithStamp());
|
|
563
|
-
// Anything else is a bug or an environment failure. It still comes back as
|
|
564
|
-
// a tool result: an agent can retry or tell the user, whereas a protocol
|
|
565
|
-
// error just ends the call with nothing it can use.
|
|
566
|
-
const failureMessage = error instanceof Error ? error.message : String(error);
|
|
567
|
-
// 13.3.5 Half A: a `ConfigError` is thrown with a full written reason
|
|
568
|
-
// specifically so a caller can read it — giving it the generic
|
|
569
|
-
// "X failed." headline and burying that reason in `disclosures` says
|
|
570
|
-
// less than the error already said. An unexplained fault keeps the
|
|
571
|
-
// opaque default `renderFailed` falls back to.
|
|
572
|
-
return renderFailed(name, failureMessage, optionsWithStamp(), error instanceof ConfigError ? `${name} could not run: ${failureMessage}` : undefined);
|
|
573
|
-
}
|
|
574
|
-
finally {
|
|
575
|
-
pending.delete(id);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Act on `notifications/cancelled`: abort the named call if it is still ours
|
|
580
|
-
* and still running.
|
|
581
|
-
*
|
|
582
|
-
* Silence in every other case is deliberate and is what the spec asks for. A
|
|
583
|
-
* cancellation racing a call that has already returned is ordinary client
|
|
584
|
-
* behaviour, not an error — the client sent it before our response reached
|
|
585
|
-
* it — and a notification cannot be answered anyway, so there is nowhere to
|
|
586
|
-
* report a bad `requestId` even if one were worth reporting.
|
|
587
|
-
*/
|
|
588
|
-
function cancel(params) {
|
|
589
|
-
const requestId = params["requestId"];
|
|
590
|
-
if (typeof requestId !== "string" && typeof requestId !== "number")
|
|
591
|
-
return;
|
|
592
|
-
const controller = pending.get(requestId);
|
|
593
|
-
if (controller === undefined)
|
|
594
|
-
return;
|
|
595
|
-
const reason = params["reason"];
|
|
596
|
-
controller.abort(new Error(typeof reason === "string" && reason !== ""
|
|
597
|
-
? `cancelled by client: ${reason}`
|
|
598
|
-
: "cancelled by client"));
|
|
599
|
-
}
|
|
600
|
-
// Monotonic per-request tick for narration with no natural count.
|
|
601
|
-
const ticks = new Map();
|
|
602
|
-
function nextTick(id) {
|
|
603
|
-
const next = (ticks.get(id) ?? 0) + 1;
|
|
604
|
-
ticks.set(id, next);
|
|
605
|
-
return next;
|
|
606
|
-
}
|
|
607
|
-
return {
|
|
608
|
-
get initialized() {
|
|
609
|
-
return initialized;
|
|
610
|
-
},
|
|
611
|
-
async dispatch(line, transport) {
|
|
612
|
-
let message;
|
|
613
|
-
try {
|
|
614
|
-
message = parseMessage(line);
|
|
615
|
-
}
|
|
616
|
-
catch (error) {
|
|
617
|
-
if (error instanceof ProtocolError) {
|
|
618
|
-
// No usable id means no response is possible: JSON-RPC has nowhere to
|
|
619
|
-
// put the answer, and inventing an id would put a frame on the wire
|
|
620
|
-
// the client cannot correlate to anything it sent.
|
|
621
|
-
if (error.id !== null)
|
|
622
|
-
transport.send(fail(error.id, error.code, error.message));
|
|
623
|
-
return;
|
|
624
|
-
}
|
|
625
|
-
throw error;
|
|
626
|
-
}
|
|
627
|
-
if (!isRequest(message)) {
|
|
628
|
-
if (message.method === "notifications/initialized")
|
|
629
|
-
initialized = true;
|
|
630
|
-
else if (message.method === "notifications/cancelled")
|
|
631
|
-
cancel(message.params ?? {});
|
|
632
|
-
// Anything else — roots changed, and every notification a future spec
|
|
633
|
-
// adds — is accepted and ignored. A notification must never be
|
|
634
|
-
// answered, so silence on the wire is the protocol; silence *in
|
|
635
|
-
// response* is what cancellation could not afford, which is why it is
|
|
636
|
-
// the one handled above.
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
try {
|
|
640
|
-
await handleRequest(message, transport);
|
|
641
|
-
}
|
|
642
|
-
catch (error) {
|
|
643
|
-
transport.send(fail(message.id, error instanceof ToolInputError ? RPC_INVALID_PARAMS : RPC_INTERNAL_ERROR, error instanceof Error ? error.message : String(error)));
|
|
644
|
-
}
|
|
645
|
-
finally {
|
|
646
|
-
ticks.delete(message.id);
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
//# sourceMappingURL=server.js.map
|