@reclaimprotocol/agent 0.1.33 → 0.1.35
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 +3 -3
- package/lib/authoring/backend.d.ts +13 -0
- package/lib/authoring/index.d.ts +1 -1
- package/lib/authoring/tools.js +78 -42
- package/lib/config/store.d.ts +10 -0
- package/lib/mcp/api/operations.gen.d.ts +238 -4
- package/lib/mcp/api/operations.gen.js +6967 -672
- package/lib/mcp/api/tools.js +21 -8
- package/lib/mcp/instructions.js +12 -12
- package/lib/mcp/server.d.ts +1 -1
- package/lib/mcp/server.js +3 -0
- package/lib/mcp/start.js +8 -7
- package/lib/mcp/success-response.js +5 -1
- package/lib/mcp/tools/agent/analyze.js +5 -4
- package/lib/mcp/tools/agent/attach.js +11 -7
- package/lib/mcp/tools/agent/build.js +5 -1
- package/lib/mcp/tools/agent/capture.d.ts +2 -2
- package/lib/mcp/tools/agent/capture.js +15 -11
- package/lib/mcp/tools/agent/check-attestor.d.ts +5 -0
- package/lib/mcp/tools/agent/check-attestor.js +37 -0
- package/lib/mcp/tools/agent/eval.js +4 -3
- package/lib/mcp/tools/agent/find.js +9 -10
- package/lib/mcp/tools/agent/how-it-works.js +1 -0
- package/lib/mcp/tools/agent/live-view.js +49 -22
- package/lib/mcp/tools/agent/pod-proof.js +7 -11
- package/lib/mcp/tools/agent/proof.d.ts +12 -0
- package/lib/mcp/tools/agent/proof.js +32 -0
- package/lib/mcp/tools/agent/propose.js +4 -3
- package/lib/mcp/tools/agent/publish.d.ts +2 -1
- package/lib/mcp/tools/agent/publish.js +12 -6
- package/lib/mcp/tools/agent/replay.js +10 -7
- package/lib/mcp/tools/agent/session.js +16 -8
- package/lib/mcp/tools/agent/shared.d.ts +2 -1
- package/lib/mcp/tools/agent/shared.js +29 -24
- package/lib/mcp/tools/agent/start-integration.d.ts +15 -0
- package/lib/mcp/tools/agent/start-integration.js +62 -0
- package/lib/mcp/tools/authenticate/authenticate.js +9 -11
- package/lib/mcp/tools/authenticate/build.js +2 -0
- package/lib/mcp/tools/authenticate/builder-access.js +1 -0
- package/lib/mcp/tools/authenticate/eth-key.d.ts +8 -0
- package/lib/mcp/tools/authenticate/eth-key.js +27 -15
- package/lib/mcp/tools/authenticate/import.js +18 -31
- package/lib/mcp/tools/authenticate/issue-org-token.d.ts +8 -0
- package/lib/mcp/tools/authenticate/issue-org-token.js +60 -0
- package/lib/mcp/tools/authenticate/issue.js +9 -9
- package/lib/mcp/tools/authenticate/org-key-store.d.ts +10 -0
- package/lib/mcp/tools/authenticate/org-key-store.js +23 -0
- package/lib/mcp/tools/authenticate/resolve-owner-key.js +10 -12
- package/lib/mcp/tools/mode/mode.js +2 -0
- package/lib/mcp/tools/verification/build.d.ts +3 -1
- package/lib/mcp/tools/verification/build.js +10 -2
- package/lib/mcp/tools/verification/callback-listener.d.ts +51 -0
- package/lib/mcp/tools/verification/callback-listener.js +163 -0
- package/lib/mcp/tools/verification/index.d.ts +2 -0
- package/lib/mcp/tools/verification/index.js +2 -0
- package/lib/mcp/tools/verification/proxy-callback-events.d.ts +59 -0
- package/lib/mcp/tools/verification/proxy-callback-events.js +300 -0
- package/lib/mcp/tools/verification/read-callback-events.d.ts +3 -0
- package/lib/mcp/tools/verification/read-callback-events.js +135 -0
- package/lib/mcp/tools/verification/result.d.ts +6 -0
- package/lib/mcp/tools/verification/result.js +11 -8
- package/lib/proof/check-attestor.d.ts +67 -0
- package/lib/proof/check-attestor.js +156 -0
- package/lib/tools/registry.d.ts +12 -0
- package/lib/tools/registry.js +1 -0
- package/package.json +2 -2
- package/skill/SKILL.builder.md +84 -75
- package/skill/SKILL.common.md +23 -10
- package/skill/builder-mode.md +140 -138
- package/skill/start-integration.md +74 -0
- package/skill/user-script.md +64 -0
- package/skill/verification-client-integration.md +40 -28
- package/src/authoring/backend.ts +15 -0
- package/src/authoring/index.ts +2 -0
- package/src/authoring/tools.ts +86 -42
- package/src/config/store.ts +11 -0
- package/src/mcp/api/operations.gen.ts +7011 -704
- package/src/mcp/api/tools.ts +21 -8
- package/src/mcp/instructions.ts +12 -12
- package/src/mcp/server.ts +4 -0
- package/src/mcp/start.ts +9 -7
- package/src/mcp/success-response.ts +5 -1
- package/src/mcp/tools/agent/analyze.ts +5 -4
- package/src/mcp/tools/agent/attach.ts +11 -7
- package/src/mcp/tools/agent/build.ts +7 -1
- package/src/mcp/tools/agent/capture.ts +20 -12
- package/src/mcp/tools/agent/check-attestor.ts +49 -0
- package/src/mcp/tools/agent/eval.ts +4 -3
- package/src/mcp/tools/agent/find.ts +9 -10
- package/src/mcp/tools/agent/how-it-works.ts +1 -0
- package/src/mcp/tools/agent/live-view.ts +49 -22
- package/src/mcp/tools/agent/pod-proof.ts +7 -11
- package/src/mcp/tools/agent/proof.ts +55 -0
- package/src/mcp/tools/agent/propose.ts +4 -3
- package/src/mcp/tools/agent/publish.ts +12 -4
- package/src/mcp/tools/agent/replay.ts +10 -7
- package/src/mcp/tools/agent/session.ts +16 -8
- package/src/mcp/tools/agent/shared.ts +39 -24
- package/src/mcp/tools/agent/start-integration.ts +84 -0
- package/src/mcp/tools/authenticate/authenticate.ts +9 -11
- package/src/mcp/tools/authenticate/build.ts +2 -0
- package/src/mcp/tools/authenticate/builder-access.ts +1 -0
- package/src/mcp/tools/authenticate/eth-key.ts +48 -18
- package/src/mcp/tools/authenticate/import.ts +21 -36
- package/src/mcp/tools/authenticate/issue-org-token.ts +84 -0
- package/src/mcp/tools/authenticate/issue.ts +9 -9
- package/src/mcp/tools/authenticate/org-key-store.ts +25 -0
- package/src/mcp/tools/authenticate/resolve-owner-key.ts +10 -12
- package/src/mcp/tools/mode/mode.ts +2 -0
- package/src/mcp/tools/verification/build.ts +10 -2
- package/src/mcp/tools/verification/callback-listener.ts +203 -0
- package/src/mcp/tools/verification/index.ts +2 -0
- package/src/mcp/tools/verification/proxy-callback-events.ts +374 -0
- package/src/mcp/tools/verification/read-callback-events.ts +160 -0
- package/src/mcp/tools/verification/result.ts +11 -8
- package/src/proof/check-attestor.ts +209 -0
- package/src/tools/registry.ts +14 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attestor reachability check. Proves a public request with a throwaway owner
|
|
3
|
+
* key to show whether the attestor works from this machine, independent of any
|
|
4
|
+
* developer provider or site.
|
|
5
|
+
*/
|
|
6
|
+
import { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
|
|
7
|
+
import { generateKeypair } from '@reclaimprotocol/client';
|
|
8
|
+
import "./patch-domhandler.js";
|
|
9
|
+
import { claimRejection, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
|
|
10
|
+
import { ensureZkFiles } from "./zk-files.js";
|
|
11
|
+
/**
|
|
12
|
+
* Default time budget for one check. A live run takes about 8 s; a longer
|
|
13
|
+
* budget risks the MCP client's own tool-call timeout.
|
|
14
|
+
*/
|
|
15
|
+
export const CHECK_ATTESTOR_TIMEOUT_MS = 45000;
|
|
16
|
+
/* eslint-disable @stylistic/max-len -- the source URL cannot wrap. */
|
|
17
|
+
/**
|
|
18
|
+
* Request params for the check: the public CoinGecko price request from the
|
|
19
|
+
* attestor-core examples. Source:
|
|
20
|
+
* https://raw.githubusercontent.com/reclaimprotocol/attestor-core/refs/heads/main/example/coin-gecko.json
|
|
21
|
+
*/
|
|
22
|
+
/* eslint-enable @stylistic/max-len */
|
|
23
|
+
export const COIN_GECKO_PARAMS = {
|
|
24
|
+
url: 'https://api.coingecko.com/api/v3/simple/price'
|
|
25
|
+
+ '?ids=cardano,solana&vs_currencies=usd',
|
|
26
|
+
method: 'GET',
|
|
27
|
+
body: '',
|
|
28
|
+
headers: {
|
|
29
|
+
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) '
|
|
30
|
+
+ 'AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1',
|
|
31
|
+
'Sec-Fetch-Mode': 'same-origin',
|
|
32
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
33
|
+
},
|
|
34
|
+
responseMatches: [
|
|
35
|
+
{
|
|
36
|
+
invert: false,
|
|
37
|
+
type: 'regex',
|
|
38
|
+
value: 'cardano":{"usd":(?<cardanoPrice>\\d*\\.*\\d*)}',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
invert: false,
|
|
42
|
+
type: 'regex',
|
|
43
|
+
value: 'solana":{"usd":(?<solanaPrice>\\d*\\.*\\d*)}',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
responseRedactions: [
|
|
47
|
+
{ jsonPath: '$.cardano', regex: 'cardano":{"usd":(.*?)}', xPath: '' },
|
|
48
|
+
{ jsonPath: '$.solana', regex: 'solana":{"usd":(.*?)}', xPath: '' },
|
|
49
|
+
],
|
|
50
|
+
additionalClientOptions: {},
|
|
51
|
+
};
|
|
52
|
+
/** The only secret in the example request. */
|
|
53
|
+
const COIN_GECKO_SECRET_HEADERS = {
|
|
54
|
+
Referer: 'https://www.coingecko.com/en/nft',
|
|
55
|
+
};
|
|
56
|
+
/** Prefix of the error raised when the check exceeds its time budget. */
|
|
57
|
+
const CHECK_TIMEOUT_MESSAGE = 'attestor check timed out';
|
|
58
|
+
/**
|
|
59
|
+
* Signals that the attestor connection failed. Bare "timeout", "timed out",
|
|
60
|
+
* and "websocket" are left out: a target site's errors contain them too.
|
|
61
|
+
*/
|
|
62
|
+
const NETWORK_ERROR_PATTERN = new RegExp([
|
|
63
|
+
'connection closed',
|
|
64
|
+
'ERROR_NETWORK_ERROR',
|
|
65
|
+
'ECONNRESET',
|
|
66
|
+
'ECONNREFUSED',
|
|
67
|
+
'ENOTFOUND',
|
|
68
|
+
'EAI_AGAIN',
|
|
69
|
+
'ETIMEDOUT',
|
|
70
|
+
'EHOSTUNREACH',
|
|
71
|
+
'ENETUNREACH',
|
|
72
|
+
'socket hang up',
|
|
73
|
+
'websocket (connection|error|closed|failed)',
|
|
74
|
+
'(failed|unable|could not) to connect',
|
|
75
|
+
CHECK_TIMEOUT_MESSAGE,
|
|
76
|
+
].join('|'), 'i');
|
|
77
|
+
/** True when `message` looks like a network failure rather than a rejection. */
|
|
78
|
+
export function isNetworkError(message) {
|
|
79
|
+
return message !== undefined && NETWORK_ERROR_PATTERN.test(message);
|
|
80
|
+
}
|
|
81
|
+
/** Prove the public CoinGecko request once and classify the outcome. */
|
|
82
|
+
export async function checkAttestor(opts = {}) {
|
|
83
|
+
const attestorUrl = resolveAttestorUrl(opts.attestorUrl);
|
|
84
|
+
const timeoutMs = opts.timeoutMs ?? CHECK_ATTESTOR_TIMEOUT_MS;
|
|
85
|
+
const createClaim = opts.createClaim ?? createClaimOnAttestor;
|
|
86
|
+
const prepare = opts.prepare ?? (async () => {
|
|
87
|
+
ensureAttestorCrypto();
|
|
88
|
+
await ensureZkFiles();
|
|
89
|
+
});
|
|
90
|
+
const startedAt = Date.now();
|
|
91
|
+
const finish = (outcome) => {
|
|
92
|
+
return { ...outcome, attestorUrl, durationMs: Date.now() - startedAt };
|
|
93
|
+
};
|
|
94
|
+
let timer;
|
|
95
|
+
const timeout = new Promise((_, reject) => {
|
|
96
|
+
timer = setTimeout(() => {
|
|
97
|
+
reject(new Error(`${CHECK_TIMEOUT_MESSAGE} after ${timeoutMs} ms`));
|
|
98
|
+
}, timeoutMs);
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
try {
|
|
102
|
+
await Promise.race([prepare(), timeout]);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const error = messageOf(err);
|
|
106
|
+
return finish({
|
|
107
|
+
ok: false,
|
|
108
|
+
error,
|
|
109
|
+
errorKind: error.startsWith(CHECK_TIMEOUT_MESSAGE)
|
|
110
|
+
? 'attestor-unreachable'
|
|
111
|
+
: 'setup-failed',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const claim = await Promise.race([
|
|
115
|
+
createClaim({
|
|
116
|
+
name: 'http',
|
|
117
|
+
params: COIN_GECKO_PARAMS,
|
|
118
|
+
secretParams: { headers: COIN_GECKO_SECRET_HEADERS },
|
|
119
|
+
ownerPrivateKey: generateKeypair().privateKey,
|
|
120
|
+
client: { url: attestorUrl },
|
|
121
|
+
zkEngine: 'stwo',
|
|
122
|
+
}),
|
|
123
|
+
timeout,
|
|
124
|
+
]);
|
|
125
|
+
const rejection = claimRejection(claim);
|
|
126
|
+
if (rejection !== undefined) {
|
|
127
|
+
return finish({
|
|
128
|
+
ok: false,
|
|
129
|
+
error: rejection,
|
|
130
|
+
errorKind: isNetworkError(rejection)
|
|
131
|
+
? 'attestor-unreachable'
|
|
132
|
+
: 'attestor-error',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return finish({
|
|
136
|
+
ok: true,
|
|
137
|
+
extractedParameters: parseClaim(claim).extractedParameters,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
const error = messageOf(err);
|
|
142
|
+
return finish({
|
|
143
|
+
ok: false,
|
|
144
|
+
error,
|
|
145
|
+
errorKind: isNetworkError(error)
|
|
146
|
+
? 'attestor-unreachable'
|
|
147
|
+
: 'attestor-error',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function messageOf(err) {
|
|
155
|
+
return err instanceof Error ? err.message : String(err);
|
|
156
|
+
}
|
package/lib/tools/registry.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import type { JSONSchema } from 'zod/v4/core';
|
|
2
|
+
/** MCP tool hints that let a client decide when to ask for approval. */
|
|
3
|
+
export interface ToolAnnotations {
|
|
4
|
+
/** The tool never changes state. */
|
|
5
|
+
readOnlyHint?: boolean;
|
|
6
|
+
/** The tool can delete or overwrite state. */
|
|
7
|
+
destructiveHint?: boolean;
|
|
8
|
+
/** Repeating a call with the same input has no further effect. */
|
|
9
|
+
idempotentHint?: boolean;
|
|
10
|
+
/** The tool reaches systems outside this machine. */
|
|
11
|
+
openWorldHint?: boolean;
|
|
12
|
+
}
|
|
2
13
|
export interface ToolDefinition {
|
|
3
14
|
name: string;
|
|
4
15
|
description: string;
|
|
5
16
|
inputSchema: JSONSchema.ObjectSchema;
|
|
17
|
+
annotations?: ToolAnnotations;
|
|
6
18
|
}
|
|
7
19
|
export interface RegisteredTool {
|
|
8
20
|
definition: ToolDefinition;
|
package/lib/tools/registry.js
CHANGED
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.35",
|
|
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",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
84
84
|
"@noble/hashes": "^2.2.0",
|
|
85
85
|
"@reclaimprotocol/attestor-core": "^5.1.5",
|
|
86
|
-
"@reclaimprotocol/client": "0.1.
|
|
86
|
+
"@reclaimprotocol/client": "0.1.35",
|
|
87
87
|
"@reclaimprotocol/tls": "^0.1.3",
|
|
88
88
|
"chrome-remote-interface": "^0.33.0",
|
|
89
89
|
"domhandler": "^6.0.0",
|
package/skill/SKILL.builder.md
CHANGED
|
@@ -11,32 +11,38 @@ Builder.
|
|
|
11
11
|
|
|
12
12
|
## The loop, at a glance
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- [ ] 4.
|
|
25
|
-
|
|
26
|
-
- [ ] 5. `
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
- [ ]
|
|
37
|
+
- [ ] 10. `run_proof(captureId, draftId, ownerAddress)`.
|
|
33
38
|
→ topics `prove`, `credentials`
|
|
34
|
-
- [ ]
|
|
35
|
-
`create_provider_version_from_capture`
|
|
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
|
-
|
|
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`, `
|
|
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. **
|
|
97
|
-
|
|
98
|
-
`
|
|
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
|
|
101
|
-
|
|
102
|
-
|
|
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?**
|
|
130
|
-
contains all of them** and draft them
|
|
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: "
|
|
151
|
+
{ value: "2019", name: "member_since_year" },
|
|
140
152
|
])
|
|
141
153
|
```
|
|
142
154
|
|
|
@@ -303,6 +315,11 @@ provider JSON. That's the final result.
|
|
|
303
315
|
developer what's happening and drive the bootstrap yourself — see topic
|
|
304
316
|
`credentials`. No restart needed, and the existing `draftId` stays valid.
|
|
305
317
|
|
|
318
|
+
**Network error from `run_proof`.** Read its `diagnosis`. Attestor reachable
|
|
319
|
+
→ the target site likely blocks the attestor's network; call
|
|
320
|
+
`run_proof_via_pod`. Attestor unreachable → `check_attestor` confirms it; the
|
|
321
|
+
fix is on the developer's network. Don't loop retries.
|
|
322
|
+
|
|
306
323
|
<!-- common: prove-tail -->
|
|
307
324
|
|
|
308
325
|
<!-- topic: publish -->
|
|
@@ -313,16 +330,13 @@ parameterization applied. `initialUrl` is the page where the user logs in / the
|
|
|
313
330
|
value is displayed (for example, `https://github.com/Syed`) — **not** the API
|
|
314
331
|
endpoint URL inside the provider.
|
|
315
332
|
|
|
316
|
-
**1.
|
|
317
|
-
`
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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".
|
|
333
|
+
**1. Resolve the `providerId`.** For a new claim, call
|
|
334
|
+
`create_provider(orgId, domain, slug, title, description)` (`orgId` from
|
|
335
|
+
`list_orgs`; `domain` such as `github.com`, `slug` such as `github-username`,
|
|
336
|
+
`title` such as "GitHub Username"). It starts PRIVATE with an empty seed
|
|
337
|
+
version. Use an existing `providerId` only when your org owns the provider and
|
|
338
|
+
you are revising it: the capture lands as a NEW VERSION on it. For another
|
|
339
|
+
org's provider that almost fits, create your own provider and version.
|
|
326
340
|
|
|
327
341
|
**2. Persist the version.**
|
|
328
342
|
`create_provider_version_from_capture(providerId, provider, initialUrl, notes)`
|
|
@@ -339,12 +353,13 @@ or archive an existing version to apply provider changes.
|
|
|
339
353
|
required at verification time. This proves that every request matched; it
|
|
340
354
|
does not automatically bind a value extracted from one response to another
|
|
341
355
|
request.
|
|
342
|
-
- **
|
|
343
|
-
|
|
344
|
-
`
|
|
345
|
-
pagination)
|
|
346
|
-
a `verifyRequestProof({ providerId })` use case, read topic
|
|
347
|
-
session-unique URL there makes verifyRequestProof
|
|
356
|
+
- **Navigation script:** the script kept with `test_user_script` (`keep: true`)
|
|
357
|
+
is published as `webSettings.jsUserScripts`. Pass `jsUserScripts` only to
|
|
358
|
+
override it. → topic `user-script`. For extra requests the script may fire
|
|
359
|
+
(for example, pagination), pass `allowedJsRequests`. Before populating it for
|
|
360
|
+
a `verifyRequestProof({ providerId })` use case, read topic
|
|
361
|
+
`hash-validation`: a session-unique URL there makes `verifyRequestProof`
|
|
362
|
+
reject every real proof.
|
|
348
363
|
|
|
349
364
|
**3. `requiredContext` is derived for you.** The publish tool scans the recipe's
|
|
350
365
|
url/body for `{{context.<name>}}` placeholders and emits a JSON Schema requiring
|
|
@@ -367,10 +382,8 @@ developer it's awaiting admin review.
|
|
|
367
382
|
context params — for example, `context: { "username": "…" }` in
|
|
368
383
|
`create_verification_session`. Quote the `requiredContext` from the created
|
|
369
384
|
version verbatim — a session missing those fields gets a 400, and verification
|
|
370
|
-
matches the supplied values exactly. Then
|
|
371
|
-
|
|
372
|
-
new app — unless they already said (see "Using a provider" in the server
|
|
373
|
-
instructions).
|
|
385
|
+
matches the supplied values exactly. Then continue as the server
|
|
386
|
+
instructions say under "What the developer wants".
|
|
374
387
|
|
|
375
388
|
**6. If the response includes `_notes` for an attached browser, follow them for
|
|
376
389
|
an optional authenticated-state retest.** Only when its profile is still signed
|
|
@@ -383,35 +396,30 @@ the session for further edits; call `dispose_browser` only after they confirm.
|
|
|
383
396
|
A `builder` session is quota-accounted, so don't leave it idle.
|
|
384
397
|
|
|
385
398
|
<!-- topic: discover -->
|
|
386
|
-
## Discover and resolve providers
|
|
399
|
+
## Discover and resolve existing providers
|
|
387
400
|
|
|
388
|
-
|
|
389
|
-
|
|
401
|
+
Use this flow only when the developer asks to reuse existing providers or
|
|
402
|
+
doesn't know what a site supports. Otherwise build a new provider (server
|
|
403
|
+
instructions, "Choose the provider").
|
|
390
404
|
|
|
391
405
|
1. Ask which website their users prove data from.
|
|
392
406
|
2. `discover_data_points({ domain })` → what's verifiable there. Confirm the
|
|
393
407
|
data points with the developer.
|
|
394
408
|
3. `discover_resolve({ domain, dataPoints })` → the smallest provider set
|
|
395
409
|
(`providers`, greedy combine), the `requiredContext` inputs to collect, and
|
|
396
|
-
any `uncovered` points (author those with the
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
5.
|
|
403
|
-
`
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
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`.
|
|
410
|
+
any `uncovered` points (author those with the checklist in topic
|
|
411
|
+
`overview`, then re-resolve).
|
|
412
|
+
4. Use only the data points the developer confirmed: show and read only those
|
|
413
|
+
and ignore the rest. A provider that needs any change gets your own copy
|
|
414
|
+
(server instructions, "Choose the provider"). Otherwise it's usable as-is;
|
|
415
|
+
don't capture, replay, or prove it unless the developer asks.
|
|
416
|
+
5. To try them: `create_verification_session({ providers: [{ providerId }, …],
|
|
417
|
+
context, verificationClientUrl })` with EVERY resolved provider id and the
|
|
418
|
+
collected context. The server instructions ("Try a provider without an
|
|
419
|
+
app") cover the callback and polling. To integrate: topic `integration`.
|
|
420
|
+
|
|
421
|
+
`merge.mergeable` only signals the set *could* collapse into one provider. Pass
|
|
422
|
+
them all; the Builder runs them in one session.
|
|
415
423
|
|
|
416
424
|
<!-- topic: integration -->
|
|
417
425
|
|
|
@@ -453,6 +461,7 @@ or omit `interceptorOptions`). If that fixes the provider, keep interception
|
|
|
453
461
|
off and replace intercepted claims with `window.Reclaim.requestClaim`. Full
|
|
454
462
|
checklist and remedies: topic `interception`.
|
|
455
463
|
|
|
456
|
-
**Proof failures / attestor errors** → topic `prove`.
|
|
464
|
+
**Proof failures / attestor errors** → topic `prove`. For a network error,
|
|
465
|
+
read `run_proof`'s `diagnosis`, then `check_attestor` or `run_proof_via_pod`.
|
|
457
466
|
**Browser won't launch or attach** → topic `browser`.
|
|
458
467
|
**Missing signing key** → topic `credentials`.
|
package/skill/SKILL.common.md
CHANGED
|
@@ -112,13 +112,18 @@ Ask plainly:
|
|
|
112
112
|
|
|
113
113
|
If they say yes:
|
|
114
114
|
|
|
115
|
-
1. Call `share_browser_view` with no arguments. It returns the viewer `port`
|
|
116
|
-
the `command` (`cloudflared tunnel --url http://localhost:<port>`). The
|
|
117
|
-
server does not run cloudflared.
|
|
118
|
-
2.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
1. Call `share_browser_view` with no arguments. It returns the viewer `port`
|
|
116
|
+
and the `command` (`cloudflared tunnel --url http://localhost:<port>`). The
|
|
117
|
+
MCP server does not run cloudflared.
|
|
118
|
+
2. Ask the developer to choose, and start no tunnel until they answer:
|
|
119
|
+
- **They run it (recommended).** They run `! <command>` in this session and
|
|
120
|
+
paste the `https://<words>.trycloudflare.com` URL. The tunnel then lives
|
|
121
|
+
in their shell, and they decide when it closes.
|
|
122
|
+
- **You run it.** They approve you running `command` in the background. If
|
|
123
|
+
`cloudflared` is not installed, ask them to install it; do not install it
|
|
124
|
+
without their approval.
|
|
125
|
+
3. When you run it, read its output for the URL. Never guess or reconstruct the
|
|
126
|
+
hostname.
|
|
122
127
|
4. Call `share_browser_view({ publicUrl })` with that URL. **Relay the returned
|
|
123
128
|
`url` verbatim, on its own line.** It includes `liveview.html?magnify=1`.
|
|
124
129
|
|
|
@@ -138,8 +143,8 @@ If they say yes:
|
|
|
138
143
|
- **Opening it on a phone lays the page out for that phone**, with touch,
|
|
139
144
|
pinch-zoom and the soft keyboard. That is the reason to reach for `container`
|
|
140
145
|
when a site only works on mobile.
|
|
141
|
-
- **Stop
|
|
142
|
-
browser keeps running. `dispose_browser` and `reset_session` stop the
|
|
146
|
+
- **Stop a cloudflared process you started as soon as they're done.** If they
|
|
147
|
+
started it, tell them to stop it. The browser keeps running. `dispose_browser` and `reset_session` stop the
|
|
143
148
|
container itself, but not your cloudflared process.
|
|
144
149
|
- **Expose only the viewer port** that `share_browser_view` returns, never the
|
|
145
150
|
browser's CDP port.
|
|
@@ -381,6 +386,13 @@ supplies are context params.
|
|
|
381
386
|
`result.attestorLogs` and dumps `~/.reclaim/proof-runs/<timestamp>.json`
|
|
382
387
|
(`runLogPath`). Off by default — suggest it for a recurring failure.
|
|
383
388
|
|
|
389
|
+
**Network errors** ("connection closed", `ERROR_NETWORK_ERROR`, timeouts):
|
|
390
|
+
read the result's `diagnosis`. It says whether the attestor is reachable
|
|
391
|
+
from this machine. If it is, the target site likely blocks the attestor's
|
|
392
|
+
network; in builder mode, run `run_proof_via_pod`. If it is not, call
|
|
393
|
+
`check_attestor` after the developer fixes their network. Do not loop
|
|
394
|
+
retries; one `run_proof` per change.
|
|
395
|
+
|
|
384
396
|
**Do not auto-retry with a different `attestorUrl`.** There is one live
|
|
385
397
|
public attestor; backup hostnames (`attestor-2.*`, and so on) **do not
|
|
386
398
|
exist**. `attestorUrl` is only for a developer-supplied private/staging URL.
|
|
@@ -424,7 +436,8 @@ conversation.
|
|
|
424
436
|
1. **`resolve_owner_key`** returns only the derived address.
|
|
425
437
|
- `{ ready: true, address }` → call `run_proof` with it. No prompts.
|
|
426
438
|
- `{ ready: false }` → ask the developer once: **their own key** →
|
|
427
|
-
`import_credentials({
|
|
439
|
+
`import_credentials({ keyFile })` (a path to a file holding the key; never
|
|
440
|
+
ask them to paste it),
|
|
428
441
|
or **a fresh one** → `issue_credentials({})` (a fine default for test
|
|
429
442
|
proofs — owner identity doesn't matter). Either writes to the project
|
|
430
443
|
`.env` (mode 0600, added to `.gitignore`), never to `~/.reclaim`. Then
|