@mcp-index/sdk 0.18.0 → 0.19.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +178 -0
  3. package/dist/src/ai.d.ts +96 -0
  4. package/dist/src/ai.d.ts.map +1 -0
  5. package/dist/src/ai.js +151 -0
  6. package/dist/src/ai.js.map +1 -0
  7. package/dist/src/lock/check.d.ts +143 -0
  8. package/dist/src/lock/check.d.ts.map +1 -0
  9. package/dist/src/lock/check.js +274 -0
  10. package/dist/src/lock/check.js.map +1 -0
  11. package/dist/src/lock/digest.d.ts +48 -0
  12. package/dist/src/lock/digest.d.ts.map +1 -0
  13. package/dist/src/lock/digest.js +234 -0
  14. package/dist/src/lock/digest.js.map +1 -0
  15. package/dist/src/lock/events.d.ts +82 -0
  16. package/dist/src/lock/events.d.ts.map +1 -0
  17. package/dist/src/lock/events.js +80 -0
  18. package/dist/src/lock/events.js.map +1 -0
  19. package/dist/src/lock/index.d.ts +20 -0
  20. package/dist/src/lock/index.d.ts.map +1 -0
  21. package/dist/src/lock/index.js +14 -0
  22. package/dist/src/lock/index.js.map +1 -0
  23. package/dist/src/lock/lock.d.ts +195 -0
  24. package/dist/src/lock/lock.d.ts.map +1 -0
  25. package/dist/src/lock/lock.js +1075 -0
  26. package/dist/src/lock/lock.js.map +1 -0
  27. package/dist/src/lock/pg.d.ts +150 -0
  28. package/dist/src/lock/pg.d.ts.map +1 -0
  29. package/dist/src/lock/pg.js +539 -0
  30. package/dist/src/lock/pg.js.map +1 -0
  31. package/dist/src/lock/rawList.d.ts +127 -0
  32. package/dist/src/lock/rawList.d.ts.map +1 -0
  33. package/dist/src/lock/rawList.js +561 -0
  34. package/dist/src/lock/rawList.js.map +1 -0
  35. package/dist/src/lock/signing.d.ts +35 -0
  36. package/dist/src/lock/signing.d.ts.map +1 -0
  37. package/dist/src/lock/signing.js +85 -0
  38. package/dist/src/lock/signing.js.map +1 -0
  39. package/dist/src/lock/store.d.ts +149 -0
  40. package/dist/src/lock/store.d.ts.map +1 -0
  41. package/dist/src/lock/store.js +459 -0
  42. package/dist/src/lock/store.js.map +1 -0
  43. package/dist/src/wrap.d.ts.map +1 -1
  44. package/dist/src/wrap.js +85 -3
  45. package/dist/src/wrap.js.map +1 -1
  46. package/package.json +31 -2
package/CHANGELOG.md CHANGED
@@ -5,12 +5,33 @@ additive feature, patch = fix). Backward-compatible additions only in 0.2.0.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ Version 0.19.0 in package.json. Not published yet.
9
+
10
+ ### Added
11
+
12
+ - Lock mode, in three new subpaths. It follows mcp.lock draft 1, revision 1d, which is not stable: files carry `lockVersion: "1-draft"` and a later reader will refuse them. It is opt-in, and the root `@mcp-index/sdk` import does not load any of it.
13
+ - `@mcp-index/sdk/lock`: reads and writes a lock in `.mcp/lock/` and `.mcp/contracts/`, checks each `tools/list` against it, and refuses calls to tools that are not approved with error -32011. `lockClient` and `LockedTransport` put it in front of the official MCP client. `FileLockStore` approves and revokes, verifies a signed manifest when a signer is configured, and refuses a `sequencePath` or `trustedRootPath` inside the lock's repository. Listing and refusal events go to a sink you pass.
14
+ - `@mcp-index/sdk/lock/pg`: `PgLockStore`, a Postgres store with append-only hash-chained records, row-level security, `app-scoped` and `role-bound` tenancy, two roles, and an optional signed head that needs a sequence store.
15
+ - `@mcp-index/sdk/ai`: `lockTransport` for `createMCPClient` from the Vercel AI SDK.
16
+ - Optional peer dependencies: `@ai-sdk/mcp` for `/ai`, `pg` for `/lock/pg`, `sigstore` for signed locks. The package still has no runtime dependencies.
17
+
18
+ ## 0.18.1 - 2026-10-13
19
+
20
+ ### Changed
21
+
22
+ - A `tools/list` read through `requestStream`, on the session or on `experimental.tasks`, goes through the same listing filter as `listTools`. Before, a tool that `listTools` leaves out still came back that way.
23
+ - With `scanResults`, a result that arrives through a stream is scanned like a `callTool` result: `requestStream` with `tools/call` on either seam, and `experimental.tasks.callToolStream`. So is a task's result read later through `request({method: "tasks/result"})`, `getTaskResult` or `experimental.tasks.getTaskResult`, under the name of the tool whose gated call created the task. Without `scanResults` nothing changes.
24
+
8
25
  ## 0.18.0 - 2026-10-11
