@reclaimprotocol/agent 0.1.39 → 0.1.41
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/README.md +32 -0
- package/lib/config/store.d.ts +7 -0
- package/lib/consts.d.ts +5 -0
- package/lib/consts.js +10 -0
- package/lib/mcp/api/operations.gen.d.ts +7 -0
- package/lib/mcp/api/operations.gen.js +54 -4
- package/lib/mcp/api/tools.js +4 -0
- package/lib/mcp/instructions.js +10 -8
- package/lib/mcp/server.js +6 -1
- package/lib/mcp/start.js +27 -1
- package/lib/mcp/tools/agent/example-app.d.ts +5 -1
- package/lib/mcp/tools/agent/example-app.js +87 -24
- package/lib/mcp/tools/agent/propose.js +7 -0
- package/lib/mcp/tools/agent/start-integration.d.ts +2 -0
- package/lib/mcp/tools/agent/start-integration.js +7 -0
- package/lib/mcp/tools/authenticate/authenticate.js +3 -0
- package/lib/mcp/tools/authenticate/eth-key.d.ts +15 -0
- package/lib/mcp/tools/authenticate/eth-key.js +72 -6
- package/lib/mcp/tools/authenticate/issue-org-keypair.d.ts +3 -2
- package/lib/mcp/tools/authenticate/issue-org-keypair.js +83 -18
- package/lib/mcp/tools/authenticate/issue-org-token.js +9 -2
- package/lib/telemetry/index.d.ts +9 -0
- package/lib/telemetry/index.js +13 -0
- package/lib/telemetry/telemetry.d.ts +54 -0
- package/lib/telemetry/telemetry.js +175 -0
- package/lib/telemetry/tool-call.d.ts +24 -0
- package/lib/telemetry/tool-call.js +102 -0
- package/package.json +2 -2
- package/skill/SKILL.builder.md +30 -11
- package/skill/SKILL.old.md +23 -5
- package/skill/builder-mode.md +29 -164
- package/skill/old-mode.md +40 -95
- package/skill/start-integration.md +12 -9
- package/skill/verification-client-integration.md +39 -9
- package/src/config/store.ts +4 -0
- package/src/consts.ts +11 -0
- package/src/mcp/api/operations.gen.ts +56 -4
- package/src/mcp/api/tools.ts +4 -0
- package/src/mcp/instructions.ts +10 -8
- package/src/mcp/server.ts +6 -1
- package/src/mcp/start.ts +34 -0
- package/src/mcp/tools/agent/example-app.ts +97 -30
- package/src/mcp/tools/agent/propose.ts +8 -0
- package/src/mcp/tools/agent/start-integration.ts +10 -0
- package/src/mcp/tools/authenticate/authenticate.ts +3 -0
- package/src/mcp/tools/authenticate/eth-key.ts +114 -6
- package/src/mcp/tools/authenticate/issue-org-keypair.ts +97 -19
- package/src/mcp/tools/authenticate/issue-org-token.ts +13 -2
- package/src/telemetry/index.ts +18 -0
- package/src/telemetry/telemetry.ts +206 -0
- package/src/telemetry/tool-call.ts +115 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { isProblemError } from '@reclaimprotocol/client/api';
|
|
2
|
+
import { currentTelemetry } from "./index.js";
|
|
3
|
+
const GOAL_MAX = 300;
|
|
4
|
+
const USER_REQUEST_MAX = 500;
|
|
5
|
+
const DOMAIN_MAX = 200;
|
|
6
|
+
const DATA_POINTS_MAX = 20;
|
|
7
|
+
const DATA_POINT_MAX = 200;
|
|
8
|
+
/**
|
|
9
|
+
* Times a tool call and records it. Call `end()` once when the call
|
|
10
|
+
* finishes. It never throws, so it can't change the outcome of the call.
|
|
11
|
+
*/
|
|
12
|
+
export function startToolCall(tool, args) {
|
|
13
|
+
const startedAt = Date.now();
|
|
14
|
+
return {
|
|
15
|
+
end(err) {
|
|
16
|
+
try {
|
|
17
|
+
const telemetry = currentTelemetry();
|
|
18
|
+
if (!telemetry) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const input = allowlistedInput(tool, args);
|
|
22
|
+
telemetry.track('tool_call', {
|
|
23
|
+
tool,
|
|
24
|
+
ok: err === undefined,
|
|
25
|
+
...(err === undefined ? {} : { errorCode: errorCode(err) }),
|
|
26
|
+
durationMs: Date.now() - startedAt,
|
|
27
|
+
mode: telemetry.mode,
|
|
28
|
+
...(input ? { input } : {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Telemetry must never affect a tool call.
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A category for the error, such as `http_401`. It's never the message,
|
|
39
|
+
* because messages can contain URLs, tokens, or file paths.
|
|
40
|
+
*/
|
|
41
|
+
export function errorCode(err) {
|
|
42
|
+
if (isProblemError(err)) {
|
|
43
|
+
return `http_${err.output.statusCode}`;
|
|
44
|
+
}
|
|
45
|
+
if (isRecord(err) && err.isBoom === true && isRecord(err.output)) {
|
|
46
|
+
return `http_${String(err.output.statusCode)}`;
|
|
47
|
+
}
|
|
48
|
+
if (err instanceof Error) {
|
|
49
|
+
if (err.name === 'ZodError') {
|
|
50
|
+
return 'invalid_input';
|
|
51
|
+
}
|
|
52
|
+
if (err.name === 'TimeoutError' || err.name === 'AbortError') {
|
|
53
|
+
return 'timeout';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return 'error';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The only arguments Reclaim records, and only for these tools. They are the
|
|
60
|
+
* developer's own description of what they want to build, which tells us
|
|
61
|
+
* which providers to add. Every other argument is dropped here, so a new tool
|
|
62
|
+
* records nothing until you add it to this list on purpose.
|
|
63
|
+
*/
|
|
64
|
+
export function allowlistedInput(tool, args) {
|
|
65
|
+
if (!isRecord(args)) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
switch (tool) {
|
|
69
|
+
case 'start_integration':
|
|
70
|
+
return compact({
|
|
71
|
+
goal: cut(args.goal, GOAL_MAX),
|
|
72
|
+
userRequest: cut(args.userRequest, USER_REQUEST_MAX),
|
|
73
|
+
});
|
|
74
|
+
case 'propose_provider':
|
|
75
|
+
return compact({ userRequest: cut(args.userRequest, USER_REQUEST_MAX) });
|
|
76
|
+
case 'discover_resolve': {
|
|
77
|
+
const query = isRecord(args.query) ? args.query : {};
|
|
78
|
+
const dataPoints = Array.isArray(query.dataPoints)
|
|
79
|
+
? query.dataPoints
|
|
80
|
+
.slice(0, DATA_POINTS_MAX)
|
|
81
|
+
.map((p) => cut(p, DATA_POINT_MAX))
|
|
82
|
+
.filter((p) => p !== undefined)
|
|
83
|
+
: undefined;
|
|
84
|
+
return compact({
|
|
85
|
+
domain: cut(query.domain, DOMAIN_MAX),
|
|
86
|
+
dataPoints: dataPoints?.length ? dataPoints : undefined,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
default:
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function cut(value, max) {
|
|
94
|
+
return typeof value === 'string' && value ? value.slice(0, max) : undefined;
|
|
95
|
+
}
|
|
96
|
+
/** Returns the object, or undefined when every field is undefined. */
|
|
97
|
+
function compact(obj) {
|
|
98
|
+
return Object.values(obj).some((v) => v !== undefined) ? obj : undefined;
|
|
99
|
+
}
|
|
100
|
+
function isRecord(value) {
|
|
101
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
102
|
+
}
|
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.41",
|
|
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.41",
|
|
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
|
@@ -68,6 +68,12 @@ immediately with a `code` and `attachUrl` — it does NOT poll.
|
|
|
68
68
|
The 2-day token is cached in `~/.reclaim/config.json` and reused on later runs
|
|
69
69
|
(`RECLAIM_API_TOKEN` in the server env overrides it).
|
|
70
70
|
|
|
71
|
+
### Backend mode
|
|
72
|
+
|
|
73
|
+
`get_devtools_mode` reports the active mode. `set_devtools_mode` persists a
|
|
74
|
+
switch to `~/.reclaim/config.json`, effective on the next server start. An
|
|
75
|
+
explicit `USE_OLD_DEVTOOLS` env var wins.
|
|
76
|
+
|
|
71
77
|
<!-- topic: devtools-migration -->
|
|
72
78
|
## Import providers from devtools
|
|
73
79
|
|
|
@@ -316,6 +322,14 @@ with no secrets/cookies, as an anonymous visitor.
|
|
|
316
322
|
— **show it to the developer as a fenced JSON block at the end**, with the
|
|
317
323
|
provider JSON. That's the final result.
|
|
318
324
|
|
|
325
|
+
**Country.** `run_proof` sends the attestor's request from the developer's own
|
|
326
|
+
IP country, which is what `{{DYNAMIC_GEO}}` becomes when they verify; `egress`
|
|
327
|
+
in the result names the country. If a site that serves one country (for
|
|
328
|
+
example, a US airline) blocks the attestor, retry once with
|
|
329
|
+
`geoLocation: "US"`. If that verifies, pin it with
|
|
330
|
+
`update_draft({ geoLocation: "US" })` so the published version goes out from
|
|
331
|
+
there too.
|
|
332
|
+
|
|
319
333
|
**`errorKind: "missing-owner-key"`** → no eth proof-owner key yet. Tell the
|
|
320
334
|
developer what's happening and drive the bootstrap yourself — see topic
|
|
321
335
|
`credentials`. No restart needed, and the existing `draftId` stays valid.
|
|
@@ -396,16 +410,17 @@ in, navigate to `initialUrl`; if a user script is present, run
|
|
|
396
410
|
`test_user_script` with that script and `initialUrl`. When the existing capture
|
|
397
411
|
has enough data, replay and prove every required request. Do not clear
|
|
398
412
|
cookies or force another sign-in. Treat an unavailable or inconclusive retest as
|
|
399
|
-
advisory and do not block publication.
|
|
400
|
-
|
|
401
|
-
|
|
413
|
+
advisory and do not block publication. Don't ask whether to close the
|
|
414
|
+
browser. Mention once in the final summary that it stays open for provider
|
|
415
|
+
changes and you can close it on request; call `dispose_browser` only when the
|
|
416
|
+
developer says so. A `builder` session is quota-accounted, so close it as soon
|
|
417
|
+
as they say the work is done.
|
|
402
418
|
|
|
403
419
|
<!-- topic: discover -->
|
|
404
420
|
## Discover and resolve existing providers
|
|
405
421
|
|
|
406
|
-
Use this flow only when the developer asks to reuse existing providers
|
|
407
|
-
doesn't know what a site supports. Otherwise build a new provider
|
|
408
|
-
instructions, "Choose the provider").
|
|
422
|
+
Use this flow only when the developer asks to reuse existing providers, names
|
|
423
|
+
one, or doesn't know what a site supports. Otherwise build a new provider.
|
|
409
424
|
|
|
410
425
|
1. Ask which website their users prove data from.
|
|
411
426
|
2. `discover_data_points({ domain })` → what's verifiable there. Confirm the
|
|
@@ -415,13 +430,17 @@ instructions, "Choose the provider").
|
|
|
415
430
|
any `uncovered` points (author those with the checklist in topic
|
|
416
431
|
`overview`, then re-resolve).
|
|
417
432
|
4. Use only the data points the developer confirmed: show and read only those
|
|
418
|
-
and ignore the rest. A provider that needs any change gets your own copy
|
|
419
|
-
(
|
|
420
|
-
|
|
433
|
+
and ignore the rest. A provider that needs any change (a missing data point, extra inputs, a different extraction) gets your own copy
|
|
434
|
+
(`create_provider_version` when your org owns it; otherwise
|
|
435
|
+
`create_provider`, then `create_provider_version` from a copy of its
|
|
436
|
+
config, trimmed to the requested data points). Otherwise it's published and
|
|
437
|
+
usable as-is; don't capture, replay, or prove it unless the developer asks.
|
|
438
|
+
When a requirement (site, account, or value) is ambiguous, ask one concise
|
|
439
|
+
question; don't guess.
|
|
421
440
|
5. To try them: `create_verification_session({ providers: [{ providerId }, …],
|
|
422
441
|
context, verificationClientUrl })` with EVERY resolved provider id and the
|
|
423
|
-
collected context.
|
|
424
|
-
|
|
442
|
+
collected context. Topic `integration` ("Try a provider without an app")
|
|
443
|
+
covers the callback and polling, and the integration steps.
|
|
425
444
|
|
|
426
445
|
`merge.mergeable` only signals the set *could* collapse into one provider. Pass
|
|
427
446
|
them all; the Builder runs them in one session.
|
package/skill/SKILL.old.md
CHANGED
|
@@ -74,6 +74,14 @@ and are NOT interchangeable.
|
|
|
74
74
|
`reclaim_authenticate` ran earlier, the old-devtools token has expired — re-run
|
|
75
75
|
it. Don't assume `authenticate_builder` fixes it.
|
|
76
76
|
|
|
77
|
+
### Backend mode
|
|
78
|
+
|
|
79
|
+
The BUILDER backend (generated API tools, orgs, verification sessions, public
|
|
80
|
+
review) is one switch away. `get_devtools_mode` reports the active mode and
|
|
81
|
+
why; `set_devtools_mode` persists a switch to `~/.reclaim/config.json`,
|
|
82
|
+
effective on the NEXT server start. An explicit `USE_OLD_DEVTOOLS` env var wins
|
|
83
|
+
over the persisted choice.
|
|
84
|
+
|
|
77
85
|
<!-- topic: browser -->
|
|
78
86
|
<!-- common: browser -->
|
|
79
87
|
|
|
@@ -320,8 +328,17 @@ applies them.
|
|
|
320
328
|
There's no create-then-version step and no org / public-review workflow here.
|
|
321
329
|
When done, tell the developer the version is live, then ask once how they want
|
|
322
330
|
to use it — try it now, integrate it into an existing backend or frontend, or
|
|
323
|
-
create a new app — unless they already said
|
|
324
|
-
|
|
331
|
+
create a new app — unless they already said:
|
|
332
|
+
|
|
333
|
+
> Want to (1) try it right now here, (2) integrate it into an existing backend
|
|
334
|
+
> or frontend (this directory or another path), or (3) create a new app for it?
|
|
335
|
+
|
|
336
|
+
Try it now → `scaffold_reclaim_demo_server` with its `providerId`. Integrate,
|
|
337
|
+
or new app → `get_js_sdk_integration_guide`, then work in the path they named.
|
|
338
|
+
|
|
339
|
+
A provider found with `get_me_providers` or `get_provider_info` is published
|
|
340
|
+
and usable as-is. Don't capture, `replay_request`, or `run_proof` against it
|
|
341
|
+
unless the developer asks you to check or test it.
|
|
325
342
|
|
|
326
343
|
**If the response includes `_notes` for an attached browser, follow them for an
|
|
327
344
|
optional authenticated-state retest.** Only when its profile is still signed in,
|
|
@@ -329,9 +346,10 @@ navigate to `initialUrl`; if `customInjection` is present, run
|
|
|
329
346
|
`test_user_script` with that script and `initialUrl`. When the existing capture
|
|
330
347
|
has enough data, replay and prove every required request. Do not clear
|
|
331
348
|
cookies or force another sign-in. Treat an unavailable or inconclusive retest as
|
|
332
|
-
advisory and do not block the completed provider.
|
|
333
|
-
|
|
334
|
-
|
|
349
|
+
advisory and do not block the completed provider. Don't ask whether to close the
|
|
350
|
+
browser. Mention once in the final summary that it stays open for provider
|
|
351
|
+
changes and you can close it on request; call `dispose_browser` only when the
|
|
352
|
+
developer says so.
|
|
335
353
|
|
|
336
354
|
<!-- topic: never-do -->
|
|
337
355
|
## Things to never do
|
package/skill/builder-mode.md
CHANGED
|
@@ -1,186 +1,51 @@
|
|
|
1
1
|
# Builder mode
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Builder API tools, credential and verification helpers, and browser authoring
|
|
5
|
-
tools.
|
|
3
|
+
Provider-authoring and verification tools for the Builder backend.
|
|
6
4
|
|
|
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."**
|
|
5
|
+
**A provider is a recipe for extracting a data point from a site. A verification is an end-user session that proves a data point with a provider. Never call a provider a "verification."**
|
|
10
6
|
|
|
11
|
-
##
|
|
7
|
+
## Routing
|
|
12
8
|
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
-
|
|
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.
|
|
9
|
+
- "Add Reclaim to my app" or similar: call `start_integration` first and follow its plan. Don't ask what they want to do with the result.
|
|
10
|
+
- A claim they describe (for example, "prove the user is over 18 on example.com"): build a new org-private provider for exactly that claim. Use an existing provider only when they name one or ask to reuse one (topic `discover`).
|
|
11
|
+
- Intent unclear: ask one short question.
|
|
19
12
|
|
|
20
|
-
|
|
13
|
+
## Authoring rules
|
|
21
14
|
|
|
22
|
-
Do the steps that need the developer first
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
- Do the steps that need the developer first (sign in, attach the browser, capture, prove). Write app code after the proof works, or while you wait.
|
|
16
|
+
- Call `attach_browser()` with no arguments. Don't ask which browser to use.
|
|
17
|
+
- Propose only the data points the claim needs.
|
|
18
|
+
- Provider versions are immutable: every change creates a new version.
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
## Asking the developer
|
|
28
21
|
|
|
29
|
-
When you need an answer or an action
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
see it. Put every link they need, such as a sign-in or verification URL, in
|
|
33
|
-
that same message.
|
|
22
|
+
- When you need an answer or an action, end your turn with the question. Don't use a background or asynchronous question tool: the developer may never see it.
|
|
23
|
+
- Put every link they need, such as a sign-in or verification URL, in that same message.
|
|
24
|
+
- Ask each question once. Act on the answer; don't ask again.
|
|
34
25
|
|
|
35
|
-
|
|
26
|
+
## Permission blocks
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
existing provider only when they name one or ask to reuse one.
|
|
28
|
+
When a permission check blocks a tool call or command:
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Make your own copy when it needs any change, for example it lacks a requested
|
|
45
|
-
data point, requires inputs the developer didn't ask for, or extracts a value
|
|
46
|
-
differently:
|
|
47
|
-
|
|
48
|
-
- Your org owns it: create a new provider version.
|
|
49
|
-
- Another org owns it: `create_provider`, then `create_provider_version` from a
|
|
50
|
-
copy of its config, trimmed to the requested data points.
|
|
51
|
-
|
|
52
|
-
Requirement ambiguous (site, account, or value): ask one concise question.
|
|
53
|
-
Don't guess.
|
|
54
|
-
|
|
55
|
-
A provider used as-is is published and ready. Don't capture, `replay_request`,
|
|
56
|
-
or `run_proof` against it unless the developer asks.
|
|
57
|
-
|
|
58
|
-
### Try a provider without an app
|
|
59
|
-
|
|
60
|
-
Session creation returns 409 while the org has no callback subscription.
|
|
61
|
-
`read_callback_events` creates the org's pull listener, which satisfies that
|
|
62
|
-
check and holds results for you to read. No tunnel or public URL is needed.
|
|
63
|
-
|
|
64
|
-
1. Call `read_callback_events`.
|
|
65
|
-
2. `create_verification_session`, then give the developer `verificationUrl`.
|
|
66
|
-
3. Poll `get_verification_session` until it is terminal.
|
|
67
|
-
`list_verification_events` shows progress. Don't read the hosted
|
|
68
|
-
verification page for progress: it streams the site as an image, so text
|
|
69
|
-
and DOM checks of it come back empty.
|
|
70
|
-
4. Call `read_callback_events({ sessionId })` for the verified result.
|
|
71
|
-
|
|
72
|
-
When you set up a new provider build, call `check_attestor` once. If it fails,
|
|
73
|
-
tell the developer before they spend time on the build.
|
|
30
|
+
1. Don't retry it or work around it.
|
|
31
|
+
2. In one message, name the blocked tool or command, what it does, and what approving it means.
|
|
32
|
+
3. Ask for approval in words that name that exact action, for example: "Approve running `npm run dev` to start the example app?" A vague question doesn't cover it.
|
|
74
33
|
|
|
75
34
|
## Secrets
|
|
76
35
|
|
|
77
|
-
- Never print, echo, or ask the developer to paste an org key (`rorg_…`) or
|
|
78
|
-
|
|
79
|
-
- `issue_org_token` writes the key to the project's env file
|
|
80
|
-
(`RECLAIM_ORG_SECRET`) and returns only its last four characters. Session
|
|
81
|
-
and org-token tools use that key when you omit `orgToken`.
|
|
82
|
-
- `issue_credentials` and `import_credentials({ keyFile })` write the proof
|
|
83
|
-
owner key to the env file. Use these tools, not shell commands that read
|
|
84
|
-
secret files.
|
|
85
|
-
|
|
86
|
-
## Integrating into an app
|
|
87
|
-
|
|
88
|
-
Call `start_integration` and follow its order: prove the provider first, then
|
|
89
|
-
write app code. Read `how_it_works({ topic: "integration" })`
|
|
90
|
-
for the HTTP session workflow, the `api=2` boundary, result verification, and
|
|
91
|
-
TEE binding. Edit the app with your file tools. Use the HTTP API
|
|
92
|
-
(`POST /verifications/sessions`, open `verificationUrl`, poll
|
|
93
|
-
`GET /verifications/sessions/{sessionId}`, read the callback) rather than
|
|
94
|
-
`@reclaimprotocol/client`. The only exception is `results.receive` on the
|
|
95
|
-
callback, or when the developer asks for the client package.
|
|
96
|
-
|
|
97
|
-
The app's frontend renders every state and every failure, never only a
|
|
98
|
-
spinner. Follow "UI states" in `how_it_works({ topic: "integration" })`. The
|
|
99
|
-
callback route responds `error.retryable ? 503 : 200` for a thrown
|
|
100
|
-
`ResultVerificationError`; a result that failed verification gets 2xx.
|
|
101
|
-
|
|
102
|
-
For local development, call `proxy_callback_events({ port, path })` to forward
|
|
103
|
-
events to the app's callback route on localhost. The local listener works only
|
|
104
|
-
while this MCP server runs. It keeps events in order per session and retries
|
|
105
|
-
a session the app rejects with backoff, so other sessions keep flowing. When
|
|
106
|
-
its status lists `blocked` sessions, read that session's callback route
|
|
107
|
-
response and logs, and fix the app. Production needs a webhook:
|
|
108
|
-
`create_org_callback_subscription` with the deployed app's public URL. Without
|
|
109
|
-
one, session creation returns 409.
|
|
110
|
-
|
|
111
|
-
Management tools (`list_orgs`, `create_org_callback_subscription`,
|
|
112
|
-
`issue_org_token`) use the developer's sign-in. Session tools
|
|
113
|
-
(`create_verification_session`, `get_verification_session`,
|
|
114
|
-
`list_verification_events`, `list_verification_deliveries`,
|
|
115
|
-
`retry_verification_callback`, `read_callback_events`,
|
|
116
|
-
`proxy_callback_events`) are the production API and use the org key.
|
|
117
|
-
|
|
118
|
-
**Existing `@reclaimprotocol/js-sdk` projects.** If `package.json` depends on
|
|
119
|
-
`@reclaimprotocol/js-sdk`, ask first:
|
|
120
|
-
|
|
121
|
-
> This project uses `@reclaimprotocol/js-sdk`. Keep it (I switch this MCP
|
|
122
|
-
> server to legacy devtools mode), or migrate to the Builder HTTP API?
|
|
123
|
-
|
|
124
|
-
- **Keep:** `set_devtools_mode({ mode: "old" })`, then tell them to restart or
|
|
125
|
-
reconnect the MCP server. An explicit `USE_OLD_DEVTOOLS` env var overrides
|
|
126
|
-
it. After the restart, read `get_js_sdk_integration_guide`.
|
|
127
|
-
- **Migrate:** stay in Builder mode and follow topic `integration`.
|
|
128
|
-
|
|
129
|
-
## Authoring a provider
|
|
130
|
-
|
|
131
|
-
Provider versions are immutable. Every change creates a new semantic version
|
|
132
|
-
(default: patch bump; larger only when the developer directs). Never use an
|
|
133
|
-
in-place update or archive tool.
|
|
134
|
-
|
|
135
|
-
**The flow:** `attach_browser` → `start_capture` ⇒ `captureId` → sign in →
|
|
136
|
-
navigation script (`test_user_script` with `keep: true`) → capture through the
|
|
137
|
-
script → `find_requests_containing` → `propose_provider` ⇒ `draftId` →
|
|
138
|
-
`replay_request` → `run_proof` → `create_provider_version_from_capture` →
|
|
139
|
-
`publish_provider_version` (private) or `submit_provider_version_for_review`
|
|
140
|
-
(public). Get the checklist from `how_it_works({ topic: "overview" })`.
|
|
141
|
-
|
|
142
|
-
- **Data points:** propose only values the claim needs, usually one or two.
|
|
143
|
-
Never add identity or profile fields. Name each for what it proves.
|
|
144
|
-
- **Browser:** call `attach_browser()` with no arguments. It opens a visible
|
|
145
|
-
local browser with the persistent Reclaim profile, and falls back to Chrome
|
|
146
|
-
for Testing itself when no installed browser can be attached. Don't ask
|
|
147
|
-
which browser or who signs in. Use another `mode` only when that fails too,
|
|
148
|
-
or when the developer explicitly asks for it (topic `browser`). Tell the
|
|
149
|
-
developer once, as a side note, that a shareable link can be set up if a
|
|
150
|
-
volunteer is helping them sign in; don't ask about it or set it up unless
|
|
151
|
-
they ask.
|
|
152
|
-
- **Public endpoints:** after `replay_request` succeeds, re-run it with
|
|
153
|
-
`withoutSecrets: true`. If the value still extracts, the endpoint is public
|
|
154
|
-
and the proof binds to nobody. Find an auth-bound request.
|
|
155
|
-
- **Country:** `run_proof` sends the attestor's request from the developer's
|
|
156
|
-
own IP country, which is what `{{DYNAMIC_GEO}}` becomes when they verify;
|
|
157
|
-
`egress` in the result says which country. If a site that serves one
|
|
158
|
-
country (for example, a US airline) blocks the attestor, retry once with
|
|
159
|
-
`geoLocation: "US"`. If that verifies, pin it with
|
|
160
|
-
`update_draft({ geoLocation: "US" })` so the published version goes out
|
|
161
|
-
from there too.
|
|
162
|
-
- **Drafting limits** (topics `draft`, `params`): never `hash` a value that
|
|
163
|
-
also appears in the request URL. A param named with `SECRET` may appear in a
|
|
164
|
-
URL only within a small character budget (2 under `key-update`, 12 under
|
|
165
|
-
`zk`).
|
|
36
|
+
- Never print, echo, or ask the developer to paste an org key (`rorg_…`) or private key.
|
|
37
|
+
- `issue_org_token` writes the org key to the project's env file (`RECLAIM_ORG_SECRET`) and returns only its last four characters. `issue_credentials` and `import_credentials({ keyFile })` write the proof-owner key there. Use these tools, not shell commands that read secret files.
|
|
166
38
|
|
|
167
39
|
## Evidence contract
|
|
168
40
|
|
|
169
|
-
Tool results are the source of truth. Never say a browser attached, a user
|
|
170
|
-
signed in, a request was captured, a proof passed, or a version was created or
|
|
171
|
-
published unless a tool result says so.
|
|
41
|
+
Tool results are the source of truth. Never say a browser attached, a user signed in, a request was captured, a proof passed, or a version was created or published unless a tool result says so.
|
|
172
42
|
|
|
173
|
-
Treat every ID, version, URL, and value as opaque: copy it from the latest tool
|
|
174
|
-
result. Never invent or reconstruct one. When state is unclear, call the
|
|
175
|
-
relevant get/list tool or `how_it_works`. State uncertainty plainly.
|
|
43
|
+
Treat every ID, version, URL, and value as opaque: copy it from the latest tool result. Never invent or reconstruct one. When state is unclear, call the relevant get/list tool or `how_it_works`. State uncertainty plainly.
|
|
176
44
|
|
|
177
|
-
|
|
178
|
-
step.
|
|
45
|
+
## Guide
|
|
179
46
|
|
|
180
|
-
|
|
181
|
-
and `attachUrl`. Give the developer the URL, then poll `authenticate({ code })`
|
|
182
|
-
until LINKED (topic `auth`).
|
|
47
|
+
`how_it_works({})` lists topics. Fetch only the one for your next step:
|
|
183
48
|
|
|
184
|
-
|
|
185
|
-
`
|
|
186
|
-
|
|
49
|
+
- `overview`: authoring checklist; `prove`, `publish`, `browser`: the details behind each step.
|
|
50
|
+
- `integration`: app integration, trying a session without an app, existing `@reclaimprotocol/js-sdk` projects.
|
|
51
|
+
- `auth`: sign-in (`get_me`, then `authenticate` on 401) and backend mode.
|
package/skill/old-mode.md
CHANGED
|
@@ -1,100 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
intentionally reduced: no generated API tools, no organizations, no public
|
|
3
|
-
review flow. Only GET/POST requests can be captured into providers.
|
|
1
|
+
# Legacy devtools mode
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
`verification` is an end-user session that proves a data point using one. Never
|
|
7
|
-
call a provider a "verification."**
|
|
3
|
+
Provider-authoring tools for the old devtools backend. The tool surface is reduced: no generated API tools, no organizations, no public review. Only GET and POST requests can be captured.
|
|
8
4
|
|
|
9
|
-
**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
**A `provider` is a recipe for extracting a data point from a site. A `verification` is an end-user session that proves a data point with a provider. Never call a provider a "verification."**
|
|
6
|
+
|
|
7
|
+
## Routing
|
|
8
|
+
|
|
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
|
+
- 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
|
+
- Call `attach_browser()` with no arguments. Don't ask which browser to use.
|
|
12
|
+
|
|
13
|
+
## Asking the developer
|
|
14
|
+
|
|
15
|
+
- When you need an answer or an action, end your turn with the question and every link they need. Don't use a background or asynchronous question tool: the developer may never see it.
|
|
16
|
+
- Ask each question once. Act on the answer; don't ask again.
|
|
17
|
+
|
|
18
|
+
## Permission blocks
|
|
19
|
+
|
|
20
|
+
When a permission check blocks a tool call or command:
|
|
21
|
+
|
|
22
|
+
1. Don't retry it or work around it.
|
|
23
|
+
2. In one message, name the blocked tool or command, what it does, and what approving it means.
|
|
24
|
+
3. Ask for approval in words that name that exact action, for example: "Approve running `npm run dev` to start the demo server?"
|
|
25
|
+
|
|
26
|
+
## Authoring rules
|
|
27
|
+
|
|
28
|
+
- Provider versions are immutable: every change creates a new version, default a patch bump. Never edit an existing version.
|
|
29
|
+
- Publishing without `providerId` registers a new provider. Check `get_me_providers` first to avoid duplicates.
|
|
30
|
+
- `reclaim_authenticate` authorizes this mode. On an auth error, run it again (topic `auth`).
|
|
13
31
|
|
|
14
32
|
## Evidence contract
|
|
15
33
|
|
|
16
|
-
Tool results are the source of truth. Never say
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
action from the developer before you can continue, end your turn with the
|
|
29
|
-
question and every link they need. Don't use a background or asynchronous
|
|
30
|
-
question tool for it: the developer may never see it.
|
|
31
|
-
|
|
32
|
-
**Use the guide as needed.** Call `how_it_works({})` for its topic index, then
|
|
33
|
-
fetch only the topic relevant to the next tool call.
|
|
34
|
-
|
|
35
|
-
**Open the browser without asking.** Call `attach_browser()` with no
|
|
36
|
-
arguments: it opens a visible browser on the developer's machine with the
|
|
37
|
-
persistent Reclaim profile, and falls back to Chrome for Testing itself when
|
|
38
|
-
no installed browser can be attached. Don't ask which browser or who signs in.
|
|
39
|
-
Use another `mode` only when that fails too, or when the developer explicitly
|
|
40
|
-
asks for it (topic `browser`). Tell the developer once, as a side note, that a
|
|
41
|
-
shareable link can be set up if a volunteer is helping them sign in; don't ask
|
|
42
|
-
about it or set it up unless they ask.
|
|
43
|
-
|
|
44
|
-
**The flow:** `reclaim_authenticate` once → `attach_browser()` (no arguments: a
|
|
45
|
-
visible local browser) → `start_capture` ⇒ **`captureId`** →
|
|
46
|
-
drive the page (`navigate`,
|
|
47
|
-
`wait_for_page`, `eval_in_page`) → inspect (`list_requests`, `get_request`,
|
|
48
|
-
`find_requests_containing`) → `propose_provider` ⇒ **`draftId`** →
|
|
49
|
-
`replay_request(captureId, draftId)` → `run_proof(captureId,
|
|
50
|
-
draftId)` → `create_provider_version_from_capture`.
|
|
51
|
-
|
|
52
|
-
`reclaim_authenticate` itself always uses a local Chrome over loopback CDP. It
|
|
53
|
-
never uses the container, remote Builder, custom-CDP, or shared authoring
|
|
54
|
-
browser; those choices begin only at `attach_browser` after dashboard sign-in.
|
|
55
|
-
|
|
56
|
-
**Publishing and ownership:** with NO `providerId`, publish REGISTERS A NEW
|
|
57
|
-
provider — re-running creates a duplicate. Pass a `providerId` from
|
|
58
|
-
`get_me_providers` (the only provider-listing tool here) to add a version to an
|
|
59
|
-
existing provider instead; you can only version a provider you own. For a
|
|
60
|
-
multi-request provider pass `providers: [draftA, draftB, …]` so each becomes a
|
|
61
|
-
parallel `requestData` entry on the one version.
|
|
62
|
-
|
|
63
|
-
**Using a provider.** A provider found with `get_me_providers` or
|
|
64
|
-
`get_provider_info` is published and usable as-is. Don't capture,
|
|
65
|
-
`replay_request`, or `run_proof` against it unless the developer asks you to
|
|
66
|
-
check or test it. Before using a provider, found or just created, ask once how
|
|
67
|
-
they want to use it (skip this if they already said):
|
|
68
|
-
|
|
69
|
-
> Want to (1) try it right now here, (2) integrate it into an existing backend
|
|
70
|
-
> or frontend (this directory or another path), or (3) create a new app for it?
|
|
71
|
-
|
|
72
|
-
Try it now → `scaffold_reclaim_demo_server` with its `providerId`. Integrate,
|
|
73
|
-
or new app → `get_js_sdk_integration_guide`, then work in the path they named.
|
|
74
|
-
|
|
75
|
-
**Two independent auth systems — don't confuse them.** `reclaim_authenticate`
|
|
76
|
-
authorizes everything in this mode; its Firebase token is short-lived (~1h), so
|
|
77
|
-
an auth error on publish or `get_me_providers` means re-run it.
|
|
78
|
-
`authenticate_builder` covers only two Builder-exclusive features: allocating a
|
|
79
|
-
remote browser (`attach_browser mode="builder"`) and
|
|
80
|
-
`list_builder_organizations`. It authorizes nothing else. `get_devtools_mode`
|
|
81
|
-
reports both.
|
|
82
|
-
|
|
83
|
-
**Never prove a public endpoint.** After `replay_request` succeeds, re-run it
|
|
84
|
-
with `withoutSecrets: true`. If the value still extracts, the endpoint is public
|
|
85
|
-
and the proof binds to nobody — find an auth-bound request instead.
|
|
86
|
-
|
|
87
|
-
**Templating:** bare `{{name}}` placeholders are extracted from the response.
|
|
88
|
-
Values the CONSUMER supplies at verification time use `{{context_<name>}}` —
|
|
89
|
-
this backend does NOT support the builder's dotted `{{context.<name>}}` form.
|
|
90
|
-
|
|
91
|
-
**Diagnosing a session:** `session_analytics_logs` returns a session's
|
|
92
|
-
milestone events; `session_logs` returns the log entries the SDK emitted, each
|
|
93
|
-
with its event type — that is where a failed match, redaction, or claim shows
|
|
94
|
-
up. Both take a `sessionId`; see topic `troubleshooting` for how to read them.
|
|
95
|
-
|
|
96
|
-
**Backend mode:** the BUILDER backend (generated API tools, orgs, verification
|
|
97
|
-
sessions, public review) is one switch away. `get_devtools_mode` reports the
|
|
98
|
-
active mode and why; `set_devtools_mode` persists a switch to
|
|
99
|
-
`~/.reclaim/config.json`, effective on the NEXT server start. An explicit
|
|
100
|
-
`USE_OLD_DEVTOOLS` env var wins over the persisted choice.
|
|
34
|
+
Tool results are the source of truth. Never say a browser attached, a user logged in, a request was captured, a proof passed, or a version was created or published unless a tool result says so. A planned call is not a completed action.
|
|
35
|
+
|
|
36
|
+
Treat every ID, version, URL, request value, and error as opaque: copy it from the latest tool result. Never invent, reconstruct, or reuse one from memory. When state is unclear, call the relevant get/list/status tool or `how_it_works`. State uncertainty plainly.
|
|
37
|
+
|
|
38
|
+
## Guide
|
|
39
|
+
|
|
40
|
+
`how_it_works({})` lists topics. Fetch only the one for your next step:
|
|
41
|
+
|
|
42
|
+
- `overview`: the authoring checklist.
|
|
43
|
+
- `auth`: sign-in, and backend mode (switching to Builder).
|
|
44
|
+
- `publish`: ownership, multi-request providers, using a provider.
|
|
45
|
+
- `troubleshooting`: `session_analytics_logs` and `session_logs` for a failed session.
|