@reclaimprotocol/agent 0.1.1-dev.1 → 0.1.1

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 (201) 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/config/store.d.ts +7 -6
  9. package/lib/config/store.js +2 -2
  10. package/lib/index.d.ts +2 -2
  11. package/lib/index.js +1 -1
  12. package/lib/mcp/api/operations.gen.d.ts +101 -45
  13. package/lib/mcp/api/operations.gen.js +996 -126
  14. package/lib/mcp/api/to-zod.d.ts +24 -0
  15. package/lib/mcp/api/to-zod.js +94 -0
  16. package/lib/mcp/api/tools.js +1 -1
  17. package/lib/mcp/credentials/authenticate.d.ts +3 -0
  18. package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
  19. package/lib/mcp/credentials/build.d.ts +5 -0
  20. package/lib/mcp/credentials/build.js +18 -0
  21. package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
  22. package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
  23. package/lib/mcp/credentials/import.d.ts +2 -0
  24. package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
  25. package/lib/mcp/credentials/issue.d.ts +2 -0
  26. package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
  27. package/lib/mcp/credentials/keypair.d.ts +17 -0
  28. package/lib/mcp/credentials/keypair.js +48 -0
  29. package/lib/mcp/credentials/link.d.ts +3 -0
  30. package/lib/mcp/credentials/link.js +107 -0
  31. package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
  32. package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
  33. package/lib/mcp/credentials/owner-key.d.ts +23 -0
  34. package/lib/mcp/credentials/owner-key.js +58 -0
  35. package/lib/mcp/credentials/paths.d.ts +12 -0
  36. package/lib/mcp/credentials/paths.js +35 -0
  37. package/lib/mcp/credentials/poll.d.ts +27 -0
  38. package/lib/mcp/credentials/poll.js +61 -0
  39. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
  40. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
  41. package/lib/mcp/credentials/session-cache.d.ts +14 -0
  42. package/lib/mcp/credentials/session-cache.js +42 -0
  43. package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
  44. package/lib/mcp/credentials/status.js +76 -0
  45. package/lib/mcp/instructions.d.ts +1 -0
  46. package/lib/mcp/instructions.js +11 -0
  47. package/lib/mcp/register.d.ts +38 -0
  48. package/lib/mcp/register.js +80 -0
  49. package/lib/mcp/server.d.ts +2 -2
  50. package/lib/mcp/server.js +3 -3
  51. package/lib/mcp/start.js +10 -4
  52. package/lib/mcp/tools/agent/build.js +2 -15
  53. package/lib/mcp/tools/agent/index.d.ts +2 -0
  54. package/lib/mcp/tools/agent/index.js +3 -0
  55. package/lib/mcp/tools/agent/proof.js +1 -6
  56. package/lib/mcp/tools/agent/propose.js +13 -2
  57. package/lib/mcp/tools/agent/publish.js +10 -2
  58. package/lib/mcp/tools/agent/replay.js +0 -5
  59. package/lib/mcp/tools/analyze.d.ts +3 -0
  60. package/lib/mcp/tools/analyze.js +26 -0
  61. package/lib/mcp/tools/attach.d.ts +11 -0
  62. package/lib/mcp/tools/attach.js +72 -0
  63. package/lib/mcp/tools/authenticate/authenticate.js +107 -0
  64. package/lib/mcp/tools/authenticate/build.d.ts +15 -0
  65. package/lib/mcp/tools/authenticate/build.js +28 -0
  66. package/lib/mcp/tools/authenticate/decrypt-key.d.ts +32 -0
  67. package/lib/mcp/tools/authenticate/decrypt-key.js +49 -0
  68. package/lib/mcp/tools/authenticate/eth-key.d.ts +38 -0
  69. package/lib/mcp/tools/authenticate/eth-key.js +130 -0
  70. package/lib/mcp/tools/authenticate/import.js +57 -0
  71. package/lib/mcp/tools/authenticate/index.d.ts +2 -0
  72. package/lib/mcp/tools/authenticate/index.js +4 -0
  73. package/lib/mcp/tools/authenticate/issue.js +42 -0
  74. package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
  75. package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
  76. package/lib/mcp/tools/capture.d.ts +10 -0
  77. package/lib/mcp/tools/capture.js +142 -0
  78. package/lib/mcp/tools/eval.d.ts +5 -0
  79. package/lib/mcp/tools/eval.js +127 -0
  80. package/lib/mcp/tools/find.d.ts +3 -0
  81. package/lib/mcp/tools/find.js +60 -0
  82. package/lib/mcp/tools/index.d.ts +3 -0
  83. package/lib/mcp/tools/index.js +6 -0
  84. package/lib/mcp/tools/owner-key.d.ts +2 -0
  85. package/lib/mcp/tools/owner-key.js +63 -0
  86. package/lib/mcp/tools/proof.d.ts +3 -0
  87. package/lib/mcp/tools/proof.js +214 -0
  88. package/lib/mcp/tools/propose.d.ts +9 -0
  89. package/lib/mcp/tools/propose.js +75 -0
  90. package/lib/mcp/tools/publish.d.ts +3 -0
  91. package/lib/mcp/tools/publish.js +59 -0
  92. package/lib/mcp/tools/replay.d.ts +3 -0
  93. package/lib/mcp/tools/replay.js +46 -0
  94. package/lib/mcp/tools/session.d.ts +10 -0
  95. package/lib/mcp/tools/session.js +29 -0
  96. package/lib/mcp/tools/verification/build.d.ts +12 -0
  97. package/lib/mcp/tools/verification/build.js +14 -0
  98. package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
  99. package/lib/mcp/tools/verification/diagnose.js +132 -0
  100. package/lib/mcp/tools/verification/index.d.ts +1 -0
  101. package/lib/mcp/tools/verification/index.js +2 -0
  102. package/lib/mcp/tools/verification/result.d.ts +12 -0
  103. package/lib/mcp/tools/verification/result.js +126 -0
  104. package/lib/mcp/verifications/build.d.ts +5 -0
  105. package/lib/mcp/verifications/build.js +14 -0
  106. package/lib/mcp/verifications/create.d.ts +3 -0
  107. package/lib/mcp/verifications/create.js +57 -0
  108. package/lib/mcp/verifications/find.d.ts +3 -0
  109. package/lib/mcp/verifications/find.js +37 -0
  110. package/lib/mcp/verifications/get.d.ts +3 -0
  111. package/lib/mcp/verifications/get.js +26 -0
  112. package/lib/mcp/verifications/update.d.ts +3 -0
  113. package/lib/mcp/verifications/update.js +78 -0
  114. package/lib/old/client.d.ts +3 -0
  115. package/lib/old/instructions.d.ts +0 -6
  116. package/lib/old/instructions.js +6 -24
  117. package/lib/old/to-register.d.ts +3 -0
  118. package/lib/old/to-register.js +35 -7
  119. package/lib/old/tools/publish.js +13 -1
  120. package/lib/proof/attestor.d.ts +33 -1
  121. package/lib/proof/attestor.js +65 -63
  122. package/lib/proof/index.d.ts +5 -0
  123. package/lib/proof/index.js +6 -0
  124. package/lib/proof/proof-core.d.ts +35 -0
  125. package/lib/proof/proof-core.js +73 -0
  126. package/lib/provider/index.d.ts +5 -0
  127. package/lib/provider/index.js +9 -0
  128. package/lib/provider/to-version.d.ts +9 -12
  129. package/lib/provider/to-version.js +38 -4
  130. package/lib/provider/verification-checks.d.ts +12 -0
  131. package/lib/provider/verification-checks.js +30 -0
  132. package/lib/routes.gen.d.ts +271 -0
  133. package/lib/routes.gen.js +73 -0
  134. package/lib/types/openapi.gen.d.ts +3967 -0
  135. package/lib/types/openapi.gen.js +5 -0
  136. package/package.json +16 -7
  137. package/skill/SKILL.md +35 -14
  138. package/skill/builder-mode.md +9 -0
  139. package/skill/old-mode.md +13 -0
  140. package/src/cdp/capture-engine.ts +256 -0
  141. package/src/cdp/capture.ts +25 -185
  142. package/src/cdp/index.ts +6 -0
  143. package/src/config/store.ts +7 -6
  144. package/src/index.ts +2 -4
  145. package/src/mcp/api/operations.gen.ts +1023 -121
  146. package/src/mcp/api/to-zod.ts +115 -0
  147. package/src/mcp/api/tools.ts +9 -3
  148. package/src/mcp/instructions.ts +15 -0
  149. package/src/mcp/server.ts +5 -4
  150. package/src/mcp/start.ts +14 -4
  151. package/src/mcp/tools/agent/build.ts +2 -18
  152. package/src/mcp/tools/agent/index.ts +4 -0
  153. package/src/mcp/tools/agent/proof.ts +1 -7
  154. package/src/mcp/tools/agent/propose.ts +13 -2
  155. package/src/mcp/tools/agent/publish.ts +10 -2
  156. package/src/mcp/tools/agent/replay.ts +0 -5
  157. package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
  158. package/src/mcp/tools/authenticate/build.ts +32 -0
  159. package/src/mcp/tools/authenticate/decrypt-key.ts +64 -0
  160. package/src/mcp/tools/authenticate/eth-key.ts +182 -0
  161. package/src/mcp/tools/authenticate/import.ts +73 -0
  162. package/src/mcp/tools/authenticate/index.ts +4 -0
  163. package/src/mcp/tools/authenticate/issue.ts +50 -0
  164. package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
  165. package/src/mcp/tools/index.ts +6 -0
  166. package/src/mcp/tools/verification/build.ts +16 -0
  167. package/src/mcp/tools/verification/index.ts +2 -0
  168. package/src/mcp/tools/verification/result.ts +155 -0
  169. package/src/old/client.ts +3 -0
  170. package/src/old/instructions.ts +10 -25
  171. package/src/old/to-register.ts +62 -27
  172. package/src/old/tools/publish.ts +17 -1
  173. package/src/proof/attestor.ts +112 -71
  174. package/src/proof/index.ts +21 -0
  175. package/src/proof/proof-core.ts +109 -0
  176. package/src/provider/index.ts +20 -0
  177. package/src/provider/to-version.ts +52 -11
  178. package/src/provider/verification-checks.ts +36 -0
  179. package/lib/mcp/tools/credentials/build.d.ts +0 -16
  180. package/lib/mcp/tools/credentials/build.js +0 -33
  181. package/lib/mcp/tools/credentials/status.js +0 -62
  182. package/src/mcp/tools/credentials/build.ts +0 -37
  183. package/src/mcp/tools/credentials/cache.ts +0 -161
  184. package/src/mcp/tools/credentials/env-file.ts +0 -101
  185. package/src/mcp/tools/credentials/import.ts +0 -72
  186. package/src/mcp/tools/credentials/issue.ts +0 -107
  187. package/src/mcp/tools/credentials/list-cached.ts +0 -66
  188. package/src/mcp/tools/credentials/register.ts +0 -49
  189. package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
  190. package/src/mcp/tools/credentials/status.ts +0 -82
  191. package/src/types/openapi.ts +0 -7
  192. /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
  193. /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
  194. /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
  195. /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
  196. /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
  197. /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
  198. /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
  199. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
  200. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
  201. /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