9
26
 
27
+ ### Security
28
+
29
+ - Fixes GHSA-phh5-4p9f-4qmg (https://github.com/mcpindex-ai/mcpindex-sdk-ts/security/advisories/GHSA-phh5-4p9f-4qmg), cases where changed or new tool text reached the agent under guard and strict. Affected: @mcp-index/sdk < 0.18.0 and mcpindex-gate < 0.20.0.
30
+
10
31
  ### Changed
11
32
 
12
33
  - The wrapper reads the server's `instructions` after connect, pins them beside the tool pins (`.<server>.context.json`, the same format the gate's proxy writes), and reports a first pin or a change through the new `onContextDrift` option and one stderr line. It never changes what `getInstructions()` returns. It needs a file pin store. A numbers-only change is reported; this SDK does not apply the gate's digit budget.
13
- - Under guard and strict a pinned tool that adds an outputSchema is left out once for review and its call holds when the schema carries any string or any name under properties, patternProperties, $defs or definitions. That covers most real outputSchemas, so expect one review per tool when a server starts returning structured output. A bare `{"type": "object"}` is still shown.
34
+ - Under guard and strict a pinned tool that adds an outputSchema is left out once for review and its call holds when the schema carries any string or any name under properties, patternProperties, $defs or definitions. A property name counts, so expect one review per tool when a server starts returning structured output. A bare `{"type": "object"}` is still shown.
14
35
  - The first paginated list on an empty pin store pins every page. Before, page 2 was held as new tools on an already-pinned server. Only the list that opened on the empty store can do this, only while it is current, and only while every pin was written by it; a list_changed, any call, a newer list or the last page ends it.
15
36
  - A tool whose title is not a string is left out of the list as a wrong type, under guard and strict, and the title is never recorded. The field-set marker moves to 3; any marker from 2 up, including one from a newer version, counts as complete.
16
37
  - Pending records carry the field-set version. Approving one written by 0.16 leaves the pin to record its fields on the next list, so the tool is not held again right after approval; one written by 0.17 keeps its version.
package/README.md CHANGED
@@ -174,6 +174,184 @@ When enabled, each tool you pin and each contract drift sends **one one-way sign
174
174
  opt-in richer tier (it behaves identically today). The full notice is exported as
175
175
  `DRIFT_TELEMETRY_NOTICE`. Unset the variable any time to stop.
176
176
 
