@reclaimprotocol/agent 0.1.33 → 0.1.34

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 (88) hide show
  1. package/lib/authoring/backend.d.ts +13 -0
  2. package/lib/authoring/index.d.ts +1 -1
  3. package/lib/authoring/tools.js +78 -42
  4. package/lib/config/store.d.ts +10 -0
  5. package/lib/mcp/api/operations.gen.d.ts +238 -4
  6. package/lib/mcp/api/operations.gen.js +6433 -328
  7. package/lib/mcp/api/tools.js +21 -8
  8. package/lib/mcp/instructions.js +11 -11
  9. package/lib/mcp/server.d.ts +1 -1
  10. package/lib/mcp/server.js +3 -0
  11. package/lib/mcp/success-response.js +5 -1
  12. package/lib/mcp/tools/agent/analyze.js +5 -4
  13. package/lib/mcp/tools/agent/attach.js +11 -7
  14. package/lib/mcp/tools/agent/build.js +3 -1
  15. package/lib/mcp/tools/agent/capture.d.ts +2 -2
  16. package/lib/mcp/tools/agent/capture.js +15 -11
  17. package/lib/mcp/tools/agent/eval.js +4 -3
  18. package/lib/mcp/tools/agent/find.js +9 -10
  19. package/lib/mcp/tools/agent/how-it-works.js +1 -0
  20. package/lib/mcp/tools/agent/live-view.js +10 -7
  21. package/lib/mcp/tools/agent/pod-proof.js +7 -11
  22. package/lib/mcp/tools/agent/propose.js +4 -3
  23. package/lib/mcp/tools/agent/publish.d.ts +2 -1
  24. package/lib/mcp/tools/agent/publish.js +12 -6
  25. package/lib/mcp/tools/agent/replay.js +10 -7
  26. package/lib/mcp/tools/agent/session.js +16 -8
  27. package/lib/mcp/tools/agent/shared.js +3 -2
  28. package/lib/mcp/tools/agent/start-integration.d.ts +15 -0
  29. package/lib/mcp/tools/agent/start-integration.js +61 -0
  30. package/lib/mcp/tools/authenticate/authenticate.js +9 -11
  31. package/lib/mcp/tools/authenticate/build.js +2 -0
  32. package/lib/mcp/tools/authenticate/builder-access.js +1 -0
  33. package/lib/mcp/tools/authenticate/eth-key.d.ts +8 -0
  34. package/lib/mcp/tools/authenticate/eth-key.js +27 -15
  35. package/lib/mcp/tools/authenticate/import.js +18 -31
  36. package/lib/mcp/tools/authenticate/issue-org-token.d.ts +8 -0
  37. package/lib/mcp/tools/authenticate/issue-org-token.js +60 -0
  38. package/lib/mcp/tools/authenticate/issue.js +9 -9
  39. package/lib/mcp/tools/authenticate/org-key-store.d.ts +10 -0
  40. package/lib/mcp/tools/authenticate/org-key-store.js +23 -0
  41. package/lib/mcp/tools/authenticate/resolve-owner-key.js +10 -12
  42. package/lib/mcp/tools/mode/mode.js +2 -0
  43. package/lib/mcp/tools/verification/result.js +10 -7
  44. package/lib/tools/registry.d.ts +12 -0
  45. package/lib/tools/registry.js +1 -0
  46. package/package.json +2 -2
  47. package/skill/SKILL.builder.md +77 -74
  48. package/skill/SKILL.common.md +2 -1
  49. package/skill/builder-mode.md +135 -138
  50. package/skill/start-integration.md +49 -0
  51. package/skill/user-script.md +64 -0
  52. package/skill/verification-client-integration.md +28 -22
  53. package/src/authoring/backend.ts +15 -0
  54. package/src/authoring/index.ts +2 -0
  55. package/src/authoring/tools.ts +86 -42
  56. package/src/config/store.ts +11 -0
  57. package/src/mcp/api/operations.gen.ts +6477 -364
  58. package/src/mcp/api/tools.ts +21 -8
  59. package/src/mcp/instructions.ts +11 -11
  60. package/src/mcp/server.ts +4 -0
  61. package/src/mcp/success-response.ts +5 -1
  62. package/src/mcp/tools/agent/analyze.ts +5 -4
  63. package/src/mcp/tools/agent/attach.ts +11 -7
  64. package/src/mcp/tools/agent/build.ts +5 -1
  65. package/src/mcp/tools/agent/capture.ts +20 -12
  66. package/src/mcp/tools/agent/eval.ts +4 -3
  67. package/src/mcp/tools/agent/find.ts +9 -10
  68. package/src/mcp/tools/agent/how-it-works.ts +1 -0
  69. package/src/mcp/tools/agent/live-view.ts +10 -7
  70. package/src/mcp/tools/agent/pod-proof.ts +7 -11
  71. package/src/mcp/tools/agent/propose.ts +4 -3
  72. package/src/mcp/tools/agent/publish.ts +12 -4
  73. package/src/mcp/tools/agent/replay.ts +10 -7
  74. package/src/mcp/tools/agent/session.ts +16 -8
  75. package/src/mcp/tools/agent/shared.ts +7 -2
  76. package/src/mcp/tools/agent/start-integration.ts +83 -0
  77. package/src/mcp/tools/authenticate/authenticate.ts +9 -11
  78. package/src/mcp/tools/authenticate/build.ts +2 -0
  79. package/src/mcp/tools/authenticate/builder-access.ts +1 -0
  80. package/src/mcp/tools/authenticate/eth-key.ts +48 -18
  81. package/src/mcp/tools/authenticate/import.ts +21 -36
  82. package/src/mcp/tools/authenticate/issue-org-token.ts +84 -0
  83. package/src/mcp/tools/authenticate/issue.ts +9 -9
  84. package/src/mcp/tools/authenticate/org-key-store.ts +25 -0
  85. package/src/mcp/tools/authenticate/resolve-owner-key.ts +10 -12
  86. package/src/mcp/tools/mode/mode.ts +2 -0
  87. package/src/mcp/tools/verification/result.ts +10 -7
  88. package/src/tools/registry.ts +14 -0