@@ -0,0 +1,126 @@
1
+ import { createReclaim, decryptCallback, DEFAULT_BASE_URL, verifyResultFull, } from '@reclaimprotocol/client';
2
+ import assert from 'node:assert';
3
+ import { defineTool } from "../../server.js";
4
+ import { resolveDecryptionKey } from "../authenticate/decrypt-key.js";
5
+ /** Statuses that can carry a submitted (terminal) result. `expired`/`pending`
6
+ * never have one. */
7
+ const TERMINAL = new Set(['success', 'rejected', 'error']);
8
+ /**
9
+ * Resolve the org secret used to authenticate verification reads. Auth is a
10
+ * single per-org bearer secret (`rorg_…`), not an eth signature — read it from
11
+ * `RECLAIM_ORG_SECRET`.
12
+ */
13
+ function resolveOrgSecret() {
14
+ const secret = process.env.RECLAIM_ORG_SECRET?.trim();
15
+ assert(secret, new Error('RECLAIM_ORG_SECRET is not set. Verification reads authenticate with ' +
16
+ 'the org secret (rorg_…) — issue one from the dashboard ' +
17
+ '(POST /orgs/{orgId}/token) and export it as RECLAIM_ORG_SECRET.'));
18
+ return secret;
19
+ }
20
+ /**
21
+ * `get_verification_result` — check a session's status and, once a result has
22
+ * been submitted, pull the stored payload(s) and verify locally. Auth is the
23
+ * org token; delivery is org-scoped. Each stored payload is either the
24
+ * plaintext signed JWS (when the org has no encryption credential) or a compact
25
+ * JWE (RFC 7516, ECDH-ES+A256GCM over X25519) that we decrypt here with the
26
+ * optional X25519 key (the `reclaim-decrypt.pem` PEM in the project). The
27
+ * Builder only ever relays the payload — decryption, when needed, happens
28
+ * 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 (compact JWE over X25519) are decrypted with your ' +
38
+ 'optional decryption key (the reclaim-decrypt.pem PEM in the ' +
39
+ 'project); plaintext 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 orgSecret = resolveOrgSecret();
55
+ // Optional X25519 decryption key — absent ⇒ plaintext-only.
56
+ const decryptionKey = await resolveDecryptionKey();
57
+ const reclaim = createReclaim({
58
+ baseUrl: process.env.RECLAIM_API_URL || DEFAULT_BASE_URL,
59
+ orgSecret,
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 (JWE) to a key this consumer does not ' +
114
+ 'hold. Place an X25519 PEM (reclaim-decrypt.pem) in the ' +
115
+ 'project matching the org credential.',
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
+ }
@@ -24,6 +24,9 @@ export interface RegisterProviderBody {
24
24
  description?: string;
25
25
  loginUrl: string;
26
26
  geoLocation?: string;
27
+ /** Provider-level flag on the old backend (defaults false there; the
28
+ * translator sends `true` to match the builder default). */
29
+ useProxy?: boolean;
27
30
  providerType?: 'PRIVATE' | 'PUBLIC';