177
+ ## Lock mode (`@mcp-index/sdk/lock`)
178
+
179
+ Lock mode checks every `tools/list` against an mcp.lock kept in your repository
180
+ (`.mcp/lock/` and `.mcp/contracts/`, format: mcp.lock draft 1, revision 1e). The model sees
181
+ only tools whose definition digest matches an approval, and a call to anything else is
182
+ refused with JSON-RPC error -32011 before it reaches the server. Lock mode is opt-in and
183
+ draft 1 is not stable. Nothing here runs unless you construct it, and the root
184
+ `@mcp-index/sdk` import does not load it.
185
+
186
+ Connect the official MCP client through `lockClient`:
187
+
188
+ ```ts
189
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
190
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
191
+ import { FileLockStore, lockClient } from "@mcp-index/sdk/lock";
192
+ import type { Identity } from "@mcp-index/sdk/lock";
193
+
194
+ const identity: Identity = { kind: "stdio", package: "npm:@example/docs-server" };
195
+ const store = new FileLockStore({ root: process.cwd() }); // the directory that holds .mcp/
196
+ const client = new Client({ name: "my-host", version: "1.0.0" });
197
+ const transport = new StdioClientTransport({ command: "npx", args: ["-y", "@example/docs-server"] });
198
+ const locked = await lockClient(client, transport, { store, identity, posture: "guard" });
199
+
200
+ const { tools } = await client.listTools(); // approved tools only
201
+ console.log(tools.map((t) => t.name), locked.decision?.withheld);
202
+ ```
203
+
204
+ `posture` is `monitor` (show everything, report what does not match), `guard` (withhold it)
205
+ or `strict` (same as guard in draft 1). Lock mode never approves a tool on first sight and
206
+ never re-pins. The lock changes only through `store.approve` and `store.revoke`, or a
207
+ reviewed edit to the lock files:
208
+
209
+ ```ts
210
+ import { readFileSync } from "node:fs";
211
+
212
+ // The Tool object exactly as the server sent it, saved for review. Not an SDK-parsed copy:
213
+ // the SDK drops members it does not know, and the digest covers every member.
214
+ const tool: unknown = JSON.parse(readFileSync("review/search.json", "utf8"));
215
+ await store.approve({ identity, tool, subject: "github:you", via: "api", ref: "pr-42" });
216
+ ```
217
+
218
+ The identity names the server, in one of three forms:
219
+
220
+ ```ts
221
+ const remote: Identity = { kind: "remote", url: "https://mcp.example.com/v1/mcp" };
222
+ const pkg: Identity = { kind: "stdio", package: "npm:@example/docs-server" }; // npm, pypi or oci
223
+ const cmd: Identity = { kind: "stdio", command: "uvx", args: ["git+https://github.com/example/server"] };
224
+ ```
225
+
226
+ `remoteIdentity`, `packageIdentity` and `commandIdentity` build them in normalized form.
227
+ `commandIdentity` throws when an argument looks like a credential.
228
+
229
+ A signed lock verifies `.mcp/lock/MANIFEST.json.sigstore` against a signer from your host
230
+ configuration. It needs the optional `sigstore` peer, a trust root file, and a sequence file
231
+ where the host keeps the highest manifest sequence it accepted, so an older signed manifest
232
+ is refused after a newer one:
233
+
234
+ ```ts
235
+ const signed = new FileLockStore({
236
+ root: "/srv/app",
237
+ signer: {
238
+ issuer: "https://token.actions.githubusercontent.com",
239
+ san: "https://github.com/acme/app/.github/workflows/lock.yml@refs/heads/main",
240
+ },
241
+ trustedRootPath: "/etc/mcplock/trusted_root.json",
242
+ sequencePath: "/var/lib/mcplock/sequence",
243
+ });
244
+ ```
245
+
246
+ Both paths must lie outside the repository that holds the lock, or the constructor throws
247
+ `HostConfigError`. The repository is the nearest directory at or above `root` with a `.git`
248
+ directory or a linked worktree's `.git` file; a submodule's `.git` file sends the search on to
249
+ the superproject. The check compares directories by device and inode, so a case-folded
250
+ spelling on macOS and a symlink followed by `..` are judged where they land, and a `..` in the
251
+ part of a path that does not exist yet is refused. When no `.git` entry exists at or above
252
+ `root`, only `root` itself is protected: a path beside it in the same untracked directory is
253
+ accepted, so keep host files somewhere the lock's writers cannot reach. A signer without a sequence store makes every load
254
+ `lock-signature-invalid`.
255
+
256
+ ## Postgres lock store (`@mcp-index/sdk/lock/pg`)
257
+
258
+ `PgLockStore` keeps approvals in Postgres instead of files: append-only, hash-chained
259
+ records per tenant, with row-level security on both tables. `pg` is an optional peer.
260
+
261
+ The schema owner runs the migrations once. They are exported as SQL text:
262
+
263
+ ```ts
264
+ import { writeFileSync } from "node:fs";
265
+ import { MIGRATION_SQL, ROLE_BOUND_SQL, ROLE_SQL } from "@mcp-index/sdk/lock/pg";
266
+
267
+ writeFileSync("mcplock-schema.sql", MIGRATION_SQL + ROLE_SQL);
268
+ writeFileSync("mcplock-role-bound.sql", ROLE_BOUND_SQL); // only for role-bound tenancy
269
+ // psql -v ON_ERROR_STOP=1 -f mcplock-schema.sql
270
+ ```
271
+
272
+ `ROLE_SQL` creates two roles without login. `mcplock_runtime` may only read, and is what hosts
273
+ in lock mode connect as. `mcplock_approver` may also append records and move the head, and
274
+ belongs to the approval path only. Neither may update or delete a record. Grant each to its
275
+ own login, and never connect as a superuser, since a superuser bypasses row-level security:
276
+
277
+ ```sql
278
+ GRANT mcplock_runtime TO host_login;
279
+ GRANT mcplock_approver TO approver_login;
280
+ ```
281
+
282
+ Two tenancy modes:
283
+
284
+ - `app-scoped` (the default, `MIGRATION_SQL` alone). The store sets the tenant from the
285
+ principal at the start of each transaction. This stops a query bug from reaching another
286
+ tenant. It does not stop someone holding a shared login, who can set any tenant.
287
+ - `role-bound` (`ROLE_BOUND_SQL` after the other two). Each tenant gets its own logins, and
288
+ the administrator maps each login to its tenant in `mcplock.tenant_logins`. The policies
289
+ read the tenant from the login, so a login reaches only its own tenant. Use this before
290
+ sharing one database between tenants that do not trust each other.
291
+
292
+ ```ts
293
+ import { PgLockStore, createPgPool } from "@mcp-index/sdk/lock/pg";
294
+
295
+ const pool = await createPgPool(process.env.MCPLOCK_PG_URL ?? "postgres://host_login@127.0.0.1/app");
296
+ const store = new PgLockStore({
297
+ pool,
298
+ principal: { tenantId: "acme", subject: "svc:docs-host" }, // from your own auth, never a header
299
+ tenancy: "app-scoped",
300
+ });
301
+ const snapshot = await store.loadSnapshot();
302
+ console.log(snapshot.snapshotId);
303
+ ```
304
+
305
+ With `headVerifier` set, each load checks a signature over the head row, and the store must
306
+ also get a `sequenceStore`, for example `fileSequenceStore("/var/lib/mcplock/pg-sequence")`
307
+ from `@mcp-index/sdk/lock`, or every load is `lock-signature-invalid`. Without a head
308
+ signature, whoever can write the tables can rewrite the chain. Errors never carry the
309
+ connection string unredacted.
310
+
311
+ ## Lock mode for the Vercel AI SDK (`@mcp-index/sdk/ai`)
312
+
313
+ Wrap the transport you hand to `createMCPClient` from `@ai-sdk/mcp` (an optional peer). The
314
+ wrapper reads the raw `tools/list` exchange, checks every tool against your mcp.lock, and the
315
+ client only ever sees approved tools, through `tools()` or `listTools()` alike:
316
+
317
+ ```ts
318
+ import { createMCPClient } from "@ai-sdk/mcp";
319
+ import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio";
320
+ import { lockTransport } from "@mcp-index/sdk/ai";
321
+ import { FileLockStore } from "@mcp-index/sdk/lock";
322
+ import type { Identity } from "@mcp-index/sdk/lock";
323
+
324
+ const identity: Identity = { kind: "stdio", package: "npm:@example/docs-server" };
325
+ const store = new FileLockStore({ root: process.cwd() });
326
+ const inner = new Experimental_StdioMCPTransport({ command: "npx", args: ["-y", "@example/docs-server"] });
327
+ const transport = lockTransport(inner, { store, identity, posture: "guard" });
328
+ const client = await createMCPClient({ transport });
329
+ const tools = await client.tools(); // approved tools only
330
+ console.log(Object.keys(tools));
331
+ ```
332
+
333
+ A call to a withheld or unlisted tool never reaches the server. `callTool()` and the tool's
334
+ `execute()` reject with an `MCPClientError` whose `code` is -32011 and `data.reason` says why;
335
+ inside `generateText` that shows up as a `tool-error` part.
336
+
337
+ Limits:
338
+
339
+ - A digest says whether the contract changed. It says nothing about what the server does
340
+ when a tool runs.
341
+ - The AI SDK client does not refetch on `notifications/tools/list_changed`. After an approval
342
+ or a server change, call `tools()` again; until then the previous allow-list holds. While a
343
+ listing is being collected, every call is refused with `no-listing`.
344
+ - A tool's top-level `_meta` is not part of its digest. It reaches the client only when it
345
+ matches the `metaDigest` recorded at approval; otherwise, under guard, the tool is shown
346
+ without it and the decision reports `meta-changed` or `meta-unapproved`.
347
+ - `@mcp-index/sdk/ai` imports only types from `@ai-sdk/mcp`, so loading it needs nothing at
348
+ runtime. The `@ai-sdk/mcp` peer itself needs Node >= 22; that is the only part with that
349
+ requirement, and the rest of the package runs on Node 20.
350
+ - The AI SDK's own transports reject any message carrying a `__proto__` key before the wrapper
351
+ sees it, so such a listing never arrives and nothing is callable. The official SDK transports
352
+ pass it through and the lock withholds the tool. Instructions given to the client as
353
+ `initialInitializeResult` never cross the transport and are not checked.
354
+
177
355
  ## Related packages
