@reclaimprotocol/agent 0.1.31 → 0.1.33

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.
@@ -26,6 +26,7 @@ export declare const MCP_TOOLS: {
26
26
  BindVerificationSessionTeeNonce: {
27
27
  description: string;
28
28
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
29
+ orgTokenOnly: boolean;
29
30
  };
30
31
  CancelPublicListingRequest: {
31
32
  description: string;
@@ -34,6 +35,7 @@ export declare const MCP_TOOLS: {
34
35
  CreateCallbackSubscription: {
35
36
  description: string;
36
37
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
38
+ orgTokenOnly: boolean;
37
39
  };
38
40
  CreateOrg: {
39
41
  description: string;
@@ -54,6 +56,7 @@ export declare const MCP_TOOLS: {
54
56
  CreateVerificationSession: {
55
57
  description: string;
56
58
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
59
+ orgTokenOnly: boolean;
57
60
  };
58
61
  DecideProviderVersionReview: {
59
62
  description: string;
@@ -62,6 +65,7 @@ export declare const MCP_TOOLS: {
62
65
  DeleteCallbackSubscription: {
63
66
  description: string;
64
67
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
68
+ orgTokenOnly: boolean;
65
69
  };
66
70
  DeleteOrgCallbackSubscription: {
67
71
  description: string;
@@ -122,6 +126,7 @@ export declare const MCP_TOOLS: {
122
126
  GetVerificationSession: {
123
127
  description: string;
124
128
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
129
+ orgTokenOnly: boolean;
125
130
  };
126
131
  ImportDevtoolsProvider: {
127
132
  description: string;
@@ -138,6 +143,7 @@ export declare const MCP_TOOLS: {
138
143
  ListCallbackSubscriptions: {
139
144
  description: string;
140
145
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
146
+ orgTokenOnly: boolean;
141
147
  };
142
148
  ListOrgCallbackSubscriptions: {
143
149
  description: string;
@@ -166,10 +172,12 @@ export declare const MCP_TOOLS: {
166
172
  ListVerificationDeliveries: {
167
173
  description: string;
168
174
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
175
+ orgTokenOnly: boolean;
169
176
  };
170
177
  ListVerificationEvents: {
171
178
  description: string;
172
179
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
180
+ orgTokenOnly: boolean;
173
181
  };
174
182
  MakePrivate: {
175
183
  description: string;
@@ -190,6 +198,7 @@ export declare const MCP_TOOLS: {
190
198
  RetryVerificationCallback: {
191
199
  description: string;
192
200
  inputSchema: import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>;
201
+ orgTokenOnly: boolean;
193
202
  };
194
203
  RevokeOrgToken: {
195
204
  description: string;
@@ -1,5 +1,5 @@
1
1
  // AUTO-GENERATED by packages/app/scripts/mcp-tools-gen.ts
2
- // from packages/app/openapi.yaml (spec v0.1.0, source sha256:9ba46b5cbd7c).
2
+ // from packages/app/openapi.yaml (spec v0.1.0, source sha256:3e28ff308da3).
3
3
  // The hash catches drift the version misses (a spec can change without a
4
4
  // version bump) — do not remove it as "redundant" with the version.
5
5
  // Run `npm run openapi:gen --workspace=packages/app` to regenerate. Do not edit by hand.
@@ -7,7 +7,7 @@
7
7
  import { toZod } from "./to-zod.js";
8
8
  export const MCP_TOOLS = {
9
9
  "AddOrgMember": {
10
- description: "Invite a member to an organization\n\nOwner only. Invites a user to the organization by email. The invitee does **not** need to be a registered user — an invite is created in either case, and an invite email with an accept link is dispatched. The new row is returned with `status: PENDING`; it flips to `ACTIVE` only when the invitee explicitly accepts via `POST /orgs/{orgId}/invite`. `PERSONAL` organizations reject this call (409).",
10
+ description: "Invite a member to an organization\n\nOwner only. Invites a user to the organization by email. The invitee does **not** need to be a registered user — an invite is created in either case, and an invite email with an accept link is dispatched. The new row is returned with `status: PENDING`; it flips to `ACTIVE` only when the invitee explicitly accepts via `POST /orgs/{orgId}/invite`.",
11
11
  inputSchema: toZod({
12
12
  "type": "object",
13
13
  "properties": {
@@ -46,7 +46,7 @@ export const MCP_TOOLS = {
46
46
  },
47
47
  "role": {
48
48
  "type": "string",
49
- "description": "Role a user holds in an organization. `OWNER` can invite, promote, demote, and remove members, and delete the org. `MEMBER` has read/write access to resources owned by the org but cannot manage membership. `PERSONAL` orgs have exactly one `OWNER` and reject all member-mutating operations.",
49
+ "description": "Role a user holds in an organization. `OWNER` can invite, promote, demote, and remove members, and delete the org. `MEMBER` has read/write access to resources owned by the org but cannot manage membership.",
50
50
  "enum": [
51
51
  "OWNER",
52
52
  "MEMBER"
@@ -407,6 +407,12 @@ export const MCP_TOOLS = {
407
407
  "maxLength": 132
408
408
  }
409
409
  }
410
+ },
411
+ "orgToken": {
412
+ "type": "string",
413
+ "pattern": "^rorg_",
414
+ "maxLength": 200,
415
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
410
416
  }
411
417
  },
412
418
  "required": [
@@ -416,6 +422,7 @@ export const MCP_TOOLS = {
416
422
  ],
417
423
  "additionalProperties": false
418
424
  }),
425
+ orgTokenOnly: true,
419
426
  },
420
427
  "CancelPublicListingRequest": {
421
428
  description: "Cancel a pending public listing review request\n\nCancels a pending public listing request by moving the version from `in_review` back to `draft`. Only org members can cancel their own review requests. This allows users to withdraw a request before admin review if they change their mind.",
@@ -557,6 +564,12 @@ export const MCP_TOOLS = {
557
564
  }
558
565
  }
559
566
  }
567
+ },
568
+ "orgToken": {
569
+ "type": "string",
570
+ "pattern": "^rorg_",
571
+ "maxLength": 200,
572
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
560
573
  }
561
574
  },
562
575
  "required": [
@@ -566,9 +579,10 @@ export const MCP_TOOLS = {
566
579
  ],
567
580
  "additionalProperties": false
568
581
  }),
582
+ orgTokenOnly: true,
569
583
  },
570
584
  "CreateOrg": {
571
- description: "Create an organization\n\nCreates a new `ORG`-kind organization with the caller as its first `OWNER`. The personal org is created automatically at user signup and is not created via this endpoint.",
585
+ description: "Create an organization\n\nCreates a new `ORG`-kind organization with the caller as its first `OWNER`. Every user gets a default organization at sign-up, and it counts toward their org-creation limit (1 active organization unless Reclaim support raises it). Past the limit this returns `409`; contact support@reclaimprotocol.org to raise the limit or archive an organization.",
572
586
  inputSchema: toZod({
573
587
  "type": "object",
574
588
  "properties": {
@@ -583,7 +597,7 @@ export const MCP_TOOLS = {
583
597
  "body": {
584
598
  "type": "object",
585
599
  "additionalProperties": false,
586
- "description": "Body for `POST /orgs` — just a name. Every org is created keyless, like auto-provisioned personal orgs; its Ethereum (secp256k1) key pair is published separately via `PUT /orgs/{orgId}/keypair`, which is also where `canEncryptResult` is set. Creation deliberately collects nothing else so it never blocks on generating and safeguarding a private key.",
600
+ "description": "Body for `POST /orgs` — just a name. Every org is created keyless, like each user's default org; its Ethereum (secp256k1) key pair is published separately via `PUT /orgs/{orgId}/keypair`, which is also where `canEncryptResult` is set. Creation deliberately collects nothing else so it never blocks on generating and safeguarding a private key.",
587
601
  "required": [
588
602
  "name"
589
603
  ],
@@ -1538,7 +1552,7 @@ export const MCP_TOOLS = {
1538
1552
  }),
1539
1553
  },
1540
1554
  "CreateVerificationSession": {
1541
- description: "Create a verification session\n\nCreates an end-user verification session. Requires an OrgToken and a callback subscription; pass providers, context, and an optional registered verificationClientUrl (omitted: the Portal). Billing refusal returns 402 or 429 with event billing_required and a terminal sessionId.",
1555
+ description: "Create a verification session\n\nCreates an end-user verification session. Requires an OrgToken and a callback subscription; pass providers, context, and an optional registered verificationClientUrl (omitted: the Portal). Send the end user to the returned verificationUrl; that is where they verify. Billing refusal returns 402 or 429 with event billing_required and a terminal sessionId.",
1542
1556
  inputSchema: toZod({
1543
1557
  "type": "object",
1544
1558
  "properties": {
@@ -1592,9 +1606,16 @@ export const MCP_TOOLS = {
1592
1606
  },
1593
1607
  "verificationClientUrl": {
1594
1608
  "type": "string",
1595
- "description": "Optional. Must exactly equal the base URL of a registered verification client (see the `verification_clients` registry / `/admin/verification-clients`). Omit to use the default (`portals`) client. The Builder resolves and stores the registered client UUID, then returns the ready-to-share `verificationUrl` with the session id and `api=2`. A URL that is not a registered client's base is rejected with 400. Consumers append any client-owned redirect parameters after receiving the URL; Builder does not manage them.",
1609
+ "description": "Optional. Must exactly equal the base URL of a registered verification client (see the `verification_clients` registry / `/admin/verification-clients`). Omit to use the default (`portals`) client. The Builder resolves and stores the registered client UUID, then returns the ready-to-share `verificationUrl` with the session id and `api=2`. A URL that is not a registered client's base is rejected with 400. Consumers append any client-owned redirect parameters after receiving the URL; Builder does not manage them. The built-in clients are `{origin}/share/{name}`, listed in the examples.",
1596
1610
  "maxLength": 2000,
1597
- "pattern": "^https?://"
1611
+ "pattern": "^https?://",
1612
+ "examples": [
1613
+ "https://build.reclaimprotocol.org/share/portals",
1614
+ "https://build.reclaimprotocol.org/share/verifier-app",
1615
+ "https://build.reclaimprotocol.org/share/reclaim-browser-extension",
1616
+ "https://build.reclaimprotocol.org/share/builder",
1617
+ "https://build.reclaimprotocol.org/share/inapp-sdk"
1618
+ ]
1598
1619
  },
1599
1620
  "themeId": {
1600
1621
  "type": "string",
@@ -1709,6 +1730,12 @@ export const MCP_TOOLS = {
1709
1730
  }
1710
1731
  }
1711
1732
  }
1733
+ },
1734
+ "orgToken": {
1735
+ "type": "string",
1736
+ "pattern": "^rorg_",
1737
+ "maxLength": 200,
1738
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
1712
1739
  }
1713
1740
  },
1714
1741
  "required": [
@@ -1718,6 +1745,7 @@ export const MCP_TOOLS = {
1718
1745
  ],
1719
1746
  "additionalProperties": false
1720
1747
  }),
1748
+ orgTokenOnly: true,
1721
1749
  },
1722
1750
  "DecideProviderVersionReview": {
1723
1751
  description: "Record a decision on a provider version review\n\nApproves or rejects a provider version awaiting review. Admin only. Approval promotes the version to the live channel; rejection moves it to the rejected branch with a reason. Use admin_reviews to find versions waiting on a decision.",
@@ -1803,6 +1831,12 @@ export const MCP_TOOLS = {
1803
1831
  },
1804
1832
  "body": {
1805
1833
  "type": "object"
1834
+ },
1835
+ "orgToken": {
1836
+ "type": "string",
1837
+ "pattern": "^rorg_",
1838
+ "maxLength": 200,
1839
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
1806
1840
  }
1807
1841
  },
1808
1842
  "required": [
@@ -1811,6 +1845,7 @@ export const MCP_TOOLS = {
1811
1845
  ],
1812
1846
  "additionalProperties": false
1813
1847
  }),
1848
+ orgTokenOnly: true,
1814
1849
  },
1815
1850
  "DeleteOrgCallbackSubscription": {
1816
1851
  description: "Delete an organization's callback subscription\n\nRemoves a callback subscription. Caller must be an active member of the owning org.",
@@ -2092,12 +2127,34 @@ export const MCP_TOOLS = {
2092
2127
  "type": "string",
2093
2128
  "enum": [
2094
2129
  "claude",
2130
+ "copilot",
2095
2131
  "cursor",
2132
+ "omp",
2096
2133
  "opencode",
2097
2134
  "codex",
2135
+ "antigravity",
2098
2136
  "others"
2099
2137
  ]
2100
2138
  },
2139
+ "providerId": {
2140
+ "type": "array",
2141
+ "maxItems": 20,
2142
+ "items": {
2143
+ "type": "string",
2144
+ "format": "uuid"
2145
+ }
2146
+ },
2147
+ "client": {
2148
+ "type": "string",
2149
+ "enum": [
2150
+ "auto",
2151
+ "portals",
2152
+ "verifier-app",
2153
+ "reclaim-browser-extension",
2154
+ "builder",
2155
+ "inapp-sdk"
2156
+ ]
2157
+ },
2101
2158
  "from": {
2102
2159
  "type": "string",
2103
2160
  "maxLength": 40,
@@ -2110,10 +2167,6 @@ export const MCP_TOOLS = {
2110
2167
  "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})?)?$",
2111
2168
  "description": "One end of a date window: either a calendar date (`2026-09-01`, read as UTC midnight) or a full ISO date-time. The date-only form is what a native `<input type=\"date\">` submits, so `format: date-time` alone would reject every filter the dashboard's own form sends."
2112
2169
  },
2113
- "providerId": {
2114
- "type": "string",
2115
- "format": "uuid"
2116
- },
2117
2170
  "verificationClientId": {
2118
2171
  "type": "string",
2119
2172
  "minLength": 1,
@@ -2484,6 +2537,12 @@ export const MCP_TOOLS = {
2484
2537
  },
2485
2538
  "body": {
2486
2539
  "type": "object"
2540
+ },
2541
+ "orgToken": {
2542
+ "type": "string",
2543
+ "pattern": "^rorg_",
2544
+ "maxLength": 200,
2545
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
2487
2546
  }
2488
2547
  },
2489
2548
  "required": [
@@ -2492,6 +2551,7 @@ export const MCP_TOOLS = {
2492
2551
  ],
2493
2552
  "additionalProperties": false
2494
2553
  }),
2554
+ orgTokenOnly: true,
2495
2555
  },
2496
2556
  "ImportDevtoolsProvider": {
2497
2557
  description: "Import a provider from devtools\n\nImports a public legacy provider into Builder by UUID. Requires human BearerAuth and a target orgId; preserves the provider UUID and is idempotent for seeded providers. Returns 409 if another Builder org owns the UUID.",
@@ -2605,6 +2665,12 @@ export const MCP_TOOLS = {
2605
2665
  },
2606
2666
  "body": {
2607
2667
  "type": "object"
2668
+ },
2669
+ "orgToken": {
2670
+ "type": "string",
2671
+ "pattern": "^rorg_",
2672
+ "maxLength": 200,
2673
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
2608
2674
  }
2609
2675
  },
2610
2676
  "required": [
@@ -2613,6 +2679,7 @@ export const MCP_TOOLS = {
2613
2679
  ],
2614
2680
  "additionalProperties": false
2615
2681
  }),
2682
+ orgTokenOnly: true,
2616
2683
  },
2617
2684
  "ListOrgCallbackSubscriptions": {
2618
2685
  description: "List an organization's callback subscriptions\n\nReturns every callback subscription owned by the organization. Caller must be an active member of the org.",
@@ -2648,7 +2715,7 @@ export const MCP_TOOLS = {
2648
2715
  }),
2649
2716
  },
2650
2717
  "ListOrgs": {
2651
- description: "List organizations the caller belongs to\n\nLists the organizations the caller belongs to, personal and shared. Use it first to find an organization id — most other tools take one.",
2718
+ description: "List organizations the caller belongs to\n\nLists the organizations the caller belongs to. Use it first to find an organization id — most other tools take one.",
2652
2719
  inputSchema: toZod({
2653
2720
  "type": "object",
2654
2721
  "properties": {
@@ -2909,6 +2976,12 @@ export const MCP_TOOLS = {
2909
2976
  },
2910
2977
  "body": {
2911
2978
  "type": "object"
2979
+ },
2980
+ "orgToken": {
2981
+ "type": "string",
2982
+ "pattern": "^rorg_",
2983
+ "maxLength": 200,
2984
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
2912
2985
  }
2913
2986
  },
2914
2987
  "required": [
@@ -2917,6 +2990,7 @@ export const MCP_TOOLS = {
2917
2990
  ],
2918
2991
  "additionalProperties": false
2919
2992
  }),
2993
+ orgTokenOnly: true,
2920
2994
  },
2921
2995
  "ListVerificationEvents": {
2922
2996
  description: "Get the event log for a session\n\nLists append-only lifecycle events for a session. Requires the owning organization's token. Use after get_verification_session to find the first missing or failed milestone; inspect eventData for failure details.",
@@ -2943,6 +3017,12 @@ export const MCP_TOOLS = {
2943
3017
  },
2944
3018
  "body": {
2945
3019
  "type": "object"
3020
+ },
3021
+ "orgToken": {
3022
+ "type": "string",
3023
+ "pattern": "^rorg_",
3024
+ "maxLength": 200,
3025
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
2946
3026
  }
2947
3027
  },
2948
3028
  "required": [
@@ -2951,6 +3031,7 @@ export const MCP_TOOLS = {
2951
3031
  ],
2952
3032
  "additionalProperties": false
2953
3033
  }),
3034
+ orgTokenOnly: true,
2954
3035
  },
2955
3036
  "MakePrivate": {
2956
3037
  description: "Change a PUBLIC provider back to PRIVATE\n\nChanges a PUBLIC provider's visibility to PRIVATE. Unlike the reverse (PRIVATE → PUBLIC), this does not require review since it restricts rather than expands access. Existing live versions remain but are no longer publicly listed.",
@@ -3132,7 +3213,7 @@ export const MCP_TOOLS = {
3132
3213
  }),
3133
3214
  },
3134
3215
  "RetryVerificationCallback": {
3135
- description: "Re-enqueue callback delivery for a session\n\nRe-enqueues delivery of a session's stored result to its callback subscriptions. Use this after `list_verification_deliveries` shows a `failed` or dead-lettered delivery, once the consumer's callback endpoint is reachable again and answers 2xx — it re-attempts every not-yet-delivered callback for the session. Usable by the session creator (authenticated by the consumer's `OrgToken`) to recover from a transient consumer-side outage.",
3216
+ description: "Re-enqueue callback delivery for a session\n\nRe-enqueues delivery of a session's stored result to its callback subscriptions. Use this after `list_verification_deliveries` shows a `failed` or dead-lettered delivery, once the consumer's callback endpoint is reachable again and answers 2xx — it re-attempts every not-yet-delivered callback for the session. Usable by the session creator (authenticated by the consumer's `OrgToken`) to recover from a transient consumer-side outage. A result left undelivered for 7 days is purged and can no longer be retried.",
3136
3217
  inputSchema: toZod({
3137
3218
  "type": "object",
3138
3219
  "properties": {
@@ -3156,6 +3237,12 @@ export const MCP_TOOLS = {
3156
3237
  },
3157
3238
  "body": {
3158
3239
  "type": "object"
3240
+ },
3241
+ "orgToken": {
3242
+ "type": "string",
3243
+ "pattern": "^rorg_",
3244
+ "maxLength": 200,
3245
+ "description": "The organization API key (`rorg_…`) this call authenticates with: from `issue_org_token`, or the app's RECLAIM_ORG_SECRET. Defaults to the MCP server's RECLAIM_ORG_SECRET. Never echo it back to the user."
3159
3246
  }
3160
3247
  },
3161
3248
  "required": [
@@ -3164,6 +3251,7 @@ export const MCP_TOOLS = {
3164
3251
  ],
3165
3252
  "additionalProperties": false
3166
3253
  }),
3254
+ orgTokenOnly: true,
3167
3255
  },
3168
3256
  "RevokeOrgToken": {
3169
3257
  description: "Revoke one of the organization's API keys\n\nRevokes a single API key by id (leaving the org's other keys intact). The caller must be an active **OWNER** of the organization. The key stops authenticating immediately.",
@@ -1,3 +1,11 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { ReclaimClient } from '@reclaimprotocol/client/api';
3
- export declare function registerTools(server: McpServer, client: ReclaimClient): void;
2
+ import { ReclaimClient } from '@reclaimprotocol/client/api';
3
+ /** The client for a call that presents the organization's API key. */
4
+ export type OrgClientFactory = (orgToken: string) => ReclaimClient;
5
+ /**
6
+ * Register a tool per generated operation. Calls go out with the developer's
7
+ * session token, except operations only an org API key (`rorg_…`) authorizes:
8
+ * those take an `orgToken` input (else the server's RECLAIM_ORG_SECRET) and go
9
+ * out through `orgClient` with that key.
10
+ */
11
+ export declare function registerTools(server: McpServer, client: ReclaimClient, orgClient?: OrgClientFactory): void;
@@ -1,3 +1,7 @@
1
+ import { unauthorized } from '@hapi/boom';
2
+ import { ReclaimClient } from '@reclaimprotocol/client/api';
3
+ import assert from 'node:assert';
4
+ import { orgSecret } from "../../consts.js";
1
5
  import { remapErrorAsResponse } from "../remap_errors.js";
2
6
  import { successResponse } from "../success-response.js";
3
7
  import { MCP_TOOLS } from "./operations.gen.js";
@@ -14,8 +18,22 @@ function toSnakeCase(name) {
14
18
  .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
15
19
  .toLowerCase();
16
20
  }
17
- export function registerTools(server, client) {
18
- for (const [opId, shape] of Object.entries(MCP_TOOLS)) {
21
+ /**
22
+ * Register a tool per generated operation. Calls go out with the developer's
23
+ * session token, except operations only an org API key (`rorg_…`) authorizes:
24
+ * those take an `orgToken` input (else the server's RECLAIM_ORG_SECRET) and go
25
+ * out through `orgClient` with that key.
26
+ */
27
+ export function registerTools(server, client, orgClient = (orgToken) => new ReclaimClient({
28
+ baseUrl: client.baseUrl,
29
+ token: orgToken,
30
+ })) {
31
+ for (const [opId, tool] of Object.entries(MCP_TOOLS)) {
32
+ const orgTokenOnly = 'orgTokenOnly' in tool && tool.orgTokenOnly === true;
33
+ const shape = {
34
+ description: tool.description,
35
+ inputSchema: tool.inputSchema,
36
+ };
19
37
  if (!isOperationId(opId)) {
20
38
  throw new Error(`Generated MCP operation is not in the API client: ${opId}`);
21
39
  }
@@ -23,12 +41,19 @@ export function registerTools(server, client) {
23
41
  // a hand-written tool throws here at startup — intentional: hand-written
24
42
  // and generated names must stay disjoint (see start.ts), so a clash is a
25
43
  // bug to surface, not silently shadow.
26
- server.registerTool(toSnakeCase(opId), shape, async (args) => {
44
+ server.registerTool(toSnakeCase(opId), shape, async (input) => {
27
45
  try {
46
+ if (!isRecord(input)) {
47
+ throw new Error(`Invalid generated MCP arguments for ${opId}`);
48
+ }
49
+ const { orgToken, ...args } = input;
28
50
  if (!isOperationArgs(opId, args)) {
29
51
  throw new Error(`Invalid generated MCP arguments for ${opId}`);
30
52
  }
31
- const result = await client.call(opId, args);
53
+ const caller = orgTokenOnly
54
+ ? orgClient(orgTokenFor(toSnakeCase(opId), orgToken))
55
+ : client;
56
+ const result = await caller.call(opId, args);
32
57
  return successResponse(result.data);
33
58
  }
34
59
  catch (err) {
@@ -56,3 +81,16 @@ function isOperationId(value) {
56
81
  function isOperationArgs(_operationId, value) {
57
82
  return typeof value === 'object' && value !== null && !Array.isArray(value);
58
83
  }
84
+ function isRecord(value) {
85
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
86
+ }
87
+ /** The org API key a call authenticates with: its `orgToken`, else the
88
+ * server's RECLAIM_ORG_SECRET. The session token (the developer's sign-in)
89
+ * can't stand in, since these routes accept only an org key. */
90
+ function orgTokenFor(tool, orgToken) {
91
+ const token = (typeof orgToken === 'string' && orgToken) || orgSecret();
92
+ assert(token, unauthorized(`${tool} authenticates with the organization's API key. Pass `
93
+ + 'orgToken: one from issue_org_token, or the app\'s '
94
+ + 'RECLAIM_ORG_SECRET. Or set RECLAIM_ORG_SECRET for the MCP server.'));
95
+ return token;
96
+ }
@@ -67,7 +67,7 @@ const TOPIC_SUMMARIES = {
67
67
  'discover': 'Finding providers, resolving them, and creating a verification '
68
68
  + 'session.',
69
69
  'integration': 'Set up a Builder token, callback, frontend and backend '
70
- + 'with @reclaimprotocol/client; direct `api=2` API and result '
70
+ + 'over the HTTP session API; direct `api=2` API and result '
71
71
  + 'verification.',
72
72
  'user-script': 'Authoring jsUserScripts / customInjection to drive '
73
73
  + 'login-gated pages.',
package/lib/mcp/start.js CHANGED
@@ -79,7 +79,12 @@ export async function startMcpServer() {
79
79
  registerToolList(server, buildVerificationTools());
80
80
  // Add auto-generated tools with snake_case wrappers
81
81
  // for every MCP-tagged operation.
82
- registerTools(server, client);
82
+ // Org-key-only operations go out with the call's `orgToken` instead.
83
+ registerTools(server, client, (orgToken) => new ReclaimClient({
84
+ baseUrl: apiUrl(),
85
+ token: orgToken,
86
+ headers: { 'User-Agent': `${NAME}/${VERSION}` },
87
+ }));
83
88
  if (agentToolsEnabled) {
84
89
  agentState = buildAgentState();
85
90
  registerToolList(server, buildAgentTools(client, client, agentState));
@@ -11,16 +11,25 @@ const TERMINAL = new Set([
11
11
  'cancelled',
12
12
  'expired',
13
13
  ]);
14
+ /** Events whose delivery is a signed result; the rest are plaintext event
15
+ * notifications. Mirrors `verification_result_events()`. */
16
+ const RESULT_EVENTS = new Set([
17
+ 'verification_success',
18
+ 'verification_rejected',
19
+ 'verification_error',
20
+ 'verification_cancelled',
21
+ ]);
14
22
  /**
15
23
  * Resolve the org secret used to authenticate verification reads. Auth is a
16
- * single per-org bearer secret (`rorg_…`), not an eth signature — read it from
17
- * `RECLAIM_ORG_SECRET`.
24
+ * single per-org bearer secret (`rorg_…`), not an eth signature: the call's
25
+ * `orgToken`, else `RECLAIM_ORG_SECRET`.
18
26
  */
19
- function resolveOrgSecret() {
20
- const secret = orgSecret()?.trim();
21
- assert(secret, new Error('RECLAIM_ORG_SECRET is not set. Verification reads authenticate with ' +
22
- 'the org secret (rorg_…) — issue one from the dashboard ' +
23
- '(POST /orgs/{orgId}/token) and export it as RECLAIM_ORG_SECRET.'));
27
+ function resolveOrgSecret(orgToken) {
28
+ const secret = orgToken?.trim() || orgSecret()?.trim();
29
+ assert(secret, new Error('No organization API key. Verification reads authenticate with the org '
30
+ + 'secret (rorg_…): pass orgToken (from issue_org_token, or the '
31
+ + 'app\'s RECLAIM_ORG_SECRET), or export RECLAIM_ORG_SECRET for the '
32
+ + 'MCP server.'));
24
33
  return secret;
25
34
  }
26
35
  /**
@@ -36,8 +45,11 @@ function resolveOrgSecret() {
36
45
  export function verificationResultTool() {
37
46
  return defineTool({
38
47
  name: 'get_verification_result',
39
- description: 'Fetches and verifies a terminal Builder result for one session. '
40
- + 'Requires `RECLAIM_ORG_SECRET`; encrypted deliveries also require '
48
+ description: 'Fetches and verifies a terminal Builder result for one session, '
49
+ + 'while Builder still holds it: until its callback is delivered, or '
50
+ + '7 days undelivered. The callback is the normal way to get results. '
51
+ + 'Authenticates with the org API key: `orgToken`, else '
52
+ + '`RECLAIM_ORG_SECRET`. Encrypted deliveries also require '
41
53
  + 'the matching ETH decryption key. Returns `ready: false` until a '
42
54
  + 'payload is available. Invalid results fail verification and are not '
43
55
  + 'returned. Use `list_verification_events` to diagnose '
@@ -50,10 +62,19 @@ export function verificationResultTool() {
50
62
  type: 'string',
51
63
  description: 'The verification session id from create_verification_session.',
52
64
  },
65
+ orgToken: {
66
+ type: 'string',
67
+ pattern: '^rorg_',
68
+ maxLength: 200,
69
+ description: 'The organization API key (`rorg_…`): from '
70
+ + '`issue_org_token`, or the app\'s RECLAIM_ORG_SECRET. '
71
+ + 'Defaults to the MCP server\'s RECLAIM_ORG_SECRET. Never echo '
72
+ + 'it back to the user.',
73
+ },
53
74
  },
54
75
  },
55
76
  }, async (args) => {
56
- const secret = resolveOrgSecret();
77
+ const secret = resolveOrgSecret(args.orgToken);
57
78
  // Optional eth decryption key — absent ⇒ plaintext-only.
58
79
  const decryptionKey = await resolveDecryptionKey();
59
80
  const reclaim = ReclaimVerification.create({
@@ -70,13 +91,29 @@ export function verificationResultTool() {
70
91
  const resultRes = await reclaim.api('GetVerificationResult', {
71
92
  params: { sessionId: args.reclaimSessionId },
72
93
  });
73
- const { items } = resultRes.data;
94
+ const signed = resultRes.data.items
95
+ .filter((item) => RESULT_EVENTS.has(item.event));
96
+ if (!signed.length) {
97
+ return {
98
+ reclaimSessionId: args.reclaimSessionId,
99
+ status,
100
+ ready: false,
101
+ note: 'Session is terminal but no result is stored: none submitted '
102
+ + 'yet, or no callback subscription covers its ending event.',
103
+ };
104
+ }
105
+ // Builder keeps a result (which can carry proofs) only until its
106
+ // callback is delivered, or 7 days undelivered.
107
+ const items = signed.flatMap((item) => (item.payload === null ? [] : [{ ...item, payload: item.payload }]));
74
108
  if (!items.length) {
75
109
  return {
76
110
  reclaimSessionId: args.reclaimSessionId,
77
111
  status,
78
112
  ready: false,
79
- note: 'Session is terminal but no result has been submitted yet.',
113
+ delivered: signed.some((item) => (item.deliveryStatus === 'delivered')),
114
+ note: 'Builder no longer holds this result: it was delivered to '
115
+ + 'the callback (read it there), or went undelivered for 7 days. '
116
+ + 'See list_verification_deliveries.',
80
117
  };
81
118
  }
82
119
  // Each item's `payload` is an ECIES ciphertext encrypted to the org's
@@ -34,7 +34,9 @@ export function getProviderInfoTool(client) {
34
34
  description: 'Read a PUBLISHED provider from the public production SDK backend ' +
35
35
  '(api.reclaimprotocol.org — what the verification SDK/attestor ' +
36
36
  'itself fetches at runtime), for ANY provider, no auth required. ' +
37
- 'This is the provider-read tool for old-devtools mode. \n\n' +
37
+ 'This is the provider-read tool for old-devtools mode. A ' +
38
+ 'published provider is usable as-is: don\'t re-verify it ' +
39
+ '(capture/replay/proof) unless the user asks to test it.\n\n' +
38
40
  'Returns two complementary reads for the given version (latest ' +
39
41
  'when `versionNumber` is omitted): `provider` (the FULL provider ' +
40
42
  '+ providerConfig — `customInjection`, `userAgent`, ' +
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@reclaimprotocol/agent",
3
3
  "title": "Reclaim Agent",
4
- "version": "0.1.31",
4
+ "version": "0.1.33",
5
5
  "description": "Reclaim Protocol tools for AI coding agents. Reclaim lets your app verify data points about its users, such as a follower count, an account balance, or an order history. This package is the Reclaim MCP server: it gives your agent the tools to find, build, test, and fix data verification providers by capturing and replaying browser requests, drafting provider recipes, running zkTLS proofs, and publishing provider versions.",
6
6
  "type": "module",
7
7
  "main": "./lib/index.js",
@@ -83,7 +83,7 @@
83
83
  "@modelcontextprotocol/sdk": "^1.29.0",
84
84
  "@noble/hashes": "^2.2.0",
85
85
  "@reclaimprotocol/attestor-core": "^5.1.5",
86
- "@reclaimprotocol/client": "0.1.31",
86
+ "@reclaimprotocol/client": "0.1.33",
87
87
  "@reclaimprotocol/tls": "^0.1.3",
88
88
  "chrome-remote-interface": "^0.33.0",
89
89
  "domhandler": "^6.0.0",