28
31
  requestData: unknown[];
29
32
  }
@@ -1,7 +1 @@
1
- /**
2
- * MCP server instructions shown to the LLM when running in OLD-devtools mode
3
- * (`USE_OLD_DEVTOOLS` unset or not `false`). Describes the REDUCED tool
4
- * surface — there are no org/credential-link/review flows and no generated
5
- * API tools here. Must not mention disabled tools.
6
- */
7
1
  export declare const OLD_MODE_INSTRUCTIONS: string;
@@ -2,28 +2,10 @@
2
2
  * MCP server instructions shown to the LLM when running in OLD-devtools mode
3
3
  * (`USE_OLD_DEVTOOLS` unset or not `false`). Describes the REDUCED tool
4
4
  * surface — there are no org/credential-link/review flows and no generated
5
- * API tools here. Must not mention disabled tools.
5
+ * API tools here. The prose lives in `skill/old-mode.md` (published via the
6
+ * `files` array); the path resolves identically from `src/old` (dev) and
7
+ * `lib/old` (published).
6
8
  */
7
- export const OLD_MODE_INSTRUCTIONS = 'This server is running against the LEGACY Reclaim devtools backend ' +
8
- '(temporary, while the new builder backend is in development), so its ' +
9
- 'capabilities are intentionally limited.\n\n' +
10
- 'Provider-authoring flow:\n' +
11
- '1. `reclaim_authenticate` — by default opens the dashboard in Chrome, ' +
12
- 'waits for you to sign in, captures the token automatically, and closes ' +
13
- 'the tab (or paste a `token` / pass an eth `ethAddress` to skip the ' +
14
- 'browser). Do this once before publishing or listing.\n' +
15
- '2. `attach_chrome` → `start_capture` → drive the page (`navigate`, ' +
16
- '`wait_for_page`) → inspect (`list_requests`, `get_request`, ' +
17
- '`find_requests_containing`).\n' +
18
- '3. `propose_provider` to draft a provider, `replay_request` to ' +
19
- 'pre-flight, `run_proof` to verify with the attestor. OPRF/`hash` ' +
20
- 'redactions are optional and supported.\n' +
21
- '4. `create_provider_version_from_capture` to publish. With NO ' +
22
- '`providerId` it REGISTERS A NEW provider (re-running creates a ' +
23
- 'duplicate); pass a ' +
24
- '`providerId` from `get_me_providers` to add a new version to an existing ' +
25
- 'provider instead.\n' +
26
- '5. `get_me_providers` lists the providers you own (the only ' +
27
- 'provider-listing tool available in this mode).\n\n' +
28
- 'Only GET/POST endpoints can be captured into providers here. There is no ' +
29
- 'organization, credential-linking, or public-review workflow in this mode.';
9
+ import { readFileSync } from 'node:fs';
10
+ import { fileURLToPath } from 'node:url';
11
+ export const OLD_MODE_INSTRUCTIONS = readFileSync(fileURLToPath(new URL('../../skill/old-mode.md', import.meta.url)), 'utf8').trim();
@@ -17,7 +17,10 @@ import type { RegisterProviderBody, UpdateProviderConfigBody } from './client.ts
17
17
  export interface OldProviderOpts {
18
18
  initialUrl: string;
19
19
  description?: string;
20
+ /** Defaults to `{{DYNAMIC_GEO}}` when omitted. */
20
21
  geoLocation?: string;
22
+ /** Defaults to `true` when omitted. Register only (Provider-level flag). */
23
+ useProxy?: boolean;
21
24
  providerType?: 'PRIVATE' | 'PUBLIC';
22
25
  }