178
356
 
179
357
  Three ways to bring mcpindex into an agent, for different surfaces:
@@ -0,0 +1,96 @@
1
+ /**
2
+ * `@mcp-index/sdk/ai`: lock mode for the Vercel AI SDK MCP client
3
+ * (`createMCPClient` from `@ai-sdk/mcp`).
4
+ *
5
+ * The AI SDK client parses `tools/list` with its own zod schema and builds
6
+ * tools from what is left, so a digest over `client.listTools()` would not be
7
+ * a digest over what the server sent. lockTransport wraps the transport the
8
+ * client is given and works on JSON-RPC messages before the client sees them.
9
+ * The message work is LockedTransport from `../lock/rawList.ts`: every page of
10
+ * a listing is collected under private ids and digested raw, withheld tools
11
+ * are dropped, and the client gets one result with no cursor. `client.tools()`
12
+ * and `client.listTools()` + `toolsFromDefinitions()` both only ever see
13
+ * approved tools (under guard).
14
+ *
15
+ * Every `tools/call` is checked against the allow-list from the latest
16
+ * complete listing. A refused call is never sent; the client gets a JSON-RPC
17
+ * -32011 error with data.reason. In @ai-sdk/mcp 2.0.74 that rejects
18
+ * `callTool()` and the tool's `execute()` with an MCPClientError carrying
19
+ * code -32011 and data { reason, tool }; it is not retried (the client never
20
+ * retries an error with a JSON-RPC code). Inside generateText the throw
21
+ * becomes a `tool-error` part, so the model sees the refusal as a tool error.
22
+ *
23
+ * Limits, all from the AI SDK client as of 2.0.74:
24
+ * - The client treats any server notification as "Unsupported message
25
+ * type" and reports it to onUncaughtError, so it never refetches on
26
+ * `notifications/tools/list_changed`. The wrapper still marks a listing
27
+ * as due (`listingDue`) and keeps the old allow-list until a new complete
28
+ * listing. The app has to call `tools()` again to see newly approved
29
+ * tools, and to drop ones the server removed.
30
+ * - The wrapper reports `supportsProtocolVersionDiscovery = false`, so the
31
+ * client uses the `initialize` handshake. Server instructions then arrive
32
+ * in the initialize result, where they are digested and, under guard,
33
+ * stripped when they differ from the lock. Instructions passed to the
34
+ * client as `initialInitializeResult` never cross the transport and are
35
+ * not checked.
36
+ * - The AI SDK's own stdio, SSE and HTTP transports parse with a secure
37
+ * JSON parser that throws on a `__proto__` key. Such a message never
38
+ * reaches the wrapper, so there is no listing and no tool is callable;
39
+ * the official SDK transports keep the key and the lock withholds the tool.
40
+ * - `@ai-sdk/mcp` needs Node >= 22. This module itself only imports types
41
+ * from it.
42
+ *
43
+ * The check covers the tool contract the model reads, and nothing about what
44
+ * the server does when a tool runs.
45
+ */
46
+ import type { JSONRPCMessage, MCPTransport, MCPTransportCloseOptions, MCPTransportSendOptions } from "@ai-sdk/mcp";
47
+ import type { CallGate, Decision } from "./lock/check.js";
48
+ import type { LockEventSink } from "./lock/events.js";
49
+ import type { Identity, Posture } from "./lock/lock.js";
50
+ import type { LockStore } from "./lock/store.js";
51
+ /** Host settings that are not about which lock or which server. */
52
+ export interface AiLockHostConfig {
53
+ /** The host name written into events. Default "mcpindex-sdk". */
54
+ readonly host?: string;
55
+ /** Age after which a call reloads the snapshot. Default 60 s. */
56
+ readonly maxStalenessMs?: number;
57
+ readonly now?: () => number;
58
+ }
59
+ export interface AiLockOptions {
60
+ readonly store: LockStore;
61
+ /** This server's identity (section 3), from host configuration. */
62
+ readonly identity: Identity;
63
+ /** monitor, guard, or strict (behaves as guard in draft 1). */
64
+ readonly posture: Posture;
65
+ readonly sink?: LockEventSink;
66
+ readonly hostConfig?: AiLockHostConfig;
67
+ }
68
+ export declare class AiLockTransport implements MCPTransport {
69
+ #private;
70
+ /** Forces the initialize handshake, where instructions are checked. */
71
+ readonly supportsProtocolVersionDiscovery = false;
72
+ onclose?: () => void;
73
+ onerror?: (error: Error) => void;
74
+ onmessage?: (message: JSONRPCMessage) => void;
75
+ constructor(inner: MCPTransport, options: AiLockOptions);
76
+ get supportsMcpToolParameterHeaders(): boolean | undefined;
77
+ get protocolVersion(): string | undefined;
78
+ set protocolVersion(version: string | undefined);
79
+ setProtocolVersion(version: string): void;
80
+ /** The per-connection allow-list. */
81
+ get gate(): CallGate;
82
+ /** The decision for the latest complete listing, or null before one. */
83
+ get decision(): Decision | null;
84
+ /** True after list_changed until the next complete listing (call tools() again). */
85
+ get listingDue(): boolean;
86
+ start(): Promise<void>;
87
+ send(message: JSONRPCMessage, options?: MCPTransportSendOptions): Promise<void>;
88
+ close(options?: MCPTransportCloseOptions): Promise<void>;
89
+ }
90
+ /**
91
+ * Wrap `inner` in lock mode for `createMCPClient({ transport })`.
92
+ * Lock mode has no auto-accept, first-use pin or re-pin; the lock changes
93
+ * only through LockStore.approve and revoke.
94
+ */
95
+ export declare function lockTransport(inner: MCPTransport, options: AiLockOptions): AiLockTransport;
96
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACxC;AAuCD,qBAAa,eAAgB,YAAW,YAAY;;IAClD,uEAAuE;IACvE,QAAQ,CAAC,gCAAgC,SAAS;IAClD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;gBAKlC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa;IAUvD,IAAI,+BAA+B,IAAI,OAAO,GAAG,SAAS,CAEzD;IAED,IAAI,eAAe,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,IAAI,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAE9C;IAED,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIzC,qCAAqC;IACrC,IAAI,IAAI,IAAI,QAAQ,CAEnB;IAED,wEAAwE;IACxE,IAAI,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAE9B;IAED,oFAAoF;IACpF,IAAI,UAAU,IAAI,OAAO,CAExB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/E,KAAK,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;CAI/D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,eAAe,CAE1F"}
package/dist/src/ai.js ADDED
@@ -0,0 +1,151 @@
1
+ /**
2
+ * `@mcp-index/sdk/ai`: lock mode for the Vercel AI SDK MCP client
3
+ * (`createMCPClient` from `@ai-sdk/mcp`).
4
+ *
5
+ * The AI SDK client parses `tools/list` with its own zod schema and builds
6
+ * tools from what is left, so a digest over `client.listTools()` would not be
7
+ * a digest over what the server sent. lockTransport wraps the transport the
8
+ * client is given and works on JSON-RPC messages before the client sees them.
9
+ * The message work is LockedTransport from `../lock/rawList.ts`: every page of
10
+ * a listing is collected under private ids and digested raw, withheld tools
11
+ * are dropped, and the client gets one result with no cursor. `client.tools()`
12
+ * and `client.listTools()` + `toolsFromDefinitions()` both only ever see
13
+ * approved tools (under guard).
14
+ *
15
+ * Every `tools/call` is checked against the allow-list from the latest
16
+ * complete listing. A refused call is never sent; the client gets a JSON-RPC
17
+ * -32011 error with data.reason. In @ai-sdk/mcp 2.0.74 that rejects
18
+ * `callTool()` and the tool's `execute()` with an MCPClientError carrying
19
+ * code -32011 and data { reason, tool }; it is not retried (the client never
20
+ * retries an error with a JSON-RPC code). Inside generateText the throw
21
+ * becomes a `tool-error` part, so the model sees the refusal as a tool error.
22
+ *
23
+ * Limits, all from the AI SDK client as of 2.0.74:
24
+ * - The client treats any server notification as "Unsupported message
25
+ * type" and reports it to onUncaughtError, so it never refetches on
26
+ * `notifications/tools/list_changed`. The wrapper still marks a listing
27
+ * as due (`listingDue`) and keeps the old allow-list until a new complete
28
+ * listing. The app has to call `tools()` again to see newly approved
29
+ * tools, and to drop ones the server removed.
30
+ * - The wrapper reports `supportsProtocolVersionDiscovery = false`, so the
31
+ * client uses the `initialize` handshake. Server instructions then arrive
32
+ * in the initialize result, where they are digested and, under guard,
33
+ * stripped when they differ from the lock. Instructions passed to the
34
+ * client as `initialInitializeResult` never cross the transport and are
35
+ * not checked.
36
+ * - The AI SDK's own stdio, SSE and HTTP transports parse with a secure
37
+ * JSON parser that throws on a `__proto__` key. Such a message never
38
+ * reaches the wrapper, so there is no listing and no tool is callable;
39
+ * the official SDK transports keep the key and the lock withholds the tool.
40
+ * - `@ai-sdk/mcp` needs Node >= 22. This module itself only imports types
41
+ * from it.
42
+ *
43
+ * The check covers the tool contract the model reads, and nothing about what
44
+ * the server does when a tool runs.
45
+ */
46
+ import { LockedTransport } from "./lock/rawList.js";
47
+ /**
48
+ * Adapts an AI SDK MCPTransport (or an official SDK transport, which has the
49
+ * same shape) to the Transport that LockedTransport drives.
50
+ */
51
+ class InnerAdapter {
52
+ inner;
53
+ onclose;
54
+ onerror;
55
+ onmessage;
56
+ closeOptions;
57
+ constructor(inner) {
58
+ this.inner = inner;
59
+ }
60
+ async start() {
61
+ this.inner.onmessage = (message) => this.onmessage?.(message);
62
+ this.inner.onerror = (error) => this.onerror?.(error instanceof Error ? error : new Error(String(error)));
63
+ this.inner.onclose = () => this.onclose?.();
64
+ await this.inner.start();
65
+ }
66
+ async send(message, options) {
67
+ const m = message;
68
+ if (options === undefined)
69
+ await this.inner.send(m);
70
+ else
71
+ await this.inner.send(m, options);
72
+ }
73
+ async close() {
74
+ const options = this.closeOptions;
75
+ if (options === undefined)
76
+ await this.inner.close();
77
+ else
78
+ await this.inner.close(options);
79
+ }
80
+ setProtocolVersion(version) {
81
+ if (typeof this.inner.setProtocolVersion === "function")
82
+ this.inner.setProtocolVersion(version);
83
+ else
84
+ this.inner.protocolVersion = version;
85
+ }
86
+ }
87
+ export class AiLockTransport {
88
+ /** Forces the initialize handshake, where instructions are checked. */
89
+ supportsProtocolVersionDiscovery = false;
90
+ onclose;
91
+ onerror;
92
+ onmessage;
93
+ #adapter;
94
+ #locked;
95
+ constructor(inner, options) {
96
+ const { hostConfig, ...rest } = options;
97
+ // hostConfig goes first so it cannot replace store, identity or posture.
98
+ // Any key the core refuses (autoAccept, tofu, repin, ...) at either level
99
+ // reaches the LockedTransport constructor and throws there.
100
+ const lockOptions = { ...(hostConfig ?? {}), ...rest };
101
+ this.#adapter = new InnerAdapter(inner);
102
+ this.#locked = new LockedTransport(this.#adapter, lockOptions);
103
+ }
104
+ get supportsMcpToolParameterHeaders() {
105
+ return this.#adapter.inner.supportsMcpToolParameterHeaders;
106
+ }
107
+ get protocolVersion() {
108
+ return this.#adapter.inner.protocolVersion;
109
+ }
110
+ set protocolVersion(version) {
111
+ if (version !== undefined)
112
+ this.#adapter.setProtocolVersion(version);
113
+ }
114
+ setProtocolVersion(version) {
115
+ this.#adapter.setProtocolVersion(version);
116
+ }
117
+ /** The per-connection allow-list. */
118
+ get gate() {
119
+ return this.#locked.gate;
120
+ }
121
+ /** The decision for the latest complete listing, or null before one. */
122
+ get decision() {
123
+ return this.#locked.decision;
124
+ }
125
+ /** True after list_changed until the next complete listing (call tools() again). */
126
+ get listingDue() {
127
+ return this.#locked.listingDue;
128
+ }
129
+ async start() {
130
+ this.#locked.onmessage = (message) => this.onmessage?.(message);
131
+ this.#locked.onerror = (error) => this.onerror?.(error);
132
+ this.#locked.onclose = () => this.onclose?.();
133
+ await this.#locked.start();
134
+ }
135
+ async send(message, options) {
136
+ await this.#locked.send(message, options);
137
+ }
138
+ async close(options) {
139
+ this.#adapter.closeOptions = options;
140
+ await this.#locked.close();
141
+ }
142
+ }
143
+ /**
144
+ * Wrap `inner` in lock mode for `createMCPClient({ transport })`.
145
+ * Lock mode has no auto-accept, first-use pin or re-pin; the lock changes
146
+ * only through LockStore.approve and revoke.
147
+ */
148
+ export function lockTransport(inner, options) {
149
+ return new AiLockTransport(inner, options);
150
+ }
151
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/ai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * The lock check (section 9): a pure decision over one complete listing, and a
3
+ * per-connection CallGate that allows `tools/call` only for names shown on the
4
+ * latest checked listing.
5
+ *
6
+ * Lock mode has no first-use pin, no auto-accept and no re-pin. Nothing here
7
+ * writes to a lock; the lock changes only through LockStore.approve/revoke.
8
+ */
9
+ import { LockError } from "./lock.js";
10
+ import type { Identity, Lock, LockErrorReason, Posture } from "./lock.js";
11
+ export declare const LOCK_REFUSAL_CODE = -32011;
12
+ export declare const LOCK_REFUSAL_MESSAGE = "Tool withheld by lock";
13
+ export type ToolReason = "unlocked-server" | "duplicate-name" | "no-digest" | "new-tool" | "upstream-changed";
14
+ /** Why a shown tool's top-level `_meta` was not relayed as approved (draft 1c). */
15
+ export type MetaReason = "meta-changed" | "meta-unapproved";
16
+ export type CallReason = ToolReason | LockErrorReason | "no-listing" | "not-listed" | "classifier-error" | "unreachable";
17
+ export interface ToolOutcome {
18
+ readonly name: string;
19
+ readonly served: string | null;
20
+ readonly approved: string | null;
21
+ readonly decision: "shown" | "withheld";
22
+ readonly reason: ToolReason | LockErrorReason | null;
23
+ /** Section 9.2.3 flag for a shown tool's top-level `_meta`, else null. */
24
+ readonly meta: MetaReason | null;
25
+ }
26
+ /** Section 9.2.3 decision for one shown tool that has a top-level `_meta`. */
27
+ export interface MetaDecision {
28
+ /** True when `_meta` reaches the client as served. */
29
+ readonly relay: boolean;
30
+ readonly flag: MetaReason | null;
31
+ }
32
+ export interface Decision {
33
+ readonly posture: Posture;
34
+ /** Names shown to the model, in listing order (a duplicate name under monitor repeats). */
35
+ readonly shown: readonly string[];
36
+ /** Name to reason, under guard (or for any lock failure). */
37
+ readonly withheld: ReadonlyMap<string, ToolReason | LockErrorReason>;
38
+ /** Name to reason, under monitor: shown but reported. */
39
+ readonly flagged: ReadonlyMap<string, ToolReason>;
40
+ readonly removed: readonly string[];
41
+ readonly instructions: "instructions-changed" | null;
42
+ readonly stripInstructions: boolean;
43
+ readonly lockError: LockErrorReason | null;
44
+ /** The allow-list for calls on this connection. */
45
+ readonly callable: ReadonlySet<string>;
46
+ /** Indexes into the listing's tools array of the entries the model may see. */
47
+ readonly shownIndexes: readonly number[];
48
+ /**
49
+ * Every shown tool with a top-level `_meta`: name to whether it is relayed
50
+ * and its flag. A served `_meta` that does not match the approved
51
+ * metaDigest is flagged; under guard it is removed before the tool is
52
+ * relayed (stripMeta), under monitor it is relayed and reported.
53
+ */
54
+ readonly meta: ReadonlyMap<string, MetaDecision>;
55
+ /** Indexes into the listing's tools array whose `_meta` is removed before relay. */
56
+ readonly stripMeta: ReadonlySet<number>;
57
+ /** One row per named listing entry, for the listing event. */
58
+ readonly tools: readonly ToolOutcome[];
59
+ readonly served: number;
60
+ }
61
+ export interface Listing {
62
+ readonly tools: readonly unknown[];
63
+ readonly instructions?: unknown;
64
+ }
65
+ export declare function isPosture(value: unknown): value is Posture;
66
+ /**
67
+ * Check one complete listing against a lock, or against a whole-lock failure.
68
+ * `listing.tools` is the raw array as received; nothing is fetched again.
69
+ */
70
+ export declare function checkListing(lock: Lock | LockError, identity: Identity, listing: Listing, posture: Posture): Decision;
71
+ /** Decide instructions alone, for a host that sees them before any listing (initialize). */
72
+ export declare function checkInstructions(lock: Lock | LockError, identity: Identity, instructions: unknown, posture: Posture): {
73
+ readonly reason: "instructions-changed" | LockErrorReason | null;
74
+ readonly strip: boolean;
75
+ };
76
+ /** 'allow', or the reason sent in data.reason of a -32011 error. */
77
+ export declare function checkCall(decision: Decision | null, name: string): "allow" | CallReason;
78
+ export interface RefusalError {
79
+ readonly code: typeof LOCK_REFUSAL_CODE;
80
+ readonly message: string;
81
+ /** `tool` is left out when the call's name was not a string, as in the Python host. */
82
+ readonly data: {
83
+ readonly reason: CallReason;
84
+ readonly tool?: string;
85
+ };
86
+ }
87
+ export declare function refusalError(name: string | null, reason: CallReason): RefusalError;
88
+ /** Error thrown to callers who check through CallGate.enforce. */
89
+ export declare class LockRefusal extends Error {
90
+ readonly code = -32011;
91
+ readonly reason: CallReason;
92
+ readonly tool: string;
93
+ constructor(tool: string, reason: CallReason);
94
+ toJsonRpcError(): RefusalError;
95
+ }
96
+ /** Default age after which a call first reloads the snapshot (section 9.8), as in the Python host. */
97
+ export declare const DEFAULT_MAX_STALENESS_MS = 60000;
98
+ export interface CallGateOptions {
99
+ /**
100
+ * Section 9.8: once the snapshot behind the decision is older than this, a
101
+ * call reloads it first (LockedTransport) and is refused with `lock-stale`
102
+ * when the reload fails. Default 60 s. Pass Infinity to never go stale.
103
+ */
104
+ readonly maxStalenessMs?: number;
105
+ readonly now?: () => number;
106
+ }
107
+ /**
108
+ * Per-connection allow-list. `record` replaces the decision only when a
109
+ * complete listing has been checked. A list_changed notification does not
110
+ * touch it. While a listing is in progress (section 9.2.1: `beginListing`
111
+ * until `record` or `markUnreachable`) every call is refused with
112
+ * `no-listing`, so nothing is called on the strength of a listing that is
113
+ * being replaced.
114
+ *
115
+ * Order of reasons (section 9.5): `no-listing` while a listing is in
116
+ * progress or before any listing has ended; then the whole-lock error of the
117
+ * latest completed listing, which a later failed listing does not clear;
118
+ * then `unreachable` after a failed listing; then `lock-stale`; then the
119
+ * per-name answer.
120
+ */
121
+ export declare class CallGate {
122
+ #private;
123
+ constructor(options?: CallGateOptions);
124
+ get decision(): Decision | null;
125
+ get snapshotId(): string | null;
126
+ /** A listing started: the host asked for its first page. */
127
+ beginListing(): void;
128
+ /** The listing in progress ended without a decision and without failing. */
129
+ endListing(): void;
130
+ get listingInProgress(): boolean;
131
+ /** Install the decision for the latest complete listing. */
132
+ record(decision: Decision, snapshot: {
133
+ readonly snapshotId: string;
134
+ readonly loadedAt: number;
135
+ }): void;
136
+ /** The latest listing failed; refuse every call with `unreachable` until one completes. */
137
+ markUnreachable(): void;
138
+ get unreachable(): boolean;
139
+ isStale(): boolean;
140
+ check(name: string): "allow" | CallReason;
141
+ enforce(name: string): void;
142
+ }
143
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/lock/check.ts"],"names":[],"mappings":"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"}