@orangecheck/agent-mcp 0.1.0 → 0.2.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/index.d.mts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +63 -59
- package/src/index.ts +48 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DelegationEnvelope } from '@orangecheck/agent-core';
|
|
2
2
|
import { SignerRef, ActionEnvelope } from '@orangecheck/agent-signer';
|
|
3
|
+
import { ConsoleClient, PostActionResult } from '@orangecheck/agent-console-client';
|
|
4
|
+
export { ConsoleClient, PostActionResult, postActionToConsole } from '@orangecheck/agent-console-client';
|
|
3
5
|
|
|
4
6
|
interface McpInvocation {
|
|
5
7
|
server: string;
|
|
@@ -26,4 +28,12 @@ interface InvokeWithStampResult<T> {
|
|
|
26
28
|
}
|
|
27
29
|
declare function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promise<InvokeWithStampResult<T>>;
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
interface InvokeWithStampAndPostInput<T> extends InvokeWithStampInput<T> {
|
|
32
|
+
console?: ConsoleClient;
|
|
33
|
+
}
|
|
34
|
+
interface InvokeWithStampAndPostResult<T> extends InvokeWithStampResult<T> {
|
|
35
|
+
posted: PostActionResult | null;
|
|
36
|
+
}
|
|
37
|
+
declare function invokeWithStampAndPost<T>(input: InvokeWithStampAndPostInput<T>): Promise<InvokeWithStampAndPostResult<T>>;
|
|
38
|
+
|
|
39
|
+
export { type InvokeWithStampAndPostInput, type InvokeWithStampAndPostResult, type InvokeWithStampInput, type InvokeWithStampResult, type McpInvocation, type StampInvocationInput, canonicalizeInvocation, invocationHash, invocationId, invokeWithStamp, invokeWithStampAndPost, stampInvocation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DelegationEnvelope } from '@orangecheck/agent-core';
|
|
2
2
|
import { SignerRef, ActionEnvelope } from '@orangecheck/agent-signer';
|
|
3
|
+
import { ConsoleClient, PostActionResult } from '@orangecheck/agent-console-client';
|
|
4
|
+
export { ConsoleClient, PostActionResult, postActionToConsole } from '@orangecheck/agent-console-client';
|
|
3
5
|
|
|
4
6
|
interface McpInvocation {
|
|
5
7
|
server: string;
|
|
@@ -26,4 +28,12 @@ interface InvokeWithStampResult<T> {
|
|
|
26
28
|
}
|
|
27
29
|
declare function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promise<InvokeWithStampResult<T>>;
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
interface InvokeWithStampAndPostInput<T> extends InvokeWithStampInput<T> {
|
|
32
|
+
console?: ConsoleClient;
|
|
33
|
+
}
|
|
34
|
+
interface InvokeWithStampAndPostResult<T> extends InvokeWithStampResult<T> {
|
|
35
|
+
posted: PostActionResult | null;
|
|
36
|
+
}
|
|
37
|
+
declare function invokeWithStampAndPost<T>(input: InvokeWithStampAndPostInput<T>): Promise<InvokeWithStampAndPostResult<T>>;
|
|
38
|
+
|
|
39
|
+
export { type InvokeWithStampAndPostInput, type InvokeWithStampAndPostResult, type InvokeWithStampInput, type InvokeWithStampResult, type McpInvocation, type StampInvocationInput, canonicalizeInvocation, invocationHash, invocationId, invokeWithStamp, invokeWithStampAndPost, stampInvocation };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var sha256 = require('@noble/hashes/sha256');
|
|
4
4
|
var agentCore = require('@orangecheck/agent-core');
|
|
5
5
|
var agentSigner = require('@orangecheck/agent-signer');
|
|
6
|
+
var agentConsoleClient = require('@orangecheck/agent-console-client');
|
|
6
7
|
|
|
7
8
|
// src/index.ts
|
|
8
9
|
function canonicalizeInvocation(inv) {
|
|
@@ -52,11 +53,28 @@ async function invokeWithStamp(input) {
|
|
|
52
53
|
const result = await input.call(input.invocation);
|
|
53
54
|
return { result, action };
|
|
54
55
|
}
|
|
56
|
+
async function invokeWithStampAndPost(input) {
|
|
57
|
+
const { result, action } = await invokeWithStamp(input);
|
|
58
|
+
let posted = null;
|
|
59
|
+
if (input.console) {
|
|
60
|
+
try {
|
|
61
|
+
posted = await agentConsoleClient.postActionToConsole(action, input.console);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error("[oc-agent-mcp] postActionToConsole failed:", err);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { result, action, posted };
|
|
67
|
+
}
|
|
55
68
|
|
|
69
|
+
Object.defineProperty(exports, "postActionToConsole", {
|
|
70
|
+
enumerable: true,
|
|
71
|
+
get: function () { return agentConsoleClient.postActionToConsole; }
|
|
72
|
+
});
|
|
56
73
|
exports.canonicalizeInvocation = canonicalizeInvocation;
|
|
57
74
|
exports.invocationHash = invocationHash;
|
|
58
75
|
exports.invocationId = invocationId;
|
|
59
76
|
exports.invokeWithStamp = invokeWithStamp;
|
|
77
|
+
exports.invokeWithStampAndPost = invokeWithStampAndPost;
|
|
60
78
|
exports.stampInvocation = stampInvocation;
|
|
61
79
|
//# sourceMappingURL=index.js.map
|
|
62
80
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["canonicalize","hexEncode","sha256","computeActionId","parseScope","isSubScope","signAsAgent"],"mappings":";;;;;;;AAqDO,SAAS,uBAAuB,GAAA,EAAgC;AACnE,EAAA,MAAM,KAAA,GAAQ;AAAA,IACV,WAAW,GAAA,CAAI,SAAA;AAAA,IACf,MAAA,EAAQ,GAAA,CAAI,MAAA,CAAO,IAAA,EAAK;AAAA,IACxB,MAAM,GAAA,CAAI;AAAA,GACd;AACA,EAAA,MAAM,GAAA,GAAMA,uBAAa,KAAsD,CAAA;AAC/E,EAAA,OAAO,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM,IAAI,CAAA;AAC9C;AAEO,SAAS,eAAe,GAAA,EAA4B;AACvD,EAAA,OAAO,YAAYC,mBAAA,CAAUC,aAAA,CAAO,sBAAA,CAAuB,GAAG,CAAC,CAAC,CAAA;AACpE;AAEO,SAAS,YAAA,CACZ,YAAA,EACA,QAAA,EACA,YAAA,EACA,gBACA,GAAA,EACM;AACN,EAAA,OAAOC,yBAAA,CAAgB;AAAA,IACnB,OAAA,EAAS,YAAA;AAAA,IACT,YAAA,EAAc,eAAe,GAAG,CAAA;AAAA,IAChC,cAAA,EAAgB,sBAAA,CAAuB,GAAG,CAAA,CAAE,UAAA;AAAA,IAC5C,YAAA,EAAc,8CAAA;AAAA,IACd,SAAA,EAAW,QAAA;AAAA,IACX,aAAA,EAAe,YAAA;AAAA,IACf,eAAA,EAAiB;AAAA,GACpB,CAAA;AACL;AAoBA,eAAsB,gBAAgB,KAAA,EAAsD;AACxF,EAAA,MAAM,cAAA,GACF,KAAA,CAAM,cAAA,IACN,CAAA,kBAAA,EAAqB,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,IAAA,EAAM,CAAA,MAAA,EAAS,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA,CAAA,CAAA;AAKrF,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,IAAIC,oBAAU,CAAA;AACtD,EAAA,MAAM,eAAA,GAAkBA,qBAAW,cAAc,CAAA;AACjD,EAAA,IAAI,CAAC,QAAQ,IAAA,CAAK,CAAC,MAAMC,oBAAA,CAAW,eAAA,EAAiB,CAAC,CAAC,CAAA,EAAG;AACtD,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,qCAAqC,cAAc,CAAA,yCAAA;AAAA,KACvD;AAAA,EACJ;AAEA,EAAA,MAAM,KAAA,GAAQ,sBAAA,CAAuB,KAAA,CAAM,UAAU,CAAA;AACrD,EAAA,OAAOC,uBAAA,CAAY;AAAA,IACf,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,OAAA,EAAS,EAAE,IAAA,EAAM,cAAA,CAAe,MAAM,UAAU,CAAA,EAAG,MAAA,EAAQ,KAAA,CAAM,UAAA,EAAW;AAAA,IAC5E,IAAA,EAAM,8CAAA;AAAA,IACN,cAAA;AAAA,IACA,UAAU,KAAA,CAAM;AAAA,GACnB,CAAA;AACL;AAyBA,eAAsB,gBAAmB,KAAA,EAAmE;AACxG,EAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,KAAK,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,IAAA,CAAK,MAAM,UAAU,CAAA;AAChD,EAAA,OAAO,EAAE,QAAQ,MAAA,EAAO;AAC5B","file":"index.js","sourcesContent":["// @orangecheck/agent-mcp — wrap MCP tool invocations in OC Agent envelopes.\n//\n// An MCP client calls tools on an MCP server: { server, name, arguments }.\n// This module stamps each invocation as an `agent-action` whose `content.hash`\n// is a SHA-256 of the canonicalized (server, name, arguments) tuple, scoped\n// as `mcp:invoke(server=<url>,tool=<name>)`. The server — or any counterparty\n// — verifies the action before trusting the call.\n//\n// The wrapper is transport-agnostic. Wire it into whatever MCP client you use\n// by calling `invokeWithStamp()` around the raw call.\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport {\n canonicalize,\n computeActionId,\n hexEncode,\n isSubScope,\n parseScope,\n type DelegationEnvelope,\n} from '@orangecheck/agent-core';\nimport {\n signAsAgent,\n type ActionEnvelope,\n type SignerRef,\n} from '@orangecheck/agent-signer';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Canonicalization of an MCP invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface McpInvocation {\n /** Origin URL of the MCP server. Trimmed and lowercased for canonicalization. */\n server: string;\n /** Tool name (method) being invoked. */\n tool: string;\n /** JSON-serializable arguments. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Produce the canonical bytes for an MCP invocation. The bytes are what the\n * action envelope's `content.hash` is a SHA-256 of.\n *\n * Shape:\n * {\n * \"arguments\": <canonical JSON of args>,\n * \"server\": <server url>,\n * \"tool\": <tool name>\n * }\n *\n * The shape is intentionally minimal so verifiers can reconstruct it without\n * knowing anything server- or tool-specific.\n */\nexport function canonicalizeInvocation(inv: McpInvocation): Uint8Array {\n const canon = {\n arguments: inv.arguments,\n server: inv.server.trim(),\n tool: inv.tool,\n };\n const str = canonicalize(canon as unknown as Parameters<typeof canonicalize>[0]);\n return new TextEncoder().encode(str + '\\n');\n}\n\nexport function invocationHash(inv: McpInvocation): string {\n return 'sha256:' + hexEncode(sha256(canonicalizeInvocation(inv)));\n}\n\nexport function invocationId(\n agentAddress: string,\n signedAt: string,\n delegationId: string,\n scopeExercised: string,\n inv: McpInvocation\n): string {\n return computeActionId({\n address: agentAddress,\n content_hash: invocationHash(inv),\n content_length: canonicalizeInvocation(inv).byteLength,\n content_mime: 'application/vnd.oc-agent.mcp-invocation+json',\n signed_at: signedAt,\n delegation_id: delegationId,\n scope_exercised: scopeExercised,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stamped invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface StampInvocationInput {\n agent: SignerRef;\n delegation: DelegationEnvelope;\n invocation: McpInvocation;\n /** Defaults to `mcp:invoke(server=<server>,tool=<tool>)` — the tightest admissible sub-scope. */\n scopeExercised?: string;\n signedAt?: Date;\n}\n\n/**\n * Stamp an MCP invocation without actually calling it. Useful when the caller\n * wants the signed envelope for out-of-band auditing before (or independent of)\n * running the tool.\n */\nexport async function stampInvocation(input: StampInvocationInput): Promise<ActionEnvelope> {\n const scopeExercised =\n input.scopeExercised ??\n `mcp:invoke(server=${input.invocation.server.trim()},tool=${input.invocation.tool})`;\n\n // Tiny pre-flight: confirm the exercised scope is a sub-scope of *some*\n // granted scope. This keeps a common integration mistake from producing\n // an envelope that later fails verifier-side.\n const granted = input.delegation.scopes.map(parseScope);\n const exercisedParsed = parseScope(scopeExercised);\n if (!granted.some((g) => isSubScope(exercisedParsed, g))) {\n throw new Error(\n `stampInvocation: scope_exercised (${scopeExercised}) is not a sub-scope of any granted scope`\n );\n }\n\n const bytes = canonicalizeInvocation(input.invocation);\n return signAsAgent({\n agent: input.agent,\n delegation: input.delegation,\n content: { hash: invocationHash(input.invocation), length: bytes.byteLength },\n mime: 'application/vnd.oc-agent.mcp-invocation+json',\n scopeExercised,\n signedAt: input.signedAt,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// invokeWithStamp — call the tool AND produce the stamp around it\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface InvokeWithStampInput<T> extends StampInvocationInput {\n /** The underlying transport call. Returns whatever the MCP server returns. */\n call: (inv: McpInvocation) => Promise<T>;\n}\n\nexport interface InvokeWithStampResult<T> {\n result: T;\n action: ActionEnvelope;\n}\n\n/**\n * Stamp the invocation *first*, then execute the call. The stamped envelope\n * is returned alongside the result so the caller can ship them together.\n *\n * Rationale for stamping first: if the downstream call hangs or fails, we\n * still have an on-record commitment that this agent attempted this specific\n * invocation. The server-side verifier sees a stamped intent plus the server's\n * own transcript.\n */\nexport async function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promise<InvokeWithStampResult<T>> {\n const action = await stampInvocation(input);\n const result = await input.call(input.invocation);\n return { result, action };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["canonicalize","hexEncode","sha256","computeActionId","parseScope","isSubScope","signAsAgent","_post"],"mappings":"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","file":"index.js","sourcesContent":["// @orangecheck/agent-mcp — wrap MCP tool invocations in OC Agent envelopes.\n//\n// An MCP client calls tools on an MCP server: { server, name, arguments }.\n// This module stamps each invocation as an `agent-action` whose `content.hash`\n// is a SHA-256 of the canonicalized (server, name, arguments) tuple, scoped\n// as `mcp:invoke(server=<url>,tool=<name>)`. The server — or any counterparty\n// — verifies the action before trusting the call.\n//\n// The wrapper is transport-agnostic. Wire it into whatever MCP client you use\n// by calling `invokeWithStamp()` around the raw call.\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport {\n canonicalize,\n computeActionId,\n hexEncode,\n isSubScope,\n parseScope,\n type DelegationEnvelope,\n} from '@orangecheck/agent-core';\nimport {\n signAsAgent,\n type ActionEnvelope,\n type SignerRef,\n} from '@orangecheck/agent-signer';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Canonicalization of an MCP invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface McpInvocation {\n /** Origin URL of the MCP server. Trimmed and lowercased for canonicalization. */\n server: string;\n /** Tool name (method) being invoked. */\n tool: string;\n /** JSON-serializable arguments. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Produce the canonical bytes for an MCP invocation. The bytes are what the\n * action envelope's `content.hash` is a SHA-256 of.\n *\n * Shape:\n * {\n * \"arguments\": <canonical JSON of args>,\n * \"server\": <server url>,\n * \"tool\": <tool name>\n * }\n *\n * The shape is intentionally minimal so verifiers can reconstruct it without\n * knowing anything server- or tool-specific.\n */\nexport function canonicalizeInvocation(inv: McpInvocation): Uint8Array {\n const canon = {\n arguments: inv.arguments,\n server: inv.server.trim(),\n tool: inv.tool,\n };\n const str = canonicalize(canon as unknown as Parameters<typeof canonicalize>[0]);\n return new TextEncoder().encode(str + '\\n');\n}\n\nexport function invocationHash(inv: McpInvocation): string {\n return 'sha256:' + hexEncode(sha256(canonicalizeInvocation(inv)));\n}\n\nexport function invocationId(\n agentAddress: string,\n signedAt: string,\n delegationId: string,\n scopeExercised: string,\n inv: McpInvocation\n): string {\n return computeActionId({\n address: agentAddress,\n content_hash: invocationHash(inv),\n content_length: canonicalizeInvocation(inv).byteLength,\n content_mime: 'application/vnd.oc-agent.mcp-invocation+json',\n signed_at: signedAt,\n delegation_id: delegationId,\n scope_exercised: scopeExercised,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stamped invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface StampInvocationInput {\n agent: SignerRef;\n delegation: DelegationEnvelope;\n invocation: McpInvocation;\n /** Defaults to `mcp:invoke(server=<server>,tool=<tool>)` — the tightest admissible sub-scope. */\n scopeExercised?: string;\n signedAt?: Date;\n}\n\n/**\n * Stamp an MCP invocation without actually calling it. Useful when the caller\n * wants the signed envelope for out-of-band auditing before (or independent of)\n * running the tool.\n */\nexport async function stampInvocation(input: StampInvocationInput): Promise<ActionEnvelope> {\n const scopeExercised =\n input.scopeExercised ??\n `mcp:invoke(server=${input.invocation.server.trim()},tool=${input.invocation.tool})`;\n\n // Tiny pre-flight: confirm the exercised scope is a sub-scope of *some*\n // granted scope. This keeps a common integration mistake from producing\n // an envelope that later fails verifier-side.\n const granted = input.delegation.scopes.map(parseScope);\n const exercisedParsed = parseScope(scopeExercised);\n if (!granted.some((g) => isSubScope(exercisedParsed, g))) {\n throw new Error(\n `stampInvocation: scope_exercised (${scopeExercised}) is not a sub-scope of any granted scope`\n );\n }\n\n const bytes = canonicalizeInvocation(input.invocation);\n return signAsAgent({\n agent: input.agent,\n delegation: input.delegation,\n content: { hash: invocationHash(input.invocation), length: bytes.byteLength },\n mime: 'application/vnd.oc-agent.mcp-invocation+json',\n scopeExercised,\n signedAt: input.signedAt,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// invokeWithStamp — call the tool AND produce the stamp around it\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface InvokeWithStampInput<T> extends StampInvocationInput {\n /** The underlying transport call. Returns whatever the MCP server returns. */\n call: (inv: McpInvocation) => Promise<T>;\n}\n\nexport interface InvokeWithStampResult<T> {\n result: T;\n action: ActionEnvelope;\n}\n\n/**\n * Stamp the invocation *first*, then execute the call. The stamped envelope\n * is returned alongside the result so the caller can ship them together.\n *\n * Rationale for stamping first: if the downstream call hangs or fails, we\n * still have an on-record commitment that this agent attempted this specific\n * invocation. The server-side verifier sees a stamped intent plus the server's\n * own transcript.\n */\nexport async function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promise<InvokeWithStampResult<T>> {\n const action = await stampInvocation(input);\n const result = await input.call(input.invocation);\n return { result, action };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Console integration — re-export from the shared client\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport {\n postActionToConsole,\n type ConsoleClient,\n type PostActionResult,\n} from '@orangecheck/agent-console-client';\n\nimport {\n postActionToConsole as _post,\n type ConsoleClient as _ConsoleClient,\n type PostActionResult as _PostActionResult,\n} from '@orangecheck/agent-console-client';\n\nexport interface InvokeWithStampAndPostInput<T> extends InvokeWithStampInput<T> {\n /** Console credentials. If absent, behaves like invokeWithStamp + posted: null. */\n console?: _ConsoleClient;\n}\n\nexport interface InvokeWithStampAndPostResult<T> extends InvokeWithStampResult<T> {\n /** Set when console is configured AND the POST succeeded. */\n posted: _PostActionResult | null;\n}\n\n/**\n * invokeWithStamp + post the stamped envelope to console.ochk.io. The\n * post happens AFTER the call so a failing post never prevents the\n * underlying MCP invocation from running. If `console` is omitted,\n * this is identical to invokeWithStamp + posted: null.\n */\nexport async function invokeWithStampAndPost<T>(\n input: InvokeWithStampAndPostInput<T>\n): Promise<InvokeWithStampAndPostResult<T>> {\n const { result, action } = await invokeWithStamp(input);\n let posted: _PostActionResult | null = null;\n if (input.console) {\n try {\n posted = await _post(action, input.console);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[oc-agent-mcp] postActionToConsole failed:', err);\n }\n }\n return { result, action, posted };\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { sha256 } from '@noble/hashes/sha256';
|
|
2
2
|
import { canonicalize, hexEncode, computeActionId, parseScope, isSubScope } from '@orangecheck/agent-core';
|
|
3
3
|
import { signAsAgent } from '@orangecheck/agent-signer';
|
|
4
|
+
import { postActionToConsole } from '@orangecheck/agent-console-client';
|
|
5
|
+
export { postActionToConsole } from '@orangecheck/agent-console-client';
|
|
4
6
|
|
|
5
7
|
// src/index.ts
|
|
6
8
|
function canonicalizeInvocation(inv) {
|
|
@@ -50,7 +52,19 @@ async function invokeWithStamp(input) {
|
|
|
50
52
|
const result = await input.call(input.invocation);
|
|
51
53
|
return { result, action };
|
|
52
54
|
}
|
|
55
|
+
async function invokeWithStampAndPost(input) {
|
|
56
|
+
const { result, action } = await invokeWithStamp(input);
|
|
57
|
+
let posted = null;
|
|
58
|
+
if (input.console) {
|
|
59
|
+
try {
|
|
60
|
+
posted = await postActionToConsole(action, input.console);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.error("[oc-agent-mcp] postActionToConsole failed:", err);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { result, action, posted };
|
|
66
|
+
}
|
|
53
67
|
|
|
54
|
-
export { canonicalizeInvocation, invocationHash, invocationId, invokeWithStamp, stampInvocation };
|
|
68
|
+
export { canonicalizeInvocation, invocationHash, invocationId, invokeWithStamp, invokeWithStampAndPost, stampInvocation };
|
|
55
69
|
//# sourceMappingURL=index.mjs.map
|
|
56
70
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["_post"],"mappings":"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","file":"index.mjs","sourcesContent":["// @orangecheck/agent-mcp — wrap MCP tool invocations in OC Agent envelopes.\n//\n// An MCP client calls tools on an MCP server: { server, name, arguments }.\n// This module stamps each invocation as an `agent-action` whose `content.hash`\n// is a SHA-256 of the canonicalized (server, name, arguments) tuple, scoped\n// as `mcp:invoke(server=<url>,tool=<name>)`. The server — or any counterparty\n// — verifies the action before trusting the call.\n//\n// The wrapper is transport-agnostic. Wire it into whatever MCP client you use\n// by calling `invokeWithStamp()` around the raw call.\n\nimport { sha256 } from '@noble/hashes/sha256';\nimport {\n canonicalize,\n computeActionId,\n hexEncode,\n isSubScope,\n parseScope,\n type DelegationEnvelope,\n} from '@orangecheck/agent-core';\nimport {\n signAsAgent,\n type ActionEnvelope,\n type SignerRef,\n} from '@orangecheck/agent-signer';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Canonicalization of an MCP invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface McpInvocation {\n /** Origin URL of the MCP server. Trimmed and lowercased for canonicalization. */\n server: string;\n /** Tool name (method) being invoked. */\n tool: string;\n /** JSON-serializable arguments. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Produce the canonical bytes for an MCP invocation. The bytes are what the\n * action envelope's `content.hash` is a SHA-256 of.\n *\n * Shape:\n * {\n * \"arguments\": <canonical JSON of args>,\n * \"server\": <server url>,\n * \"tool\": <tool name>\n * }\n *\n * The shape is intentionally minimal so verifiers can reconstruct it without\n * knowing anything server- or tool-specific.\n */\nexport function canonicalizeInvocation(inv: McpInvocation): Uint8Array {\n const canon = {\n arguments: inv.arguments,\n server: inv.server.trim(),\n tool: inv.tool,\n };\n const str = canonicalize(canon as unknown as Parameters<typeof canonicalize>[0]);\n return new TextEncoder().encode(str + '\\n');\n}\n\nexport function invocationHash(inv: McpInvocation): string {\n return 'sha256:' + hexEncode(sha256(canonicalizeInvocation(inv)));\n}\n\nexport function invocationId(\n agentAddress: string,\n signedAt: string,\n delegationId: string,\n scopeExercised: string,\n inv: McpInvocation\n): string {\n return computeActionId({\n address: agentAddress,\n content_hash: invocationHash(inv),\n content_length: canonicalizeInvocation(inv).byteLength,\n content_mime: 'application/vnd.oc-agent.mcp-invocation+json',\n signed_at: signedAt,\n delegation_id: delegationId,\n scope_exercised: scopeExercised,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stamped invocation\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface StampInvocationInput {\n agent: SignerRef;\n delegation: DelegationEnvelope;\n invocation: McpInvocation;\n /** Defaults to `mcp:invoke(server=<server>,tool=<tool>)` — the tightest admissible sub-scope. */\n scopeExercised?: string;\n signedAt?: Date;\n}\n\n/**\n * Stamp an MCP invocation without actually calling it. Useful when the caller\n * wants the signed envelope for out-of-band auditing before (or independent of)\n * running the tool.\n */\nexport async function stampInvocation(input: StampInvocationInput): Promise<ActionEnvelope> {\n const scopeExercised =\n input.scopeExercised ??\n `mcp:invoke(server=${input.invocation.server.trim()},tool=${input.invocation.tool})`;\n\n // Tiny pre-flight: confirm the exercised scope is a sub-scope of *some*\n // granted scope. This keeps a common integration mistake from producing\n // an envelope that later fails verifier-side.\n const granted = input.delegation.scopes.map(parseScope);\n const exercisedParsed = parseScope(scopeExercised);\n if (!granted.some((g) => isSubScope(exercisedParsed, g))) {\n throw new Error(\n `stampInvocation: scope_exercised (${scopeExercised}) is not a sub-scope of any granted scope`\n );\n }\n\n const bytes = canonicalizeInvocation(input.invocation);\n return signAsAgent({\n agent: input.agent,\n delegation: input.delegation,\n content: { hash: invocationHash(input.invocation), length: bytes.byteLength },\n mime: 'application/vnd.oc-agent.mcp-invocation+json',\n scopeExercised,\n signedAt: input.signedAt,\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// invokeWithStamp — call the tool AND produce the stamp around it\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface InvokeWithStampInput<T> extends StampInvocationInput {\n /** The underlying transport call. Returns whatever the MCP server returns. */\n call: (inv: McpInvocation) => Promise<T>;\n}\n\nexport interface InvokeWithStampResult<T> {\n result: T;\n action: ActionEnvelope;\n}\n\n/**\n * Stamp the invocation *first*, then execute the call. The stamped envelope\n * is returned alongside the result so the caller can ship them together.\n *\n * Rationale for stamping first: if the downstream call hangs or fails, we\n * still have an on-record commitment that this agent attempted this specific\n * invocation. The server-side verifier sees a stamped intent plus the server's\n * own transcript.\n */\nexport async function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promise<InvokeWithStampResult<T>> {\n const action = await stampInvocation(input);\n const result = await input.call(input.invocation);\n return { result, action };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Console integration — re-export from the shared client\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport {\n postActionToConsole,\n type ConsoleClient,\n type PostActionResult,\n} from '@orangecheck/agent-console-client';\n\nimport {\n postActionToConsole as _post,\n type ConsoleClient as _ConsoleClient,\n type PostActionResult as _PostActionResult,\n} from '@orangecheck/agent-console-client';\n\nexport interface InvokeWithStampAndPostInput<T> extends InvokeWithStampInput<T> {\n /** Console credentials. If absent, behaves like invokeWithStamp + posted: null. */\n console?: _ConsoleClient;\n}\n\nexport interface InvokeWithStampAndPostResult<T> extends InvokeWithStampResult<T> {\n /** Set when console is configured AND the POST succeeded. */\n posted: _PostActionResult | null;\n}\n\n/**\n * invokeWithStamp + post the stamped envelope to console.ochk.io. The\n * post happens AFTER the call so a failing post never prevents the\n * underlying MCP invocation from running. If `console` is omitted,\n * this is identical to invokeWithStamp + posted: null.\n */\nexport async function invokeWithStampAndPost<T>(\n input: InvokeWithStampAndPostInput<T>\n): Promise<InvokeWithStampAndPostResult<T>> {\n const { result, action } = await invokeWithStamp(input);\n let posted: _PostActionResult | null = null;\n if (input.console) {\n try {\n posted = await _post(action, input.console);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[oc-agent-mcp] postActionToConsole failed:', err);\n }\n }\n return { result, action, posted };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,62 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"files": [
|
|
37
|
-
"dist",
|
|
38
|
-
"src",
|
|
39
|
-
"README.md",
|
|
40
|
-
"LICENSE"
|
|
41
|
-
],
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsup",
|
|
44
|
-
"dev": "tsup --watch",
|
|
45
|
-
"type-check": "tsc --noEmit",
|
|
46
|
-
"test": "vitest run",
|
|
47
|
-
"test:watch": "vitest",
|
|
48
|
-
"clean": "rm -rf dist",
|
|
49
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"@noble/hashes": "^1.5.0",
|
|
53
|
-
"@orangecheck/agent-core": "^0.1.0",
|
|
54
|
-
"@orangecheck/agent-signer": "^0.1.0"
|
|
55
|
-
},
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"@types/node": "^22.10.2",
|
|
58
|
-
"tsup": "^8.3.5",
|
|
59
|
-
"typescript": "^5.7.2",
|
|
60
|
-
"vitest": "^3.2.4"
|
|
2
|
+
"name": "@orangecheck/agent-mcp",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Wrap Model Context Protocol tool invocations in OC Agent envelopes — every call produces a signed, scope-constrained, verifiable agent-action stamp.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bitcoin",
|
|
7
|
+
"agent",
|
|
8
|
+
"authority",
|
|
9
|
+
"mcp",
|
|
10
|
+
"model-context-protocol",
|
|
11
|
+
"bip322",
|
|
12
|
+
"oc-agent",
|
|
13
|
+
"orangecheck"
|
|
14
|
+
],
|
|
15
|
+
"author": "OrangeCheck",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/orangecheck/oc-packages.git",
|
|
20
|
+
"directory": "agent-mcp"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/orangecheck/oc-agent-protocol",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/orangecheck/oc-agent-protocol/issues"
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"module": "./dist/index.mjs",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.mjs",
|
|
33
|
+
"require": "./dist/index.js"
|
|
61
34
|
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"type-check": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"clean": "rm -rf dist",
|
|
49
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@noble/hashes": "^1.5.0",
|
|
53
|
+
"@orangecheck/agent-console-client": "0.1.0",
|
|
54
|
+
"@orangecheck/agent-core": "^0.1.0",
|
|
55
|
+
"@orangecheck/agent-signer": "^0.1.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^22.10.2",
|
|
59
|
+
"tsup": "^8.3.5",
|
|
60
|
+
"typescript": "^5.7.2",
|
|
61
|
+
"vitest": "^3.2.4"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
62
66
|
}
|
package/src/index.ts
CHANGED
|
@@ -156,3 +156,51 @@ export async function invokeWithStamp<T>(input: InvokeWithStampInput<T>): Promis
|
|
|
156
156
|
const result = await input.call(input.invocation);
|
|
157
157
|
return { result, action };
|
|
158
158
|
}
|
|
159
|
+
|
|
160
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
161
|
+
// Console integration — re-export from the shared client
|
|
162
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
postActionToConsole,
|
|
166
|
+
type ConsoleClient,
|
|
167
|
+
type PostActionResult,
|
|
168
|
+
} from '@orangecheck/agent-console-client';
|
|
169
|
+
|
|
170
|
+
import {
|
|
171
|
+
postActionToConsole as _post,
|
|
172
|
+
type ConsoleClient as _ConsoleClient,
|
|
173
|
+
type PostActionResult as _PostActionResult,
|
|
174
|
+
} from '@orangecheck/agent-console-client';
|
|
175
|
+
|
|
176
|
+
export interface InvokeWithStampAndPostInput<T> extends InvokeWithStampInput<T> {
|
|
177
|
+
/** Console credentials. If absent, behaves like invokeWithStamp + posted: null. */
|
|
178
|
+
console?: _ConsoleClient;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface InvokeWithStampAndPostResult<T> extends InvokeWithStampResult<T> {
|
|
182
|
+
/** Set when console is configured AND the POST succeeded. */
|
|
183
|
+
posted: _PostActionResult | null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* invokeWithStamp + post the stamped envelope to console.ochk.io. The
|
|
188
|
+
* post happens AFTER the call so a failing post never prevents the
|
|
189
|
+
* underlying MCP invocation from running. If `console` is omitted,
|
|
190
|
+
* this is identical to invokeWithStamp + posted: null.
|
|
191
|
+
*/
|
|
192
|
+
export async function invokeWithStampAndPost<T>(
|
|
193
|
+
input: InvokeWithStampAndPostInput<T>
|
|
194
|
+
): Promise<InvokeWithStampAndPostResult<T>> {
|
|
195
|
+
const { result, action } = await invokeWithStamp(input);
|
|
196
|
+
let posted: _PostActionResult | null = null;
|
|
197
|
+
if (input.console) {
|
|
198
|
+
try {
|
|
199
|
+
posted = await _post(action, input.console);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
// eslint-disable-next-line no-console
|
|
202
|
+
console.error('[oc-agent-mcp] postActionToConsole failed:', err);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { result, action, posted };
|
|
206
|
+
}
|