@reclaimprotocol/agent 0.1.1-dev.1 → 0.1.2

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 (232) hide show
  1. package/README.md +1 -1
  2. package/lib/cdp/capture-engine.d.ts +66 -0
  3. package/lib/cdp/capture-engine.js +153 -0
  4. package/lib/cdp/capture.d.ts +9 -20
  5. package/lib/cdp/capture.js +14 -138
  6. package/lib/cdp/index.d.ts +3 -0
  7. package/lib/cdp/index.js +6 -0
  8. package/lib/cdp/launcher.js +4 -3
  9. package/lib/config/store.d.ts +7 -6
  10. package/lib/config/store.js +2 -2
  11. package/lib/consts.d.ts +68 -0
  12. package/lib/consts.js +134 -0
  13. package/lib/index.d.ts +2 -2
  14. package/lib/index.js +1 -1
  15. package/lib/logger.js +2 -1
  16. package/lib/mcp/api/operations.gen.d.ts +100 -48
  17. package/lib/mcp/api/operations.gen.js +1129 -194
  18. package/lib/mcp/api/to-zod.d.ts +24 -0
  19. package/lib/mcp/api/to-zod.js +94 -0
  20. package/lib/mcp/api/tools.js +1 -1
  21. package/lib/mcp/credentials/authenticate.d.ts +3 -0
  22. package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
  23. package/lib/mcp/credentials/build.d.ts +5 -0
  24. package/lib/mcp/credentials/build.js +18 -0
  25. package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
  26. package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
  27. package/lib/mcp/credentials/import.d.ts +2 -0
  28. package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
  29. package/lib/mcp/credentials/issue.d.ts +2 -0
  30. package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
  31. package/lib/mcp/credentials/keypair.d.ts +17 -0
  32. package/lib/mcp/credentials/keypair.js +48 -0
  33. package/lib/mcp/credentials/link.d.ts +3 -0
  34. package/lib/mcp/credentials/link.js +107 -0
  35. package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
  36. package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
  37. package/lib/mcp/credentials/owner-key.d.ts +23 -0
  38. package/lib/mcp/credentials/owner-key.js +58 -0
  39. package/lib/mcp/credentials/paths.d.ts +12 -0
  40. package/lib/mcp/credentials/paths.js +35 -0
  41. package/lib/mcp/credentials/poll.d.ts +27 -0
  42. package/lib/mcp/credentials/poll.js +61 -0
  43. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
  44. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
  45. package/lib/mcp/credentials/session-cache.d.ts +14 -0
  46. package/lib/mcp/credentials/session-cache.js +42 -0
  47. package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
  48. package/lib/mcp/credentials/status.js +76 -0
  49. package/lib/mcp/instructions.d.ts +1 -0
  50. package/lib/mcp/instructions.js +11 -0
  51. package/lib/mcp/register.d.ts +38 -0
  52. package/lib/mcp/register.js +80 -0
  53. package/lib/mcp/server.d.ts +2 -8
  54. package/lib/mcp/server.js +3 -33
  55. package/lib/mcp/start.js +17 -11
  56. package/lib/mcp/tools/agent/build.d.ts +5 -9
  57. package/lib/mcp/tools/agent/build.js +7 -24
  58. package/lib/mcp/tools/agent/index.d.ts +2 -0
  59. package/lib/mcp/tools/agent/index.js +3 -0
  60. package/lib/mcp/tools/agent/proof.js +3 -7
  61. package/lib/mcp/tools/agent/propose.js +13 -2
  62. package/lib/mcp/tools/agent/publish.js +172 -75
  63. package/lib/mcp/tools/agent/replay.js +0 -5
  64. package/lib/mcp/tools/analyze.d.ts +3 -0
  65. package/lib/mcp/tools/analyze.js +26 -0
  66. package/lib/mcp/tools/attach.d.ts +11 -0
  67. package/lib/mcp/tools/attach.js +72 -0
  68. package/lib/mcp/tools/authenticate/authenticate.js +107 -0
  69. package/lib/mcp/tools/authenticate/build.d.ts +15 -0
  70. package/lib/mcp/tools/authenticate/build.js +28 -0
  71. package/lib/mcp/tools/authenticate/decrypt-key.d.ts +19 -0
  72. package/lib/mcp/tools/authenticate/decrypt-key.js +46 -0
  73. package/lib/mcp/tools/authenticate/eth-key.d.ts +31 -0
  74. package/lib/mcp/tools/authenticate/eth-key.js +116 -0
  75. package/lib/mcp/tools/authenticate/import.js +57 -0
  76. package/lib/mcp/tools/authenticate/index.d.ts +2 -0
  77. package/lib/mcp/tools/authenticate/index.js +4 -0
  78. package/lib/mcp/tools/authenticate/issue.js +42 -0
  79. package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
  80. package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
  81. package/lib/mcp/tools/capture.d.ts +10 -0
  82. package/lib/mcp/tools/capture.js +142 -0
  83. package/lib/mcp/tools/eval.d.ts +5 -0
  84. package/lib/mcp/tools/eval.js +127 -0
  85. package/lib/mcp/tools/find.d.ts +3 -0
  86. package/lib/mcp/tools/find.js +60 -0
  87. package/lib/mcp/tools/index.d.ts +3 -0
  88. package/lib/mcp/tools/index.js +6 -0
  89. package/lib/mcp/tools/owner-key.d.ts +2 -0
  90. package/lib/mcp/tools/owner-key.js +63 -0
  91. package/lib/mcp/tools/proof.d.ts +3 -0
  92. package/lib/mcp/tools/proof.js +214 -0
  93. package/lib/mcp/tools/propose.d.ts +9 -0
  94. package/lib/mcp/tools/propose.js +75 -0
  95. package/lib/mcp/tools/publish.d.ts +3 -0
  96. package/lib/mcp/tools/publish.js +59 -0
  97. package/lib/mcp/tools/replay.d.ts +3 -0
  98. package/lib/mcp/tools/replay.js +46 -0
  99. package/lib/mcp/tools/session.d.ts +10 -0
  100. package/lib/mcp/tools/session.js +29 -0
  101. package/lib/mcp/tools/verification/build.d.ts +12 -0
  102. package/lib/mcp/tools/verification/build.js +14 -0
  103. package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
  104. package/lib/mcp/tools/verification/diagnose.js +132 -0
  105. package/lib/mcp/tools/verification/index.d.ts +1 -0
  106. package/lib/mcp/tools/verification/index.js +2 -0
  107. package/lib/mcp/tools/verification/result.d.ts +11 -0
  108. package/lib/mcp/tools/verification/result.js +126 -0
  109. package/lib/mcp/verifications/build.d.ts +5 -0
  110. package/lib/mcp/verifications/build.js +14 -0
  111. package/lib/mcp/verifications/create.d.ts +3 -0
  112. package/lib/mcp/verifications/create.js +57 -0
  113. package/lib/mcp/verifications/find.d.ts +3 -0
  114. package/lib/mcp/verifications/find.js +37 -0
  115. package/lib/mcp/verifications/get.d.ts +3 -0
  116. package/lib/mcp/verifications/get.js +26 -0
  117. package/lib/mcp/verifications/update.d.ts +3 -0
  118. package/lib/mcp/verifications/update.js +78 -0
  119. package/lib/old/client.d.ts +3 -0
  120. package/lib/old/flag.d.ts +4 -1
  121. package/lib/old/flag.js +4 -3
  122. package/lib/old/identity.d.ts +0 -10
  123. package/lib/old/identity.js +8 -7
  124. package/lib/old/instructions.d.ts +0 -6
  125. package/lib/old/instructions.js +6 -24
  126. package/lib/old/login-cdp.d.ts +0 -3
  127. package/lib/old/login-cdp.js +2 -4
  128. package/lib/old/to-register.d.ts +3 -0
  129. package/lib/old/to-register.js +32 -7
  130. package/lib/old/tools/authenticate.js +2 -1
  131. package/lib/old/tools/publish.js +71 -10
  132. package/lib/paths.js +2 -2
  133. package/lib/proof/attestor.d.ts +33 -1
  134. package/lib/proof/attestor.js +67 -64
  135. package/lib/proof/index.d.ts +5 -0
  136. package/lib/proof/index.js +6 -0
  137. package/lib/proof/proof-core.d.ts +35 -0
  138. package/lib/proof/proof-core.js +84 -0
  139. package/lib/provider/index.d.ts +5 -0
  140. package/lib/provider/index.js +9 -0
  141. package/lib/provider/injection-doc.d.ts +1 -0
  142. package/lib/provider/injection-doc.js +17 -0
  143. package/lib/provider/match-redaction-warning.d.ts +25 -0
  144. package/lib/provider/match-redaction-warning.js +35 -0
  145. package/lib/provider/schema.d.ts +16 -0
  146. package/lib/provider/schema.js +11 -1
  147. package/lib/provider/to-version.d.ts +61 -12
  148. package/lib/provider/to-version.js +109 -24
  149. package/lib/provider/verification-checks.d.ts +12 -0
  150. package/lib/provider/verification-checks.js +30 -0
  151. package/lib/routes.gen.d.ts +271 -0
  152. package/lib/routes.gen.js +73 -0
  153. package/lib/types/openapi.gen.d.ts +3967 -0
  154. package/lib/types/openapi.gen.js +5 -0
  155. package/package.json +16 -7
  156. package/skill/SKILL.md +35 -14
  157. package/skill/builder-mode.md +13 -0
  158. package/skill/injection-api.md +42 -0
  159. package/skill/old-mode.md +15 -0
  160. package/src/cdp/capture-engine.ts +256 -0
  161. package/src/cdp/capture.ts +25 -185
  162. package/src/cdp/index.ts +6 -0
  163. package/src/cdp/launcher.ts +5 -4
  164. package/src/config/store.ts +7 -6
  165. package/src/consts.ts +164 -0
  166. package/src/index.ts +2 -4
  167. package/src/logger.ts +2 -1
  168. package/src/mcp/api/operations.gen.ts +1155 -194
  169. package/src/mcp/api/to-zod.ts +115 -0
  170. package/src/mcp/api/tools.ts +9 -3
  171. package/src/mcp/instructions.ts +15 -0
  172. package/src/mcp/server.ts +5 -50
  173. package/src/mcp/start.ts +27 -11
  174. package/src/mcp/tools/agent/build.ts +7 -27
  175. package/src/mcp/tools/agent/index.ts +4 -0
  176. package/src/mcp/tools/agent/proof.ts +3 -8
  177. package/src/mcp/tools/agent/propose.ts +13 -2
  178. package/src/mcp/tools/agent/publish.ts +218 -92
  179. package/src/mcp/tools/agent/replay.ts +0 -5
  180. package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
  181. package/src/mcp/tools/authenticate/build.ts +32 -0
  182. package/src/mcp/tools/authenticate/decrypt-key.ts +59 -0
  183. package/src/mcp/tools/authenticate/eth-key.ts +162 -0
  184. package/src/mcp/tools/authenticate/import.ts +73 -0
  185. package/src/mcp/tools/authenticate/index.ts +4 -0
  186. package/src/mcp/tools/authenticate/issue.ts +50 -0
  187. package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
  188. package/src/mcp/tools/index.ts +6 -0
  189. package/src/mcp/tools/verification/build.ts +16 -0
  190. package/src/mcp/tools/verification/index.ts +2 -0
  191. package/src/mcp/tools/verification/result.ts +154 -0
  192. package/src/old/client.ts +3 -0
  193. package/src/old/flag.ts +4 -3
  194. package/src/old/identity.ts +8 -7
  195. package/src/old/instructions.ts +10 -25
  196. package/src/old/login-cdp.ts +2 -5
  197. package/src/old/to-register.ts +58 -26
  198. package/src/old/tools/authenticate.ts +2 -1
  199. package/src/old/tools/publish.ts +92 -16
  200. package/src/paths.ts +2 -2
  201. package/src/proof/attestor.ts +114 -72
  202. package/src/proof/index.ts +21 -0
  203. package/src/proof/proof-core.ts +119 -0
  204. package/src/provider/index.ts +20 -0
  205. package/src/provider/injection-doc.ts +21 -0
  206. package/src/provider/match-redaction-warning.ts +53 -0
  207. package/src/provider/schema.ts +23 -0
  208. package/src/provider/to-version.ts +180 -33
  209. package/src/provider/verification-checks.ts +36 -0
  210. package/lib/mcp/tools/credentials/build.d.ts +0 -16
  211. package/lib/mcp/tools/credentials/build.js +0 -33
  212. package/lib/mcp/tools/credentials/status.js +0 -62
  213. package/src/mcp/tools/credentials/build.ts +0 -37
  214. package/src/mcp/tools/credentials/cache.ts +0 -161
  215. package/src/mcp/tools/credentials/env-file.ts +0 -101
  216. package/src/mcp/tools/credentials/import.ts +0 -72
  217. package/src/mcp/tools/credentials/issue.ts +0 -107
  218. package/src/mcp/tools/credentials/list-cached.ts +0 -66
  219. package/src/mcp/tools/credentials/register.ts +0 -49
  220. package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
  221. package/src/mcp/tools/credentials/status.ts +0 -82
  222. package/src/types/openapi.ts +0 -7
  223. /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
  224. /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
  225. /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
  226. /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
  227. /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
  228. /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
  229. /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
  230. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
  231. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
  232. /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
