@reclaimprotocol/agent 0.1.41 → 0.1.43
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.
- package/lib/authoring/tools.js +4 -1
- package/lib/mcp/tools/agent/proof.js +4 -2
- package/lib/mcp/tools/agent/publish.js +4 -1
- package/lib/mcp/tools/agent/replay.js +3 -1
- package/package.json +2 -2
- package/skill/SKILL.builder.md +13 -1
- package/skill/SKILL.common.md +34 -3
- package/skill/SKILL.old.md +5 -0
- package/skill/builder-mode.md +1 -0
- package/skill/old-mode.md +1 -0
- package/skill/verification-client-integration.md +66 -0
- package/src/authoring/tools.ts +4 -1
- package/src/mcp/tools/agent/proof.ts +4 -2
- package/src/mcp/tools/agent/publish.ts +4 -1
- package/src/mcp/tools/agent/replay.ts +3 -1
package/lib/authoring/tools.js
CHANGED
|
@@ -394,7 +394,10 @@ export function authoringTools(resolveBackend) {
|
|
|
394
394
|
+ 'of the site, not a bug in the draft. HTTP 403/406/429/503 or a '
|
|
395
395
|
+ 'challenge page from the attestor while the replay succeeded '
|
|
396
396
|
+ 'means the site blocks non-browser clients: copying headers or '
|
|
397
|
-
+ 'cookies will not help
|
|
397
|
+
+ 'cookies will not help. Try one other endpoint; if that is '
|
|
398
|
+
+ 'blocked too, publish the version from the capture and have '
|
|
399
|
+
+ 'the developer try a real verification '
|
|
400
|
+
+ '(how_it_works({ topic: "prove" })). Do not keep retrying.',
|
|
398
401
|
inputSchema: objectSchema({ draftId: { type: 'string' } }, ['draftId']),
|
|
399
402
|
annotations: { openWorldHint: true, destructiveHint: false },
|
|
400
403
|
},
|
|
@@ -212,8 +212,10 @@ export function diagnoseBlockedClient(result, lastReplay, geoLocation) {
|
|
|
212
212
|
+ 'published version goes out from there too. Otherwise, try a '
|
|
213
213
|
+ 'different endpoint that returns the value, such as a JSON API the '
|
|
214
214
|
+ 'page calls (find_requests_containing), then propose and prove '
|
|
215
|
-
+ 'that. If none works, stop
|
|
216
|
-
+ '
|
|
215
|
+
+ 'that. If none works, stop retrying: publish the version from the '
|
|
216
|
+
+ 'capture, unproven, and ask the developer to try a real '
|
|
217
|
+
+ 'verification (how_it_works({ topic: "prove" })). Do not tweak '
|
|
218
|
+
+ 'headers.',
|
|
217
219
|
};
|
|
218
220
|
}
|
|
219
221
|
/** True when an attestor error embeds a response element (base64, from a
|
|
@@ -168,7 +168,10 @@ const BROWSER_REQUEST_ACTION_SCHEMA = {
|
|
|
168
168
|
export function createVersionFromCaptureTool(client, attachRef, kept) {
|
|
169
169
|
return defineTool({
|
|
170
170
|
name: 'create_provider_version_from_capture',
|
|
171
|
-
description: 'Creates a new immutable provider version after `run_proof` succeeds
|
|
171
|
+
description: 'Creates a new immutable provider version after `run_proof` succeeds, '
|
|
172
|
+
+ 'or from the captured draft when the site keeps answering replay or '
|
|
173
|
+
+ 'proof with 403 past the retry budget in '
|
|
174
|
+
+ 'how_it_works({ topic: "prove" }). '
|
|
172
175
|
+ 'Publishes the navigation script kept by `test_user_script` as '
|
|
173
176
|
+ '`jsUserScripts` unless `jsUserScripts` is passed. Pass exactly '
|
|
174
177
|
+ 'one `provider` or `providers` value returned by '
|
|
@@ -18,7 +18,9 @@ export function replayTool(resolveBackend) {
|
|
|
18
18
|
+ 'no cookies or auth headers, like an anonymous visitor. If the '
|
|
19
19
|
+ 'values still extract (`valid: true`), the endpoint is public and '
|
|
20
20
|
+ 'the proof would not bind to the user: choose an auth-bound '
|
|
21
|
-
+ 'request instead.'
|
|
21
|
+
+ 'request instead. A 403 that survives one retry and one '
|
|
22
|
+
+ 'correction is a site defense, not a recipe bug: stop retrying '
|
|
23
|
+
+ 'and publish from the capture (how_it_works({ topic: "prove" })).',
|
|
22
24
|
inputSchema: objectSchema({
|
|
23
25
|
draftId: { type: 'string' },
|
|
24
26
|
withoutSecrets: { type: 'boolean' },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reclaimprotocol/agent",
|
|
3
3
|
"title": "Reclaim Agent",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.43",
|
|
5
5
|
"description": "Reclaim Protocol tools for AI coding agents. Reclaim lets your app verify data points about its users, such as a follower count, an account balance, or an order history. This package is the Reclaim MCP server: it gives your agent the tools to find, build, test, and fix data verification providers by capturing and replaying browser requests, drafting provider recipes, running zkTLS proofs, and publishing provider versions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./lib/index.js",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"@noble/hashes": "^2.2.0",
|
|
85
85
|
"@puppeteer/browsers": "3.2.4",
|
|
86
86
|
"@reclaimprotocol/attestor-core": "^5.1.6",
|
|
87
|
-
"@reclaimprotocol/client": "0.1.
|
|
87
|
+
"@reclaimprotocol/client": "0.1.43",
|
|
88
88
|
"@reclaimprotocol/tls": "^0.1.3",
|
|
89
89
|
"chrome-remote-interface": "^0.33.0",
|
|
90
90
|
"domhandler": "^6.0.0",
|
package/skill/SKILL.builder.md
CHANGED
|
@@ -46,6 +46,11 @@ or asynchronous question tool for a blocking question.
|
|
|
46
46
|
`webSettings.jsUserScripts`) → `publish_provider_version` or
|
|
47
47
|
`submit_provider_version_for_review`. → topic `publish`
|
|
48
48
|
|
|
49
|
+
Replay or proof blocked with 403 after one retry and one correction? Stop
|
|
50
|
+
retrying and go straight to step 11: publish the draft unproven from the
|
|
51
|
+
captured request, then ask the developer to try a real verification. → topic
|
|
52
|
+
`prove`, "publish from the capture".
|
|
53
|
+
|
|
49
54
|
Data points on different requests? Run steps 7-10 once per request, then
|
|
50
55
|
publish every proven draft in one call. See topic `publish`.
|
|
51
56
|
|
|
@@ -439,7 +444,14 @@ one, or doesn't know what a site supports. Otherwise build a new provider.
|
|
|
439
444
|
question; don't guess.
|
|
440
445
|
5. To try them: `create_verification_session({ providers: [{ providerId }, …],
|
|
441
446
|
context, verificationClientUrl })` with EVERY resolved provider id and the
|
|
442
|
-
collected context.
|
|
447
|
+
collected context. A session opens only in the client it was created for:
|
|
448
|
+
for an in-app SDK or add-to-app host, pass
|
|
449
|
+
`https://build.reclaimprotocol.org/share/inapp-sdk`; omitted, it is a
|
|
450
|
+
Portal session. For a native app, read the README of the
|
|
451
|
+
[iOS SDK](https://github.com/reclaimprotocol/reclaim-inapp-ios-sdk#readme)
|
|
452
|
+
or the
|
|
453
|
+
[Android SDK](https://github.com/reclaimprotocol/reclaim-inapp-android-sdk#readme)
|
|
454
|
+
before writing app code. Topic `integration` ("Try a provider without an app")
|
|
443
455
|
covers the callback and polling, and the integration steps.
|
|
444
456
|
|
|
445
457
|
`merge.mergeable` only signals the set *could* collapse into one provider. Pass
|
package/skill/SKILL.common.md
CHANGED
|
@@ -409,9 +409,37 @@ supplies are context params.
|
|
|
409
409
|
often after `replay_request` succeeded): the site blocks clients that
|
|
410
410
|
aren't a real browser (bot protection or TLS fingerprint). Copying
|
|
411
411
|
headers or cookies won't help, and `run_proof_via_pod` doesn't change the
|
|
412
|
-
TLS fingerprint.
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
TLS fingerprint. Run `check_matchers` first so a recipe bug isn't
|
|
413
|
+
mistaken for blocking, then try ONE other endpoint that returns the value
|
|
414
|
+
(a JSON API the page calls). Blocked there too → publish from the
|
|
415
|
+
capture, below.
|
|
416
|
+
|
|
417
|
+
**Replay or proof keeps returning 403 (or another block): publish from
|
|
418
|
+
the capture.** A 403 from `replay_request` or `run_proof` says the site
|
|
419
|
+
defends against the authoring path. It does not say the recipe is wrong,
|
|
420
|
+
and a real verification runs inside the end user's own browser session,
|
|
421
|
+
which those defenses usually let through. Retry budget: one retry of the
|
|
422
|
+
same call, one correction (another endpoint, a `geoLocation` pin, or a
|
|
423
|
+
matcher fix via `check_matchers`), and one retry after the correction.
|
|
424
|
+
Past that, STOP. Don't re-capture, re-propose, or re-prove the same
|
|
425
|
+
request, and don't wait for the developer to tell you to stop. Instead:
|
|
426
|
+
|
|
427
|
+
1. Say plainly that replay/proof is blocked and that you are publishing
|
|
428
|
+
the version UNPROVEN, from the request you intercepted. Never say it
|
|
429
|
+
was proven.
|
|
430
|
+
2. Publish the draft as topic `publish` says
|
|
431
|
+
(`create_provider_version_from_capture`, then go live). The draft
|
|
432
|
+
holds the intercepted request, selectors, and params; that is all the
|
|
433
|
+
version needs.
|
|
434
|
+
3. Ask the developer to try it with a real verification. Builder mode:
|
|
435
|
+
`create_verification_session` and put its URL in the message. Legacy
|
|
436
|
+
devtools mode: the "try it" option in topic `publish`. End your turn
|
|
437
|
+
there.
|
|
438
|
+
4. When they return, check the session the usual way
|
|
439
|
+
(`get_verification_session` / `list_verification_events`, or the
|
|
440
|
+
devtools equivalent). Passed → done; it was only the authoring path
|
|
441
|
+
that was blocked. Failed with the same block → the site blocks
|
|
442
|
+
verification too; say so and look for a different endpoint.
|
|
415
443
|
|
|
416
444
|
**Do not auto-retry with a different `attestorUrl`.** There is one live
|
|
417
445
|
public attestor; backup hostnames (`attestor-2.*`, and so on) **do not
|
|
@@ -431,6 +459,9 @@ supplies are context params.
|
|
|
431
459
|
never repeat them.
|
|
432
460
|
- Never call `run_proof` before `replay_request` succeeds. Attestor calls are
|
|
433
461
|
expensive.
|
|
462
|
+
- Never loop a blocked replay or proof. A 403 that survives the retry budget
|
|
463
|
+
in `prove` means publish from the capture, unproven, and hand the developer
|
|
464
|
+
a real verification to try.
|
|
434
465
|
- Never pretend a proof succeeded when `verified: false`. Show the error and
|
|
435
466
|
iterate.
|
|
436
467
|
- Never write a literal value into `responseMatches.value` — that bakes the
|
package/skill/SKILL.old.md
CHANGED
|
@@ -28,6 +28,11 @@ topic before a step you aren't already fluent in.
|
|
|
28
28
|
→ topics `prove`, `credentials`
|
|
29
29
|
- [ ] 10. `create_provider_version_from_capture`. → topic `publish`
|
|
30
30
|
|
|
31
|
+
Replay or proof blocked with 403 after one retry and one correction? Stop
|
|
32
|
+
retrying and go straight to step 10: publish the draft unproven from the
|
|
33
|
+
captured request, then ask the developer to try a real verification. → topic
|
|
34
|
+
`prove`, "publish from the capture".
|
|
35
|
+
|
|
31
36
|
Multi-request provider? Run steps 6–9 once per request, then publish every
|
|
32
37
|
proven draft in one call. See topic `publish`.
|
|
33
38
|
|
package/skill/builder-mode.md
CHANGED
|
@@ -16,6 +16,7 @@ Provider-authoring and verification tools for the Builder backend.
|
|
|
16
16
|
- Call `attach_browser()` with no arguments. Don't ask which browser to use.
|
|
17
17
|
- Propose only the data points the claim needs.
|
|
18
18
|
- Provider versions are immutable: every change creates a new version.
|
|
19
|
+
- A 403 (or similar block) from `replay_request` or `run_proof` that survives one retry and one correction is not a reason to keep retrying. Publish the version from the captured request, say it is unproven, and ask the developer to try a real verification (topic `prove`).
|
|
19
20
|
|
|
20
21
|
## Asking the developer
|
|
21
22
|
|
package/skill/old-mode.md
CHANGED
|
@@ -9,6 +9,7 @@ Provider-authoring tools for the old devtools backend. The tool surface is reduc
|
|
|
9
9
|
- A provider found with `get_me_providers` or `get_provider_info` is published and usable as-is. Don't capture, replay, or prove it unless the developer asks.
|
|
10
10
|
- Before using a provider, found or just created, ask once how they want to use it (try it, integrate it, or build a new app), unless they already said. Topic `publish` has the options.
|
|
11
11
|
- Call `attach_browser()` with no arguments. Don't ask which browser to use.
|
|
12
|
+
- A 403 (or similar block) from `replay_request` or `run_proof` that survives one retry and one correction is not a reason to keep retrying. Publish the version from the captured request, say it is unproven, and ask the developer to try it (topic `prove`).
|
|
12
13
|
|
|
13
14
|
## Asking the developer
|
|
14
15
|
|
|
@@ -98,6 +98,18 @@ legacy devtools mode), or migrate to the Builder HTTP API?"
|
|
|
98
98
|
from `VerificationClient` in the SDK. Do not send an unregistered URL or
|
|
99
99
|
call a legacy backend for an `api=2` session.
|
|
100
100
|
|
|
101
|
+
A session only works in the client it was created for: Builder fixes the
|
|
102
|
+
client at creation, and any other client gets
|
|
103
|
+
`403 x-reclaim-vc-id does not match this session`. For a mobile app using
|
|
104
|
+
the in-app SDK or the add-to-app module, create every session with
|
|
105
|
+
`verificationClientUrl` set to
|
|
106
|
+
`https://build.reclaimprotocol.org/share/inapp-sdk`
|
|
107
|
+
(`VerificationClient.inAppSdk`); the default Portal link won't open there.
|
|
108
|
+
For native iOS or Android apps, follow the
|
|
109
|
+
[iOS SDK README](https://github.com/reclaimprotocol/reclaim-inapp-ios-sdk#readme)
|
|
110
|
+
or the
|
|
111
|
+
[Android SDK README](https://github.com/reclaimprotocol/reclaim-inapp-android-sdk#readme).
|
|
112
|
+
|
|
101
113
|
The hosted verification page streams the target site as an image, so text
|
|
102
114
|
and DOM checks of that page come back empty. Check a session's progress
|
|
103
115
|
with `list_verification_events` and `get_verification_session` instead.
|
|
@@ -164,6 +176,60 @@ curl -X POST https://build.reclaimprotocol.org/verifications/sessions \
|
|
|
164
176
|
}'
|
|
165
177
|
```
|
|
166
178
|
|
|
179
|
+
For an in-app SDK or add-to-app host, add the in-app SDK's client URL and pass
|
|
180
|
+
the returned `verificationUrl` to the app's `startVerificationFromUrl`:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
curl -X POST https://build.reclaimprotocol.org/verifications/sessions \
|
|
184
|
+
-H "authorization: Bearer $RECLAIM_ORG_SECRET" \
|
|
185
|
+
-H "content-type: application/json" \
|
|
186
|
+
-d '{
|
|
187
|
+
"providers": [
|
|
188
|
+
{
|
|
189
|
+
"providerId": "<your-provider-id>"
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"context": {
|
|
193
|
+
"userId": "abc"
|
|
194
|
+
},
|
|
195
|
+
"verificationClientUrl": "https://build.reclaimprotocol.org/share/inapp-sdk"
|
|
196
|
+
}'
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
With `@reclaimprotocol/client`:
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
import { ReclaimVerification, VerificationClient } from '@reclaimprotocol/client'
|
|
203
|
+
|
|
204
|
+
const reclaim = ReclaimVerification.create({
|
|
205
|
+
orgSecret: process.env.RECLAIM_ORG_SECRET,
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
const session = await reclaim.sessions.create({
|
|
209
|
+
providers: [{ providerId: '<your-provider-id>' }],
|
|
210
|
+
context: { userId: 'abc' },
|
|
211
|
+
// Required for the in-app SDK and add-to-app module. Omitted, Builder
|
|
212
|
+
// selects the Portal, and the app's requests get 403.
|
|
213
|
+
verificationClientUrl: VerificationClient.inAppSdk,
|
|
214
|
+
})
|
|
215
|
+
// Store session.id; hand session.verificationUrl to the app.
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The app opens it with `startVerificationFromUrl(verificationUrl)`. If the
|
|
219
|
+
backend returns fields instead of a link, it calls
|
|
220
|
+
`startVerificationFromJson({ "api": "2", "sessionId": session.id })` with the
|
|
221
|
+
same result. Add `"diag": "1"` only when `verificationUrl` contains `diag=1`;
|
|
222
|
+
other keys are ignored.
|
|
223
|
+
|
|
224
|
+
For a native app, read the SDK's README before writing app code. Each README
|
|
225
|
+
has a Builder mode section covering installation, starting from a URL or
|
|
226
|
+
JSON, and handling the result:
|
|
227
|
+
|
|
228
|
+
- iOS (Swift):
|
|
229
|
+
[reclaim-inapp-ios-sdk](https://github.com/reclaimprotocol/reclaim-inapp-ios-sdk#readme)
|
|
230
|
+
- Android (Kotlin/Java):
|
|
231
|
+
[reclaim-inapp-android-sdk](https://github.com/reclaimprotocol/reclaim-inapp-android-sdk#readme)
|
|
232
|
+
|
|
167
233
|
Receive and verify the result on the callback route. This is the one place the
|
|
168
234
|
client package is needed:
|
|
169
235
|
|
package/src/authoring/tools.ts
CHANGED
|
@@ -521,7 +521,10 @@ export function authoringTools(
|
|
|
521
521
|
+ 'of the site, not a bug in the draft. HTTP 403/406/429/503 or a '
|
|
522
522
|
+ 'challenge page from the attestor while the replay succeeded '
|
|
523
523
|
+ 'means the site blocks non-browser clients: copying headers or '
|
|
524
|
-
+ 'cookies will not help
|
|
524
|
+
+ 'cookies will not help. Try one other endpoint; if that is '
|
|
525
|
+
+ 'blocked too, publish the version from the capture and have '
|
|
526
|
+
+ 'the developer try a real verification '
|
|
527
|
+
+ '(how_it_works({ topic: "prove" })). Do not keep retrying.',
|
|
525
528
|
inputSchema: objectSchema({ draftId: { type: 'string' } }, ['draftId']),
|
|
526
529
|
annotations: { openWorldHint: true, destructiveHint: false },
|
|
527
530
|
},
|
|
@@ -286,8 +286,10 @@ export function diagnoseBlockedClient(
|
|
|
286
286
|
+ 'published version goes out from there too. Otherwise, try a '
|
|
287
287
|
+ 'different endpoint that returns the value, such as a JSON API the '
|
|
288
288
|
+ 'page calls (find_requests_containing), then propose and prove '
|
|
289
|
-
+ 'that. If none works, stop
|
|
290
|
-
+ '
|
|
289
|
+
+ 'that. If none works, stop retrying: publish the version from the '
|
|
290
|
+
+ 'capture, unproven, and ask the developer to try a real '
|
|
291
|
+
+ 'verification (how_it_works({ topic: "prove" })). Do not tweak '
|
|
292
|
+
+ 'headers.',
|
|
291
293
|
}
|
|
292
294
|
}
|
|
293
295
|
|
|
@@ -239,7 +239,10 @@ export function createVersionFromCaptureTool(
|
|
|
239
239
|
{
|
|
240
240
|
name: 'create_provider_version_from_capture',
|
|
241
241
|
description:
|
|
242
|
-
'Creates a new immutable provider version after `run_proof` succeeds
|
|
242
|
+
'Creates a new immutable provider version after `run_proof` succeeds, '
|
|
243
|
+
+ 'or from the captured draft when the site keeps answering replay or '
|
|
244
|
+
+ 'proof with 403 past the retry budget in '
|
|
245
|
+
+ 'how_it_works({ topic: "prove" }). '
|
|
243
246
|
+ 'Publishes the navigation script kept by `test_user_script` as '
|
|
244
247
|
+ '`jsUserScripts` unless `jsUserScripts` is passed. Pass exactly '
|
|
245
248
|
+ 'one `provider` or `providers` value returned by '
|
|
@@ -21,7 +21,9 @@ export function replayTool(resolveBackend: ResolveBackend): RegisteredTool {
|
|
|
21
21
|
+ 'no cookies or auth headers, like an anonymous visitor. If the '
|
|
22
22
|
+ 'values still extract (`valid: true`), the endpoint is public and '
|
|
23
23
|
+ 'the proof would not bind to the user: choose an auth-bound '
|
|
24
|
-
+ 'request instead.'
|
|
24
|
+
+ 'request instead. A 403 that survives one retry and one '
|
|
25
|
+
+ 'correction is a site defense, not a recipe bug: stop retrying '
|
|
26
|
+
+ 'and publish from the capture (how_it_works({ topic: "prove" })).',
|
|
25
27
|
inputSchema: objectSchema(
|
|
26
28
|
{
|
|
27
29
|
draftId: { type: 'string' },
|