@descryy/mcp 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-handshake.d.ts +8 -75
- package/dist/action-handshake.d.ts.map +1 -1
- package/dist/action-handshake.js +9 -79
- package/dist/action-handshake.js.map +1 -1
- package/dist/bin/descry-mcp.d.ts +4 -15
- package/dist/bin/descry-mcp.d.ts.map +1 -1
- package/dist/bin/descry-mcp.js +12 -42
- package/dist/bin/descry-mcp.js.map +1 -1
- package/dist/browser/driver.d.ts +62 -178
- package/dist/browser/driver.d.ts.map +1 -1
- package/dist/browser/driver.js +14 -46
- package/dist/browser/driver.js.map +1 -1
- package/dist/browser/evidence.d.ts +11 -35
- package/dist/browser/evidence.d.ts.map +1 -1
- package/dist/browser/evidence.js +25 -51
- package/dist/browser/evidence.js.map +1 -1
- package/dist/browser/fake-driver.d.ts +12 -16
- package/dist/browser/fake-driver.d.ts.map +1 -1
- package/dist/browser/fake-driver.js +24 -17
- package/dist/browser/fake-driver.js.map +1 -1
- package/dist/browser/graph-write.d.ts +4 -45
- package/dist/browser/graph-write.d.ts.map +1 -1
- package/dist/browser/graph-write.js +8 -53
- package/dist/browser/graph-write.js.map +1 -1
- package/dist/browser/playwright-driver.d.ts +17 -67
- package/dist/browser/playwright-driver.d.ts.map +1 -1
- package/dist/browser/playwright-driver.js +169 -166
- package/dist/browser/playwright-driver.js.map +1 -1
- package/dist/browser/provider.d.ts +5 -34
- package/dist/browser/provider.d.ts.map +1 -1
- package/dist/browser/provider.js +4 -24
- package/dist/browser/provider.js.map +1 -1
- package/dist/browser/registry.d.ts +26 -106
- package/dist/browser/registry.d.ts.map +1 -1
- package/dist/browser/registry.js +20 -77
- package/dist/browser/registry.js.map +1 -1
- package/dist/browser/scenario-resolve.d.ts +10 -44
- package/dist/browser/scenario-resolve.d.ts.map +1 -1
- package/dist/browser/scenario-resolve.js +10 -41
- package/dist/browser/scenario-resolve.js.map +1 -1
- package/dist/browser/scenario-runner.d.ts +12 -70
- package/dist/browser/scenario-runner.d.ts.map +1 -1
- package/dist/browser/scenario-runner.js +33 -91
- package/dist/browser/scenario-runner.js.map +1 -1
- package/dist/browser/stack-parser.d.ts +4 -28
- package/dist/browser/stack-parser.d.ts.map +1 -1
- package/dist/browser/stack-parser.js +12 -39
- package/dist/browser/stack-parser.js.map +1 -1
- package/dist/browser/tool-support.d.ts +20 -67
- package/dist/browser/tool-support.d.ts.map +1 -1
- package/dist/browser/tool-support.js +22 -66
- package/dist/browser/tool-support.js.map +1 -1
- package/dist/browser/url-scheme.d.ts +14 -0
- package/dist/browser/url-scheme.d.ts.map +1 -0
- package/dist/browser/url-scheme.js +38 -0
- package/dist/browser/url-scheme.js.map +1 -0
- package/dist/cancellation.d.ts +11 -46
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +11 -46
- package/dist/cancellation.js.map +1 -1
- package/dist/capped.d.ts +17 -0
- package/dist/capped.d.ts.map +1 -0
- package/dist/capped.js +15 -0
- package/dist/capped.js.map +1 -0
- package/dist/disclosure-ledger.d.ts +6 -30
- package/dist/disclosure-ledger.d.ts.map +1 -1
- package/dist/disclosure-ledger.js +4 -26
- package/dist/disclosure-ledger.js.map +1 -1
- package/dist/index.d.ts +10 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -17
- package/dist/index.js.map +1 -1
- package/dist/module-trust.d.ts +24 -0
- package/dist/module-trust.d.ts.map +1 -0
- package/dist/module-trust.js +60 -0
- package/dist/module-trust.js.map +1 -0
- package/dist/path-confinement.d.ts +31 -0
- package/dist/path-confinement.d.ts.map +1 -0
- package/dist/path-confinement.js +44 -0
- package/dist/path-confinement.js.map +1 -0
- package/dist/protocol.d.ts +10 -53
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +14 -60
- package/dist/protocol.js.map +1 -1
- package/dist/registry.d.ts +10 -58
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +38 -90
- package/dist/registry.js.map +1 -1
- package/dist/render.d.ts +79 -11
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +126 -14
- package/dist/render.js.map +1 -1
- package/dist/runtime-registry.d.ts +8 -49
- package/dist/runtime-registry.d.ts.map +1 -1
- package/dist/runtime-registry.js +72 -63
- package/dist/runtime-registry.js.map +1 -1
- package/dist/scenarios/index.d.ts +1 -1
- package/dist/scenarios/index.d.ts.map +1 -1
- package/dist/scenarios/index.js +1 -1
- package/dist/scenarios/index.js.map +1 -1
- package/dist/scenarios/parse.d.ts +4 -18
- package/dist/scenarios/parse.d.ts.map +1 -1
- package/dist/scenarios/parse.js +14 -34
- package/dist/scenarios/parse.js.map +1 -1
- package/dist/scenarios/scenario.d.ts +18 -74
- package/dist/scenarios/scenario.d.ts.map +1 -1
- package/dist/scenarios/scenario.js +7 -34
- package/dist/scenarios/scenario.js.map +1 -1
- package/dist/scenarios/storage.d.ts +11 -41
- package/dist/scenarios/storage.d.ts.map +1 -1
- package/dist/scenarios/storage.js +57 -47
- package/dist/scenarios/storage.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +55 -13
- package/dist/server.js.map +1 -1
- package/dist/session.d.ts +69 -239
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +76 -231
- package/dist/session.js.map +1 -1
- package/dist/tools/analyze.d.ts +27 -101
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +58 -148
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/browser-click.d.ts +3 -21
- package/dist/tools/browser-click.d.ts.map +1 -1
- package/dist/tools/browser-click.js +10 -31
- package/dist/tools/browser-click.js.map +1 -1
- package/dist/tools/browser-close-session.d.ts +4 -13
- package/dist/tools/browser-close-session.d.ts.map +1 -1
- package/dist/tools/browser-close-session.js +4 -13
- package/dist/tools/browser-close-session.js.map +1 -1
- package/dist/tools/browser-fill.d.ts +5 -36
- package/dist/tools/browser-fill.d.ts.map +1 -1
- package/dist/tools/browser-fill.js +9 -44
- package/dist/tools/browser-fill.js.map +1 -1
- package/dist/tools/browser-navigate.d.ts +6 -27
- package/dist/tools/browser-navigate.d.ts.map +1 -1
- package/dist/tools/browser-navigate.js +6 -23
- package/dist/tools/browser-navigate.js.map +1 -1
- package/dist/tools/browser-run-scenario.d.ts +5 -31
- package/dist/tools/browser-run-scenario.d.ts.map +1 -1
- package/dist/tools/browser-run-scenario.js +10 -46
- package/dist/tools/browser-run-scenario.js.map +1 -1
- package/dist/tools/browser-save-scenario.d.ts +3 -28
- package/dist/tools/browser-save-scenario.d.ts.map +1 -1
- package/dist/tools/browser-save-scenario.js +102 -55
- package/dist/tools/browser-save-scenario.js.map +1 -1
- package/dist/tools/browser-snapshot.d.ts +6 -39
- package/dist/tools/browser-snapshot.d.ts.map +1 -1
- package/dist/tools/browser-snapshot.js +4 -31
- package/dist/tools/browser-snapshot.js.map +1 -1
- package/dist/tools/browser-start-session.d.ts +4 -23
- package/dist/tools/browser-start-session.d.ts.map +1 -1
- package/dist/tools/browser-start-session.js +38 -51
- package/dist/tools/browser-start-session.js.map +1 -1
- package/dist/tools/browser-type.d.ts +5 -35
- package/dist/tools/browser-type.d.ts.map +1 -1
- package/dist/tools/browser-type.js +10 -45
- package/dist/tools/browser-type.js.map +1 -1
- package/dist/tools/contracts.d.ts +17 -63
- package/dist/tools/contracts.d.ts.map +1 -1
- package/dist/tools/contracts.js +91 -47
- package/dist/tools/contracts.js.map +1 -1
- package/dist/tools/cross-pr.d.ts +56 -15
- package/dist/tools/cross-pr.d.ts.map +1 -1
- package/dist/tools/cross-pr.js +141 -38
- package/dist/tools/cross-pr.js.map +1 -1
- package/dist/tools/git-diff.d.ts +18 -2
- package/dist/tools/git-diff.d.ts.map +1 -1
- package/dist/tools/git-diff.js +143 -23
- package/dist/tools/git-diff.js.map +1 -1
- package/dist/tools/git-history.d.ts +5 -16
- package/dist/tools/git-history.d.ts.map +1 -1
- package/dist/tools/git-history.js +3 -10
- package/dist/tools/git-history.js.map +1 -1
- package/dist/tools/history.d.ts +4 -33
- package/dist/tools/history.d.ts.map +1 -1
- package/dist/tools/history.js +6 -31
- package/dist/tools/history.js.map +1 -1
- package/dist/tools/impact.d.ts +7 -51
- package/dist/tools/impact.d.ts.map +1 -1
- package/dist/tools/impact.js +15 -67
- package/dist/tools/impact.js.map +1 -1
- package/dist/tools/index.d.ts +3 -8
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/kit.d.ts +66 -113
- package/dist/tools/kit.d.ts.map +1 -1
- package/dist/tools/kit.js +60 -28
- package/dist/tools/kit.js.map +1 -1
- package/dist/tools/link-workspace.d.ts +7 -45
- package/dist/tools/link-workspace.d.ts.map +1 -1
- package/dist/tools/link-workspace.js +10 -48
- package/dist/tools/link-workspace.js.map +1 -1
- package/dist/tools/lookup.d.ts +4 -14
- package/dist/tools/lookup.d.ts.map +1 -1
- package/dist/tools/lookup.js +4 -14
- package/dist/tools/lookup.js.map +1 -1
- package/dist/tools/mark-incident.d.ts +7 -54
- package/dist/tools/mark-incident.d.ts.map +1 -1
- package/dist/tools/mark-incident.js +15 -68
- package/dist/tools/mark-incident.js.map +1 -1
- package/dist/tools/observe-runtime.d.ts +27 -210
- package/dist/tools/observe-runtime.d.ts.map +1 -1
- package/dist/tools/observe-runtime.js +258 -436
- package/dist/tools/observe-runtime.js.map +1 -1
- package/dist/tools/observe-tests.d.ts +9 -88
- package/dist/tools/observe-tests.d.ts.map +1 -1
- package/dist/tools/observe-tests.js +34 -108
- package/dist/tools/observe-tests.js.map +1 -1
- package/dist/tools/pr-analysis.d.ts +18 -2
- package/dist/tools/pr-analysis.d.ts.map +1 -1
- package/dist/tools/pr-analysis.js +73 -23
- package/dist/tools/pr-analysis.js.map +1 -1
- package/dist/tools/pre-push.d.ts +94 -9
- package/dist/tools/pre-push.d.ts.map +1 -1
- package/dist/tools/pre-push.js +139 -34
- package/dist/tools/pre-push.js.map +1 -1
- package/dist/tools/propagation.d.ts +11 -53
- package/dist/tools/propagation.d.ts.map +1 -1
- package/dist/tools/propagation.js +14 -57
- package/dist/tools/propagation.js.map +1 -1
- package/dist/tools/questions.d.ts +13 -63
- package/dist/tools/questions.d.ts.map +1 -1
- package/dist/tools/questions.js +33 -105
- package/dist/tools/questions.js.map +1 -1
- package/dist/tools/refusal-fetch.d.ts +4 -40
- package/dist/tools/refusal-fetch.d.ts.map +1 -1
- package/dist/tools/refusal-fetch.js +4 -40
- package/dist/tools/refusal-fetch.js.map +1 -1
- package/dist/tools/runtime-incident.d.ts +4 -63
- package/dist/tools/runtime-incident.d.ts.map +1 -1
- package/dist/tools/runtime-incident.js +10 -87
- package/dist/tools/runtime-incident.js.map +1 -1
- package/dist/tools/scope.d.ts +7 -25
- package/dist/tools/scope.d.ts.map +1 -1
- package/dist/tools/scope.js +17 -20
- package/dist/tools/scope.js.map +1 -1
- package/dist/tools/similar-incidents.d.ts +11 -86
- package/dist/tools/similar-incidents.d.ts.map +1 -1
- package/dist/tools/similar-incidents.js +7 -71
- package/dist/tools/similar-incidents.js.map +1 -1
- package/dist/tools/validate.d.ts +31 -47
- package/dist/tools/validate.d.ts.map +1 -1
- package/dist/tools/validate.js +133 -61
- package/dist/tools/validate.js.map +1 -1
- package/dist/tools/verification-status.d.ts +9 -64
- package/dist/tools/verification-status.d.ts.map +1 -1
- package/dist/tools/verification-status.js +9 -62
- package/dist/tools/verification-status.js.map +1 -1
- package/dist/tools/verify-claim.d.ts +5 -52
- package/dist/tools/verify-claim.d.ts.map +1 -1
- package/dist/tools/verify-claim.js +6 -56
- package/dist/tools/verify-claim.js.map +1 -1
- package/dist/transport.d.ts +15 -52
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +16 -60
- package/dist/transport.js.map +1 -1
- package/package.json +33 -16
|
@@ -1,66 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* `action`
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* external model and this server, so there is no control flow to hold the
|
|
7
|
-
* gate. The handshake is what replaces it. An unconfirmed call to an
|
|
8
|
-
* `action`-class tool performs nothing and returns a token plus a
|
|
9
|
-
* plain-English description of what confirming would do; only a second call
|
|
10
|
-
* presenting that exact token performs anything, and it performs the
|
|
11
|
-
* arguments frozen when the token was minted — never whatever the second
|
|
12
|
-
* call happens to supply. **The gate holds without the client's
|
|
13
|
-
* cooperation, because the server owns both the decision and the state.**
|
|
14
|
-
*
|
|
15
|
-
* ## Generic by construction
|
|
16
|
-
*
|
|
17
|
-
* A tool takes part by declaring `class: "action"` and providing
|
|
18
|
-
* `describeAction`, nothing else — the mint/redeem/expiry/single-use
|
|
19
|
-
* machinery below is shared by every present and future action tool rather
|
|
20
|
-
* than reimplemented per tool. `describeAction` returning `undefined` means
|
|
21
|
-
* *this particular call* has nothing to confirm — `questions` called with no
|
|
22
|
-
* `answer` is a pure read of the open-question queue, and gating that behind
|
|
23
|
-
* a token would make the tool unable to answer the first question asked of
|
|
24
|
-
* it (the same failure §4 names for over-gating `stateful-read`).
|
|
25
|
-
*
|
|
26
|
-
* ## The seam with the server's dispatch loop
|
|
27
|
-
*
|
|
28
|
-
* `resolveActionDispatch` decides *before* the caller's budget timer starts:
|
|
29
|
-
* a mint has no real work to time out on (no I/O, no `tool.run`), so it must
|
|
30
|
-
* not be raced against `tools.md` §6's budget the way a real call is. The
|
|
31
|
-
* caller (`server.ts`) checks `decision.kind` — `"handshake"` renders via
|
|
32
|
-
* `render.ts`'s `renderHandshake` immediately; `"run"` proceeds exactly as
|
|
33
|
-
* an ungated call would, using `decision.args` (the original arguments for
|
|
34
|
-
* a `read`/`stateful-read` tool or a pass-through `action` call, or the
|
|
35
|
-
* arguments captured at mint time for a redeemed one).
|
|
36
|
-
*
|
|
37
|
-
* ## Token design, decided here because nothing upstream decides it
|
|
38
|
-
*
|
|
39
|
-
* - **Binds to call 1's exact arguments.** The token is not a bare
|
|
40
|
-
* capability — it is minted together with a stored copy of the arguments
|
|
41
|
-
* that produced its `willDo`. Redeeming it runs *that* stored copy,
|
|
42
|
-
* ignoring whatever the redeeming call supplies alongside the token. A
|
|
43
|
-
* client cannot describe one action and, on confirmation, have a
|
|
44
|
-
* different one performed.
|
|
45
|
-
* - **Single-use.** A token is deleted from the store the moment it is
|
|
46
|
-
* looked up for redemption, whether or not that redemption goes on to
|
|
47
|
-
* succeed — replay is not a retry, and a caller that wants to do the same
|
|
48
|
-
* thing twice must be told about it twice.
|
|
49
|
-
* - **Five-minute expiry.** A starting value, not a measurement (no
|
|
50
|
-
* confirmation flow has run yet to measure a real gap between mint and
|
|
51
|
-
* confirm) — long enough for a human or a model to read `willDo` and
|
|
52
|
-
* decide, short enough that a token is not a standing credential.
|
|
53
|
-
* - **Unknown, expired or wrong-tool token → `ToolInputError`, never a
|
|
54
|
-
* silent no-op.** This is an argument the caller can fix (ask again,
|
|
55
|
-
* without `confirmToken`, for a fresh one) so it takes the same path as
|
|
56
|
-
* any other bad argument — a tool result the caller can read and act on,
|
|
57
|
-
* not a protocol error and not a quiet success that performed nothing.
|
|
58
|
-
* - **Session-scoped.** One MCP server process serves exactly one `Session`
|
|
59
|
-
* (`McpServerOptions` takes a single session, not a pool), so the store is
|
|
60
|
-
* keyed on the `Session` instance via a `WeakMap` rather than kept as
|
|
61
|
-
* module-global mutable state — the scoping a second session would need is
|
|
62
|
-
* already correct without anything having to change if one is ever added.
|
|
63
|
-
*/
|
|
1
|
+
/** Two-call action-tool handshake, §7/DEC-278. G5 doesn't run in MCP mode, so this replaces it —
|
|
2
|
+
* the server owns both decision and state, holding the gate without client cooperation. A tool
|
|
3
|
+
* opts in via `class: "action"` + `describeAction`. Token binds to call 1's exact args
|
|
4
|
+
* (redemption ignores anything else supplied), is single-use, expires in 5 minutes (a starting
|
|
5
|
+
* value), and any bad token throws `ToolInputError` rather than a silent no-op. */
|
|
64
6
|
import { type ToolContext, type ToolDefinition } from "./tools/kit.ts";
|
|
65
7
|
export type ActionDispatch = {
|
|
66
8
|
readonly kind: "run";
|
|
@@ -70,17 +12,8 @@ export type ActionDispatch = {
|
|
|
70
12
|
readonly token: string;
|
|
71
13
|
readonly willDo: string;
|
|
72
14
|
};
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* `read` and `stateful-read` tools, and an `action` tool whose
|
|
77
|
-
* `describeAction` says this call has nothing to confirm, resolve to
|
|
78
|
-
* `{ kind: "run", args }` with `args` unchanged. An unconfirmed call to a
|
|
79
|
-
* gated `action` tool resolves to `{ kind: "handshake", token, willDo }` —
|
|
80
|
-
* the caller must render this directly and must not call `tool.run`. A
|
|
81
|
-
* confirmed call (an `args.confirmToken` that redeems) resolves to `{ kind:
|
|
82
|
-
* "run", args }` with `args` replaced by the arguments captured at mint
|
|
83
|
-
* time.
|
|
84
|
-
*/
|
|
15
|
+
/** Decides what a call should do, before any budget timer starts. `read`/`stateful-read` and an
|
|
16
|
+
* ungated `action` call resolve to `{ kind: "run", args }`; an unconfirmed gated call resolves to
|
|
17
|
+
* `{ kind: "handshake", token, willDo }`; a redeemed one runs the args captured at mint time. */
|
|
85
18
|
export declare function resolveActionDispatch(tool: ToolDefinition, args: Record<string, unknown>, ctx: ToolContext): Promise<ActionDispatch>;
|
|
86
19
|
//# sourceMappingURL=action-handshake.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-handshake.d.ts","sourceRoot":"","sources":["../src/action-handshake.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"action-handshake.d.ts","sourceRoot":"","sources":["../src/action-handshake.ts"],"names":[],"mappings":"AAAA;;;;oFAIoF;AAIpF,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAiCvF,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF;;kGAEkG;AAClG,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,cAAc,CAAC,CAazB"}
|
package/dist/action-handshake.js
CHANGED
|
@@ -1,66 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* `action`
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* external model and this server, so there is no control flow to hold the
|
|
7
|
-
* gate. The handshake is what replaces it. An unconfirmed call to an
|
|
8
|
-
* `action`-class tool performs nothing and returns a token plus a
|
|
9
|
-
* plain-English description of what confirming would do; only a second call
|
|
10
|
-
* presenting that exact token performs anything, and it performs the
|
|
11
|
-
* arguments frozen when the token was minted — never whatever the second
|
|
12
|
-
* call happens to supply. **The gate holds without the client's
|
|
13
|
-
* cooperation, because the server owns both the decision and the state.**
|
|
14
|
-
*
|
|
15
|
-
* ## Generic by construction
|
|
16
|
-
*
|
|
17
|
-
* A tool takes part by declaring `class: "action"` and providing
|
|
18
|
-
* `describeAction`, nothing else — the mint/redeem/expiry/single-use
|
|
19
|
-
* machinery below is shared by every present and future action tool rather
|
|
20
|
-
* than reimplemented per tool. `describeAction` returning `undefined` means
|
|
21
|
-
* *this particular call* has nothing to confirm — `questions` called with no
|
|
22
|
-
* `answer` is a pure read of the open-question queue, and gating that behind
|
|
23
|
-
* a token would make the tool unable to answer the first question asked of
|
|
24
|
-
* it (the same failure §4 names for over-gating `stateful-read`).
|
|
25
|
-
*
|
|
26
|
-
* ## The seam with the server's dispatch loop
|
|
27
|
-
*
|
|
28
|
-
* `resolveActionDispatch` decides *before* the caller's budget timer starts:
|
|
29
|
-
* a mint has no real work to time out on (no I/O, no `tool.run`), so it must
|
|
30
|
-
* not be raced against `tools.md` §6's budget the way a real call is. The
|
|
31
|
-
* caller (`server.ts`) checks `decision.kind` — `"handshake"` renders via
|
|
32
|
-
* `render.ts`'s `renderHandshake` immediately; `"run"` proceeds exactly as
|
|
33
|
-
* an ungated call would, using `decision.args` (the original arguments for
|
|
34
|
-
* a `read`/`stateful-read` tool or a pass-through `action` call, or the
|
|
35
|
-
* arguments captured at mint time for a redeemed one).
|
|
36
|
-
*
|
|
37
|
-
* ## Token design, decided here because nothing upstream decides it
|
|
38
|
-
*
|
|
39
|
-
* - **Binds to call 1's exact arguments.** The token is not a bare
|
|
40
|
-
* capability — it is minted together with a stored copy of the arguments
|
|
41
|
-
* that produced its `willDo`. Redeeming it runs *that* stored copy,
|
|
42
|
-
* ignoring whatever the redeeming call supplies alongside the token. A
|
|
43
|
-
* client cannot describe one action and, on confirmation, have a
|
|
44
|
-
* different one performed.
|
|
45
|
-
* - **Single-use.** A token is deleted from the store the moment it is
|
|
46
|
-
* looked up for redemption, whether or not that redemption goes on to
|
|
47
|
-
* succeed — replay is not a retry, and a caller that wants to do the same
|
|
48
|
-
* thing twice must be told about it twice.
|
|
49
|
-
* - **Five-minute expiry.** A starting value, not a measurement (no
|
|
50
|
-
* confirmation flow has run yet to measure a real gap between mint and
|
|
51
|
-
* confirm) — long enough for a human or a model to read `willDo` and
|
|
52
|
-
* decide, short enough that a token is not a standing credential.
|
|
53
|
-
* - **Unknown, expired or wrong-tool token → `ToolInputError`, never a
|
|
54
|
-
* silent no-op.** This is an argument the caller can fix (ask again,
|
|
55
|
-
* without `confirmToken`, for a fresh one) so it takes the same path as
|
|
56
|
-
* any other bad argument — a tool result the caller can read and act on,
|
|
57
|
-
* not a protocol error and not a quiet success that performed nothing.
|
|
58
|
-
* - **Session-scoped.** One MCP server process serves exactly one `Session`
|
|
59
|
-
* (`McpServerOptions` takes a single session, not a pool), so the store is
|
|
60
|
-
* keyed on the `Session` instance via a `WeakMap` rather than kept as
|
|
61
|
-
* module-global mutable state — the scoping a second session would need is
|
|
62
|
-
* already correct without anything having to change if one is ever added.
|
|
63
|
-
*/
|
|
1
|
+
/** Two-call action-tool handshake, §7/DEC-278. G5 doesn't run in MCP mode, so this replaces it —
|
|
2
|
+
* the server owns both decision and state, holding the gate without client cooperation. A tool
|
|
3
|
+
* opts in via `class: "action"` + `describeAction`. Token binds to call 1's exact args
|
|
4
|
+
* (redemption ignores anything else supplied), is single-use, expires in 5 minutes (a starting
|
|
5
|
+
* value), and any bad token throws `ToolInputError` rather than a silent no-op. */
|
|
64
6
|
import { randomBytes } from "node:crypto";
|
|
65
7
|
import { ToolInputError } from "./tools/kit.js";
|
|
66
8
|
const TOKEN_TTL_MS = 5 * 60 * 1000;
|
|
@@ -83,18 +25,9 @@ function prune(store) {
|
|
|
83
25
|
function mintToken() {
|
|
84
26
|
return `act_${randomBytes(9).toString("base64url")}`;
|
|
85
27
|
}
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `read` and `stateful-read` tools, and an `action` tool whose
|
|
90
|
-
* `describeAction` says this call has nothing to confirm, resolve to
|
|
91
|
-
* `{ kind: "run", args }` with `args` unchanged. An unconfirmed call to a
|
|
92
|
-
* gated `action` tool resolves to `{ kind: "handshake", token, willDo }` —
|
|
93
|
-
* the caller must render this directly and must not call `tool.run`. A
|
|
94
|
-
* confirmed call (an `args.confirmToken` that redeems) resolves to `{ kind:
|
|
95
|
-
* "run", args }` with `args` replaced by the arguments captured at mint
|
|
96
|
-
* time.
|
|
97
|
-
*/
|
|
28
|
+
/** Decides what a call should do, before any budget timer starts. `read`/`stateful-read` and an
|
|
29
|
+
* ungated `action` call resolve to `{ kind: "run", args }`; an unconfirmed gated call resolves to
|
|
30
|
+
* `{ kind: "handshake", token, willDo }`; a redeemed one runs the args captured at mint time. */
|
|
98
31
|
export async function resolveActionDispatch(tool, args, ctx) {
|
|
99
32
|
if (tool.class !== "action")
|
|
100
33
|
return { kind: "run", args };
|
|
@@ -109,10 +42,7 @@ export async function resolveActionDispatch(tool, args, ctx) {
|
|
|
109
42
|
}
|
|
110
43
|
async function mintOrPassThrough(tool, args, ctx) {
|
|
111
44
|
if (tool.describeAction === undefined) {
|
|
112
|
-
//
|
|
113
|
-
// `class: "action"` without saying how to describe it. Thrown, not
|
|
114
|
-
// returned as a refusal — there is no argument the caller could change
|
|
115
|
-
// to fix this.
|
|
45
|
+
// Registry bug, not a caller mistake: `class: "action"` declared with no describeAction.
|
|
116
46
|
throw new Error(`${tool.name} declares class "action" but has no describeAction`);
|
|
117
47
|
}
|
|
118
48
|
const willDo = await tool.describeAction(args, ctx);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-handshake.js","sourceRoot":"","sources":["../src/action-handshake.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"action-handshake.js","sourceRoot":"","sources":["../src/action-handshake.ts"],"names":[],"mappings":"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"}
|
package/dist/bin/descry-mcp.d.ts
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* directory — which is what a host passes when it starts the server inside a
|
|
7
|
-
* project. Everything else comes from `.descry/config.json`.
|
|
8
|
-
*
|
|
9
|
-
* ## Nothing may print before the transport is installed
|
|
10
|
-
*
|
|
11
|
-
* `serveStdio` redirects every console channel to stderr on its first line. Any
|
|
12
|
-
* output *before* that call goes to real stdout and corrupts the very first
|
|
13
|
-
* frame — the handshake — which is the worst place to fail, because the host
|
|
14
|
-
* reports it as "server did not start" with no further detail. So this file
|
|
15
|
-
* writes nothing itself and does its argument handling before opening anything.
|
|
16
|
-
*/
|
|
2
|
+
/** The executable an MCP host launches. Takes the repo path (default cwd); everything else comes
|
|
3
|
+
* from `.descry/config.json`. `serveStdio` redirects console to stderr on its first line, so this
|
|
4
|
+
* file writes nothing before opening anything — earlier output corrupts the handshake frame, the
|
|
5
|
+
* worst place to fail (host just reports "server did not start"). */
|
|
17
6
|
export {};
|
|
18
7
|
//# sourceMappingURL=descry-mcp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descry-mcp.d.ts","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"descry-mcp.d.ts","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":";AACA;;;sEAGsE"}
|
package/dist/bin/descry-mcp.js
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* directory — which is what a host passes when it starts the server inside a
|
|
7
|
-
* project. Everything else comes from `.descry/config.json`.
|
|
8
|
-
*
|
|
9
|
-
* ## Nothing may print before the transport is installed
|
|
10
|
-
*
|
|
11
|
-
* `serveStdio` redirects every console channel to stderr on its first line. Any
|
|
12
|
-
* output *before* that call goes to real stdout and corrupts the very first
|
|
13
|
-
* frame — the handshake — which is the worst place to fail, because the host
|
|
14
|
-
* reports it as "server did not start" with no further detail. So this file
|
|
15
|
-
* writes nothing itself and does its argument handling before opening anything.
|
|
16
|
-
*/
|
|
2
|
+
/** The executable an MCP host launches. Takes the repo path (default cwd); everything else comes
|
|
3
|
+
* from `.descry/config.json`. `serveStdio` redirects console to stderr on its first line, so this
|
|
4
|
+
* file writes nothing before opening anything — earlier output corrupts the handshake frame, the
|
|
5
|
+
* worst place to fail (host just reports "server did not start"). */
|
|
17
6
|
import process from "node:process";
|
|
18
7
|
import { createRequire } from "node:module";
|
|
19
8
|
import { resolve } from "node:path";
|
|
@@ -21,17 +10,9 @@ import { createMcpServer, isOutOfBand } from "../server.js";
|
|
|
21
10
|
import { Session } from "../session.js";
|
|
22
11
|
import { serveStdio } from "../transport.js";
|
|
23
12
|
import { createPlaywrightBrowserDriver } from "../browser/playwright-driver.js";
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* It was the literal `"0.0.0"` for every release, so every host reported the
|
|
29
|
-
* same version no matter which package it was running — and that is not a
|
|
30
|
-
* cosmetic gap. `@descryy/mcp` 0.1.2 went to npm from a branch that never
|
|
31
|
-
* reached `main`, carrying a tool `main` did not have, and nothing any host
|
|
32
|
-
* could see said so: `tools/list` showed seventeen tools and `serverInfo` said
|
|
33
|
-
* 0.0.0. A server that cannot say what it is cannot be caught drifting.
|
|
34
|
-
*/
|
|
13
|
+
/** Read from the installed package, not hardcoded. It used to be literal `"0.0.0"` for every
|
|
14
|
+
* release, so no host could tell that 0.1.2 shipped from an off-main branch with an extra tool —
|
|
15
|
+
* a server that can't say what it is can't be caught drifting. */
|
|
35
16
|
const VERSION = (() => {
|
|
36
17
|
try {
|
|
37
18
|
const pkg = createRequire(import.meta.url)("../../package.json");
|
|
@@ -58,15 +39,9 @@ async function main() {
|
|
|
58
39
|
}
|
|
59
40
|
const repoPath = resolve(args[0] ?? process.cwd());
|
|
60
41
|
const session = await Session.open({ repoPath });
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
// null. Without this line the tools refuse unconditionally in every real
|
|
65
|
-
// MCP host regardless of what is installed: declaring the dependency in
|
|
66
|
-
// package.json makes `@descryy/runtime-browser` resolvable, not reachable.
|
|
67
|
-
// `createPlaywrightBrowserDriver` itself still turns a missing package, a
|
|
68
|
-
// failed import or a missing Chromium binary into a named refusal rather
|
|
69
|
-
// than a crash — this wiring does not change that.
|
|
42
|
+
// Session never defaults this driver factory away from null; without this line every browser_*
|
|
43
|
+
// tool refuses unconditionally regardless of what's installed. createPlaywrightBrowserDriver
|
|
44
|
+
// still turns a missing package/binary into a named refusal, not a crash.
|
|
70
45
|
session.useBrowserDriverFactory((options) => createPlaywrightBrowserDriver(options));
|
|
71
46
|
const server = createMcpServer({ session, name: "descry", version: VERSION });
|
|
72
47
|
try {
|
|
@@ -77,13 +52,8 @@ async function main() {
|
|
|
77
52
|
return 0;
|
|
78
53
|
}
|
|
79
54
|
finally {
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
// `dispose`, not `close`, because end-of-stdin is how an MCP host says
|
|
84
|
-
// "disconnect" — and §4 requires that signal to reap every browser this
|
|
85
|
-
// connection owns. A leaked SQLite handle costs a file descriptor; a
|
|
86
|
-
// leaked Chromium keeps running on the developer's machine.
|
|
55
|
+
// `dispose`, not `close`: end-of-stdin is "disconnect," and §4 requires reaping every browser
|
|
56
|
+
// this connection owns — a leaked Chromium keeps running on the developer's machine.
|
|
87
57
|
await session.dispose();
|
|
88
58
|
}
|
|
89
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descry-mcp.js","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"descry-mcp.js","sourceRoot":"","sources":["../../src/bin/descry-mcp.ts"],"names":[],"mappings":"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"}
|