@reclaimprotocol/agent 0.1.4 → 0.1.6

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 (126) hide show
  1. package/README.md +5 -5
  2. package/lib/authoring/backend.d.ts +71 -0
  3. package/lib/authoring/backend.js +24 -0
  4. package/lib/authoring/find.d.ts +3 -0
  5. package/lib/authoring/find.js +54 -0
  6. package/lib/authoring/index.d.ts +4 -0
  7. package/lib/authoring/index.js +6 -0
  8. package/lib/authoring/propose.d.ts +3 -0
  9. package/lib/authoring/propose.js +109 -0
  10. package/lib/authoring/replay.d.ts +10 -0
  11. package/lib/authoring/replay.js +34 -0
  12. package/lib/authoring/tools.d.ts +16 -0
  13. package/lib/authoring/tools.js +193 -0
  14. package/lib/authoring/util.d.ts +27 -0
  15. package/lib/authoring/util.js +21 -0
  16. package/lib/cdp/capture-engine.js +1 -1
  17. package/lib/consts.d.ts +6 -1
  18. package/lib/consts.js +9 -2
  19. package/lib/mcp/api/operations.gen.js +46 -18
  20. package/lib/mcp/server.d.ts +2 -25
  21. package/lib/mcp/server.js +4 -17
  22. package/lib/mcp/start.js +4 -2
  23. package/lib/mcp/tools/agent/analyze.js +3 -3
  24. package/lib/mcp/tools/agent/build.d.ts +4 -4
  25. package/lib/mcp/tools/agent/build.js +13 -15
  26. package/lib/mcp/tools/agent/capture.d.ts +13 -1
  27. package/lib/mcp/tools/agent/capture.js +18 -85
  28. package/lib/mcp/tools/agent/eval.d.ts +5 -2
  29. package/lib/mcp/tools/agent/eval.js +11 -121
  30. package/lib/mcp/tools/agent/find.d.ts +10 -3
  31. package/lib/mcp/tools/agent/find.js +25 -31
  32. package/lib/mcp/tools/agent/proof.d.ts +13 -3
  33. package/lib/mcp/tools/agent/proof.js +81 -132
  34. package/lib/mcp/tools/agent/propose.d.ts +10 -9
  35. package/lib/mcp/tools/agent/propose.js +87 -64
  36. package/lib/mcp/tools/agent/publish.js +2 -2
  37. package/lib/mcp/tools/agent/replay.d.ts +10 -3
  38. package/lib/mcp/tools/agent/replay.js +29 -36
  39. package/lib/mcp/tools/agent/session.d.ts +1 -3
  40. package/lib/mcp/tools/agent/session.js +5 -5
  41. package/lib/mcp/tools/agent/shared.d.ts +8 -0
  42. package/lib/mcp/tools/agent/shared.js +125 -0
  43. package/lib/old/client.d.ts +35 -0
  44. package/lib/old/client.js +18 -0
  45. package/lib/old/login-cdp.d.ts +24 -0
  46. package/lib/old/login-cdp.js +28 -3
  47. package/lib/old/sdk-client.d.ts +39 -0
  48. package/lib/old/sdk-client.js +85 -0
  49. package/lib/old/to-register.d.ts +69 -0
  50. package/lib/old/to-register.js +52 -2
  51. package/lib/old/tools/build.d.ts +6 -1
  52. package/lib/old/tools/build.js +11 -1
  53. package/lib/old/tools/get-provider-info.d.ts +16 -0
  54. package/lib/old/tools/get-provider-info.js +73 -0
  55. package/lib/old/tools/get-version-config.d.ts +17 -0
  56. package/lib/old/tools/get-version-config.js +47 -0
  57. package/lib/old/tools/publish.js +189 -2
  58. package/lib/old/tools/update-provider-metadata.d.ts +16 -0
  59. package/lib/old/tools/update-provider-metadata.js +61 -0
  60. package/lib/proof/attestor.d.ts +6 -3
  61. package/lib/proof/attestor.js +10 -1
  62. package/lib/proof/debug-response-dump.d.ts +4 -0
  63. package/lib/proof/debug-response-dump.js +55 -0
  64. package/lib/proof/patch-domhandler.d.ts +1 -0
  65. package/lib/proof/patch-domhandler.js +59 -0
  66. package/lib/proof/proof-core.d.ts +1 -1
  67. package/lib/proof/proof-core.js +1 -1
  68. package/lib/proof/zk-files.js +7 -6
  69. package/lib/provider/dom-xpath.d.ts +17 -0
  70. package/lib/provider/dom-xpath.js +187 -0
  71. package/lib/provider/draft.d.ts +30 -2
  72. package/lib/provider/draft.js +117 -28
  73. package/lib/provider/index.d.ts +4 -0
  74. package/lib/provider/index.js +7 -0
  75. package/lib/provider/injection-doc.js +6 -0
  76. package/lib/provider/matcher.d.ts +17 -20
  77. package/lib/provider/matcher.js +394 -280
  78. package/lib/provider/schema.d.ts +7 -5
  79. package/lib/tools/registry.d.ts +50 -0
  80. package/lib/tools/registry.js +49 -0
  81. package/package.json +9 -1
  82. package/skill/SKILL.builder.md +55 -32
  83. package/skill/SKILL.old.md +20 -12
  84. package/skill/builder-mode.md +1 -1
  85. package/skill/injection-api.md +117 -0
  86. package/src/authoring/backend.ts +98 -0
  87. package/src/authoring/index.ts +20 -0
  88. package/src/authoring/tools.ts +273 -0
  89. package/src/authoring/util.ts +42 -0
  90. package/src/cdp/capture-engine.ts +1 -1
  91. package/src/consts.ts +15 -2
  92. package/src/mcp/api/operations.gen.ts +46 -18
  93. package/src/mcp/server.ts +9 -39
  94. package/src/mcp/start.ts +4 -1
  95. package/src/mcp/tools/agent/analyze.ts +3 -3
  96. package/src/mcp/tools/agent/build.ts +13 -21
  97. package/src/mcp/tools/agent/capture.ts +31 -115
  98. package/src/mcp/tools/agent/eval.ts +19 -155
  99. package/src/mcp/tools/agent/find.ts +33 -36
  100. package/src/mcp/tools/agent/proof.ts +87 -160
  101. package/src/mcp/tools/agent/propose.ts +93 -85
  102. package/src/mcp/tools/agent/publish.ts +2 -2
  103. package/src/mcp/tools/agent/replay.ts +32 -42
  104. package/src/mcp/tools/agent/session.ts +4 -5
  105. package/src/mcp/tools/agent/shared.ts +152 -0
  106. package/src/old/client.ts +56 -0
  107. package/src/old/login-cdp.ts +28 -3
  108. package/src/old/sdk-client.ts +105 -0
  109. package/src/old/to-register.ts +98 -6
  110. package/src/old/tools/build.ts +12 -0
  111. package/src/old/tools/get-provider-info.ts +91 -0
  112. package/src/old/tools/get-version-config.ts +56 -0
  113. package/src/old/tools/publish.ts +244 -1
  114. package/src/old/tools/update-provider-metadata.ts +72 -0
  115. package/src/proof/attestor.ts +16 -4
  116. package/src/proof/debug-response-dump.ts +70 -0
  117. package/src/proof/patch-domhandler.ts +68 -0
  118. package/src/proof/proof-core.ts +1 -1
  119. package/src/proof/zk-files.ts +7 -6
  120. package/src/provider/dom-xpath.ts +225 -0
  121. package/src/provider/draft.ts +168 -35
  122. package/src/provider/index.ts +8 -0
  123. package/src/provider/injection-doc.ts +6 -0
  124. package/src/provider/matcher.ts +477 -357
  125. package/src/provider/schema.ts +7 -5
  126. package/src/tools/registry.ts +92 -0
