@reclaimprotocol/agent 0.1.23 → 0.1.25

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 (149) hide show
  1. package/README.md +56 -20
  2. package/lib/authoring/backend.d.ts +5 -4
  3. package/lib/authoring/tools.js +30 -30
  4. package/lib/cdp/capture-engine.js +8 -7
  5. package/lib/cdp/claims.d.ts +21 -0
  6. package/lib/cdp/claims.js +129 -0
  7. package/lib/cdp/container.d.ts +85 -0
  8. package/lib/cdp/container.js +481 -0
  9. package/lib/cdp/geo.d.ts +10 -0
  10. package/lib/cdp/geo.js +36 -0
  11. package/lib/cdp/index.d.ts +1 -0
  12. package/lib/cdp/index.js +1 -0
  13. package/lib/live/cloudflared.d.ts +15 -0
  14. package/lib/live/cloudflared.js +268 -0
  15. package/lib/live/tunnel.d.ts +26 -0
  16. package/lib/live/tunnel.js +160 -0
  17. package/lib/mcp/api/operations.gen.js +34 -26
  18. package/lib/mcp/api/to-zod.d.ts +1 -1
  19. package/lib/mcp/api/to-zod.js +1 -1
  20. package/lib/mcp/api/tools.js +1 -1
  21. package/lib/mcp/instructions.d.ts +15 -2
  22. package/lib/mcp/instructions.js +102 -38
  23. package/lib/mcp/start.js +62 -6
  24. package/lib/mcp/tools/agent/analyze.js +5 -1
  25. package/lib/mcp/tools/agent/attach.d.ts +29 -2
  26. package/lib/mcp/tools/agent/attach.js +310 -24
  27. package/lib/mcp/tools/agent/build.d.ts +18 -8
  28. package/lib/mcp/tools/agent/build.js +30 -12
  29. package/lib/mcp/tools/agent/capture.js +5 -1
  30. package/lib/mcp/tools/agent/eval.js +3 -1
  31. package/lib/mcp/tools/agent/find.js +6 -5
  32. package/lib/mcp/tools/agent/how-it-works.d.ts +15 -7
  33. package/lib/mcp/tools/agent/how-it-works.js +57 -17
  34. package/lib/mcp/tools/agent/index.d.ts +1 -2
  35. package/lib/mcp/tools/agent/index.js +1 -1
  36. package/lib/mcp/tools/agent/live-view.d.ts +17 -0
  37. package/lib/mcp/tools/agent/live-view.js +146 -0
  38. package/lib/mcp/tools/agent/pod-proof.d.ts +8 -0
  39. package/lib/mcp/tools/agent/pod-proof.js +64 -0
  40. package/lib/mcp/tools/agent/propose.js +4 -2
  41. package/lib/mcp/tools/agent/publish.js +47 -77
  42. package/lib/mcp/tools/agent/session.d.ts +16 -1
  43. package/lib/mcp/tools/agent/session.js +32 -7
  44. package/lib/mcp/tools/authenticate/authenticate.js +26 -13
  45. package/lib/mcp/tools/mode/mode.d.ts +1 -1
  46. package/lib/mcp/tools/mode/mode.js +10 -22
  47. package/lib/old/client.d.ts +1 -1
  48. package/lib/old/client.js +1 -1
  49. package/lib/old/instructions.d.ts +9 -1
  50. package/lib/old/instructions.js +4 -6
  51. package/lib/old/login-cdp.d.ts +2 -2
  52. package/lib/old/login-cdp.js +46 -6
  53. package/lib/old/to-register.d.ts +3 -2
  54. package/lib/old/to-register.js +1 -1
  55. package/lib/old/tools/authenticate.js +9 -1
  56. package/lib/old/tools/get-provider-info.js +6 -5
  57. package/lib/old/tools/issue-app-credentials.js +3 -2
  58. package/lib/old/tools/publish.d.ts +1 -1
  59. package/lib/old/tools/publish.js +90 -131
  60. package/lib/old/tools/update-provider-metadata.d.ts +1 -1
  61. package/lib/old/tools/update-provider-metadata.js +1 -1
  62. package/lib/old/tools/verify-sdk-setup.js +1 -1
  63. package/lib/proof/attestor.d.ts +3 -3
  64. package/lib/proof/debug-response-dump.js +4 -4
  65. package/lib/proof/index.d.ts +1 -0
  66. package/lib/proof/index.js +1 -0
  67. package/lib/proof/page-replay.d.ts +1 -1
  68. package/lib/proof/page-replay.js +1 -1
  69. package/lib/proof/pod-prover.d.ts +47 -0
  70. package/lib/proof/pod-prover.js +155 -0
  71. package/lib/provider/dom-xpath.js +11 -9
  72. package/lib/provider/draft.d.ts +10 -7
  73. package/lib/provider/draft.js +11 -9
  74. package/lib/provider/injection-doc.d.ts +23 -1
  75. package/lib/provider/injection-doc.js +34 -21
  76. package/lib/provider/match-redaction-warning.d.ts +2 -2
  77. package/lib/provider/match-redaction-warning.js +3 -3
  78. package/lib/provider/matcher.js +13 -12
  79. package/lib/provider/secrets.d.ts +3 -3
  80. package/lib/provider/secrets.js +3 -3
  81. package/lib/provider/to-version.d.ts +7 -6
  82. package/lib/provider/to-version.js +3 -3
  83. package/lib/tools/registry.d.ts +5 -5
  84. package/lib/tools/registry.js +5 -5
  85. package/package.json +3 -3
  86. package/samples/demo-server/README.md +7 -6
  87. package/skill/SKILL.builder.md +356 -189
  88. package/skill/SKILL.common.md +400 -97
  89. package/skill/SKILL.old.md +340 -155
  90. package/skill/builder-mode.md +60 -17
  91. package/skill/hash-validation.md +170 -0
  92. package/skill/interception.md +236 -0
  93. package/skill/js-sdk-integration.md +13 -7
  94. package/skill/old-mode.md +62 -21
  95. package/skill/user-script.md +61 -0
  96. package/src/authoring/backend.ts +5 -4
  97. package/src/authoring/tools.ts +31 -30
  98. package/src/cdp/capture-engine.ts +8 -7
  99. package/src/cdp/claims.ts +153 -0
  100. package/src/cdp/container.ts +593 -0
  101. package/src/cdp/geo.ts +52 -0
  102. package/src/cdp/index.ts +1 -0
  103. package/src/consts.ts +1 -0
  104. package/src/live/cloudflared.ts +348 -0
  105. package/src/live/tunnel.ts +208 -0
  106. package/src/mcp/api/operations.gen.ts +34 -26
  107. package/src/mcp/api/to-zod.ts +1 -1
  108. package/src/mcp/api/tools.ts +1 -1
  109. package/src/mcp/instructions.ts +122 -48
  110. package/src/mcp/start.ts +69 -5
  111. package/src/mcp/tools/agent/analyze.ts +5 -1
  112. package/src/mcp/tools/agent/attach.ts +367 -26
  113. package/src/mcp/tools/agent/build.ts +35 -16
  114. package/src/mcp/tools/agent/capture.ts +5 -1
  115. package/src/mcp/tools/agent/eval.ts +4 -1
  116. package/src/mcp/tools/agent/find.ts +6 -5
  117. package/src/mcp/tools/agent/how-it-works.ts +62 -21
  118. package/src/mcp/tools/agent/index.ts +6 -2
  119. package/src/mcp/tools/agent/live-view.ts +182 -0
  120. package/src/mcp/tools/agent/pod-proof.ts +90 -0
  121. package/src/mcp/tools/agent/propose.ts +4 -2
  122. package/src/mcp/tools/agent/publish.ts +52 -77
  123. package/src/mcp/tools/agent/session.ts +33 -6
  124. package/src/mcp/tools/authenticate/authenticate.ts +28 -13
  125. package/src/mcp/tools/mode/mode.ts +10 -22
  126. package/src/old/client.ts +2 -2
  127. package/src/old/instructions.ts +4 -10
  128. package/src/old/login-cdp.ts +50 -6
  129. package/src/old/to-register.ts +3 -2
  130. package/src/old/tools/authenticate.ts +9 -1
  131. package/src/old/tools/get-provider-info.ts +6 -5
  132. package/src/old/tools/issue-app-credentials.ts +3 -2
  133. package/src/old/tools/publish.ts +95 -131
  134. package/src/old/tools/update-provider-metadata.ts +1 -1
  135. package/src/old/tools/verify-sdk-setup.ts +1 -1
  136. package/src/proof/attestor.ts +3 -3
  137. package/src/proof/debug-response-dump.ts +4 -4
  138. package/src/proof/index.ts +8 -0
  139. package/src/proof/page-replay.ts +1 -1
  140. package/src/proof/pod-prover.ts +231 -0
  141. package/src/provider/dom-xpath.ts +11 -9
  142. package/src/provider/draft.ts +13 -10
  143. package/src/provider/injection-doc.ts +37 -24
  144. package/src/provider/match-redaction-warning.ts +3 -3
  145. package/src/provider/matcher.ts +13 -12
  146. package/src/provider/secrets.ts +3 -3
  147. package/src/provider/to-version.ts +11 -9
  148. package/src/tools/registry.ts +5 -5
  149. package/skill/injection-api.md +0 -364