@@ -11,32 +11,38 @@ Builder.
11
11
 
12
12
  ## The loop, at a glance
13
13
 
14
- Copy this checklist and check off each step as you finish it. Read the linked
15
- topic before a step you aren't already fluent in.
16
-
17
- - [ ] 1. `attach_browser` — pick a browser source with the developer.
18
- → topic `browser`
19
- - [ ] 2. `list_tabs` → `start_capture(tabId)` ⇒ **`captureId`**, your handle for
20
- everything below. → topic `capture`
21
- - [ ] 3. Drive the page: `navigate`, `wait_for_page`, `eval_in_page`,
22
- `get_cookies`. Detect login, land on the page showing the value, trigger
23
- the request. → topic `capture`
24
- - [ ] 4. `find_requests_containing` → `analyze_request_constraints` → pick an
25
- **authenticated** request. → topic `capture`
26
- - [ ] 5. `propose_provider(captureId, requestId, …)` ⇒ **`draftId`** (recipe +
27
- captured secrets, held server-side — secrets never enter the transcript).
28
- → topic `draft`
29
- - [ ] 6. Parameterize user-specific URL segments; mark secrets. → topic `params`
30
- - [ ] 7. `replay_request(captureId, draftId)`, then again with
14
+ Build a new org-private provider for the claim the developer described. Ask
15
+ one question if the site, account, or value is ambiguous. Copy this checklist
16
+ and check off each step. Read the linked topic before a step you don't know.
17
+
18
+ - [ ] 1. Name the data points: only the values the claim must prove, usually
19
+ one or two. No identity or profile fields.
20
+ - [ ] 2. `attach_browser`, then `list_tabs` → `start_capture(tabId)` ⇒
21
+ **`captureId`**. → topics `browser`, `capture`
22
+ - [ ] 3. Open the sign-in page and wait for the developer to sign in
23
+ (`wait_for_page`). → topic `capture`
24
+ - [ ] 4. Write the navigation script: sign-in redirect, then each data
25
+ point's page in order. → topic `user-script`
26
+ - [ ] 5. `test_user_script({ script, keep: true })`. Fix and retest until it
27
+ reaches every page, also after a reload.
28
+ - [ ] 6. Capture by letting the script navigate: `find_requests_containing` →
29
+ `analyze_request_constraints` → pick an **authenticated** request per
30
+ data point. → topic `capture`
31
+ - [ ] 7. `propose_provider(captureId, requestId, …)` ⇒ **`draftId`**
32
+ (`targets` = the data points). → topic `draft`
33
+ - [ ] 8. Parameterize user-specific URL segments; mark secrets.
34
+ → topic `params`
35
+ - [ ] 9. `replay_request(captureId, draftId)`, then again with
31
36
  `withoutSecrets: true`. → topic `prove`
32
- - [ ] 8. `run_proof(captureId, draftId, ownerAddress)`.
37
+ - [ ] 10. `run_proof(captureId, draftId, ownerAddress)`.
33
38
  → topics `prove`, `credentials`
34
- - [ ] 9. Resolve a `providerId` (**reuse before create**) →
35
- `create_provider_version_from_capture` → `publish_provider_version` or
39
+ - [ ] 11. `create_provider` (or a new version of a provider your org owns) →
40
+ `create_provider_version_from_capture` (publishes the kept script as
41
+ `webSettings.jsUserScripts`) → `publish_provider_version` or
36
42
  `submit_provider_version_for_review`. → topic `publish`
37
43
 
38
- Multi-request provider? Run steps 5–8 once per request, then publish every
39
- proven draft in one call. See topic `publish`.
44
+ Data points on different requests? Run steps 7-10 once per request, then
45
+ publish every proven draft in one call. See topic `publish`.
40
46
 
41
47
  <!-- topic: contributions -->
42
48
 
@@ -84,7 +90,7 @@ integration. Prefer Builder for new integrations.
84
90
  2. **Pick a tab and start the capture.** `list_tabs`, then