@@ -98,7 +98,7 @@ export const MCP_TOOLS = {
98
98
  }),
99
99
  },
100
100
  "AdminProviders": {
101
- description: "All verifications (admin-only)\n\nAdmin only. Lists all verifications across all organizations. Supports filtering by visibility, status, and free-text search on title/domain/slug.",
101
+ description: "All providers (admin-only)\n\nAdmin only. Lists all providers across all organizations. Supports filtering by visibility, status, and free-text search on title/domain/slug.",
102
102
  inputSchema: toZod({
103
103
  "type": "object",
104
104
  "properties": {
@@ -485,7 +485,7 @@ export const MCP_TOOLS = {
485
485
  }),
486
486
  },
487
487
  "CreateProvider": {
488
- description: "Create a verification\n\nCreate a new Reclaim verification. Use this only after `providers` returned nothing useful for the domain. The caller must be an active member of the target organization.\nCreates a new verification in the specified organization. `visibility` is coerced to `PRIVATE` at creation regardless of what's sent; the author may toggle to `PUBLIC` later via `PATCH /providers/{id}`. While `PRIVATE`, versions go to the go live freely; once `PUBLIC`, non-admin versions need admin review. See `Provider.visibility`.\nThe server also seeds an initial `0.1.0` version on the `draft` branch in the same transaction so the verification is immediately editable. Its `initialUrl` defaults to `https://<domain>`; all other version fields fall back to their schema-declared defaults (structured verification, empty requests, empty web settings). `Provider.latestVersion` stays `null` until the draft is promoted to the live channel.",
488
+ description: "Create a provider\n\nCreate a new Reclaim provider. Use this only after `providers` returned nothing useful for the domain. The caller must be an active member of the target organization.\nCreates a new provider in the specified organization. `visibility` is coerced to `PRIVATE` at creation regardless of what's sent; the author may toggle to `PUBLIC` later via `PATCH /providers/{id}`. While `PRIVATE`, versions go to the go live freely; once `PUBLIC`, non-admin versions need admin review. See `Provider.visibility`.\nThe server also seeds an initial `0.1.0` version on the `draft` branch in the same transaction so the provider is immediately editable. Its `initialUrl` defaults to `https://<domain>`; all other version fields fall back to their schema-declared defaults (a `structured` verificationType, empty requests, empty web settings). `Provider.latestVersion` stays `null` until the draft is promoted to the live channel.",
489
489
  inputSchema: toZod({
490
490
  "type": "object",
491
491
  "properties": {
@@ -618,7 +618,7 @@ export const MCP_TOOLS = {
618
618
  }),
619
619
  },
620
620
  "CreateProviderVersion": {
621
- description: "Create a new verification version\n\nCreates a new version of the verification. The starting branch\ndepends on the verification's `visibility` and the caller's role:\n\n- `PRIVATE` verification (any caller): the live channel (no review).\n\n- `PUBLIC` verification, admin caller (Reclaim staff): the live channel\n (no review).\n\n- `PUBLIC` verification, non-admin caller: `draft` (or `ai` if\n authored by the AI assistant). Must pass review (see\n `POST /providers/{id}/versions/{version}/review`) before\n reaching the live channel.\n",
621
+ description: "Create a new provider version\n\nCreates a new version of the provider. The starting branch\ndepends on the provider's `visibility` and the caller's role:\n\n- `PRIVATE` provider (any caller): the live channel (no review).\n\n- `PUBLIC` provider, admin caller (Reclaim staff): the live channel\n (no review).\n\n- `PUBLIC` provider, non-admin caller: `draft` (or `ai` if\n authored by the AI assistant). Must pass review (see\n `POST /providers/{id}/versions/{version}/review`) before\n reaching the live channel.\n",
622
622
  inputSchema: toZod({
623
623
  "type": "object",
624
624
  "properties": {
@@ -644,7 +644,7 @@ export const MCP_TOOLS = {
644
644
  "body": {
645
645
  "type": "object",
646
646
  "additionalProperties": false,
647
- "description": "Body for creating a new version of a provider. Every new version starts on the `draft` branch — see `CreateProviderVersion`. The request body never sets `branch` directly; going live is a separate, explicit step (publish for PRIVATE, submit-for-review → approve for PUBLIC). The version's `verificationType` is always `structured` and is not settable here; a `prompt` field is reserved for a future AI authoring flow and is also not accepted on this surface.",
647
+ "description": "Body for creating a new version of a provider. Every new version starts on the `draft` branch — see `CreateProviderVersion`. The request body never sets `branch` directly; going live is a separate, explicit step (publish for PRIVATE, submit-for-review → approve for PUBLIC). `verificationType` defaults to `structured`; pass `llm` with a `prompt` to author an AI-verification provider.",
648
648
  "required": [
649
649
  "initialUrl",
650
650
  "requests",
@@ -652,6 +652,20 @@ export const MCP_TOOLS = {
652
652
  "webSettings"
653
653
  ],
654
654
  "properties": {
655
+ "verificationType": {
656
+ "type": "string",
657
+ "description": "How a provider version verifies a claim. `structured` uses the explicit match rules on this version (the `matches` / `allowedJsMatches` and related settings). `llm` defers the verification decision to a language model and requires `prompt` to be set.",
658
+ "enum": [
659
+ "llm",
660
+ "structured"
661
+ ]
662
+ },
663
+ "prompt": {
664
+ "type": "string",
665
+ "description": "Extraction prompt, used (and required) when `verificationType` is `llm`.",
666
+ "minLength": 0,
667
+ "maxLength": 1000000
668
+ },
655
669
  "version": {
656
670
  "type": "object",
657
671
  "additionalProperties": false,
@@ -1211,7 +1225,7 @@ export const MCP_TOOLS = {
1211
1225
  }),
1212
1226
  },
1213
1227
  "DecideProviderVersionReview": {
1214
- description: "Record a decision on a verification version review\n\nAdmin only (Reclaim staff). Approves or rejects a verification version currently on the `in_review` branch. `APPROVED` clears the branch tag and promotes the version to the live channel; `REJECTED` moves it to the `rejected` branch where the author can address feedback and resubmit. A rejected version stays rejected — the author either fixes and resubmits, or abandons it.\nUntil RBAC is designed, \"admin\" is detected via the user's email domain (`@reclaimprotocol.org`). Non-admin callers receive a 403.",
1228
+ description: "Record a decision on a provider version review\n\nAdmin only (Reclaim staff). Approves or rejects a provider version currently on the `in_review` branch. `APPROVED` clears the branch tag and promotes the version to the live channel; `REJECTED` moves it to the `rejected` branch where the author can address feedback and resubmit. A rejected version stays rejected — the author either fixes and resubmits, or abandons it.\nUntil RBAC is designed, \"admin\" is detected via the user's email domain (`@reclaimprotocol.org`). Non-admin callers receive a 403.",
1215
1229
  inputSchema: toZod({
1216
1230
  "type": "object",
1217
1231
  "properties": {
@@ -1384,7 +1398,7 @@ export const MCP_TOOLS = {
1384
1398
  }),
1385
1399
  },
1386
1400
  "DeleteProvider": {
1387
- description: "Delete a verification\n\nOwner of the verification's organization only. Soft-archives the verification (sets `status` to `ARCHIVED`) so historical references remain resolvable. Supports optimistic concurrency via `If-Match`.",
1401
+ description: "Delete a provider\n\nOwner of the provider's organization only. Soft-archives the provider (sets `status` to `ARCHIVED`) so historical references remain resolvable. Supports optimistic concurrency via `If-Match`.",
1388
1402
  inputSchema: toZod({
1389
1403
  "type": "object",
1390
1404
  "properties": {
@@ -1429,7 +1443,7 @@ export const MCP_TOOLS = {
1429
1443
  }),
1430
1444
  },
1431
1445
  "DeleteProviderVersion": {
1432
- description: "Delete a verification version\n\nSoft-archives a version on the `draft`, `ai`, or `rejected` branch — sets `status` to `ARCHIVED` so history is preserved. Trunk (live) and `in_review` versions cannot be archived this way; archive the parent verification instead. Supports optimistic concurrency via `If-Match`.",
1446
+ description: "Delete a provider version\n\nSoft-archives a version on the `draft`, `ai`, or `rejected` branch — sets `status` to `ARCHIVED` so history is preserved. Trunk (live) and `in_review` versions cannot be archived this way; archive the parent provider instead. Supports optimistic concurrency via `If-Match`.",
1433
1447
  inputSchema: toZod({
1434
1448
  "type": "object",
1435
1449
  "properties": {
@@ -1521,7 +1535,7 @@ export const MCP_TOOLS = {
1521
1535
  }),
1522
1536
  },
1523
1537
  "DiscoverResolve": {
1524
- description: "Resolve a website + data points to verification providers\n\nProvider resolution: given a website and the data points the user wants their users to prove, return the smallest set of existing providers whose data points COVER the selection (greedy combine), the `requiredContext` inputs the consumer must supply, and any `uncovered` points no provider exposes yet (`needsCreation` is true then — author a provider with the agent tools). When the chosen providers can be fused into one (same start page, no clashing page scripts) `merge.mergeable` is true.\n\nAgent flow: pick a website (`GET /discover/data-points` lists what's verifiable there), confirm the data points with the user, call this to get the `providers` + `requiredContext`, collect those context values from the user, then `POST /verifications/sessions` with `providers` (pass every id) and `context` to mint a verification.",
1538
+ description: "Resolve a website + data points to providers\n\nProvider resolution: given a website and the data points the user wants their users to prove, return the smallest set of existing providers whose data points COVER the selection (greedy combine), the `requiredContext` inputs the consumer must supply, and any `uncovered` points no provider exposes yet (`needsCreation` is true then — author a provider with the agent tools). When the chosen providers can be fused into one (same start page, no clashing page scripts) `merge.mergeable` is true.\n\nAgent flow: pick a website (`GET /discover/data-points` lists what's verifiable there), confirm the data points with the user, call this to get the `providers` + `requiredContext`, collect those context values from the user, then `POST /verifications/sessions` with `providers` (pass every id) and `context` to mint a verification.",
1525
1539
  inputSchema: toZod({
1526
1540
  "type": "object",
1527
1541
  "properties": {
@@ -1792,7 +1806,7 @@ export const MCP_TOOLS = {
1792
1806
  }),
1793
1807
  },
1794
1808
  "GetProvider": {
1795
- description: "Get a verification\n\nFetch a single Reclaim verification by id. Returns every field needed\nto integrate it into a flow: domain, the live version (initialUrl + requests),\nand the data points it can prove. Use `providers` first if you only\nhave a query string.\n\nReturns the verification record.\n\n**Canonical URL.** For SEO and stable sharing, the canonical\nHTML URL for a verification is `/providers/{providerId}/{slug}`\n(see `GetProviderBySlug`). HTML callers (`Accept: text/html`)\nthat hit this route — which omits the slug — receive a `301`\nredirect to the slugged URL. JSON callers\n(`Accept: application/json`) receive the body directly without\nredirect; the slug is on the response.\n",
1809
+ description: "Get a provider\n\nFetch a single Reclaim provider by id. Returns every field needed\nto integrate it into a flow: domain, the live version (initialUrl + requests),\nand the data points it can prove. Use `providers` first if you only\nhave a query string.\n\nReturns the provider record.\n\n**Canonical URL.** For SEO and stable sharing, the canonical\nHTML URL for a provider is `/providers/{providerId}/{slug}`\n(see `GetProviderBySlug`). HTML callers (`Accept: text/html`)\nthat hit this route — which omits the slug — receive a `301`\nredirect to the slugged URL. JSON callers\n(`Accept: application/json`) receive the body directly without\nredirect; the slug is on the response.\n",
1796
1810
  inputSchema: toZod({
1797
1811
  "type": "object",
1798
1812
  "properties": {
@@ -1827,7 +1841,7 @@ export const MCP_TOOLS = {
1827
1841
  }),
1828
1842
  },
1829
1843
  "GetProviderVersion": {
1830
- description: "Get a specific verification version",
1844
+ description: "Get a specific provider version",
1831
1845
  inputSchema: toZod({
1832
1846
  "type": "object",
1833
1847
  "properties": {
@@ -2165,7 +2179,7 @@ export const MCP_TOOLS = {
2165
2179
  }),
2166
2180
  },
2167
2181
  "ListProviderVersions": {
2168
- description: "List a verification's versions\n\nLists versions visible to the caller. Non-public branches (`ai`, `draft`, `in_review`, `rejected`) are only visible to members of the verification's owning organization.",
2182
+ description: "List a provider's versions\n\nLists versions visible to the caller. Non-public branches (`ai`, `draft`, `in_review`, `rejected`) are only visible to members of the provider's owning organization.",
2169
2183
  inputSchema: toZod({
2170
2184
  "type": "object",
2171
2185
  "properties": {
@@ -2320,7 +2334,7 @@ export const MCP_TOOLS = {
2320
2334
  }),
2321
2335
  },
2322
2336
  "Providers": {
2323
- description: "Search verifications\n\nSearch published Reclaim verifications by domain or data point. A verification is the recipe an end-user follows to prove something about themselves (e.g. \"I have N followers on Twitter\"). Returns a list of matches. Call this BEFORE `create_provider` — most popular domains already have a public verification you can reuse.\nCatalog page listing all verifications. Returns a paginated list of verifications the caller can see. Public verifications are visible to everyone; private verifications are only visible to org members.",
2337
+ description: "Search providers\n\nSearch published Reclaim providers by domain or data point. A provider is the recipe an end-user follows to prove something about themselves (e.g. \"I have N followers on Twitter\"). Returns a list of matches. Call this BEFORE `create_provider` — most popular domains already have a public provider you can reuse.\nCatalog page listing all providers. Returns a paginated list of providers the caller can see. Public providers are visible to everyone; private providers are only visible to org members.",
2324
2338
  inputSchema: toZod({
2325
2339
  "type": "object",
2326
2340
  "properties": {
@@ -2366,7 +2380,7 @@ export const MCP_TOOLS = {
2366
2380
  }),
2367
2381
  },
2368
2382
  "PublishProviderVersion": {
2369
- description: "Publish a draft version directly (PRIVATE providers only)\n\nPublishes a verification version on the `draft` branch directly to the live channel (trunk). Only allowed for PRIVATE providers — PUBLIC providers must use the review flow (`POST .../review` → admin decision). On success the version's branch transitions from `draft` to `null` (trunk/live).",
2383
+ description: "Publish a draft version directly (PRIVATE providers only)\n\nPublishes a provider version on the `draft` branch directly to the live channel (trunk). Only allowed for PRIVATE providers — PUBLIC providers must use the review flow (`POST .../review` → admin decision). On success the version's branch transitions from `draft` to `null` (trunk/live).",
2370
2384
  inputSchema: toZod({
2371
2385
  "type": "object",
2372
2386
  "properties": {
@@ -2615,7 +2629,7 @@ export const MCP_TOOLS = {
2615
2629
  }),
2616
2630
  },
2617
2631
  "SubmitProviderVersionForReview": {
2618
- description: "Submit a verification version for review\n\nSubmits a verification version (currently on the `draft` or `rejected` branch) for admin review. On success the version's branch transitions to `in_review`. Callable by any authenticated member of the verification's owning org. Meaningful only on `PUBLIC` verifications — on `PRIVATE` verifications new versions go to the live channel directly and never need review.",
2632
+ description: "Submit a provider version for review\n\nSubmits a provider version (currently on the `draft` or `rejected` branch) for admin review. On success the version's branch transitions to `in_review`. Callable by any authenticated member of the provider's owning org. Meaningful only on `PUBLIC` providers — on `PRIVATE` providers new versions go to the live channel directly and never need review.",
2619
2633
  inputSchema: toZod({
2620
2634
  "type": "object",
2621
2635
  "properties": {
@@ -2666,7 +2680,7 @@ export const MCP_TOOLS = {
2666
2680
  }),
2667
2681
  },
2668
2682
  "TransferProvider": {
2669
- description: "Transfer a verification to a different workspace\n\nAdmin-only. Moves the verification's `orgId` to the supplied workspace; preserves slug, versions, members. SQL function `builder.transfer_provider` enforces the admin gate and target existence atomically.",
2683
+ description: "Transfer a provider to a different workspace\n\nAdmin-only. Moves the provider's `orgId` to the supplied workspace; preserves slug, versions, members. SQL function `builder.transfer_provider` enforces the admin gate and target existence atomically.",
2670
2684
  inputSchema: toZod({
2671
2685
  "type": "object",
2672
2686
  "properties": {
@@ -2825,7 +2839,7 @@ export const MCP_TOOLS = {
2825
2839
  }),
2826
2840
  },
2827
2841
  "UpdateProvider": {
2828
- description: "Update a verification\n\nUpdate a Reclaim verification's metadata. Partial PATCH — pass only fields you want to change. The caller must be an active member of the owning organization. To change the verification's recipe (initialUrl, requests, …) cut a new version via the dashboard. Use `seo` to control how the verification appears in search results and social shares; omit a subfield to keep the server default.\nCaller must be a member of the verification's owning organization. `id`, `orgId`, and `slug` are immutable. Supports optimistic concurrency via `If-Match`.",
2842
+ description: "Update a provider\n\nUpdate a Reclaim provider's metadata. Partial PATCH — pass only fields you want to change. The caller must be an active member of the owning organization. To change the provider's recipe (initialUrl, requests, …) cut a new version via the dashboard. Use `seo` to control how the provider appears in search results and social shares; omit a subfield to keep the server default.\nCaller must be a member of the provider's owning organization. `id`, `orgId`, and `slug` are immutable. Supports optimistic concurrency via `If-Match`.",
2829
2843
  inputSchema: toZod({
2830
2844
  "type": "object",
2831
2845
  "properties": {
@@ -2962,7 +2976,7 @@ export const MCP_TOOLS = {
2962
2976
  }),
2963
2977
  },
2964
2978
  "UpdateProviderVersion": {
2965
- description: "Update a verification version\n\nMutable only while the version is on the `draft` or `rejected` branch. Versions on `in_review` or the live channel reject all writes here. Caller must be a member of the verification's owning organization. Supports optimistic concurrency via `If-Match`.",
2979
+ description: "Update a provider version\n\nMutable only while the version is on the `draft` or `rejected` branch. Versions on `in_review` or the live channel reject all writes here. Caller must be a member of the provider's owning organization. Supports optimistic concurrency via `If-Match`.",
2966
2980
  inputSchema: toZod({
2967
2981
  "type": "object",
2968
2982
  "properties": {
@@ -3004,13 +3018,27 @@ export const MCP_TOOLS = {
3004
3018
  "body": {
3005
3019
  "type": "object",
3006
3020
  "additionalProperties": false,
3007
- "description": "Partial update of a provider version. Mutable only while the version is on the `draft` or `rejected` branch; versions on `in_review` or the live channel reject all writes here. The semver does not change on update — `build_number` increments instead, giving callers a monotonic revision counter without touching the (major, minor, patch) PK. `verificationType` / `prompt` are not accepted; see `ProviderVersion` for why.",
3021
+ "description": "Partial update of a provider version. Mutable only while the version is on the `draft` or `rejected` branch; versions on `in_review` or the live channel reject all writes here. The semver does not change on update — `build_number` increments instead, giving callers a monotonic revision counter without touching the (major, minor, patch) PK. `verificationType` and `prompt` may be updated; omit either to carry the prior build's value forward.",
3008
3022
  "properties": {
3009
3023
  "initialUrl": {
3010
3024
  "type": "string",
3011
3025
  "format": "uri",
3012
3026
  "maxLength": 300
3013
3027
  },
3028
+ "verificationType": {
3029
+ "type": "string",
3030
+ "description": "How a provider version verifies a claim. `structured` uses the explicit match rules on this version (the `matches` / `allowedJsMatches` and related settings). `llm` defers the verification decision to a language model and requires `prompt` to be set.",
3031
+ "enum": [
3032
+ "llm",
3033
+ "structured"
3034
+ ]
3035
+ },
3036
+ "prompt": {
3037
+ "type": "string",
3038
+ "description": "Extraction prompt, used when `verificationType` is `llm`.",
3039
+ "minLength": 0,
3040
+ "maxLength": 1000000
3041
+ },
3014
3042
  "requests": {
3015
3043
  "type": "array",
3016
3044
  "minItems": 0,
package/src/mcp/server.ts CHANGED
@@ -1,46 +1,16 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
2
- import type { JSONSchema } from 'zod/v4/core'
2
+ import { type RegisteredTool } from '../tools/registry.ts'
3
3
  import { toZod } from './api/to-zod.ts'
4
4
  import { remapErrorAsResponse } from './remap_errors.ts'
5
5
 
6
- export interface ToolDefinition {
7
- name: string
8
- description: string
9
- inputSchema: JSONSchema.ObjectSchema
10
- }
11
-
12
- export interface RegisteredTool {
13
- definition: ToolDefinition
14
- /**
15
- * @param args Tool arguments
16
- * @returns A JSON stringifiable content to be returned to the llm
17
- * @throws Any error encountered during tool execution will be caught and
18
- * returned as a response using
19
- * [remapErrorAsResponse](./src/mcp/remap_errors.ts).
20
- */
21
- handler: (args: unknown) => Promise<unknown>
22
- }
23
-
24
- /**
25
- * Define a tool with a single inputSchema (JSON Schema) used as the
26
- * source of truth. The handler receives args already parsed and
27
- * type-narrowed via a Zod schema derived from that same JSON Schema —
28
- * so the description sent to the MCP client and the validation applied
29
- * to inbound args cannot drift.
30
- */
31
- export function defineTool<TArgs>(
32
- definition: ToolDefinition,
33
- handler: (args: TArgs) => Promise<unknown>,
34
- ): RegisteredTool {
35
- const schema = toZod(definition.inputSchema)
36
- return {
37
- definition,
38
- handler: async(raw) => {
39
- const args = schema.parse(raw) as TArgs
40
- return await handler(args)
41
- },
42
- }
43
- }
6
+ // The tool primitive lives in `../tools/registry.ts` (SDK-free, so the cloud
7
+ // loop can use it too). Re-exported here so the MCP-side tool files can keep
8
+ // importing `defineTool`/`RegisteredTool` from the server module.
9
+ export {
10
+ defineTool,
11
+ type RegisteredTool,
12
+ type ToolDefinition,
13
+ } from '../tools/registry.ts'
44
14
 
45
15
  /**
46
16
  * Registers a list of RegisteredTool entries on a high-level McpServer.
package/src/mcp/start.ts CHANGED
@@ -7,11 +7,13 @@ import {
7
7
  apiUrl,
8
8
  oldApiUrl,
9
9
  oldLogsUrl,
10
+ sdkApiUrl,
10
11
  useOldDevtools,
11
12
  } from '../consts.ts'
12
13
  import { ReclaimOldClient } from '../old/client.ts'
13
14
  import { resolveInitialIdentity } from '../old/identity.ts'
14
15
  import { OLD_MODE_INSTRUCTIONS } from '../old/instructions.ts'
16
+ import { ReclaimSdkClient } from '../old/sdk-client.ts'
15
17
  import { buildOldBackendTools } from '../old/tools/build.ts'
16
18
  import { NAME, VERSION } from '../pkg.ts'
17
19
  import { registerTools } from './api/tools.ts'
@@ -53,9 +55,10 @@ export async function startMcpServer() {
53
55
  logsBaseUrl: oldLogsUrl(),
54
56
  identity: resolveInitialIdentity(),
55
57
  })
58
+ const sdkClient = new ReclaimSdkClient({ baseUrl: sdkApiUrl() })
56
59
 
57
60
  registerToolList(server, buildLocalCredentialTools())
58
- registerToolList(server, buildOldBackendTools(oldClient))
61
+ registerToolList(server, buildOldBackendTools(oldClient, sdkClient))
59
62
  if(agentToolsEnabled) {
60
63
  // No builder client → no builder publish tool (old mode has its own).
61
64
  registerToolList(server, buildAgentTools())
@@ -18,12 +18,12 @@ export function analyzeTool(captures: CaptureStore): RegisteredTool {
18
18
  },
19
19
  },
20
20
  async({ captureId, requestId }) => {
21
- const session = captures.sessions.get(captureId)
22
- if(!session) {
21
+ const entry = captures.sessions.get(captureId)
22
+ if(!entry) {
23
23
  throw new Error(`no capture ${captureId}`)
24
24
  }
25
25
 
26
- const r = session.requests.get(requestId)
26
+ const r = entry.session.requests.get(requestId)
27
27
  if(!r) {
28
28
  throw new Error(`no request ${requestId} in capture ${captureId}`)
29
29
  }
@@ -4,8 +4,10 @@
4
4
  * `@modelcontextprotocol/sdk` `McpServer`. Folds the agent's tools
5
5
  * alongside the auto-generated API tools.
6
6
  *
7
- * Shared state — Chrome attach state, capture store, secret store — is
8
- * built once per server and threaded through every tool factory.
7
+ * Shared state — Chrome attach state + capture store — is built once per
8
+ * server and threaded through every tool factory. Per-capture drafts (and the
9
+ * secrets they hold) live inside each capture entry, so a capture IS the
10
+ * session for the shared authoring tools.
9
11
  */
10
12
 
11
13
  import type { ReclaimClient } from '@reclaimprotocol/client'
@@ -15,30 +17,21 @@ import { type RegisteredTool } from '../../server.ts'
15
17
  import { analyzeTool } from './analyze.ts'
16
18
  import { type AttachState, attachTool } from './attach.ts'
17
19
  import { type CaptureStore, captureTools } from './capture.ts'
18
- import { browserTools } from './eval.ts'
19
- import { findTool } from './find.ts'
20
+ import { listTabsTool } from './eval.ts'
20
21
  import { howItWorksTool } from './how-it-works.ts'
21
- import { proofTool } from './proof.ts'
22
- import {
23
- makeSecretStore,
24
- proposeTool,
25
- type SecretStore,
26
- } from './propose.ts'
27
22
  import { createVersionFromCaptureTool } from './publish.ts'
28
- import { replayTool } from './replay.ts'
29
23
  import { sessionTools } from './session.ts'
24
+ import { sharedAuthoringTools } from './shared.ts'
30
25
 
31
26
  export interface AgentState {
32
27
  attach: { current?: AttachState, config: ConfigStore }
33
28
  captures: CaptureStore
34
- secrets: SecretStore
35
29
  }
36
30
 
37
31
  function buildAgentState(): AgentState {
38
32
  return {
39
33
  attach: { config: new ConfigStore() },
40
34
  captures: { sessions: new Map() },
41
- secrets: makeSecretStore(),
42
35
  }
43
36
  }
44
37
 
@@ -57,24 +50,23 @@ export function buildAgentTools(
57
50
  // client. No `client` ⇒ old-devtools mode (see `mcp/start.ts`).
58
51
  tools.push(howItWorksTool(!client))
59
52
  tools.push(attachTool(state.attach))
53
+ tools.push(listTabsTool(state.attach))
60
54
  for(const t of captureTools(state.attach, state.captures)) {
61
55
  tools.push(t)
62
56
  }
63
57
 
64
- tools.push(findTool(state.captures))
65
- for(const t of browserTools(state.attach)) {
58
+ for(const t of sessionTools(state.attach, state.captures)) {
66
59
  tools.push(t)
67
60
  }
68
61
 
69
- for(const t of sessionTools(state.attach, state.captures, state.secrets)) {
62
+ tools.push(analyzeTool(state.captures))
63
+ // navigate / eval_in_page / wait_for_page / get_cookies / list_requests /
64
+ // find_requests_containing / propose_provider / replay_request / run_proof —
65
+ // shared with the cloud loop, bound to each capture's local backend.
66
+ for(const t of sharedAuthoringTools(state.captures)) {
70
67
  tools.push(t)
71
68
  }
72
69
 
73
- tools.push(analyzeTool(state.captures))
74
- tools.push(proposeTool(state.captures, state.secrets))
75
- tools.push(replayTool(state.secrets))
76
- tools.push(proofTool(state.secrets))
77
-
78
70
  if(client) {
79
71
  tools.push(createVersionFromCaptureTool(client))
80
72
  }
@@ -1,9 +1,22 @@
1
+ import { type DraftStore, makeDraftStore } from '../../../authoring/index.ts'
1
2
  import { type CaptureSession, startCapture } from '../../../cdp/capture.ts'
2
3
  import { defineTool, type RegisteredTool } from '../../server.ts'
3
4
  import type { AttachState } from './attach.ts'
4
5
 
6
+ /**
7
+ * One capture == a session (network requests) + the tab CDP client it runs on +
8
+ * a draft store. Bundling the tab client is what lets the shared authoring
9
+ * tools treat a `captureId` as a full session (drive the browser AND read
10
+ * capture AND hold drafts) behind one id.
11
+ */
12
+ export interface CaptureEntry {
13
+ session: CaptureSession
14
+ tabClient: Awaited<ReturnType<AttachState['handles']['attachToTab']>>
15
+ drafts: DraftStore
16
+ }
17
+
5
18
  export interface CaptureStore {
6
- sessions: Map<string, CaptureSession>
19
+ sessions: Map<string, CaptureEntry>
7
20
  activeTab?: string
8
21
  }
9
22
 
@@ -23,8 +36,9 @@ export function captureTools(
23
36
  {
24
37
  name: 'start_capture',
25
38
  description:
26
- 'Begin recording network requests on the specified tab. ' +
27
- 'Returns a captureId.',
39
+ 'Begin recording network requests on the specified tab. '
40
+ + 'Returns a captureId — the session handle the authoring tools '
41
+ + '(navigate, propose_provider, run_proof, …) all take.',
28
42
  inputSchema: {
29
43
  type: 'object',
30
44
  properties: { tabId: { type: 'string' } },
@@ -35,7 +49,9 @@ export function captureTools(
35
49
  const attached = requireAttached()
36
50
  const tabClient = await attached.handles.attachToTab(tabId)
37
51
  const session = await startCapture(tabClient)
38
- captures.sessions.set(session.captureId, session)
52
+ captures.sessions.set(session.captureId, {
53
+ session, tabClient, drafts: makeDraftStore(),
54
+ })
39
55
  captures.activeTab = tabId
40
56
  return { captureId: session.captureId }
41
57
  },
@@ -45,8 +61,8 @@ export function captureTools(
45
61
  {
46
62
  name: 'stop_capture',
47
63
  description:
48
- 'Stop recording on the given capture. ' +
49
- 'Captured data remains queryable until reset_session.',
64
+ 'Stop recording on the given capture. '
65
+ + 'Captured data remains queryable until reset_session.',
50
66
  inputSchema: {
51
67
  type: 'object',
52
68
  properties: { captureId: { type: 'string' } },
@@ -54,104 +70,13 @@ export function captureTools(
54
70
  },
55
71
  },
56
72
  async({ captureId }) => {
57
- const session = captures.sessions.get(captureId)
58
- if(!session) {
73
+ const entry = captures.sessions.get(captureId)
74
+ if(!entry) {
59
75
  throw new Error(`no capture ${captureId}`)
60
76
  }
61
77
 
62
- await session.stop()
63
- return { stopped: true, requestCount: session.requests.size }
64
- },
65
- )
66
-
67
- const listTool = defineTool<{
68
- captureId: string
69
- filter?: {
70
- method?: string
71
- urlGlob?: string
72
- statusMin?: number
73
- statusMax?: number
74
- contentType?: string
75
- graphqlOp?: string
76
- }
77
- }>(
78
- {
79
- name: 'list_requests',
80
- description:
81
- 'List metadata for captured requests. ' +
82
- 'Filter by method, URL glob, status, content-type, ' +
83
- 'or graphqlOp. Returns only metadata, never bodies — ' +
84
- 'use get_request for those.',
85
- inputSchema: {
86
- type: 'object',
87
- properties: {
88
- captureId: { type: 'string' },
89
- filter: {
90
- type: 'object',
91
- properties: {
92
- method: { type: 'string' },
93
- urlGlob: { type: 'string' },
94
- statusMin: { type: 'number' },
95
- statusMax: { type: 'number' },
96
- contentType: { type: 'string' },
97
- graphqlOp: { type: 'string' },
98
- },
99
- },
100
- },
101
- required: ['captureId'],
102
- },
103
- },
104
- async({ captureId, filter }) => {
105
- const session = captures.sessions.get(captureId)
106
- if(!session) {
107
- throw new Error(`no capture ${captureId}`)
108
- }
109
-
110
- const out = []
111
- for(const r of session.requests.values()) {
112
- if(filter?.method && r.method !== filter.method.toUpperCase()) {
113
- continue
114
- }
115
-
116
- if(filter?.urlGlob && !globMatch(filter.urlGlob, r.url)) {
117
- continue
118
- }
119
-
120
- if(filter?.statusMin !== undefined && r.status < filter.statusMin) {
121
- continue
122
- }
123
-
124
- if(filter?.statusMax !== undefined && r.status > filter.statusMax) {
125
- continue
126
- }
127
-
128
- if(
129
- filter?.contentType &&
130
- !r.contentType.includes(filter.contentType)
131
- ) {
132
- continue
133
- }
134
-
135
- if(filter?.graphqlOp && r.graphqlOp !== filter.graphqlOp) {
136
- continue
137
- }
138
-
139
- const item: Record<string, unknown> = {
140
- requestId: r.requestId,
141
- method: r.method,
142
- url: r.url,
143
- status: r.status,
144
- contentType: r.contentType,
145
- size: r.size,
146
- }
147
- if(r.graphqlOp !== undefined) {
148
- item.graphqlOp = r.graphqlOp
149
- }
150
-
151
- out.push(item)
152
- }
153
-
154
- return { requests: out }
78
+ await entry.session.stop()
79
+ return { stopped: true, requestCount: entry.session.requests.size }
155
80
  },
156
81
  )
157
82
 
@@ -170,17 +95,17 @@ export function captureTools(
170
95
  },
171
96
  },
172
97
  async({ captureId, requestId }) => {
173
- const session = captures.sessions.get(captureId)
174
- if(!session) {
98
+ const entry = captures.sessions.get(captureId)
99
+ if(!entry) {
175
100
  throw new Error(`no capture ${captureId}`)
176
101
  }
177
102
 
178
- const r = session.requests.get(requestId)
103
+ const r = entry.session.requests.get(requestId)
179
104
  if(!r) {
180
105
  throw new Error(`no request ${requestId} in capture ${captureId}`)
181
106
  }
182
107
 
183
- const body = session.bodies.get(requestId)
108
+ const body = entry.session.bodies.get(requestId)
184
109
  if(!body.available) {
185
110
  return { ...r, bodyAvailable: false, reason: body.reason }
186
111
  }
@@ -189,14 +114,5 @@ export function captureTools(
189
114
  },
190
115
  )
191
116
 
192
- return [startTool, stopTool, listTool, getTool]
193
- }
194
-
195
- function globMatch(pattern: string, str: string): boolean {
196
- const re = new RegExp(
197
- '^' +
198
- pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') +
199
- '$',
200
- )
201
- return re.test(str)
117
+ return [startTool, stopTool, getTool]
202
118
  }