@@ -440,7 +440,7 @@ export const MCP_TOOLS = {
440
440
  }),
441
441
  },
442
442
  "CreateProvider": {
443
- 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.",
443
+ 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 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.",
444
444
  inputSchema: toZod({
445
445
  "type": "object",
446
446
  "properties": {
@@ -467,7 +467,7 @@ export const MCP_TOOLS = {
467
467
  "format": "uuid"
468
468
  },
469
469
  "domain": {
470
- "description": "Canonical root domain (e.g. `github.com`). No scheme, no port, no path.",
470
+ "description": "Canonical root domain (for example, `github.com`). No scheme, no port, no path.",
471
471
  "type": "string",
472
472
  "format": "hostname",
473
473
  "minLength": 1,
@@ -526,12 +526,12 @@ export const MCP_TOOLS = {
526
526
  "brandUrl": {
527
527
  "type": "string",
528
528
  "format": "uri",
529
- "description": "Canonical homepage of the brand (e.g. `https://google.com`). Used in brand-link cards and JSON-LD.",
529
+ "description": "Canonical homepage of the brand (for example, `https://google.com`). Used in brand-link cards and JSON-LD.",
530
530
  "maxLength": 2000
531
531
  },
532
532
  "primaryDataPoint": {
533
533
  "type": "string",
534
- "description": "Headline data point — the single most-important variable this provider can verify (e.g. `subscriber count`). Used in the provider's SEO title.",
534
+ "description": "Headline data point — the single most-important variable this provider can verify (for example, `subscriber count`). Used in the provider's SEO title.",
535
535
  "maxLength": 200
536
536
  },
537
537
  "dataPoints": {
@@ -636,10 +636,11 @@ export const MCP_TOOLS = {
636
636
  },
637
637
  "branch": {
638
638
  "type": "string",
639
- "description": "Branch (lifecycle stage) of this provider version.\n\n- `ai`: changes authored by the AI assistant live on this branch.\n\n- `draft`: a human is actively editing the version.\n\n- `in_review`: the author has submitted the version to be made\n public and it is awaiting review. On approval the branch tag\n is cleared (the version is promoted to the live channel and becomes\n public).\n\n- `rejected`: review concluded with a rejection. When the author\n addresses the feedback the branch transitions back to\n `in_review`.",
639
+ "description": "Branch (lifecycle stage) of this provider version.\n\n- `ai`: changes authored by the AI assistant live on this branch.\n\n- `draft`: a human is actively editing the version.\n\n- `fixed`: a proven AI repair. It remains pinned to its explicit\n version and does not replace the live trunk version.\n\n- `in_review`: the author has submitted the version to be made\n public and it is awaiting review. On approval the branch tag\n is cleared (the version is promoted to the live channel and becomes\n public).\n\n- `rejected`: review concluded with a rejection. When the author\n addresses the feedback the branch transitions back to\n `in_review`.",
640
640
  "enum": [
641
641
  "ai",
642
642
  "draft",
643
+ "fixed",
643
644
  "in_review",
644
645
  "rejected"
645
646
  ]
@@ -775,7 +776,7 @@ export const MCP_TOOLS = {
775
776
  "items": {
776
777
  "type": "object",
777
778
  "additionalProperties": false,
778
- "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. \"HTTP/1.1 200 OK\")",
779
+ "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (that is, \"HTTP/1.1 200 OK\")",
779
780
  "properties": {
780
781
  "xPath": {
781
782
  "type": "string",
@@ -783,7 +784,7 @@ export const MCP_TOOLS = {
783
784
  },
784
785
  "jsonPath": {
785
786
  "type": "string",
786
- "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'"
787
+ "description": "expect a JSON response, retrieve the item at this path using dot notation, for example 'email.addresses.0'."
787
788
  },
788
789
  "regex": {
789
790
  "type": "string",
@@ -926,7 +927,7 @@ export const MCP_TOOLS = {
926
927
  "items": {
927
928
  "type": "object",
928
929
  "additionalProperties": false,
929
- "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. \"HTTP/1.1 200 OK\")",
930
+ "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (that is, \"HTTP/1.1 200 OK\")",
930
931
  "properties": {
931
932
  "xPath": {
932
933
  "type": "string",
@@ -934,7 +935,7 @@ export const MCP_TOOLS = {
934
935
  },
935
936
  "jsonPath": {
936
937
  "type": "string",
937
- "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'"
938
+ "description": "expect a JSON response, retrieve the item at this path using dot notation, for example 'email.addresses.0'."
938
939
  },
939
940
  "regex": {
940
941
  "type": "string",
@@ -991,8 +992,8 @@ export const MCP_TOOLS = {
991
992
  "properties": {
992
993
  "geoLocation": {
993
994
  "type": "string",
994
- "description": "Geographic location (e.g. ISO country code or {{DYNAMIC_GEO}} to use user's geo location) the verification should appear to originate from.",
995
- "maxLength": 15,
995
+ "description": "Geographic location the verification should appear to originate from: a 2-letter ISO country code, or a parameter the attestor resolves at proof time. `{{DYNAMIC_GEO}}` and `{{DYNAMIC_GEO_SECRET}}` are the Verification Client's standard names for the end-user's own country — the `_SECRET` one is delivered as a secret param, so the attestor never learns which country the proof egressed from.",
996
+ "maxLength": 64,
996
997
  "default": "{{DYNAMIC_GEO}}"
997
998
  },
998
999
  "clientOptions": {
@@ -1386,7 +1387,7 @@ export const MCP_TOOLS = {
1386
1387
  }),
1387
1388
  },
1388
1389
  "DeleteProviderVersion": {
1389
- 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`.",
1390
+ 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. `fixed`, trunk (live), and `in_review` versions cannot be archived this way; archive the parent provider instead. Supports optimistic concurrency via `If-Match`.",
1390
1391
  inputSchema: toZod({
1391
1392
  "type": "object",
1392
1393
  "properties": {
@@ -1706,7 +1707,7 @@ export const MCP_TOOLS = {
1706
1707
  }),
1707
1708
  },
1708
1709
  "GetProviderVersion": {
1709
- description: "Get a specific provider version",
1710
+ description: "Get a specific provider version\n\nFetches one exact canonical version. Trunk is public when the provider is public. Non-trunk versions are visible to admins and members of the provider's organization. A member of the organization that paid for a successful AI repair may also read only the exact `fixed` version created by that repair.",
1710
1711
  inputSchema: toZod({
1711
1712
  "type": "object",
1712
1713
  "properties": {
@@ -2061,7 +2062,7 @@ export const MCP_TOOLS = {
2061
2062
  }),
2062
2063
  },
2063
2064
  "ListProviderVersions": {
2064
- 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.",
2065
+ description: "List a provider's versions\n\nLists versions visible to the caller. Non-public branches (`ai`, `draft`, `fixed`, `in_review`, `rejected`) are only visible to members of the provider's owning organization.",
2065
2066
  inputSchema: toZod({
2066
2067
  "type": "object",
2067
2068
  "properties": {
@@ -2210,7 +2211,7 @@ export const MCP_TOOLS = {
2210
2211
  }),
2211
2212
  },
2212
2213
  "Providers": {
2213
- 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.",
2214
+ description: "Search providers\n\nSearch Reclaim providers by domain or data point. A provider is the recipe an end-user follows to prove something about themselves, such as \"I have N followers on Twitter\".\nCall this BEFORE `create_provider` — most popular domains already have a public provider you can reuse, and creating another one just stacks duplicates.\nReturns a paginated list of the providers the caller can see: public providers to everyone, private providers only to members of the owning organization.",
2214
2215
  inputSchema: toZod({
2215
2216
  "type": "object",
2216
2217
  "properties": {
@@ -2567,7 +2568,7 @@ export const MCP_TOOLS = {
2567
2568
  "properties": {
2568
2569
  "notes": {
2569
2570
  "type": "string",
2570
- "description": "Optional note from the author to reviewers (changelog, areas to focus on, etc.).",
2571
+ "description": "Optional note from the author to reviewers (changelog, areas to focus on, and so on).",
2571
2572
  "maxLength": 10000
2572
2573
  }
2573
2574
  }
@@ -2724,6 +2725,13 @@ export const MCP_TOOLS = {
2724
2725
  "minLength": 1,
2725
2726
  "maxLength": 200
2726
2727
  },
2728
+ "region": {
2729
+ "type": "string",
2730
+ "nullable": true,
2731
+ "description": "Confirm or override the provider's region. Send `null` to clear it so the provider applies to every region. See `Provider.region`.",
2732
+ "pattern": "^[a-z]{2}(-[a-z]{2})?$",
2733
+ "maxLength": 5
2734
+ },
2727
2735
  "title": {
2728
2736
  "type": "string",
2729
2737
  "minLength": 1,
@@ -2776,12 +2784,12 @@ export const MCP_TOOLS = {
2776
2784
  "brandUrl": {
2777
2785
  "type": "string",
2778
2786
  "format": "uri",
2779
- "description": "Canonical homepage of the brand (e.g. `https://google.com`). Used in brand-link cards and JSON-LD.",
2787
+ "description": "Canonical homepage of the brand (for example, `https://google.com`). Used in brand-link cards and JSON-LD.",
2780
2788
  "maxLength": 2000
2781
2789
  },
2782
2790
  "primaryDataPoint": {
2783
2791
  "type": "string",
2784
- "description": "Headline data point — the single most-important variable this provider can verify (e.g. `subscriber count`). Used in the provider's SEO title.",
2792
+ "description": "Headline data point — the single most-important variable this provider can verify (for example, `subscriber count`). Used in the provider's SEO title.",
2785
2793
  "maxLength": 200
2786
2794
  },
2787
2795
  "dataPoints": {
@@ -2817,7 +2825,7 @@ export const MCP_TOOLS = {
2817
2825
  }),
2818
2826
  },
2819
2827
  "UpdateProviderVersion": {
2820
- 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`.",
2828
+ description: "Update a provider version\n\nMutable only while the version is on the `draft` or `rejected` branch. Versions on `fixed`, `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`.",
2821
2829
  inputSchema: toZod({
2822
2830
  "type": "object",
2823
2831
  "properties": {
@@ -2857,7 +2865,7 @@ export const MCP_TOOLS = {
2857
2865
  "body": {
2858
2866
  "type": "object",
2859
2867
  "additionalProperties": false,
2860
- "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.",
2868
+ "description": "Partial update of a provider version. Mutable only while the version is on the `draft` or `rejected` branch; versions on `fixed`, `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.",
2861
2869
  "properties": {
2862
2870
  "initialUrl": {
2863
2871
  "type": "string",
@@ -2996,7 +3004,7 @@ export const MCP_TOOLS = {
2996
3004
  "items": {
2997
3005
  "type": "object",
2998
3006
  "additionalProperties": false,
2999
- "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. \"HTTP/1.1 200 OK\")",
3007
+ "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (that is, \"HTTP/1.1 200 OK\")",
3000
3008
  "properties": {
3001
3009
  "xPath": {
3002
3010
  "type": "string",
@@ -3004,7 +3012,7 @@ export const MCP_TOOLS = {
3004
3012
  },
3005
3013
  "jsonPath": {
3006
3014
  "type": "string",
3007
- "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'"
3015
+ "description": "expect a JSON response, retrieve the item at this path using dot notation, for example 'email.addresses.0'."
3008
3016
  },
3009
3017
  "regex": {
3010
3018
  "type": "string",
@@ -3146,7 +3154,7 @@ export const MCP_TOOLS = {
3146
3154
  "items": {
3147
3155
  "type": "object",
3148
3156
  "additionalProperties": false,
3149
- "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (i.e. \"HTTP/1.1 200 OK\")",
3157
+ "description": "Which portions to select from a response. These are selected in order, xpath => jsonPath => regex * These redactions are done client side and only the selected portions are sent to the attestor. The attestor will only be able to see the selected portions alongside the first line of the HTTP response (that is, \"HTTP/1.1 200 OK\")",
3150
3158
  "properties": {
3151
3159
  "xPath": {
3152
3160
  "type": "string",
@@ -3154,7 +3162,7 @@ export const MCP_TOOLS = {
3154
3162
  },
3155
3163
  "jsonPath": {
3156
3164
  "type": "string",
3157
- "description": "expect a JSON response, retrieve the item at this path using dot notation for e.g. 'email.addresses.0'"
3165
+ "description": "expect a JSON response, retrieve the item at this path using dot notation, for example 'email.addresses.0'."
3158
3166
  },
3159
3167
  "regex": {
3160
3168
  "type": "string",
@@ -3211,8 +3219,8 @@ export const MCP_TOOLS = {
3211
3219
  "properties": {
3212
3220
  "geoLocation": {
3213
3221
  "type": "string",
3214
- "description": "Geographic location (e.g. ISO country code or {{DYNAMIC_GEO}} to use user's geo location) the verification should appear to originate from.",
3215
- "maxLength": 15,
3222
+ "description": "Geographic location the verification should appear to originate from: a 2-letter ISO country code, or a parameter the attestor resolves at proof time. `{{DYNAMIC_GEO}}` and `{{DYNAMIC_GEO_SECRET}}` are the Verification Client's standard names for the end-user's own country — the `_SECRET` one is delivered as a secret param, so the attestor never learns which country the proof egressed from.",
3223
+ "maxLength": 64,
3216
3224
  "default": "{{DYNAMIC_GEO}}"
3217
3225
  },
3218
3226
  "clientOptions": {
@@ -5,7 +5,7 @@ import type { JSONSchema } from 'zod/v4/core';
5
5
  *
6
6
  * The generator (`packages/app/scripts/mcp-tools-gen.ts`) inlines `$ref`s it
7
7
  * walks through `properties`/`items`, but it does NOT recurse into `allOf` /
8
- * `anyOf` / `oneOf`. So a schema composed with `allOf` (e.g.
8
+ * `anyOf` / `oneOf`. So a schema composed with `allOf` (for example,
9
9
  * `RequestSelectionTemplate =
10
10
  * allOf[ RequestSelection, { multiple, required } ]`,
11
11
  * surfaced by the proof tools' `allowedJsRequests`) can carry a dangling
@@ -4,7 +4,7 @@ import { z } from 'zod';
4
4
  *
5
5
  * The generator (`packages/app/scripts/mcp-tools-gen.ts`) inlines `$ref`s it
6
6
  * walks through `properties`/`items`, but it does NOT recurse into `allOf` /
7
- * `anyOf` / `oneOf`. So a schema composed with `allOf` (e.g.
7
+ * `anyOf` / `oneOf`. So a schema composed with `allOf` (for example,
8
8
  * `RequestSelectionTemplate =
9
9
  * allOf[ RequestSelection, { multiple, required } ]`,
10
10
  * surfaced by the proof tools' `allowedJsRequests`) can carry a dangling
@@ -2,7 +2,7 @@ import { remapErrorAsResponse } from "../remap_errors.js";
2
2
  import { MCP_TOOLS } from "./operations.gen.js";
3
3
  /**
4
4
  * The generated `MCP_TOOLS` are keyed by OpenAPI `operationId` (PascalCase,
5
- * e.g. `GetMe`). MCP tools are conventionally snake_case, matching the
5
+ * For example, `GetMe`). MCP tools are conventionally snake_case, matching the
6
6
  * hand-written tools in this server. Convert the public tool name here while
7
7
  * still dispatching to the API with the original operationId — doing this in
8
8
  * the (non-generated) registration keeps it from being reverted on regen.
@@ -1,3 +1,16 @@
1
1
  export declare const BUILDER_MODE_INSTRUCTIONS: string;
2
- export declare const PROVIDER_GUIDE_BUILDER: string;
3
- export declare const PROVIDER_GUIDE_OLD: string;
2
+ export declare const OLD_MODE_INSTRUCTIONS: string;
3
+ export interface Guide {
4
+ /** Topic name → its markdown, in document order. */
5
+ topics: Map<string, string>;
6
+ /** `{ topic, summary }` for every topic this mode has. */
7
+ index: Array<{
8
+ topic: string;
9
+ summary: string;
10
+ }>;
11
+ /** Every topic concatenated — the whole guide, as it used to be served. */
12
+ full: string;
13
+ }
14
+ export declare const GUIDE_BUILDER: Guide;
15
+ export declare const GUIDE_OLD: Guide;
16
+ export declare function guideFor(oldMode: boolean): Guide;
@@ -1,51 +1,115 @@
1
1
  /**
2
- * MCP server instructions shown to the LLM when running in BUILDER mode
3
- * (`USE_OLD_DEVTOOLS=false`). The prose lives in `skill/builder-mode.md`
4
- * (published via the `files` array) so it can be edited as markdown without
5
- * touching code. The path resolves identically from `src/mcp` (dev) and
6
- * `lib/mcp` (published) — both are two levels below the package root.
7
- * Old-devtools mode has its own reduced set in `../old/instructions.ts`.
2
+ * The authoring documentation, assembled from `skill/*.md` at module load.
3
+ *
4
+ * Two things are served from here:
5
+ * - the always-on MCP server `instructions` (one file per backend mode) —
6
+ * deliberately small, since every client pays for them on every turn;
7
+ * - the deep authoring guide, split into TOPICS and served on demand by the
8
+ * `how_it_works` tool. Nothing here is inlined into a tool schema: a doc
9
+ * embedded in an input-schema description is paid for on every request
10
+ * whether or not it's ever relevant.
11
+ *
12
+ * The prose lives in markdown (published via package.json's `files`) so it
13
+ * can be edited without touching code. Paths resolve identically from
14
+ * `src/mcp` (dev) and `lib/mcp` (published) — both are two levels below the
15
+ * package root.
16
+ *
17
+ * Assembly has three steps:
18
+ * 1. `<!-- common: name -->` splices a shared block out of `SKILL.common.md`
19
+ * (delimited there by `<!-- section: name -->`), so the two mode guides
20
+ * don't drift on the ~60% of prose that is identical.
21
+ * 2. `%CTX%` expands to the mode's consumer-param namespace — `context.` on
22
+ * the builder, `context_` on old-devtools. That is the only textual
23
+ * difference across most shared blocks, so tokenizing it keeps them
24
+ * shared.
25
+ * 3. `<!-- topic: name -->` splits the result into the units `how_it_works`
26
+ * serves. Backend-independent topics come from their own files instead.
8
27
  */
9
28
  import assert from 'node:assert';
10
29
  import { readFileSync } from 'node:fs';
11
30
  import { fileURLToPath } from 'node:url';
12
- export const BUILDER_MODE_INSTRUCTIONS = readFileSync(fileURLToPath(new URL('../../skill/builder-mode.md', import.meta.url)), 'utf8').trim();
13
- /**
14
- * `SKILL.builder.md` and `SKILL.old.md` share a lot of prose (steps that are
15
- * identical regardless of backend, "never do" rules, common troubleshooting).
16
- * That shared text lives once in `skill/SKILL.common.md`, split into named
17
- * `<!-- section: name -->`-delimited blocks; each mode file splices a block
18
- * back in at `<!-- common: name -->`. Parsed once at module load.
19
- */
20
- const COMMON_SECTIONS = parseCommonSections(readFileSync(fileURLToPath(new URL('../../skill/SKILL.common.md', import.meta.url)), 'utf8'));
21
- function parseCommonSections(text) {
22
- const sections = {};
23
- const re = /<!-- section: (\S+) -->\n([\s\S]*?)(?=\n<!-- section: |$)/g;
31
+ function readSkill(file) {
32
+ const url = new URL(`../../skill/${file}`, import.meta.url);
33
+ return readFileSync(fileURLToPath(url), 'utf8')
34
+ // Strip any leading frontmatter defensively.
35
+ .replace(/^---\n[\s\S]*?\n---\n/, '')
36
+ .trim();
37
+ }
38
+ export const BUILDER_MODE_INSTRUCTIONS = readSkill('builder-mode.md');
39
+ export const OLD_MODE_INSTRUCTIONS = readSkill('old-mode.md');
40
+ /** Split `<!-- marker: name -->`-delimited blocks, keeping document order. */
41
+ function splitBlocks(text, marker) {
42
+ const blocks = new Map();
43
+ const re = new RegExp(`<!-- ${marker}: (\\S+) -->\\n([\\s\\S]*?)(?=\\n<!-- ${marker}: |$)`, 'g');
24
44
  for (const match of text.matchAll(re)) {
25
- // Trim blank LINES only, not inline indentation — some sections are
45
+ // Trim blank LINES only, not inline indentation — some blocks are
26
46
  // list-continuation text that's intentionally indented on its first line.
27
- sections[match[1]] = match[2].replace(/^\n+/, '').replace(/\n+$/, '');
47
+ blocks.set(match[1], match[2].replace(/^\n+/, '').replace(/\n+$/, ''));
28
48
  }
29
- return sections;
49
+ return blocks;
30
50
  }
31
- /**
32
- * The full provider-authoring guide — the deep capture→prove→publish workflow,
33
- * decision frameworks, and troubleshooting. Served on demand by the
34
- * `how_it_works` MCP tool so every client (not just Claude Code, which
35
- * auto-loads skills) can pull it. There's a guide PER MODE so an agent is never
36
- * shown auth/publish tools that don't exist in its backend: the server picks
37
- * one by `oldMode` (see `mcp/start.ts`). Same `../../skill/` path resolution as
38
- * the instructions above; any leading frontmatter is stripped defensively.
39
- */
40
- function readGuide(file) {
41
- const url = new URL(file, import.meta.url);
42
- const raw = readFileSync(fileURLToPath(url), 'utf8');
43
- const stripped = raw.replace(/^---\n[\s\S]*?\n---\n/, '').trim();
44
- return stripped.replace(/<!-- common: (\S+) -->/g, (whole, name) => {
45
- const section = COMMON_SECTIONS[name];
51
+ const COMMON_SECTIONS = splitBlocks(readSkill('SKILL.common.md'), 'section');
52
+ /** Topics that read the same on both backends, each its own file. */
53
+ const SHARED_TOPIC_FILES = {
54
+ 'user-script': 'user-script.md',
55
+ 'interception': 'interception.md',
56
+ 'hash-validation': 'hash-validation.md',
57
+ };
58
+ /** One line per topic, shown in the `how_it_works` index so a caller can pick
59
+ * the right one without fetching several. Keyed across both modes; only the
60
+ * topics a mode actually has are listed back to it. */
61
+ const TOPIC_SUMMARIES = {
62
+ 'overview': 'Terminology, your stance, and the whole loop at a glance.',
63
+ 'auth': 'Signing in to the backend, and which token authorizes what.',
64
+ 'browser': 'Choosing a browser source (local Chrome, the Reclaim runtime in '
65
+ + 'Docker, a remote Popcorn browser, or a custom CDP endpoint), '
66
+ + 'geolocation, live view, and launch troubleshooting.',
67
+ 'capture': 'Tabs, login detection, driving the page, and picking an '
68
+ + 'authenticated request to prove.',
69
+ 'draft': 'The OPRF/privacy decision, propose_provider, and the canonical '
70
+ + 'drafted shape.',
71
+ 'params': 'Extracted vs consumer-supplied vs secret params, the URL '
72
+ + 'character budget, and runtime resolution.',
73
+ 'prove': 'replay_request, the mandatory auth-bound check, run_proof, and '
74
+ + 'diagnosing failures.',
75
+ 'publish': 'Creating/reusing a provider, versions, multi-request providers, '
76
+ + 'and going live.',
77
+ 'discover': 'Finding the right providers for a dev\'s app and creating a '
78
+ + 'verification session.',
79
+ 'user-script': 'Authoring jsUserScripts / customInjection to drive '
80
+ + 'login-gated pages.',
81
+ 'interception': 'injectionType / interceptorType, live interception, the '
82
+ + 'document-replay flag, and what to do when a site won\'t load or '
83
+ + 'won\'t let the user sign in.',
84
+ 'hash-validation': 'bodySniff, and how verifyProof({ providerId }) gates on '
85
+ + 'the declared spec hash.',
86
+ 'credentials': 'The eth proof-owner key run_proof signs with.',
87
+ 'never-do': 'The short list of things that always break a provider.',
88
+ 'troubleshooting': 'Expired drafts, browser problems, and where to look '
89
+ + 'next.',
90
+ };
91
+ function buildGuide(file, ctxPrefix) {
92
+ const raw = readSkill(file)
93
+ .replace(/<!-- common: (\S+) -->/g, (_whole, name) => {
94
+ const section = COMMON_SECTIONS.get(name);
46
95
  assert(section, `${file}: no SKILL.common.md section named "${name}"`);
47
96
  return section;
97
+ })
98
+ .replaceAll('%CTX%', ctxPrefix);
99
+ const topics = splitBlocks(raw, 'topic');
100
+ assert(topics.size, `${file}: no <!-- topic: … --> sections found`);
101
+ for (const [name, path] of Object.entries(SHARED_TOPIC_FILES)) {
102
+ topics.set(name, readSkill(path));
103
+ }
104
+ const index = [...topics.keys()].map((topic) => {
105
+ const summary = TOPIC_SUMMARIES[topic];
106
+ assert(summary, `${file}: no TOPIC_SUMMARIES entry for "${topic}"`);
107
+ return { topic, summary };
48
108
  });
109
+ return { topics, index, full: [...topics.values()].join('\n\n') };
110
+ }
111
+ export const GUIDE_BUILDER = buildGuide('SKILL.builder.md', 'context.');
112
+ export const GUIDE_OLD = buildGuide('SKILL.old.md', 'context_');
113
+ export function guideFor(oldMode) {
114
+ return oldMode ? GUIDE_OLD : GUIDE_BUILDER;
49
115
  }
50
- export const PROVIDER_GUIDE_BUILDER = readGuide('../../skill/SKILL.builder.md');
51
- export const PROVIDER_GUIDE_OLD = readGuide('../../skill/SKILL.old.md');
package/lib/mcp/start.js CHANGED
@@ -3,6 +3,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
3
  import { ReclaimClient } from '@reclaimprotocol/client';
4
4
  import { ConfigStore } from "../config/store.js";
5
5
  import { agentDisabled, apiToken, apiUrl, oldApiUrl, oldLogsUrl, resolveOldMode, sdkApiUrl, } from "../consts.js";
6
+ import { LOGGER } from "../logger.js";
6
7
  import { ReclaimOldClient } from "../old/client.js";
7
8
  import { resolveInitialIdentity } from "../old/identity.js";
8
9
  import { OLD_MODE_INSTRUCTIONS } from "../old/instructions.js";
@@ -10,7 +11,7 @@ import { ReclaimSdkClient } from "../old/sdk-client.js";
10
11
  import { buildOldBackendTools } from "../old/tools/build.js";
11
12
  import { NAME, VERSION } from "../pkg.js";
12
13
  import { registerTools } from "./api/tools.js";
13
- import { buildAgentState, buildAgentTools, buildBuilderAuthenticationTools, buildBuilderOrganizationTools, buildCredentialTools, buildLocalCredentialTools, buildModeTools, buildVerificationTools, readSession, } from "./tools/index.js";
14
+ import { buildAgentState, buildAgentTools, buildBuilderAuthenticationTools, buildBuilderOrganizationTools, buildCredentialTools, buildLocalCredentialTools, buildModeTools, buildVerificationTools, disposeAgentState, readSession, } from "./tools/index.js";
14
15
  import { BUILDER_MODE_INSTRUCTIONS } from "./instructions.js";
15
16
  import { registerToolList } from "./server.js";
16
17
  export async function startMcpServer() {
@@ -28,6 +29,8 @@ export async function startMcpServer() {
28
29
  // deployments — set RECLAIM_AGENT_DISABLED=1 to register only the API
29
30
  // surface.
30
31
  const agentToolsEnabled = !agentDisabled();
32
+ /** The agent state this server registered, for shutdown to release. */
33
+ let agentState;
31
34
  const builderClient = new ReclaimClient({
32
35
  baseUrl: apiUrl(),
33
36
  // Builder access is orthogonal to publishing mode. A legacy-devtools
@@ -50,8 +53,9 @@ export async function startMcpServer() {
50
53
  });
51
54
  const sdkClient = new ReclaimSdkClient({ baseUrl: sdkApiUrl() });
52
55
  // Shared with buildAgentTools below so the old-mode publish tool can see
53
- // the live attach state (e.g. to flag a still-open browser session).
54
- const agentState = buildAgentState();
56
+ // the live attach state (for example, to flag a still-open browser
57
+ // session).
58
+ agentState = buildAgentState();
55
59
  registerToolList(server, buildBuilderAuthenticationTools(builderClient));
56
60
  registerToolList(server, buildBuilderOrganizationTools(builderClient));
57
61
  registerToolList(server, buildLocalCredentialTools());
@@ -71,16 +75,68 @@ export async function startMcpServer() {
71
75
  // collision instead of one tool silently shadowing the other.
72
76
  // Register credential tools for ETH credential management.
73
77
  registerToolList(server, buildCredentialTools(client));
74
- // Higher-level verification orchestrations (e.g. fetch + decrypt result).
75
- // Authenticates with RECLAIM_ORG_SECRET, not the session client.
78
+ // Higher-level verification orchestrations (for example, fetch + decrypt
79
+ // result). Authenticates with RECLAIM_ORG_SECRET, not the session client.
76
80
  registerToolList(server, buildVerificationTools());
77
81
  // Add auto-generated tools with snake_case wrappers
78
82
  // for every MCP-tagged operation.
79
83
  registerTools(server, client);
80
84
  if (agentToolsEnabled) {
81
- registerToolList(server, buildAgentTools(client));
85
+ agentState = buildAgentState();
86
+ registerToolList(server, buildAgentTools(client, client, agentState));
82
87
  }
83
88
  }
89
+ // Anything the session holds has to be released when the session ends, and
90
+ // the session can end without a single tool call: the developer closes their
91
+ // agent, the client kills the server, stdin drops. Nothing ran here before,
92
+ // which left a container up and — worse — a public tunnel still pointing at a
93
+ // live browser after the session that made it was gone.
94
+ if (agentToolsEnabled) {
95
+ installShutdownHooks(() => agentState);
96
+ }
84
97
  const transport = new StdioServerTransport();
85
98
  await server.connect(transport);
86
99
  }
100
+ /** How long teardown gets before the process leaves anyway. */
101
+ const SHUTDOWN_GRACE_MS = 10000;
102
+ /**
103
+ * Release the browser on every way out we can observe.
104
+ *
105
+ * `SIGTERM`/`SIGINT` is how a client stops us; stdin ending is how a stdio
106
+ * transport says the other side is gone. A `SIGKILL` cannot be caught at all,
107
+ * which is why `reapOrphanedContainers` exists as the backstop.
108
+ */
109
+ function installShutdownHooks(state) {
110
+ let shuttingDown = false;
111
+ const shutdown = (reason) => {
112
+ if (shuttingDown) {
113
+ return;
114
+ }
115
+ shuttingDown = true;
116
+ const current = state();
117
+ if (!current) {
118
+ process.exit(0);
119
+ }
120
+ LOGGER.info({ reason }, 'releasing the browser before exit');
121
+ // Bounded: a wedged `docker stop` must not keep the process alive, but
122
+ // nor should we skip cleanup that would have finished in a second.
123
+ const timer = setTimeout(() => {
124
+ LOGGER.warn({ reason }, 'teardown timed out; exiting anyway');
125
+ process.exit(0);
126
+ }, SHUTDOWN_GRACE_MS);
127
+ timer.unref();
128
+ void disposeAgentState(current)
129
+ .catch((err) => {
130
+ LOGGER.warn({ err }, 'teardown failed');
131
+ })
132
+ .finally(() => {
133
+ clearTimeout(timer);
134
+ process.exit(0);
135
+ });
136
+ };
137
+ process.once('SIGTERM', () => shutdown('SIGTERM'));
138
+ process.once('SIGINT', () => shutdown('SIGINT'));
139
+ // The transport's own end of the conversation.
140
+ process.stdin.once('end', () => shutdown('stdin ended'));
141
+ process.stdin.once('close', () => shutdown('stdin closed'));
142
+ }
@@ -3,7 +3,11 @@ import { defineTool } from "../../server.js";
3
3
  export function analyzeTool(captures) {
4
4
  return defineTool({
5
5
  name: 'analyze_request_constraints',
6
- description: 'Flag potential provider-authoring concerns for a captured request.',
6
+ description: 'Flag provider-authoring concerns for one captured request — signed '
7
+ + 'request, CSRF dependency, bot challenge, short-lived token, '
8
+ + 'GraphQL. Call it on each top candidate from '
9
+ + 'find_requests_containing before drafting, and relay the returned '
10
+ + '`concerns` to the developer verbatim.',
7
11
  inputSchema: {
8
12
  type: 'object',
9
13
  properties: {
@@ -1,8 +1,18 @@
1
1
  import type { ReclaimClient } from '@reclaimprotocol/client';
2
2
  import { type CdpHandles, connectCdp, connectCdpUrl } from '../../../cdp/client.ts';
3
+ import { dockerAvailable, startContainer } from '../../../cdp/container.ts';
3
4
  import type { ConfigStore } from '../../../config/store.ts';
4
5
  import { type RegisteredTool } from '../../server.ts';
5
- export type BrowserMode = 'dedicated' | 'attach' | 'builder' | 'custom';
6
+ export type BrowserMode = 'dedicated' | 'attach' | 'builder' | 'custom' | 'container';
7
+ /**
8
+ * Modes with a live view that `share_browser_view` can put behind a public URL.
9
+ *
10
+ * Only `container`: it runs the Reclaim browser runtime, whose viewer already
11
+ * serves on loopback, so sharing is a tunnel in front of it. `builder` gives a
12
+ * hosted `liveViewUrl` instead, and a plain local browser has nothing to
13
+ * show — one on this machine is watched by looking at it.
14
+ */
15
+ export declare const SHAREABLE_MODES: Set<BrowserMode>;
6
16
  export interface AttachState {
7
17
  handles: CdpHandles;
8
18
  mode: BrowserMode;
@@ -10,6 +20,20 @@ export interface AttachState {
10
20
  liveViewUrl?: string;
11
21
  browserSessionId?: string;
12
22
  orgId?: string;
23
+ /** The Popcorn pod's own TEE api base (builder mode only) — lets
24
+ * `run_proof_via_pod` prove through the SAME enclave that holds the
25
+ * browser's TLS session (and its country-routed egress), instead of the
26
+ * local in-process attestor SDK. */
27
+ apiUrl?: string;
28
+ /** The exit country this remote browser was allocated with, if any. */
29
+ countryCode?: string;
30
+ /** Docker's name for a `container`-mode browser, for diagnostics. */
31
+ containerName?: string;
32
+ /** Loopback port the container's own live viewer serves on, which is what
33
+ * `share_browser_view` tunnels. Never the CDP port. */
34
+ viewerPort?: number;
35
+ /** Whether the runtime image had to be downloaded on this attach. */
36
+ imagePulled?: boolean;
13
37
  disposeRemote?: () => Promise<void>;
14
38
  }
15
39
  export interface AttachRef {
@@ -19,7 +43,10 @@ export interface AttachRef {
19
43
  interface AttachDependencies {
20
44
  connectLocal: typeof connectCdp;
21
45
  connectRemote: typeof connectCdpUrl;
46
+ /** Injected so container mode is testable without Docker installed. */
47
+ dockerAvailable: typeof dockerAvailable;
48
+ startContainer: typeof startContainer;
22
49
  }
23
- export declare function attachTool(state: AttachRef, builderClient?: ReclaimClient, name?: 'attach_browser' | 'attach_chrome', beforeReplace?: () => Promise<void>, dependencies?: AttachDependencies): RegisteredTool;
50
+ export declare function attachTool(state: AttachRef, builderClient?: ReclaimClient, beforeReplace?: () => Promise<void>, dependencies?: Partial<AttachDependencies>): RegisteredTool;
24
51
  export declare function disposeAttached(state: AttachRef): Promise<void>;
25
52
  export {};