85
91
  `start_capture(tabId)` ⇒ a **`captureId`**: the session handle every browser
86
92
  and inspect tool takes as its first argument (`navigate`, `eval_in_page`,
87
- `wait_for_page`, `get_cookies`, `list_requests`, `find_requests_containing`,
93
+ `wait_for_page`, `list_requests`, `find_requests_containing`,
88
94
  `propose_provider`). If a tab is already on the right origin use it,
89
95
  otherwise the first is usually fine. Capturing from the start is harmless —
90
96
  it also records the login navigation. Then `navigate(captureId, url)` to
@@ -93,13 +99,18 @@ integration. Prefer Builder for new integrations.
93
99
 
94
100
  3. <!-- common: login-detect -->
95
101
 
96
- 4. **Navigate to the page that displays the value.** Construct the URL from what
97
- you know about the site; eval for anything you need (for example, GitHub's
98
- `meta[name="user-login"]`'s `content`), then `navigate(captureId, url)`.
102
+ 4. **Write and keep the navigation script** (topic `user-script`) as soon as
103
+ the developer is signed in, or the sign-in URL is known. Test it with
104
+ `test_user_script` and `keep: true`. The script visits each data point's
105
+ page; build its URLs from what you know about the site and read page state
106
+ with `eval_in_page` when needed (for example, GitHub's
107
+ `meta[name="user-login"]`'s `content`).
99
108
 
100
- 5. **Trigger the request.** Capture has been live since step 2, so make the
101
- call fire: `eval_in_page(captureId, "location.reload()")`, or click an
102
- element / hit a SPA route programmatically. Don't ask the developer to click.
109
+ 5. **Trigger the requests by letting the script navigate.** Capture has been
110
+ live since step 2. Reload the page (`eval_in_page(captureId,
111
+ "location.reload()")`) so the kept script runs from the start. Don't click
112
+ by hand or ask the developer to; if a request needs an interaction, add it
113
+ to the script.
103
114
 
104
115
  6. <!-- common: identify-value -->
105
116
 
@@ -126,8 +137,9 @@ integration. Prefer Builder for new integrations.
126
137
  under that `draftId`; the secrets never enter the transcript, so you carry the
127
138
  `draftId`, not the provider JSON, into replay/prove.
128
139
 
129
- **Extracting more than one value?** Prefer a **single request whose response
130
- contains all of them** and draft them together — one `responseMatches` +
140
+ **Extracting more than one value?** Add a value only when the claim needs it.
141
+ Prefer a **single request whose response contains all of them** and draft them
142
+ together — one `responseMatches` +
131
143
  `responseRedactions` pair per value. Find that request by running
132
144
  `find_requests_containing` for each value and picking a `requestId` common to
133
145
  all. Then pass a `targets` array, each entry with its `value` (exactly as it
@@ -136,7 +148,7 @@ appears) and a distinct `name`:
136
148
  ```
137
149
  propose_provider(captureId, requestId, name, targets: [
138
150
  { value: "Scratch-net", name: "username" },
139
- { value: "Alex", name: "name" },
151
+ { value: "2019", name: "member_since_year" },
140
152
  ])
141
153
  ```
142
154
 
@@ -313,16 +325,13 @@ parameterization applied. `initialUrl` is the page where the user logs in / the
313
325
  value is displayed (for example, `https://github.com/Syed`) — **not** the API
314
326
  endpoint URL inside the provider.
315
327
 
316
- **1. Reuse before create — this is how duplicates happen.**
317
- `create_provider_version_from_capture` requires a `providerId`. Before minting a
318
- new one, search your existing providers with `providers` (by domain / data
319
- point) — a site you've already built is there. Match → pass its
320
- `providerId` and the capture lands as a NEW VERSION on it. Only call
321
- `create_provider(orgId, domain, slug, title, description)` when none exists
322
- (`orgId` from `list_orgs`; `domain` such as `github.com`, `slug` such as
323
- `github-username`, `title` such as "GitHub Username"). It starts PRIVATE with an
324
- empty seed version. Routing every run through `create_provider` is what stacks
325
- duplicates in "My providers".
328
+ **1. Resolve the `providerId`.** For a new claim, call
329
+ `create_provider(orgId, domain, slug, title, description)` (`orgId` from
330
+ `list_orgs`; `domain` such as `github.com`, `slug` such as `github-username`,
331
+ `title` such as "GitHub Username"). It starts PRIVATE with an empty seed
332
+ version. Use an existing `providerId` only when your org owns the provider and
333
+ you are revising it: the capture lands as a NEW VERSION on it. For another
334
+ org's provider that almost fits, create your own provider and version.
326
335
 
327
336
  **2. Persist the version.**
328
337
  `create_provider_version_from_capture(providerId, provider, initialUrl, notes)`
@@ -339,12 +348,13 @@ or archive an existing version to apply provider changes.
339
348
  required at verification time. This proves that every request matched; it
340
349
  does not automatically bind a value extracted from one response to another
341
350
  request.
342
- - **Login/navigation-gated data:** supply `jsUserScripts` (plain page JS that
343
- drives login/waits/navigation so the target request fires), or
344
- `allowedJsRequests` (extra requests the script may fire, for example,
345
- pagination). → topic `user-script`. Before populating `allowedJsRequests` for
346
- a `verifyRequestProof({ providerId })` use case, read topic `hash-validation` — a
347
- session-unique URL there makes verifyRequestProof reject every real proof.
351
+ - **Navigation script:** the script kept with `test_user_script` (`keep: true`)
352
+ is published as `webSettings.jsUserScripts`. Pass `jsUserScripts` only to
353
+ override it. → topic `user-script`. For extra requests the script may fire
354
+ (for example, pagination), pass `allowedJsRequests`. Before populating it for
355
+ a `verifyRequestProof({ providerId })` use case, read topic
356
+ `hash-validation`: a session-unique URL there makes `verifyRequestProof`
357
+ reject every real proof.
348
358
 
349
359
  **3. `requiredContext` is derived for you.** The publish tool scans the recipe's
350
360
  url/body for `{{context.<name>}}` placeholders and emits a JSON Schema requiring
@@ -367,10 +377,8 @@ developer it's awaiting admin review.
367
377
  context params — for example, `context: { "username": "…" }` in
368
378
  `create_verification_session`. Quote the `requiredContext` from the created
369
379
  version verbatim — a session missing those fields gets a 400, and verification
370
- matches the supplied values exactly. Then ask once how they want to use it —
371
- try it now here, integrate it into an existing backend or frontend, or create a
372
- new app — unless they already said (see "Using a provider" in the server
373
- instructions).
380
+ matches the supplied values exactly. Then continue as the server
381
+ instructions say under "What the developer wants".
374
382
 
375
383
  **6. If the response includes `_notes` for an attached browser, follow them for
376
384
  an optional authenticated-state retest.** Only when its profile is still signed
@@ -383,35 +391,30 @@ the session for further edits; call `dispose_browser` only after they confirm.
383
391
  A `builder` session is quota-accounted, so don't leave it idle.
384
392
 
385
393
  <!-- topic: discover -->
386
- ## Discover and resolve providers for the developer's app
394
+ ## Discover and resolve existing providers
387
395
 
388
- When a developer wants to add verification but doesn't know which providers to
389
- use, run the same flow the Discover UI does:
396
+ Use this flow only when the developer asks to reuse existing providers or
397
+ doesn't know what a site supports. Otherwise build a new provider (server
398
+ instructions, "Choose the provider").
390
399
 
391
400
  1. Ask which website their users prove data from.
392
401
  2. `discover_data_points({ domain })` → what's verifiable there. Confirm the
393
402
  data points with the developer.
394
403
  3. `discover_resolve({ domain, dataPoints })` → the smallest provider set
395
404
  (`providers`, greedy combine), the `requiredContext` inputs to collect, and
396
- any `uncovered` points (author those with the flow above, then re-resolve).
397
- 4. Resolved providers are published and usable as-is: don't capture, replay,
398
- or prove them unless the developer asks you to check or test one. Ask once
399
- whether they just want to try them or want them in an app — just try it
400
- now, integrate into an existing backend or frontend (this directory or
401
- another path), or create a new app — unless they already said.
402
- 5. Just try it (no app, callback, or client package) →
403
- `create_verification_session({ providers: [{ providerId }, …], context,
404
- verificationClientUrl })` with EVERY resolved provider id and the collected
405
- context, give them `verificationUrl`, poll `get_verification_session` until
406
- it is terminal, and report the outcome with `get_verification_result`
407
- (builder-mode instructions cover the org key and temporary callback).
408
- Integrate or new app → topic `integration`.
409
-
410
- `merge.mergeable` only signals the set *could* collapse into one provider — you
411
- still pass them all; the Builder runs them in one session.
412
-
413
- For client integration, result verification, or TEE binding, read topic
414
- `integration`.
405
+ any `uncovered` points (author those with the checklist in topic
406
+ `overview`, then re-resolve).
407
+ 4. Use only the data points the developer confirmed: show and read only those
408
+ and ignore the rest. A provider that needs any change gets your own copy
409
+ (server instructions, "Choose the provider"). Otherwise it's usable as-is;
410
+ don't capture, replay, or prove it unless the developer asks.
411
+ 5. To try them: `create_verification_session({ providers: [{ providerId }, …],
412
+ context, verificationClientUrl })` with EVERY resolved provider id and the
413
+ collected context. The server instructions ("Try a provider without an
414
+ app") cover the callback and polling. To integrate: topic `integration`.
415
+
416
+ `merge.mergeable` only signals the set *could* collapse into one provider. Pass
417
+ them all; the Builder runs them in one session.
415
418
 
416
419
  <!-- topic: integration -->
417
420
 
@@ -424,7 +424,8 @@ conversation.
424
424
  1. **`resolve_owner_key`** returns only the derived address.
425
425
  - `{ ready: true, address }` → call `run_proof` with it. No prompts.
426
426
  - `{ ready: false }` → ask the developer once: **their own key** →
427
- `import_credentials({ privateKey: "0x…" })` (a `keyFile` path also works),
427
+ `import_credentials({ keyFile })` (a path to a file holding the key; never
428
+ ask them to paste it),
428
429
  or **a fresh one** → `issue_credentials({})` (a fine default for test
429
430
  proofs — owner identity doesn't matter). Either writes to the project
430
431
  `.env` (mode 0600, added to `.gitignore`), never to `~/.reclaim`. Then
@@ -1,146 +1,143 @@
1
1
  # Builder mode
2
2
 
3
- Reclaim provider-authoring tools run against the Builder backend. They include
4
- generated Builder API tools, credential and verification helpers, and browser
5
- authoring tools.
6
-
7
- ## Claimant-facing Builder sessions
8
-
9
- This integration is separate from provider authoring.
10
-
11
- **Using a provider.** A provider found with `providers`, `discover_resolve`, or
12
- another lookup is published and usable as-is. Don't capture, `replay_request`,
13
- or `run_proof` against it unless the developer asks you to check or test it.
14
- Before using a provider, found or just created, ask once whether they just want
15
- to try it or want it in an app (skip this if they already said):
16
-
17
- > Want to (1) just try it right now, (2) integrate it into an existing backend
18
- > or frontend (this directory or another path), or (3) create a new app for it?
19
-
20
- - **Just try it:** no app or client package, but the same production API the
21
- app will use. You need an org API key (`rorg_…`): reuse one the developer
22
- already has, else `issue_org_token` (owner only; the key is shown once).
23
- Session creation returns 409 while the org has no callback subscription, and
24
- the result is only stored for subscriptions to the event the session ends
25
- with. If the org has none, register a temporary one for all five ending
26
- events with `create_org_callback_subscription` (for example, a tunnel to a
27
- local listener that saves the body it receives). Then call
28
- `create_verification_session` with `orgToken`, give the developer
29
- `verificationUrl` to open, poll `get_verification_session` (with `orgToken`)
30
- until it is terminal, and report the outcome: from the body your listener
31
- received, or with `get_verification_result` (with `orgToken`), which only
32
- works until the callback is delivered. Delete the temporary subscription with
33
- `delete_org_callback_subscription` only after that: deleting it also deletes
34
- its stored results.
35
- - **Integrate, or new app:** follow the setup below in the path they named.
36
-
37
- **Org API key vs. sign-in.** Management tools (`list_orgs`,
38
- `create_org_callback_subscription`, `issue_org_token`, …) use the developer's
39
- sign-in. Session tools (`create_verification_session`,
40
- `get_verification_session`, `list_verification_events`,
41
- `list_verification_deliveries`, `retry_verification_callback`) are the
42
- production API a backend calls, so they take the org key as `orgToken`
43
- (defaulting to this server's `RECLAIM_ORG_SECRET`). Never print the key back to
44
- the developer.
45
-
46
- **Prefer the HTTP API over `@reclaimprotocol/client`** for every option:
47
- create sessions with `POST /verifications/sessions`, open `verificationUrl`,
48
- poll `GET /verifications/sessions/{sessionId}`, and take the result on the
49
- callback. Use the client package only when the developer asks for it — the one
50
- exception is `results.receive`, to verify the result on your callback.
51
-
52
- When integrating into an app, read `how_it_works({ topic: "integration" })`,
53
- then configure the organization with generated tools (`list_orgs`,
54
- `create_org`, `create_org_callback_subscription`, and owner-only
55
- `issue_org_token`) and edit the app's frontend and backend with the coding
56
- agent's file tools. The guide
57
- covers the HTTP session workflow, exact `api=2` boundary, result
58
- verification, request-proof contract, and optional TEE binding. A URL without
59
- `api=2` stays on its existing legacy path.
60
-
61
- **Existing `@reclaimprotocol/js-sdk` projects.** If the app's `package.json`
62
- depends on `@reclaimprotocol/js-sdk`, ask the developer before doing anything
63
- else:
3
+ Reclaim provider-authoring tools run against the Builder backend: generated
4
+ Builder API tools, credential and verification helpers, and browser authoring
5
+ tools.
6
+
7
+ **A provider is a recipe for extracting a data point from a site. A
8
+ verification is an end-user session that proves a data point with a provider.
9
+ Never call a provider a "verification."**
10
+
11
+ ## What the developer wants
12
+
13
+ - **"Add Reclaim to my app" or similar:** call `start_integration` first and
14
+ follow the plan it returns. Don't ask what they want to do with the result.
15
+ - **A claim they describe** (for example, "prove the user is over 18 on
16
+ example.com"): build a new org-private provider for exactly that claim. See
17
+ "Choose the provider".
18
+ - **Intent unclear:** ask one short question.
19
+
20
+ ### Choose the provider
21
+
22
+ Default: build a new provider for the claim the developer described. Use an
23
+ existing provider only when they name one or ask to reuse one.
24
+
25
+ With an existing provider, use only the data points the developer asked for.
26
+ Show the developer only those, collect only the inputs they need, and read
27
+ only those from results. Ignore the provider's other data points.
28
+
29
+ Make your own copy when it needs any change, for example it lacks a requested
30
+ data point, requires inputs the developer didn't ask for, or extracts a value
31
+ differently:
32
+
33
+ - Your org owns it: create a new provider version.
34
+ - Another org owns it: `create_provider`, then `create_provider_version` from a
35
+ copy of its config, trimmed to the requested data points.
36
+
37
+ Requirement ambiguous (site, account, or value): ask one concise question.
38
+ Don't guess.
39
+
40
+ A provider used as-is is published and ready. Don't capture, `replay_request`,
41
+ or `run_proof` against it unless the developer asks.
42
+
43
+ ### Try a provider without an app
44
+
45
+ Use the production API the app will use. Session creation returns 409 while the
46
+ org has no callback subscription, and results are stored only for subscriptions
47
+ to the event the session ends with.
48
+
49
+ 1. If the org has none, register a temporary subscription for all five ending
50
+ events with `create_org_callback_subscription` (for example, a tunnel to a
51
+ local listener that saves the body it receives).
52
+ 2. `create_verification_session`, then give the developer `verificationUrl`.
53
+ 3. Poll `get_verification_session` until it is terminal. Report the outcome
54
+ from the listener's body, or with `get_verification_result` (works only
55
+ until the callback is delivered).
56
+ 4. `delete_org_callback_subscription` only after that. Deleting it also
57
+ deletes its stored results.
58
+
59
+ ## Secrets
60
+
61
+ - Never print, echo, or ask the developer to paste an org key (`rorg_…`) or
62
+ private key.
63
+ - `issue_org_token` writes the key to the project's env file
64
+ (`RECLAIM_ORG_SECRET`) and returns only its last four characters. Session
65
+ and org-token tools use that key when you omit `orgToken`.
66
+ - `issue_credentials` and `import_credentials({ keyFile })` write the proof
67
+ owner key to the env file. Use these tools, not shell commands that read
68
+ secret files.
69
+
70
+ ## Integrating into an app
71
+
72
+ Call `start_integration`, then read `how_it_works({ topic: "integration" })`
73
+ for the HTTP session workflow, the `api=2` boundary, result verification, and
74
+ TEE binding. Edit the app with your file tools. Use the HTTP API
75
+ (`POST /verifications/sessions`, open `verificationUrl`, poll
76
+ `GET /verifications/sessions/{sessionId}`, read the callback) rather than
77
+ `@reclaimprotocol/client`. The only exception is `results.receive` on the
78
+ callback, or when the developer asks for the client package.
79
+
80
+ Management tools (`list_orgs`, `create_org_callback_subscription`,
81
+ `issue_org_token`) use the developer's sign-in. Session tools
82
+ (`create_verification_session`, `get_verification_session`,
83
+ `list_verification_events`, `list_verification_deliveries`,
84
+ `retry_verification_callback`) are the production API and use the org key.
85
+
86
+ **Existing `@reclaimprotocol/js-sdk` projects.** If `package.json` depends on
87
+ `@reclaimprotocol/js-sdk`, ask first:
64
88
 
65
89
  > This project uses `@reclaimprotocol/js-sdk`. Keep it (I switch this MCP
66
- > server to legacy devtools mode), or migrate to the Builder integration
67
- > (Builder HTTP API)?
68
-
69
- - **Keep js-sdk:** call `set_devtools_mode({ mode: "old" })`, then tell them to
70
- restart or reconnect the MCP server; the switch applies on the next start. An
71
- explicit `USE_OLD_DEVTOOLS` env var overrides it. After the restart, read
72
- `get_js_sdk_integration_guide`.
73
- - **Migrate:** stay in Builder mode. Follow `how_it_works({ topic:
74
- "integration" })` to replace `@reclaimprotocol/js-sdk` with the Builder
75
- HTTP session flow and update the app's code.
76
-
77
- **A `provider` is a recipe for extracting a data point from a site. A
78
- `verification` is an end-user session that proves a data point using one. Never
79
- call a provider a "verification."**
80
-
81
- **Provider versions are immutable in agent workflows.** Every recipe or
82
- configuration change creates a new semantic version. Default to a patch bump;
83
- use a major/minor bump or exact higher version when the user directs it. Never
84
- use an in-place provider-version update or archive tool.
90
+ > server to legacy devtools mode), or migrate to the Builder HTTP API?
91
+
92
+ - **Keep:** `set_devtools_mode({ mode: "old" })`, then tell them to restart or
93
+ reconnect the MCP server. An explicit `USE_OLD_DEVTOOLS` env var overrides
94
+ it. After the restart, read `get_js_sdk_integration_guide`.
95
+ - **Migrate:** stay in Builder mode and follow topic `integration`.
96
+
97
+ ## Authoring a provider
98
+
99
+ Provider versions are immutable. Every change creates a new semantic version
100
+ (default: patch bump; larger only when the developer directs). Never use an
101
+ in-place update or archive tool.
102
+
103
+ **The flow:** `attach_browser` → `start_capture` ⇒ `captureId` → sign in →
104
+ navigation script (`test_user_script` with `keep: true`) → capture through the
105
+ script → `find_requests_containing` → `propose_provider` ⇒ `draftId` →
106
+ `replay_request` → `run_proof` → `create_provider_version_from_capture` →
107
+ `publish_provider_version` (private) or `submit_provider_version_for_review`
108
+ (public). Get the checklist from `how_it_works({ topic: "overview" })`.
109
+
110
+ - **Data points:** propose only values the claim needs, usually one or two.
111
+ Never add identity or profile fields. Name each for what it proves.
112
+ - **Browser:** ask who signs in. The developer themselves: `dedicated` or
113
+ `attach` (local). Someone else, or a phone-only site: `container` (Docker,
114
+ free, shareable with `share_browser_view`) or `builder` (hosted,
115
+ **chargeable**). Say which costs money.
116
+ - **Public endpoints:** after `replay_request` succeeds, re-run it with
117
+ `withoutSecrets: true`. If the value still extracts, the endpoint is public
118
+ and the proof binds to nobody. Find an auth-bound request.
119
+ - **Drafting limits** (topics `draft`, `params`): never `hash` a value that
120
+ also appears in the request URL. A param named with `SECRET` may appear in a
121
+ URL only within a small character budget (2 under `key-update`, 12 under
122
+ `zk`).
85
123
 
86
124
  ## Evidence contract
87
125
 
88
- Tool results are the source of truth. Never say that a browser attached, a user
89
- logged in, a request was captured, a proof passed, or a version was created or
90
- published unless the corresponding tool result says it happened. A planned tool
91
- call is not a completed action.
92
-
93
- Treat every ID, semantic version, URL, request value, and error as opaque: copy
94
- it from the latest tool result exactly. Never invent, autocomplete, reconstruct,
95
- shorten, or reuse one from memory. When state is missing or ambiguous, inspect
96
- it with the relevant get/list/status tool or call `how_it_works` before
97
- answering. State uncertainty plainly instead of guessing.
98
-
99
- **Use the guide as needed.** Call `how_it_works({})` for its topic index, then
100
- fetch only the topic relevant to the next tool call.
101
-
102
- **Authentication:** try `get_me` first. On 401, `authenticate({})` returns a
103
- device-pairing `code` + `attachUrl` — give the user the URL, then poll
104
- `authenticate({ code })` until LINKED. Tokens cache ~2 days.
105
- (→ `how_it_works({ topic: "auth" })`)
106
-
107
- **Ask who is doing the signing in, then offer a browser.** "Yourself, or does
108
- someone else need to log in?" decides half of `attach_browser`'s list. Doing it
109
- themselves → `dedicated` or `attach`, both local, neither shareable. Someone
110
- else, or a phone-only site → `container` (the Reclaim runtime in Docker, free,
111
- shareable with `share_browser_view`) or `builder` (hosted, no install,
112
- **chargeable**). Say which costs money, and say `container` exists at all:
113
- nobody guesses it.
114
-
115
- **The flow:** `attach_browser` (ask the developer which browser source — local
116
- Chrome, the Reclaim runtime in Docker, a remote Builder browser, or a CDP URL
117
- they supply) → `start_capture`
118
- ⇒ **`captureId`** (the handle every browser/inspect tool takes first) → drive
119
- the page (`navigate`, `wait_for_page`, `eval_in_page`, `get_cookies`) → inspect
120
- (`list_requests`, `get_request`, `find_requests_containing`) →
121
- `propose_provider` ⇒ **`draftId`** (recipe + captured secrets, held server-side
122
- — secrets never enter the transcript) → `replay_request(captureId, draftId)` →
123
- `run_proof(captureId, draftId, ownerAddress)` → resolve a `providerId` →
124
- `create_provider_version_from_capture` (lands on the draft branch) →
125
- `publish_provider_version` (PRIVATE) or `submit_provider_version_for_review`
126
- (PUBLIC).
127
-
128
- **Reuse before create.** `create_provider_version_from_capture` needs a
129
- `providerId`. Search your existing providers with `providers` (by domain / data
130
- point) BEFORE calling `create_provider` — routing every run through
131
- `create_provider` is what stacks duplicates in "My providers".
132
-
133
- **Never prove a public endpoint.** After `replay_request` succeeds, re-run it
134
- with `withoutSecrets: true`. If the value still extracts, the endpoint is public
135
- and the proof binds to nobody — find an auth-bound request instead.
136
-
137
- **Two hard constraints when drafting** (details in topics `draft` / `params`):
138
- never `hash`/OPRF a value that also appears in the request URL; any param named
139
- with `SECRET` may be used in a URL only within a tiny TOTAL character budget (2
140
- under `key-update`, 12 under `zk`), checked at verification time.
141
-
142
- **Backend mode:** this server can instead run against the devtools backend with
143
- a reduced tool set. `get_devtools_mode` reports the active mode and why;
126
+ Tool results are the source of truth. Never say a browser attached, a user
127
+ signed in, a request was captured, a proof passed, or a version was created or
128
+ published unless a tool result says so.
129
+
130
+ Treat every ID, version, URL, and value as opaque: copy it from the latest tool
131
+ result. Never invent or reconstruct one. When state is unclear, call the
132
+ relevant get/list tool or `how_it_works`. State uncertainty plainly.
133
+
134
+ **Guide:** `how_it_works({})` lists topics. Fetch only the one for your next
135
+ step.
136
+
137
+ **Authentication:** call `get_me`. On 401, `authenticate({})` returns `code`
138
+ and `attachUrl`. Give the developer the URL, then poll `authenticate({ code })`
139
+ until LINKED (topic `auth`).
140
+
141
+ **Backend mode:** `get_devtools_mode` reports the active mode.
144
142
  `set_devtools_mode` persists a switch to `~/.reclaim/config.json`, effective on
145
- the NEXT server start. An explicit `USE_OLD_DEVTOOLS` env var wins over the
146
- persisted choice.
143
+ the next server start. An explicit `USE_OLD_DEVTOOLS` env var wins.
@@ -0,0 +1,49 @@
1
+ # Plan: let users prove "{{goal}}" in this app
2
+
3
+ Follow this plan end to end. Mark each step done as you go. Do not ask the developer whether to integrate: integrating into this codebase is the goal.
4
+
5
+ ## 1. Sign in and pick the organization
6
+
7
+ - [ ] Call `reclaim_authenticate` if you are not signed in. The developer approves in their browser.
8
+ <!-- if:orgId -->
9
+ - [ ] Use organization `{{orgId}}` for every call below.
10
+ <!-- endif -->
11
+ <!-- ifnot:orgId -->
12
+ - [ ] Call `list_orgs`. Use the only organization, or ask the developer which one when there are several.
13
+ <!-- endif -->
14
+
15
+ ## 2. Get a provider
16
+
17
+ <!-- if:providerIds -->
18
+ - [ ] Use these existing providers: {{providerIds}}. Read each with `get_provider` and keep only the data points "{{goal}}" needs. Show the developer and use only those; ignore the rest.
19
+ - [ ] If a provider needs any change (a missing data point, inputs the developer didn't ask for, a different value), make your own copy as the server instructions describe ("Choose the provider"). Otherwise skip to step 3.
20
+ <!-- endif -->
21
+ <!-- ifnot:providerIds -->
22
+ Build a new organization-private provider for exactly "{{goal}}". Do not search published providers first.
23
+
24
+ - [ ] If the site, the account, or the value to prove is unclear, ask one concise question. Otherwise do not ask.
25
+ - [ ] Choose the minimum data points: only the values the claim needs, usually one or two. Add no profile or identity extras.
26
+ - [ ] If the developer names an existing provider, use only the data points they asked for and ignore the rest. If it needs any change, make your own copy: a new version when the organization owns it, otherwise a new organization provider from a copy of its config.
27
+ - [ ] Call `how_it_works` with topics `overview`, `user-script`, `capture`, and `publish` before you start. Do not repeat their detail here.
28
+ - [ ] Call `attach_browser` without `mode`, ask the developer which browser to use, then call it again with their choice. Use `start_capture` on the tab.
29
+ - [ ] Open the sign-in page with `navigate`. The developer signs in; use `wait_for_login`.
30
+ - [ ] Write the navigation script first. Signed out, it goes to the sign-in page. After sign-in, it visits each data page in order. It must stay correct across reloads.
31
+ - [ ] Test it with `test_user_script` and `keep: true`. The kept script stays installed for every later navigation and is published with the provider version.
32
+ - [ ] While the script drives the browser, find the request that returns each data point (`find_requests_containing`, then `analyze_request_constraints`).
33
+ - [ ] Call `propose_provider` with only the needed data points.
34
+ - [ ] Call `replay_request`, then `replay_request` with `withoutSecrets: true` to confirm the request is auth-bound.
35
+ - [ ] Call `resolve_owner_key`, then `run_proof`.
36
+ - [ ] Call `create_provider_version_from_capture`. It publishes the kept script as `jsUserScripts`. Follow its `_notes`, then publish the version.
37
+ - [ ] Call `dispose_browser` after asking the developer.
38
+ <!-- endif -->
39
+
40
+ ## 3. Integrate into this codebase
41
+
42
+ - [ ] Read `how_it_works({ topic: "integration" })`.
43
+ - [ ] Detect the app's framework and package manager from the repository, and use them.
44
+ - [ ] Call `issue_org_token` with the organization, this project's absolute path, and the server env file. It writes the key to that file and never returns it. Never print or commit the key. Confirm the env file is in `.gitignore`.
45
+ - [ ] Add a backend route that creates a verification session (`POST /verifications/sessions`) for the provider and returns `verificationUrl`.
46
+ - [ ] Add a callback route that verifies each result with `results.receive` from `@reclaimprotocol/client`, then stores only the requested data points.
47
+ - [ ] Call `create_org_callback_subscription` for the result events, pointing at the callback route. Use a tunnel for local development.
48
+ - [ ] Add a frontend Verify button that opens `verificationUrl`, and shows the stored result when it arrives.
49
+ - [ ] Run the app, then tell the developer exactly how to test end to end: open the app, click Verify, sign in, and see the stored result.