@@ -0,0 +1,46 @@
1
+ import { replayProvider } from "../../proof/replay.js";
2
+ import { defineTool } from "../server.js";
3
+ export function replayTool(secrets) {
4
+ return defineTool({
5
+ name: 'replay_request',
6
+ description: 'Replay a drafted provider against the live endpoint ' +
7
+ 'using Node fetch (no attestor). ' +
8
+ 'Pre-flight gate before run_proof — ' +
9
+ 'diagnoses CSRF / token-rotation / matcher-too-tight ' +
10
+ 'issues with richer hints than the attestor would produce.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ // `type: 'object'` is required so MCP clients (the LLM)
15
+ // serialize the value as an object, not a JSON-stringified
16
+ // string. `properties: {}` is required so zod-from-json-schema
17
+ // compiles to a passthrough instead of strict-strip — leaving
18
+ // it off makes the server receive `{}`.
19
+ provider: { type: 'object', properties: {} },
20
+ secretParamsRef: { type: 'string' },
21
+ },
22
+ required: ['provider'],
23
+ },
24
+ }, async ({ provider, secretParamsRef }) => {
25
+ let resolved = {};
26
+ if (secretParamsRef !== undefined) {
27
+ const r = secrets.resolve(secretParamsRef);
28
+ if (!r) {
29
+ throw new Error(`unknown secretParamsRef "${secretParamsRef}" — ` +
30
+ 'the MCP server has restarted or reset_session was called. ' +
31
+ 'Re-run propose_provider to mint a fresh ref.');
32
+ }
33
+ resolved = r;
34
+ }
35
+ const result = await replayProvider(provider, resolved);
36
+ const out = {
37
+ status: result.status,
38
+ matchesOriginal: result.matchesOriginal,
39
+ bodySnippet: result.body.slice(0, 256),
40
+ };
41
+ if (result.hints !== undefined) {
42
+ out.hints = result.hints;
43
+ }
44
+ return out;
45
+ });
46
+ }
@@ -0,0 +1,10 @@
1
+ import type { ConfigStore } from '../../config/store.ts';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ import type { AttachState } from './attach.ts';
4
+ import type { CaptureStore } from './capture.ts';
5
+ export declare function sessionTools(attachRef: {
6
+ current?: AttachState;
7
+ config: ConfigStore;
8
+ }, captures: CaptureStore, secrets: {
9
+ clear: () => void;
10
+ }): RegisteredTool[];
@@ -0,0 +1,29 @@
1
+ import { defineTool } from "../server.js";
2
+ export function sessionTools(attachRef, captures, secrets) {
3
+ return [
4
+ defineTool({
5
+ name: 'get_session',
6
+ description: 'Return current attach state, active captures, and persisted config.',
7
+ inputSchema: { type: 'object', properties: {} },
8
+ }, async () => ({
9
+ config: attachRef.config.read(),
10
+ attached: Boolean(attachRef.current),
11
+ port: attachRef.current?.port,
12
+ captures: [...captures.sessions.keys()],
13
+ activeTab: captures.activeTab,
14
+ })),
15
+ defineTool({
16
+ name: 'reset_session',
17
+ description: 'Stop all captures, drop in-memory secrets, and clear capture state.',
18
+ inputSchema: { type: 'object', properties: {} },
19
+ }, async () => {
20
+ for (const s of captures.sessions.values()) {
21
+ await s.stop().catch(() => { });
22
+ }
23
+ captures.sessions.clear();
24
+ delete captures.activeTab;
25
+ secrets.clear();
26
+ return { reset: true };
27
+ }),
28
+ ];
29
+ }
@@ -0,0 +1,12 @@
1
+ import type { RegisteredTool } from '../../server.ts';
2
+ /**
3
+ * Builder-mode verification tools: higher-level orchestrations over the
4
+ * generated API surface. `get_verification_result` authenticates with the org
5
+ * token, checks status, pulls the stored payload, and decrypts it locally with
6
+ * the optional eth key — a flow the generated raw-API tools can't express
7
+ * (the decryption key never leaves the consumer). Diagnosis is left to the
8
+ * agent over the generated tools (`get_verification_session`,
9
+ * `list_verification_events`, `list_verification_deliveries`), whose
10
+ * descriptions carry the lifecycle and delivery semantics.
11
+ */
12
+ export declare function buildVerificationTools(): RegisteredTool[];
@@ -0,0 +1,14 @@
1
+ import { verificationResultTool } from "./result.js";
2
+ /**
3
+ * Builder-mode verification tools: higher-level orchestrations over the
4
+ * generated API surface. `get_verification_result` authenticates with the org
5
+ * token, checks status, pulls the stored payload, and decrypts it locally with
6
+ * the optional eth key — a flow the generated raw-API tools can't express
7
+ * (the decryption key never leaves the consumer). Diagnosis is left to the
8
+ * agent over the generated tools (`get_verification_session`,
9
+ * `list_verification_events`, `list_verification_deliveries`), whose
10
+ * descriptions carry the lifecycle and delivery semantics.
11
+ */
12
+ export function buildVerificationTools() {
13
+ return [verificationResultTool()];
14
+ }
@@ -0,0 +1,11 @@
1
+ import { type ReclaimClient } from '@reclaimprotocol/client';
2
+ import { type RegisteredTool } from '../../server.ts';
3
+ /**
4
+ * `diagnose_verification_session` — one call that answers "what's wrong
5
+ * with this session?". Pulls the session, its full event log, and its
6
+ * callback-delivery diagnostics, then derives findings (where the flow
7
+ * stalled or failed) and concrete suggestions (what to check or do next).
8
+ * Read-only; authenticates with the active eth credential like
9
+ * `get_verification_result`.
10
+ */
11
+ export declare function verificationDiagnoseTool(client: ReclaimClient): RegisteredTool;
@@ -0,0 +1,132 @@
1
+ import { buildAuthHeaders } from '@reclaimprotocol/client';
2
+ import { defineTool } from "../../server.js";
3
+ import { resolveActivePrivateKey } from "./result.js";
4
+ const TERMINAL = new Set(['success', 'rejected', 'error']);
5
+ /**
6
+ * `diagnose_verification_session` — one call that answers "what's wrong
7
+ * with this session?". Pulls the session, its full event log, and its
8
+ * callback-delivery diagnostics, then derives findings (where the flow
9
+ * stalled or failed) and concrete suggestions (what to check or do next).
10
+ * Read-only; authenticates with the active eth credential like
11
+ * `get_verification_result`.
12
+ */
13
+ export function verificationDiagnoseTool(client) {
14
+ return defineTool({
15
+ name: 'diagnose_verification_session',
16
+ description: 'Diagnose a verification session: fetches its status, event ' +
17
+ 'timeline, and callback-delivery state, then reports findings ' +
18
+ '(where the flow stalled or failed — link never opened, proof ' +
19
+ 'failed, callback endpoint erroring, dead-lettered delivery, ' +
20
+ 'expiry) and suggested next steps. Read-only. Use ' +
21
+ 'get_verification_result to fetch and decrypt the actual result.',
22
+ inputSchema: {
23
+ type: 'object',
24
+ required: ['sessionId'],
25
+ properties: {
26
+ sessionId: {
27
+ type: 'string',
28
+ description: 'The verification session id to diagnose.',
29
+ },
30
+ },
31
+ },
32
+ }, async (args) => {
33
+ const privateKey = resolveActivePrivateKey();
34
+ const auth = () => buildAuthHeaders(privateKey, 'VerificationAuth');
35
+ const params = { sessionId: args.sessionId };
36
+ const [session, events, deliveries] = await Promise.all([
37
+ client.call('GetVerificationSession', { params, headers: auth() })
38
+ .then((r) => r.data),
39
+ client.call('ListVerificationEvents', { params, headers: auth() })
40
+ .then((r) => r.data.items),
41
+ client.call('ListVerificationDeliveries', { params, headers: auth() })
42
+ .then((r) => r.data.items),
43
+ ]);
44
+ const seen = new Set(events.map((e) => e.event));
45
+ const last = events[events.length - 1];
46
+ const findings = [];
47
+ const suggestions = [];
48
+ // Where did the flow get to?
49
+ if (session.status === 'pending') {
50
+ if (new Date(session.expiresAt).getTime() < Date.now()) {
51
+ findings.push('Session is past expiresAt — it will flip to expired on the ' +
52
+ 'next sweep; the end-user can no longer complete it.');
53
+ suggestions.push('Create a new session and share a fresh link.');
54
+ }
55
+ else if (!seen.has('verification_client_opened')) {
56
+ findings.push('The end-user has not opened the verification link yet.');
57
+ suggestions.push(`Re-share the link (${session.verificationUrl}) before ` +
58
+ `it expires at ${session.expiresAt}.`);
59
+ }
60
+ else if (!seen.has('request_matched')) {
61
+ findings.push('The page was opened but the target request was never ' +
62
+ 'captured — the end-user likely has not completed the ' +
63
+ 'login/journey on the provider site.');
64
+ }
65
+ else {
66
+ findings.push('Proof flow is in progress — the target request was ' +
67
+ 'captured and the run has not reached a terminal event.');
68
+ }
69
+ }
70
+ if (session.status === 'expired') {
71
+ findings.push(seen.has('verification_client_opened')
72
+ ? 'Session expired mid-flow — the end-user started but did ' +
73
+ 'not finish before expiresAt.'
74
+ : 'Session expired without the link ever being opened.');
75
+ suggestions.push('Create a new session and share a fresh link.');
76
+ }
77
+ // Surface failure detail from the event log.
78
+ for (const e of events) {
79
+ if (e.event === 'request_claim_failed' ||
80
+ e.event === 'request_claim_rejected' ||
81
+ e.event === 'verification_error' ||
82
+ e.event === 'verification_rejected') {
83
+ findings.push(`${e.event} at ${e.createdAt}` +
84
+ (e.eventData ? `: ${JSON.stringify(e.eventData)}` : ''));
85
+ }
86
+ }
87
+ // Callback delivery health (only meaningful after a terminal event).
88
+ for (const d of deliveries) {
89
+ if (d.deliveryStatus === 'delivered') {
90
+ continue;
91
+ }
92
+ findings.push(`Callback to ${d.callbackUrl} is ${d.deliveryStatus} after ` +
93
+ `${d.attempts} attempt(s)` +
94
+ (d.lastError ? ` — last error: ${d.lastError}` : '') +
95
+ (d.deadLettered ? ' (dead-lettered; retries exhausted)' : ''));
96
+ suggestions.push(`Check that ${d.callbackUrl} is reachable and answers 2xx.`);
97
+ if (d.deadLettered) {
98
+ suggestions.push('Once the endpoint is fixed, re-deliver via ' +
99
+ 'POST /verifications/sessions/{sessionId}/retry-callback ' +
100
+ '(or ask an admin to retry it from the Callback DLQ).');
101
+ }
102
+ }
103
+ if (TERMINAL.has(session.status) &&
104
+ deliveries.every((d) => d.deliveryStatus === 'delivered')) {
105
+ suggestions.push('Result delivered. Use get_verification_result to fetch and ' +
106
+ 'decrypt it locally.');
107
+ }
108
+ if (!findings.length) {
109
+ findings.push('No problems detected.');
110
+ }
111
+ return {
112
+ sessionId: session.id,
113
+ status: session.status,
114
+ callbackDeliveryStatus: session.callbackDeliveryStatus,
115
+ mode: session.mode,
116
+ createdAt: session.createdAt,
117
+ expiresAt: session.expiresAt,
118
+ completedAt: session.completedAt,
119
+ lastEvent: last
120
+ ? { event: last.event, at: last.createdAt }
121
+ : undefined,
122
+ events: events.map((e) => ({
123
+ event: e.event,
124
+ at: e.createdAt,
125
+ ...(e.eventData ? { data: e.eventData } : {}),
126
+ })),
127
+ deliveries,
128
+ findings,
129
+ suggestions,
130
+ };
131
+ });
132
+ }
@@ -0,0 +1 @@
1
+ export { buildVerificationTools } from './build.ts';
@@ -0,0 +1,2 @@
1
+ // Barrel for the verification tool group (result retrieval + decryption).
2
+ export { buildVerificationTools } from "./build.js";
@@ -0,0 +1,11 @@
1
+ import { type RegisteredTool } from '../../server.ts';
2
+ /**
3
+ * `get_verification_result` — check a session's status and, once a result has
4
+ * been submitted, pull the stored payload(s) and verify locally. Auth is the
5
+ * org token; delivery is org-scoped. Each stored payload is either the
6
+ * plaintext signed JWS (when the org's encryption is off) or an ECIES
7
+ * ciphertext that we decrypt here with the optional eth key
8
+ * (`RECLAIM_DECRYPT_KEY` or the `reclaim-decrypt.key` hex file). The Builder
9
+ * only ever relays the payload — decryption, when needed, happens here.
10
+ */
11
+ export declare function verificationResultTool(): RegisteredTool;
@@ -0,0 +1,126 @@
1
+ import { createReclaim, decryptCallback, verifyResultFull, } from '@reclaimprotocol/client';
2
+ import assert from 'node:assert';
3
+ import { apiUrl, orgSecret } from "../../../consts.js";
4
+ import { defineTool } from "../../server.js";
5
+ import { resolveDecryptionKey } from "../authenticate/decrypt-key.js";
6
+ /** Statuses that can carry a submitted (terminal) result. `expired`/`pending`
7
+ * never have one. */
8
+ const TERMINAL = new Set(['success', 'rejected', 'error']);
9
+ /**
10
+ * Resolve the org secret used to authenticate verification reads. Auth is a
11
+ * single per-org bearer secret (`rorg_…`), not an eth signature — read it from
12
+ * `RECLAIM_ORG_SECRET`.
13
+ */
14
+ function resolveOrgSecret() {
15
+ const secret = orgSecret()?.trim();
16
+ assert(secret, new Error('RECLAIM_ORG_SECRET is not set. Verification reads authenticate with ' +
17
+ 'the org secret (rorg_…) — issue one from the dashboard ' +
18
+ '(POST /orgs/{orgId}/token) and export it as RECLAIM_ORG_SECRET.'));
19
+ return secret;
20
+ }
21
+ /**
22
+ * `get_verification_result` — check a session's status and, once a result has
23
+ * been submitted, pull the stored payload(s) and verify locally. Auth is the
24
+ * org token; delivery is org-scoped. Each stored payload is either the
25
+ * plaintext signed JWS (when the org's encryption is off) or an ECIES
26
+ * ciphertext that we decrypt here with the optional eth key
27
+ * (`RECLAIM_DECRYPT_KEY` or the `reclaim-decrypt.key` hex file). The Builder
28
+ * only ever relays the payload — decryption, when needed, happens here.
29
+ */
30
+ export function verificationResultTool() {
31
+ return defineTool({
32
+ name: 'get_verification_result',
33
+ description: 'Check a verification session and return its result when ready. ' +
34
+ 'Authenticates with the org secret (RECLAIM_ORG_SECRET). Fetches the ' +
35
+ 'session status; if it is terminal and a result has been submitted, ' +
36
+ 'pulls the stored result(s) and verifies them locally. Encrypted ' +
37
+ 'deliveries (ECIES over secp256k1) are decrypted with your optional ' +
38
+ 'eth key (RECLAIM_DECRYPT_KEY or reclaim-decrypt.key); plaintext ' +
39
+ 'deliveries are read directly. Returns ' +
40
+ '`ready: false` while the session is still pending or no result has ' +
41
+ 'been delivered yet. Use list_verification_events for the full ' +
42
+ 'lifecycle log.',
43
+ inputSchema: {
44
+ type: 'object',
45
+ required: ['sessionId'],
46
+ properties: {
47
+ sessionId: {
48
+ type: 'string',
49
+ description: 'The verification session id from create_verification_session.',
50
+ },
51
+ },
52
+ },
53
+ }, async (args) => {
54
+ const secret = resolveOrgSecret();
55
+ // Optional eth decryption key — absent ⇒ plaintext-only.
56
+ const decryptionKey = await resolveDecryptionKey();
57
+ const reclaim = createReclaim({
58
+ baseUrl: apiUrl(),
59
+ orgSecret: secret,
60
+ });
61
+ const sessionRes = await reclaim.api('GetVerificationSession', {
62
+ params: { sessionId: args.sessionId },
63
+ });
64
+ const status = sessionRes.data.status;
65
+ if (!TERMINAL.has(status)) {
66
+ return { sessionId: args.sessionId, status, ready: false };
67
+ }
68
+ const resultRes = await reclaim.api('GetVerificationResult', {
69
+ params: { sessionId: args.sessionId },
70
+ });
71
+ const { items } = resultRes.data;
72
+ if (!items.length) {
73
+ return {
74
+ sessionId: args.sessionId,
75
+ status,
76
+ ready: false,
77
+ note: 'Session is terminal but no result has been submitted yet.',
78
+ };
79
+ }
80
+ // Each item's `payload` is a compact JWE (encrypted to the org's
81
+ // credential) or the plaintext signed JWS, as raw text. `decryptCallback`
82
+ // branches on the body shape; an encrypted delivery with no key throws
83
+ // a clear error, which we surface per-subscription rather than skip.
84
+ const results = [];
85
+ const undecryptable = [];
86
+ for (const item of items) {
87
+ let jws;
88
+ try {
89
+ jws = await decryptCallback(decryptionKey, item.payload);
90
+ }
91
+ catch (err) {
92
+ undecryptable.push(item.subscriptionId);
93
+ void err;
94
+ continue;
95
+ }
96
+ const outcome = await verifyResultFull(jws, {
97
+ expectedReclaimSessionId: args.sessionId,
98
+ });
99
+ results.push({
100
+ subscriptionId: item.subscriptionId,
101
+ valid: outcome.valid,
102
+ reason: outcome.reason,
103
+ payload: outcome.payload,
104
+ proofs: outcome.proofs,
105
+ });
106
+ }
107
+ if (!results.length) {
108
+ return {
109
+ sessionId: args.sessionId,
110
+ status,
111
+ ready: false,
112
+ note: 'A result was stored, but no payload could be read — it is ' +
113
+ 'corrupt, or encrypted (ECIES) to a key this consumer does not ' +
114
+ 'hold. Set RECLAIM_DECRYPT_KEY (or reclaim-decrypt.key) to the ' +
115
+ 'eth private key matching the org keypair.',
116
+ };
117
+ }
118
+ return {
119
+ sessionId: args.sessionId,
120
+ status,
121
+ ready: true,
122
+ results,
123
+ ...(undecryptable.length ? { undecryptable } : {}),
124
+ };
125
+ });
126
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReclaimClient } from '@reclaimprotocol/client';
2
+ import type { RegisteredTool } from '../server.ts';
3
+ /** Verification CRUD tools — build the flat list of RegisteredTool
4
+ * entries. Mirrors buildAgentTools() in mcp/register.ts. */
5
+ export declare function buildVerificationTools(client: ReclaimClient): RegisteredTool[];
@@ -0,0 +1,14 @@
1
+ import { createTool } from "./create.js";
2
+ import { findTool } from "./find.js";
3
+ import { getTool } from "./get.js";
4
+ import { updateTool } from "./update.js";
5
+ /** Verification CRUD tools — build the flat list of RegisteredTool
6
+ * entries. Mirrors buildAgentTools() in mcp/register.ts. */
7
+ export function buildVerificationTools(client) {
8
+ return [
9
+ findTool(client),
10
+ getTool(client),
11
+ createTool(client),
12
+ updateTool(client),
13
+ ];
14
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReclaimClient } from '@reclaimprotocol/client';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ export declare function createTool(client: ReclaimClient): RegisteredTool;
@@ -0,0 +1,57 @@
1
+ import { defineTool } from "../server.js";
2
+ export function createTool(client) {
3
+ return defineTool({
4
+ name: 'create_verification',
5
+ description: 'Create a new Reclaim verification. Use this only ' +
6
+ 'after `find_verification` returned nothing useful ' +
7
+ 'for the domain. The caller must be an active ' +
8
+ 'member of the target organization.',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ orgId: {
13
+ type: 'string',
14
+ description: 'uuid identifier of the organization ' +
15
+ 'that will own the verification.'
16
+ },
17
+ domain: {
18
+ type: 'string',
19
+ minLength: 1,
20
+ maxLength: 200,
21
+ description: 'Canonical root domain (e.g. `github.com`). ' +
22
+ 'No scheme, no port, no path.',
23
+ },
24
+ slug: {
25
+ type: 'string',
26
+ pattern: '^[a-z0-9]+(?:-[a-z0-9]+)*$',
27
+ minLength: 1,
28
+ maxLength: 100,
29
+ description: 'URL-safe identifier. Globally unique — pick ' +
30
+ 'something domain-specific like `github-followers`.',
31
+ },
32
+ title: {
33
+ type: 'string',
34
+ minLength: 1,
35
+ maxLength: 100,
36
+ description: 'Short headline shown to end-users. Defaults ' +
37
+ 'to a domain-derived brand name.',
38
+ },
39
+ description: { type: 'string', minLength: 1, maxLength: 2000 },
40
+ iconUrl: { type: 'string', description: 'uri of the icon' },
41
+ tags: { type: 'array', items: { type: 'string' }, maxItems: 50 },
42
+ },
43
+ required: ['orgId', 'domain', 'slug'],
44
+ },
45
+ }, async (args) => client.call('CreateProvider', {
46
+ body: {
47
+ orgId: args.orgId,
48
+ domain: args.domain,
49
+ slug: args.slug,
50
+ title: args.title,
51
+ description: args.description,
52
+ iconUrl: args.iconUrl,
53
+ tags: args.tags ?? [],
54
+ visibility: 'PRIVATE'
55
+ },
56
+ }));
57
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReclaimClient } from '@reclaimprotocol/client';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ export declare function findTool(client: ReclaimClient): RegisteredTool;
@@ -0,0 +1,37 @@
1
+ import { defineTool } from "../server.js";
2
+ export function findTool(client) {
3
+ return defineTool({
4
+ name: 'find_verification',
5
+ description: 'Search published Reclaim verifications by domain or ' +
6
+ 'data point. A verification is the recipe an end-user ' +
7
+ 'follows to prove something about themselves (e.g. ' +
8
+ '"I have N followers on Twitter"). Returns a list of ' +
9
+ 'matches. Call this BEFORE `create_verification` — ' +
10
+ 'most popular domains already have a public ' +
11
+ 'verification you can reuse.',
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ query: {
16
+ type: 'string',
17
+ minLength: 1,
18
+ maxLength: 200,
19
+ description: 'Free-text query. Matches domain (e.g. ' +
20
+ '"github.com"), title, description, and the ' +
21
+ 'data points a verification can prove.',
22
+ },
23
+ tags: {
24
+ type: 'array',
25
+ items: { type: 'string' },
26
+ description: 'Restrict to verifications carrying every tag.',
27
+ },
28
+ limit: { type: 'number', minimum: 1, maximum: 100 },
29
+ },
30
+ },
31
+ }, async (args) => client.call('Providers', {
32
+ query: {
33
+ q: args.query,
34
+ tag: args.tags ?? [],
35
+ },
36
+ }));
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReclaimClient } from '@reclaimprotocol/client';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ export declare function getTool(client: ReclaimClient): RegisteredTool;
@@ -0,0 +1,26 @@
1
+ import { defineTool } from "../server.js";
2
+ export function getTool(client) {
3
+ return defineTool({
4
+ name: 'get_verification',
5
+ description: 'Fetch a single Reclaim verification by id. Returns ' +
6
+ 'every field needed to integrate it into a flow: ' +
7
+ 'domain, the live version (initialUrl + requests), ' +
8
+ 'and the data points it can prove. Use ' +
9
+ '`find_verification` first if you only have a query ' +
10
+ 'string.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ providerId: {
15
+ type: 'string',
16
+ description: 'UUID of the verification. (Internally stored ' +
17
+ 'as `providerId` — the field name reflects ' +
18
+ 'the openapi schema.)',
19
+ },
20
+ },
21
+ required: ['providerId'],
22
+ },
23
+ }, async (args) => client.call('GetProvider', {
24
+ params: { providerId: args.providerId },
25
+ }));
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReclaimClient } from '@reclaimprotocol/client';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ export declare function updateTool(client: ReclaimClient): RegisteredTool;
@@ -0,0 +1,78 @@
1
+ import { defineTool } from "../server.js";
2
+ export function updateTool(client) {
3
+ return defineTool({
4
+ name: 'update_verification',
5
+ description: "Update a Reclaim verification's metadata. Partial " +
6
+ 'PATCH — pass only fields you want to change. The ' +
7
+ 'caller must be an active member of the owning ' +
8
+ "organization. To change the verification's " +
9
+ 'recipe (initialUrl, requests, …) cut a new ' +
10
+ 'version via the dashboard. Use `seo` to control how ' +
11
+ 'the verification appears in search results and social ' +
12
+ 'shares; omit a subfield to keep the server default.',
13
+ inputSchema: {
14
+ type: 'object',
15
+ properties: {
16
+ providerId: {
17
+ type: 'string',
18
+ description: 'UUID of the verification. (Internally stored ' +
19
+ 'as `providerId` — the field name reflects ' +
20
+ 'the openapi schema.)',
21
+ },
22
+ title: { type: 'string', minLength: 1, maxLength: 100 },
23
+ description: { type: 'string', minLength: 1, maxLength: 2000 },
24
+ iconUrl: { type: 'string', description: 'uri of icon' },
25
+ clearIcon: {
26
+ type: 'boolean',
27
+ description: 'Set true to wipe the icon explicitly.',
28
+ },
29
+ visibility: { type: 'string', enum: ['PRIVATE', 'PUBLIC'] },
30
+ status: { type: 'string', enum: ['ACTIVE', 'ARCHIVED'] },
31
+ tags: { type: 'array', items: { type: 'string' }, maxItems: 50 },
32
+ seo: {
33
+ type: 'object',
34
+ additionalProperties: false,
35
+ description: 'Author SEO overrides. Each field falls back to a ' +
36
+ 'server-derived suggestion when unset.',
37
+ properties: {
38
+ brandUrl: {
39
+ type: 'string',
40
+ maxLength: 2000,
41
+ description: 'Canonical homepage url of the brand.',
42
+ },
43
+ primaryDataPoint: {
44
+ type: 'string',
45
+ maxLength: 200,
46
+ description: 'Headline data point (e.g. "subscriber ' +
47
+ 'count"); used in the SEO title.',
48
+ },
49
+ dataPoints: {
50
+ type: 'array',
51
+ items: { type: 'string', maxLength: 200 },
52
+ maxItems: 50,
53
+ description: 'Full list of verifiable data points.',
54
+ },
55
+ titleOverride: {
56
+ type: 'string',
57
+ maxLength: 200,
58
+ description: 'Replaces the composed page title.',
59
+ },
60
+ descriptionOverride: {
61
+ type: 'string',
62
+ maxLength: 320,
63
+ description: 'Replaces the composed meta description.',
64
+ },
65
+ },
66
+ },
67
+ },
68
+ required: ['providerId'],
69
+ },
70
+ }, async (args) => {
71
+ const { providerId, ...rest } = args;
72
+ return client.call('UpdateProvider', {
73
+ params: { providerId },
74
+ headers: {},
75
+ body: rest,
76
+ });
77
+ });
78
+ }