23
26
  /** Body for `POST /api/providers/register` — new provider + v1.0.0. */
@@ -1,3 +1,9 @@
1
+ /** Default web settings, mirroring the builder openapi defaults
2
+ * (`ProviderWebSettings.geoLocation`, `PortalClientOptions.useProxy`). The old
3
+ * backend accepts both: `geoLocation` lives on the providerConfig, `useProxy`
4
+ * is a Provider-level flag (register only). */
5
+ const DEFAULT_GEO_LOCATION = '{{DYNAMIC_GEO}}';
6
+ const DEFAULT_USE_PROXY = true;
1
7
  /** Build the single `requestData` entry shared by register + update. */
2
8
  function requestDataFromProvider(provider) {
3
9
  const method = String(provider.method).toUpperCase();
@@ -5,13 +11,34 @@ function requestDataFromProvider(provider) {
5
11
  throw new Error('Old devtools supports only GET/POST requests; got ' +
6
12
  `"${provider.method}". Re-capture against a GET/POST endpoint.`);
7
13
  }
14
+ // The old backend has no dotted interpolation: consumer-supplied params
15
+ // must use the `{{context_<name>}}` form here, not the builder's
16
+ // `{{context.<name>}}`. Catch the mix-up at publish with a clear error
17
+ // instead of a template that silently never resolves.
18
+ const dotted = `${provider.url}\n${provider.body ?? ''}`
19
+ .match(/\{\{context\.[A-Za-z_][A-Za-z0-9_]*\}\}/);
20
+ if (dotted) {
21
+ throw new Error(`Old devtools does not support ${dotted[0]} — rename ` +
22
+ 'consumer-supplied params to the {{context_<name>}} form ' +
23
+ 'for this backend.');
24
+ }
8
25
  const responseMatches = provider.responseMatches.map((m, i) => ({
9
26
  value: m.value,
10
27
  type: m.type ?? 'contains',
11
28
  isOptional: false,
12
29
  order: i,
13
30
  }));
14
- const responseRedactions = (provider.responseRedactions ?? []).map((r, i) => {
31
+ // Old devtools wants `responseMatches` and `responseRedactions` as PARALLEL
32
+ // arrays. A drafted provider may instead carry each redaction nested in its
33
+ // match's `extract` (the builder shape). Prefer the explicit parallel array;
34
+ // fall back to the nested `extract`s so redactions are never dropped.
35
+ const nestedRedactions = provider.responseMatches
36
+ .map((m) => m.extract)
37
+ .filter((e) => Boolean(e));
38
+ const sourceRedactions = provider.responseRedactions?.length
39
+ ? provider.responseRedactions
40
+ : nestedRedactions;
41
+ const responseRedactions = sourceRedactions.map((r, i) => {
15
42
  const out = { order: i };
16
43
  if (r.xPath !== undefined) {
17
44
  out.xPath = r.xPath;
@@ -54,27 +81,28 @@ export function providerToRegisterBody(provider, opts) {
54
81
  name: provider.name,
55
82
  loginUrl: opts.initialUrl,
56
83
  providerType: opts.providerType ?? 'PRIVATE',
84
+ // Web-settings defaults mirror the builder openapi defaults.
85
+ geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
86
+ useProxy: opts.useProxy ?? DEFAULT_USE_PROXY,
57
87
  requestData: [requestDataFromProvider(provider)],
58
88
  };
59
89
  if (opts.description !== undefined) {
60
90
  body.description = opts.description;
61
91
  }
62
- if (opts.geoLocation !== undefined) {
63
- body.geoLocation = opts.geoLocation;
64
- }
65
92
  return body;
66
93
  }
67
94
  /** Body for `POST /api/providers/:providerId/config` — adds a new version to
68
95
  * an EXISTING provider. `version` must not already exist; `versionInfo` is
69
96
  * required and must be ≥10 chars (enforced by the backend). */
70
97
  export function providerToConfigBody(provider, opts, version, versionInfo) {
98
+ // `useProxy` is a Provider-level flag on the old backend, not part of a
99
+ // version's providerConfig — so the config (new-version) path only carries
100
+ // `geoLocation`. It defaults the same way as register.
71
101
  const providerConfig = {
72
102
  loginUrl: opts.initialUrl,
103
+ geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
73
104
  requestData: [requestDataFromProvider(provider)],
74
105
  };
75
- if (opts.geoLocation !== undefined) {
76
- providerConfig.geoLocation = opts.geoLocation;
77
- }
78
106
  return { providerConfig, version, versionInfo };
79
107
  }
80
108
  /**
@@ -58,7 +58,16 @@ export function createVersionFromCaptureTool(client) {
58
58
  type: 'string',
59
59
  description: 'Provider description (new-provider register only).',
60
60
  },
61
- geoLocation: { type: 'string' },
61
+ geoLocation: {
62
+ type: 'string',
63
+ description: 'Geo the verification appears to originate from. Defaults to ' +
64
+ "'{{DYNAMIC_GEO}}' (the user's geo) when omitted.",
65
+ },
66
+ useProxy: {
67
+ type: 'boolean',
68
+ description: 'Route portal/attestation traffic through a proxy. Defaults to ' +
69
+ 'true when omitted. Applied on register only.',
70
+ },
62
71
  providerType: { type: 'string', enum: ['PRIVATE', 'PUBLIC'] },
63
72
  notes: {
64
73
  type: 'string',
@@ -76,6 +85,9 @@ export function createVersionFromCaptureTool(client) {
76
85
  if (args.geoLocation !== undefined) {
77
86
  opts.geoLocation = args.geoLocation;
78
87
  }
88
+ if (args.useProxy !== undefined) {
89
+ opts.useProxy = args.useProxy;
90
+ }
79
91
  if (args.providerType !== undefined) {
80
92
  opts.providerType = args.providerType;
81
93
  }
@@ -4,6 +4,35 @@ export interface AttestorLogEntry {
4
4
  msg: string;
5
5
  ctx?: Record<string, unknown>;
6
6
  }
7
+ /** The attestor's signed claim data + signature, for building the nested proof
8
+ * JWS a Consumer verifies against the attestor's key. Populated when
9
+ * `includeAttestorClaim` is set (the app's verification runner needs it; the
10
+ * MCP `run_proof` tool ignores it). */
11
+ export interface AttestorClaim {
12
+ /** ProviderClaimData: provider, parameters, context (JSON string), owner,
13
+ * timestampS, epoch, identifier. */
14
+ claim: Record<string, unknown>;
15
+ /** Hex (0x) attestor ETH address that signed the claim (the nested `kid`). */
16
+ attestorAddress: string;
17
+ /** Hex (0x) attestor claim signature (EIP-191 over the claim sign-data). */
18
+ claimSignature: string;
19
+ }
20
+ /** Options for {@link runAttestorProof}. */
21
+ export interface RunAttestorProofOptions {
22
+ attestorUrl?: string;
23
+ /** When resolving the key from env/.env/file, the address the caller expects
24
+ * to sign with (sanity check). Ignored when `ownerPrivateKey` is given. */
25
+ ownerAddress?: string;
26
+ /** Sign with this key directly (e.g. the app/VC's ephemeral per-session key)
27
+ * instead of resolving from env/.env/file. */
28
+ ownerPrivateKey?: string;
29
+ /** ZK engine for `createClaimOnAttestor`. Defaults to `'gnark'`; the app's
30
+ * server-side verification runner uses `'snarkjs'`. */
31
+ zkEngine?: 'gnark' | 'snarkjs';
32
+ /** Extract the structured {@link AttestorClaim} (claim + attestor signature)
33
+ * onto the result for nested-proof construction. */
34
+ includeAttestorClaim?: boolean;
35
+ }
7
36
  export interface ProofResult {
8
37
  proof: unknown;
9
38
  extractedValue: string;
@@ -12,6 +41,9 @@ export interface ProofResult {
12
41
  owner?: string;
13
42
  verified: boolean;
14
43
  error?: string;
44
+ /** Structured claim + signature for nested-proof verification. Set only when
45
+ * `includeAttestorClaim` was requested and the claim carries signatures. */
46
+ attestorClaim?: AttestorClaim;
15
47
  /** Set to `'missing-owner-key'` when no credential was available to
16
48
  * sign with — distinguishes this recoverable case from other proof
17
49
  * errors so the skill can point the dev at `issue_credentials` /
@@ -36,4 +68,4 @@ export declare function tailLogs(entries: AttestorLogEntry[], n?: number): Attes
36
68
  /** Filter to just warn/error/fatal — for the LLM-visible response on
37
69
  * successful proofs, where chatty trace/info would just waste context. */
38
70
  export declare function warnsAndErrors(entries: AttestorLogEntry[]): AttestorLogEntry[];
39
- export declare function runAttestorProof(provider: ReclaimProvider, secrets: Record<string, string>, attestorUrl?: string, ownerAddress?: string): Promise<ProofResult>;
71
+ export declare function runAttestorProof(provider: ReclaimProvider, secrets: Record<string, string>, opts?: RunAttestorProofOptions): Promise<ProofResult>;