@traceglass/mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rahul Bhardwaj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @traceglass/mcp
2
+
3
+ Record **Model Context Protocol** tool calls as [traceglass](https://www.npmjs.com/package/traceglass)
4
+ runs. One MCP session becomes one hash-chained, signed record: every `tools/call` is
5
+ chained and journaled the moment it returns, so the tamper window closes at capture
6
+ time — not at ingest.
7
+
8
+ ```bash
9
+ npm install @traceglass/mcp
10
+ ```
11
+
12
+ ## Wrap the client — every tool it calls is recorded
13
+
14
+ ```ts
15
+ import { startMcpRecording } from '@traceglass/mcp';
16
+
17
+ const rec = startMcpRecording({ name: 'support agent — ticket 8812', currency: 'INR' });
18
+ const mcp = rec.wrapClient(client); // your @modelcontextprotocol/sdk Client
19
+
20
+ rec.step({ type: 'user_input', label: 'Refund request', input: { ticket: '8812' } });
21
+ await mcp.callTool({ name: 'lookup_order', arguments: { id: '4471' } });
22
+ await mcp.callTool({ name: 'issue_refund', arguments: { id: '4471', amount: 1200 } });
23
+ rec.step({ type: 'final_output', label: 'Refund issued' });
24
+
25
+ const run = await rec.end(); // verified, signed (if `traceglass keygen` was run), stored
26
+ console.log(run?.id, run?.runHash);
27
+ ```
28
+
29
+ `wrapClient` returns the same client type — pass it wherever the original went. Replay
30
+ with `npx traceglass open --id <runId>`, verify with `npx traceglass verify <runId>`.
31
+
32
+ ## What lands in each step
33
+
34
+ | Step field | From |
35
+ | ------------- | ------------------------------------------------------------------------------ |
36
+ | `type` | `tool_call`, or `error` when the result has `isError: true` or the call throws |
37
+ | `toolName` | the `tools/call` tool name |
38
+ | `input` | the call's `arguments` (`{}` when a tool takes none) |
39
+ | `output` | the whole result, verbatim |
40
+ | `dataPayload` | `structuredContent` — the data the agent actually read |
41
+ | `tokens` | `_meta["traceglass/tokens"]` (or the `usage` hook) |
42
+ | `cost` | `_meta["traceglass/cost"]` (or the `usage` hook) |
43
+
44
+ MCP has no convention for tokens or cost. If your server reports them somewhere else,
45
+ pass `usage: ({ result }) => ({ tokens, cost })` and it wins over the `_meta` reading.
46
+
47
+ ## Server side
48
+
49
+ ```ts
50
+ server.registerTool('summarize', schema, rec.wrapToolHandler('summarize', handler));
51
+ ```
52
+
53
+ - **Order is capture order.** Concurrent tool calls are chained as they complete and are
54
+ never re-sorted afterwards — re-ordering a sealed chain is the one thing a flight
55
+ recorder must not be able to do.
56
+ - **Crash-safe:** if the process dies mid-session, `npx traceglass recover` finalizes the
57
+ journal into a `failed` run whose chain still verifies up to the crash point.
58
+ - **Local-first:** everything is written under `~/.traceglass` (or `TRACEGLASS_HOME`).
59
+ Zero network egress, and no production dependency outside traceglass itself — this
60
+ package speaks MCP structurally, so it works with whatever MCP SDK you already have.
61
+ - `end()` returns `null` for a session in which nothing was recorded: an empty session is
62
+ not evidence of anything, and no journal is left behind for `recover` to trip over.
@@ -0,0 +1,4 @@
1
+ export { startMcpRecording, type McpRecorder, type McpToolCallRecord, type McpUsageContext, type StartMcpRecordingOptions, } from './recorder.js';
2
+ export { COST_META_KEYS, TOKENS_META_KEYS, dataPayloadFromResult, errorOutput, isErrorResult, labelForTool, usageFromResult, } from './map.js';
3
+ export type { CallToolParams, CallToolResultLike, McpToolCaller, McpUsage } from './mcp-types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Public barrel for @traceglass/mcp.
2
+ export { startMcpRecording, } from './recorder.js';
3
+ export { COST_META_KEYS, TOKENS_META_KEYS, dataPayloadFromResult, errorOutput, isErrorResult, labelForTool, usageFromResult, } from './map.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EACL,iBAAiB,GAKlB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC"}
package/dist/map.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import type { McpUsage } from './mcp-types.js';
2
+ /**
3
+ * MCP → traceglass step mapping.
4
+ *
5
+ * MCP has no convention for cost or tokens, so this reads two OPTIONAL `_meta`
6
+ * keys on the tool result. `_meta` keys are namespaced by the spec, hence the
7
+ * `traceglass/` prefix; the dotted spelling is accepted too because plenty of
8
+ * emitters reach for it out of habit.
9
+ *
10
+ * Anything a server reports elsewhere is reachable through the `usage` hook on
11
+ * `startMcpRecording` — this module stays free of per-server guesswork.
12
+ */
13
+ export declare const TOKENS_META_KEYS: readonly ["traceglass/tokens", "traceglass.tokens"];
14
+ export declare const COST_META_KEYS: readonly ["traceglass/cost", "traceglass.cost"];
15
+ /** Read `_meta`-reported tokens/cost off a tool result. Absent members stay absent. */
16
+ export declare function usageFromResult(result: unknown): McpUsage;
17
+ /**
18
+ * Did the tool answer with a protocol-level error? MCP reports tool failures
19
+ * in-band (`isError: true` on a successful JSON-RPC response), so a failed tool
20
+ * call is invisible unless this flag is read.
21
+ */
22
+ export declare function isErrorResult(result: unknown): boolean;
23
+ /**
24
+ * The data the agent actually received, for the compliance-critical
25
+ * `dataPayload` field: `structuredContent` when the tool returns it, otherwise
26
+ * undefined (the full result is already recorded verbatim as `output`).
27
+ */
28
+ export declare function dataPayloadFromResult(result: unknown): unknown;
29
+ /** Human-readable step label, matching the SDK's `Tool: <name>` convention. */
30
+ export declare function labelForTool(toolName: string): string;
31
+ /**
32
+ * Normalize a thrown value into something JSON-serializable for the record.
33
+ * A transport rejection must still produce a step, so this never throws:
34
+ * a circular or unserializable value degrades to a placeholder.
35
+ */
36
+ export declare function errorOutput(err: unknown): {
37
+ error: string;
38
+ name?: string;
39
+ };
40
+ //# sourceMappingURL=map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,qDAAsD,CAAC;AACpF,eAAO,MAAM,cAAc,iDAAkD,CAAC;AAoB9E,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAUzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAG9D;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAW1E"}
package/dist/map.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * MCP → traceglass step mapping.
3
+ *
4
+ * MCP has no convention for cost or tokens, so this reads two OPTIONAL `_meta`
5
+ * keys on the tool result. `_meta` keys are namespaced by the spec, hence the
6
+ * `traceglass/` prefix; the dotted spelling is accepted too because plenty of
7
+ * emitters reach for it out of habit.
8
+ *
9
+ * Anything a server reports elsewhere is reachable through the `usage` hook on
10
+ * `startMcpRecording` — this module stays free of per-server guesswork.
11
+ */
12
+ export const TOKENS_META_KEYS = ['traceglass/tokens', 'traceglass.tokens'];
13
+ export const COST_META_KEYS = ['traceglass/cost', 'traceglass.cost'];
14
+ function isRecord(value) {
15
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
16
+ }
17
+ /** A finite, non-negative number, or undefined. Step fields reject the rest. */
18
+ function nonNegative(value) {
19
+ const n = typeof value === 'number' ? value : typeof value === 'string' ? Number(value) : NaN;
20
+ return Number.isFinite(n) && n >= 0 ? n : undefined;
21
+ }
22
+ function firstOf(meta, keys) {
23
+ for (const key of keys) {
24
+ const n = nonNegative(meta[key]);
25
+ if (n !== undefined)
26
+ return n;
27
+ }
28
+ return undefined;
29
+ }
30
+ /** Read `_meta`-reported tokens/cost off a tool result. Absent members stay absent. */
31
+ export function usageFromResult(result) {
32
+ if (!isRecord(result))
33
+ return {};
34
+ const meta = result._meta;
35
+ if (!isRecord(meta))
36
+ return {};
37
+ const tokens = firstOf(meta, TOKENS_META_KEYS);
38
+ const cost = firstOf(meta, COST_META_KEYS);
39
+ return {
40
+ ...(tokens !== undefined ? { tokens } : {}),
41
+ ...(cost !== undefined ? { cost } : {}),
42
+ };
43
+ }
44
+ /**
45
+ * Did the tool answer with a protocol-level error? MCP reports tool failures
46
+ * in-band (`isError: true` on a successful JSON-RPC response), so a failed tool
47
+ * call is invisible unless this flag is read.
48
+ */
49
+ export function isErrorResult(result) {
50
+ return isRecord(result) && result.isError === true;
51
+ }
52
+ /**
53
+ * The data the agent actually received, for the compliance-critical
54
+ * `dataPayload` field: `structuredContent` when the tool returns it, otherwise
55
+ * undefined (the full result is already recorded verbatim as `output`).
56
+ */
57
+ export function dataPayloadFromResult(result) {
58
+ if (!isRecord(result))
59
+ return undefined;
60
+ return result.structuredContent;
61
+ }
62
+ /** Human-readable step label, matching the SDK's `Tool: <name>` convention. */
63
+ export function labelForTool(toolName) {
64
+ return `Tool: ${toolName}`;
65
+ }
66
+ /**
67
+ * Normalize a thrown value into something JSON-serializable for the record.
68
+ * A transport rejection must still produce a step, so this never throws:
69
+ * a circular or unserializable value degrades to a placeholder.
70
+ */
71
+ export function errorOutput(err) {
72
+ if (err instanceof Error) {
73
+ return { error: err.message, name: err.name };
74
+ }
75
+ if (typeof err === 'string')
76
+ return { error: err };
77
+ try {
78
+ const json = JSON.stringify(err);
79
+ return { error: json ?? `[${typeof err}]` };
80
+ }
81
+ catch {
82
+ return { error: '[unserializable error]' };
83
+ }
84
+ }
85
+ //# sourceMappingURL=map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.js","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Structural types for the Model Context Protocol shapes this adapter touches.
3
+ *
4
+ * Deliberately NOT imported from `@modelcontextprotocol/sdk`. This package adds
5
+ * no production dependency of its own, so:
6
+ * - it records whatever MCP SDK version (or hand-rolled client/server) the
7
+ * host application already has, instead of pinning a second copy, and
8
+ * - the supply chain behind an audit record stays two packages wide.
9
+ *
10
+ * Compatibility with the real SDK signatures is asserted at compile time in
11
+ * `type-compat.ts` rather than assumed.
12
+ */
13
+ /** `tools/call` request params. Extra members are preserved, never required. */
14
+ export interface CallToolParams {
15
+ name: string;
16
+ arguments?: Record<string, unknown> | undefined;
17
+ _meta?: Record<string, unknown> | undefined;
18
+ }
19
+ /**
20
+ * A `tools/call` result. Every member is optional: a tool may answer with
21
+ * content, with `structuredContent`, with both, or with neither.
22
+ */
23
+ export interface CallToolResultLike {
24
+ content?: unknown;
25
+ structuredContent?: unknown;
26
+ isError?: boolean;
27
+ _meta?: Record<string, unknown> | undefined;
28
+ }
29
+ /**
30
+ * Anything that can invoke an MCP tool — an SDK `Client`, a transport shim, a
31
+ * fake in a test. Method syntax (not a property) is deliberate: TypeScript
32
+ * checks method parameters bivariantly, so a real client whose `callTool` takes
33
+ * extra optional arguments (a result schema, request options) still satisfies
34
+ * this interface.
35
+ */
36
+ export interface McpToolCaller {
37
+ callTool(params: CallToolParams, ...rest: never[]): Promise<unknown>;
38
+ }
39
+ /** Token/cost figures for one tool call, when the server reports any. */
40
+ export interface McpUsage {
41
+ tokens?: number;
42
+ cost?: number;
43
+ }
44
+ //# sourceMappingURL=mcp-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-types.d.ts","sourceRoot":"","sources":["../src/mcp-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE;AAED,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Structural types for the Model Context Protocol shapes this adapter touches.
3
+ *
4
+ * Deliberately NOT imported from `@modelcontextprotocol/sdk`. This package adds
5
+ * no production dependency of its own, so:
6
+ * - it records whatever MCP SDK version (or hand-rolled client/server) the
7
+ * host application already has, instead of pinning a second copy, and
8
+ * - the supply chain behind an audit record stays two packages wide.
9
+ *
10
+ * Compatibility with the real SDK signatures is asserted at compile time in
11
+ * `type-compat.ts` rather than assumed.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=mcp-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-types.js","sourceRoot":"","sources":["../src/mcp-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,86 @@
1
+ import type { Run, Step } from '@traceglass/core';
2
+ import { type RecordStepInput } from '@traceglass/sdk';
3
+ import type { CallToolParams, McpToolCaller, McpUsage } from './mcp-types.js';
4
+ /**
5
+ * MCP session recorder.
6
+ *
7
+ * One MCP session becomes one traceglass run: every `tools/call` is a
8
+ * `tool_call` step, hash-chained the moment it returns and journaled to disk
9
+ * before the caller gets its result back. The chain is therefore fixed at
10
+ * capture time — the same guarantee `@traceglass/sdk` gives, reached without
11
+ * the host application writing any per-tool recording code.
12
+ *
13
+ * Steps land in COMPLETION order, which is the order the agent actually learned
14
+ * things. Concurrent tool calls are not re-sorted by start time afterwards:
15
+ * re-ordering a chain after the fact is exactly what a flight recorder must not
16
+ * be able to do.
17
+ */
18
+ /** Context handed to the `usage` hook for one completed call. */
19
+ export interface McpUsageContext {
20
+ toolName: string;
21
+ params: CallToolParams;
22
+ /** The tool result, or undefined when the call threw. */
23
+ result: unknown;
24
+ }
25
+ export interface StartMcpRecordingOptions {
26
+ /** Run name. Defaults to `MCP session`. */
27
+ name?: string;
28
+ /** Explicit run id; defaults to `mcp-<date>-<hex>`. */
29
+ id?: string;
30
+ currency?: string;
31
+ /** traceglass data dir; `null` for a memory-only recording. See the SDK. */
32
+ dir?: string | null;
33
+ /** Per-leaf commitments so payloads can be redacted later (default on). */
34
+ redactable?: boolean;
35
+ /** Built-in redaction patterns applied at capture time, before hashing. */
36
+ redactPatterns?: string[];
37
+ /**
38
+ * Pull tokens/cost out of a result when your server reports them somewhere
39
+ * other than the `_meta` keys `map.ts` knows about. Returning `undefined`
40
+ * (or omitting a member) falls back to the `_meta` reading.
41
+ */
42
+ usage?: (ctx: McpUsageContext) => McpUsage | undefined;
43
+ }
44
+ /** One tool invocation to record. Everything except `name` is optional. */
45
+ export interface McpToolCallRecord {
46
+ /** Tool name as sent in `tools/call`. */
47
+ name: string;
48
+ arguments?: Record<string, unknown> | undefined;
49
+ /** The tool result, when the call completed. */
50
+ result?: unknown;
51
+ /** The thrown value, when the call failed at the transport/protocol level. */
52
+ error?: unknown;
53
+ /** ISO 8601 start time; defaults to now. */
54
+ startedAt?: string;
55
+ durationMs?: number;
56
+ /** Overrides anything derived from the result. */
57
+ usage?: McpUsage;
58
+ }
59
+ export interface McpRecorder {
60
+ readonly runId: string;
61
+ /** Record one tool invocation. Returns the chained step. */
62
+ recordToolCall(call: McpToolCallRecord): Step;
63
+ /**
64
+ * Wrap an MCP client so every `tools/call` it makes is recorded. The returned
65
+ * value is the same client type — pass it wherever the original went.
66
+ */
67
+ wrapClient<T extends McpToolCaller>(client: T): T;
68
+ /**
69
+ * Server side: wrap one tool handler so every invocation it serves is
70
+ * recorded. `args` is the tool's argument object as MCP delivers it.
71
+ */
72
+ wrapToolHandler<A extends unknown[], R>(name: string, handler: (...args: A) => R | Promise<R>): (...args: A) => Promise<R>;
73
+ /** Record a non-tool step (user input, final output, an approval, ...). */
74
+ step(input: RecordStepInput): Step;
75
+ /**
76
+ * Finalize: totals, warnings, anchor, signature (if `traceglass keygen` was
77
+ * run), store. Returns `null` for a session in which nothing was recorded —
78
+ * an empty session is not evidence of anything, and a run with no steps
79
+ * cannot be anchored (SPEC §6.1).
80
+ */
81
+ end(opts?: {
82
+ status?: 'completed' | 'failed';
83
+ }): Promise<Run | null>;
84
+ }
85
+ export declare function startMcpRecording(opts?: StartMcpRecordingOptions): McpRecorder;
86
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAkB,KAAK,eAAe,EAAiB,MAAM,iBAAiB,CAAC;AAQtF,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AAEH,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,yDAAyD;IACzD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,QAAQ,GAAG,SAAS,CAAC;CACxD;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAChD,gDAAgD;IAChD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC9C;;;OAGG;IACH,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IAClD;;;OAGG;IACH,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACtC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9B,2EAA2E;IAC3E,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC;;;;;OAKG;IACH,GAAG,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CACtE;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,wBAA6B,GAAG,WAAW,CA+JlF"}
@@ -0,0 +1,154 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { startRecording } from '@traceglass/sdk';
3
+ import { dataPayloadFromResult, errorOutput, isErrorResult, labelForTool, usageFromResult, } from './map.js';
4
+ function nowMs() {
5
+ return performance.now();
6
+ }
7
+ export function startMcpRecording(opts = {}) {
8
+ const runId = opts.id ?? `mcp-${new Date().toISOString().slice(0, 10)}-${randomBytes(3).toString('hex')}`;
9
+ /**
10
+ * The underlying recorder is created on the FIRST recorded step, not here.
11
+ * An MCP session that never calls a tool would otherwise leave a stepless
12
+ * journal on disk, which `traceglass recover` cannot finalize (a run with no
13
+ * steps is not a record of anything). The run id is fixed up front so callers
14
+ * can log or correlate it before anything is recorded.
15
+ */
16
+ let inner = null;
17
+ function recorder() {
18
+ inner ??= startRecording({
19
+ name: opts.name ?? 'MCP session',
20
+ id: runId,
21
+ ...(opts.currency !== undefined ? { currency: opts.currency } : {}),
22
+ ...(opts.dir !== undefined ? { dir: opts.dir } : {}),
23
+ ...(opts.redactable !== undefined ? { redactable: opts.redactable } : {}),
24
+ ...(opts.redactPatterns !== undefined ? { redactPatterns: opts.redactPatterns } : {}),
25
+ });
26
+ return inner;
27
+ }
28
+ let count = 0;
29
+ let ended = false;
30
+ function recordToolCall(call) {
31
+ if (ended) {
32
+ throw new Error(`MCP recording "${runId}" has already ended.`);
33
+ }
34
+ const failed = call.error !== undefined || isErrorResult(call.result);
35
+ const output = call.error !== undefined ? errorOutput(call.error) : call.result;
36
+ const dataPayload = dataPayloadFromResult(call.result);
37
+ const fromResult = usageFromResult(call.result);
38
+ const hook = opts.usage?.({
39
+ toolName: call.name,
40
+ params: { name: call.name, arguments: call.arguments },
41
+ result: call.result,
42
+ });
43
+ const usage = { ...fromResult, ...hook, ...call.usage };
44
+ const step = recorder().step({
45
+ type: failed ? 'error' : 'tool_call',
46
+ label: labelForTool(call.name),
47
+ toolName: call.name,
48
+ // `arguments` may legitimately be absent (a tool that takes none); an
49
+ // empty object records "called with nothing" rather than "not recorded".
50
+ input: call.arguments ?? {},
51
+ ...(output !== undefined ? { output } : {}),
52
+ ...(dataPayload !== undefined ? { dataPayload } : {}),
53
+ ...(usage.tokens !== undefined ? { tokens: usage.tokens } : {}),
54
+ ...(usage.cost !== undefined ? { cost: usage.cost } : {}),
55
+ ...(call.startedAt !== undefined ? { startedAt: call.startedAt } : {}),
56
+ ...(call.durationMs !== undefined ? { durationMs: call.durationMs } : {}),
57
+ });
58
+ count += 1;
59
+ return step;
60
+ }
61
+ return {
62
+ runId,
63
+ recordToolCall,
64
+ wrapClient(client) {
65
+ const original = client.callTool.bind(client);
66
+ const wrapped = async (params, ...rest) => {
67
+ const startedAt = new Date().toISOString();
68
+ const t0 = nowMs();
69
+ try {
70
+ const result = await original(params, ...rest);
71
+ recordToolCall({
72
+ name: params.name,
73
+ arguments: params.arguments,
74
+ result,
75
+ startedAt,
76
+ durationMs: Math.round(nowMs() - t0),
77
+ });
78
+ return result;
79
+ }
80
+ catch (err) {
81
+ recordToolCall({
82
+ name: params.name,
83
+ arguments: params.arguments,
84
+ error: err,
85
+ startedAt,
86
+ durationMs: Math.round(nowMs() - t0),
87
+ });
88
+ throw err;
89
+ }
90
+ };
91
+ // A Proxy keeps the wrapped value assignment-compatible with the original
92
+ // client (same type, same extra methods). Every non-intercepted member is
93
+ // read with the TARGET as receiver and bound to it, so methods that touch
94
+ // private state still run on the real object rather than on the proxy.
95
+ return new Proxy(client, {
96
+ get(target, prop, _receiver) {
97
+ if (prop === 'callTool')
98
+ return wrapped;
99
+ const value = Reflect.get(target, prop, target);
100
+ return typeof value === 'function'
101
+ ? value.bind(target)
102
+ : value;
103
+ },
104
+ });
105
+ },
106
+ wrapToolHandler(name, handler) {
107
+ return async (...args) => {
108
+ const startedAt = new Date().toISOString();
109
+ const t0 = nowMs();
110
+ const first = args[0];
111
+ const argObject = typeof first === 'object' && first !== null && !Array.isArray(first)
112
+ ? first
113
+ : undefined;
114
+ try {
115
+ const result = await handler(...args);
116
+ recordToolCall({
117
+ name,
118
+ arguments: argObject,
119
+ result,
120
+ startedAt,
121
+ durationMs: Math.round(nowMs() - t0),
122
+ });
123
+ return result;
124
+ }
125
+ catch (err) {
126
+ recordToolCall({
127
+ name,
128
+ arguments: argObject,
129
+ error: err,
130
+ startedAt,
131
+ durationMs: Math.round(nowMs() - t0),
132
+ });
133
+ throw err;
134
+ }
135
+ };
136
+ },
137
+ step(input) {
138
+ if (ended)
139
+ throw new Error(`MCP recording "${runId}" has already ended.`);
140
+ const step = recorder().step(input);
141
+ count += 1;
142
+ return step;
143
+ },
144
+ async end(endOpts = {}) {
145
+ if (ended)
146
+ throw new Error(`MCP recording "${runId}" has already ended.`);
147
+ ended = true;
148
+ if (count === 0 || inner === null)
149
+ return null;
150
+ return inner.end(endOpts);
151
+ },
152
+ };
153
+ }
154
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Nothing here is meant to be imported; the assertions above are the payload. */
2
+ export declare const TYPE_COMPAT_ASSERTIONS = 3;
3
+ //# sourceMappingURL=type-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-compat.d.ts","sourceRoot":"","sources":["../src/type-compat.ts"],"names":[],"mappings":"AA4DA,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,IAAI,CAAC"}
@@ -0,0 +1,9 @@
1
+ const _clientIsCaller = true;
2
+ const _wrappedKeepsType = wrapLike(_upstream);
3
+ const _wrappedHandler = wrapHandlerLike('t', _upstreamHandler);
4
+ /** Nothing here is meant to be imported; the assertions above are the payload. */
5
+ export const TYPE_COMPAT_ASSERTIONS = 3;
6
+ void _clientIsCaller;
7
+ void _wrappedKeepsType;
8
+ void _wrappedHandler;
9
+ //# sourceMappingURL=type-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-compat.js","sourceRoot":"","sources":["../src/type-compat.ts"],"names":[],"mappings":"AAoCA,MAAM,eAAe,GAAoB,IAAI,CAAC;AAK9C,MAAM,iBAAiB,GAAmB,QAAQ,CAAC,SAAS,CAAC,CAAC;AAiB9D,MAAM,eAAe,GAAwB,eAAe,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAEpF,kFAAkF;AAClF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC,KAAK,eAAe,CAAC;AACrB,KAAK,iBAAiB,CAAC;AACvB,KAAK,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@traceglass/mcp",
3
+ "version": "1.0.0",
4
+ "description": "Record Model Context Protocol tool calls as tamper-evident traceglass runs",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "ai",
18
+ "agents",
19
+ "audit",
20
+ "compliance"
21
+ ],
22
+ "license": "MIT",
23
+ "scripts": {
24
+ "build": "tsc -b",
25
+ "test": "vitest run"
26
+ },
27
+ "dependencies": {
28
+ "@traceglass/core": "1.0.0",
29
+ "@traceglass/sdk": "1.0.0"
30
+ }
31
+ }