@reclaimprotocol/agent 0.1.1-dev.1 → 0.1.1

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 (201) hide show
  1. package/README.md +1 -1
  2. package/lib/cdp/capture-engine.d.ts +66 -0
  3. package/lib/cdp/capture-engine.js +153 -0
  4. package/lib/cdp/capture.d.ts +9 -20
  5. package/lib/cdp/capture.js +14 -138
  6. package/lib/cdp/index.d.ts +3 -0
  7. package/lib/cdp/index.js +6 -0
  8. package/lib/config/store.d.ts +7 -6
  9. package/lib/config/store.js +2 -2
  10. package/lib/index.d.ts +2 -2
  11. package/lib/index.js +1 -1
  12. package/lib/mcp/api/operations.gen.d.ts +101 -45
  13. package/lib/mcp/api/operations.gen.js +996 -126
  14. package/lib/mcp/api/to-zod.d.ts +24 -0
  15. package/lib/mcp/api/to-zod.js +94 -0
  16. package/lib/mcp/api/tools.js +1 -1
  17. package/lib/mcp/credentials/authenticate.d.ts +3 -0
  18. package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
  19. package/lib/mcp/credentials/build.d.ts +5 -0
  20. package/lib/mcp/credentials/build.js +18 -0
  21. package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
  22. package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
  23. package/lib/mcp/credentials/import.d.ts +2 -0
  24. package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
  25. package/lib/mcp/credentials/issue.d.ts +2 -0
  26. package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
  27. package/lib/mcp/credentials/keypair.d.ts +17 -0
  28. package/lib/mcp/credentials/keypair.js +48 -0
  29. package/lib/mcp/credentials/link.d.ts +3 -0
  30. package/lib/mcp/credentials/link.js +107 -0
  31. package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
  32. package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
  33. package/lib/mcp/credentials/owner-key.d.ts +23 -0
  34. package/lib/mcp/credentials/owner-key.js +58 -0
  35. package/lib/mcp/credentials/paths.d.ts +12 -0
  36. package/lib/mcp/credentials/paths.js +35 -0
  37. package/lib/mcp/credentials/poll.d.ts +27 -0
  38. package/lib/mcp/credentials/poll.js +61 -0
  39. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
  40. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
  41. package/lib/mcp/credentials/session-cache.d.ts +14 -0
  42. package/lib/mcp/credentials/session-cache.js +42 -0
  43. package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
  44. package/lib/mcp/credentials/status.js +76 -0
  45. package/lib/mcp/instructions.d.ts +1 -0
  46. package/lib/mcp/instructions.js +11 -0
  47. package/lib/mcp/register.d.ts +38 -0
  48. package/lib/mcp/register.js +80 -0
  49. package/lib/mcp/server.d.ts +2 -2
  50. package/lib/mcp/server.js +3 -3
  51. package/lib/mcp/start.js +10 -4
  52. package/lib/mcp/tools/agent/build.js +2 -15
  53. package/lib/mcp/tools/agent/index.d.ts +2 -0
  54. package/lib/mcp/tools/agent/index.js +3 -0
  55. package/lib/mcp/tools/agent/proof.js +1 -6
  56. package/lib/mcp/tools/agent/propose.js +13 -2
  57. package/lib/mcp/tools/agent/publish.js +10 -2
  58. package/lib/mcp/tools/agent/replay.js +0 -5
  59. package/lib/mcp/tools/analyze.d.ts +3 -0
  60. package/lib/mcp/tools/analyze.js +26 -0
  61. package/lib/mcp/tools/attach.d.ts +11 -0
  62. package/lib/mcp/tools/attach.js +72 -0
  63. package/lib/mcp/tools/authenticate/authenticate.js +107 -0
  64. package/lib/mcp/tools/authenticate/build.d.ts +15 -0
  65. package/lib/mcp/tools/authenticate/build.js +28 -0
  66. package/lib/mcp/tools/authenticate/decrypt-key.d.ts +32 -0
  67. package/lib/mcp/tools/authenticate/decrypt-key.js +49 -0
  68. package/lib/mcp/tools/authenticate/eth-key.d.ts +38 -0
  69. package/lib/mcp/tools/authenticate/eth-key.js +130 -0
  70. package/lib/mcp/tools/authenticate/import.js +57 -0
  71. package/lib/mcp/tools/authenticate/index.d.ts +2 -0
  72. package/lib/mcp/tools/authenticate/index.js +4 -0
  73. package/lib/mcp/tools/authenticate/issue.js +42 -0
  74. package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
  75. package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
  76. package/lib/mcp/tools/capture.d.ts +10 -0
  77. package/lib/mcp/tools/capture.js +142 -0
  78. package/lib/mcp/tools/eval.d.ts +5 -0
  79. package/lib/mcp/tools/eval.js +127 -0
  80. package/lib/mcp/tools/find.d.ts +3 -0
  81. package/lib/mcp/tools/find.js +60 -0
  82. package/lib/mcp/tools/index.d.ts +3 -0
  83. package/lib/mcp/tools/index.js +6 -0
  84. package/lib/mcp/tools/owner-key.d.ts +2 -0
  85. package/lib/mcp/tools/owner-key.js +63 -0
  86. package/lib/mcp/tools/proof.d.ts +3 -0
  87. package/lib/mcp/tools/proof.js +214 -0
  88. package/lib/mcp/tools/propose.d.ts +9 -0
  89. package/lib/mcp/tools/propose.js +75 -0
  90. package/lib/mcp/tools/publish.d.ts +3 -0
  91. package/lib/mcp/tools/publish.js +59 -0
  92. package/lib/mcp/tools/replay.d.ts +3 -0
  93. package/lib/mcp/tools/replay.js +46 -0
  94. package/lib/mcp/tools/session.d.ts +10 -0
  95. package/lib/mcp/tools/session.js +29 -0
  96. package/lib/mcp/tools/verification/build.d.ts +12 -0
  97. package/lib/mcp/tools/verification/build.js +14 -0
  98. package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
  99. package/lib/mcp/tools/verification/diagnose.js +132 -0
  100. package/lib/mcp/tools/verification/index.d.ts +1 -0
  101. package/lib/mcp/tools/verification/index.js +2 -0
  102. package/lib/mcp/tools/verification/result.d.ts +12 -0
  103. package/lib/mcp/tools/verification/result.js +126 -0
  104. package/lib/mcp/verifications/build.d.ts +5 -0
  105. package/lib/mcp/verifications/build.js +14 -0
  106. package/lib/mcp/verifications/create.d.ts +3 -0
  107. package/lib/mcp/verifications/create.js +57 -0
  108. package/lib/mcp/verifications/find.d.ts +3 -0
  109. package/lib/mcp/verifications/find.js +37 -0
  110. package/lib/mcp/verifications/get.d.ts +3 -0
  111. package/lib/mcp/verifications/get.js +26 -0
  112. package/lib/mcp/verifications/update.d.ts +3 -0
  113. package/lib/mcp/verifications/update.js +78 -0
  114. package/lib/old/client.d.ts +3 -0
  115. package/lib/old/instructions.d.ts +0 -6
  116. package/lib/old/instructions.js +6 -24
  117. package/lib/old/to-register.d.ts +3 -0
  118. package/lib/old/to-register.js +35 -7
  119. package/lib/old/tools/publish.js +13 -1
  120. package/lib/proof/attestor.d.ts +33 -1
  121. package/lib/proof/attestor.js +65 -63
  122. package/lib/proof/index.d.ts +5 -0
  123. package/lib/proof/index.js +6 -0
  124. package/lib/proof/proof-core.d.ts +35 -0
  125. package/lib/proof/proof-core.js +73 -0
  126. package/lib/provider/index.d.ts +5 -0
  127. package/lib/provider/index.js +9 -0
  128. package/lib/provider/to-version.d.ts +9 -12
  129. package/lib/provider/to-version.js +38 -4
  130. package/lib/provider/verification-checks.d.ts +12 -0
  131. package/lib/provider/verification-checks.js +30 -0
  132. package/lib/routes.gen.d.ts +271 -0
  133. package/lib/routes.gen.js +73 -0
  134. package/lib/types/openapi.gen.d.ts +3967 -0
  135. package/lib/types/openapi.gen.js +5 -0
  136. package/package.json +16 -7
  137. package/skill/SKILL.md +35 -14
  138. package/skill/builder-mode.md +9 -0
  139. package/skill/old-mode.md +13 -0
  140. package/src/cdp/capture-engine.ts +256 -0
  141. package/src/cdp/capture.ts +25 -185
  142. package/src/cdp/index.ts +6 -0
  143. package/src/config/store.ts +7 -6
  144. package/src/index.ts +2 -4
  145. package/src/mcp/api/operations.gen.ts +1023 -121
  146. package/src/mcp/api/to-zod.ts +115 -0
  147. package/src/mcp/api/tools.ts +9 -3
  148. package/src/mcp/instructions.ts +15 -0
  149. package/src/mcp/server.ts +5 -4
  150. package/src/mcp/start.ts +14 -4
  151. package/src/mcp/tools/agent/build.ts +2 -18
  152. package/src/mcp/tools/agent/index.ts +4 -0
  153. package/src/mcp/tools/agent/proof.ts +1 -7
  154. package/src/mcp/tools/agent/propose.ts +13 -2
  155. package/src/mcp/tools/agent/publish.ts +10 -2
  156. package/src/mcp/tools/agent/replay.ts +0 -5
  157. package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
  158. package/src/mcp/tools/authenticate/build.ts +32 -0
  159. package/src/mcp/tools/authenticate/decrypt-key.ts +64 -0
  160. package/src/mcp/tools/authenticate/eth-key.ts +182 -0
  161. package/src/mcp/tools/authenticate/import.ts +73 -0
  162. package/src/mcp/tools/authenticate/index.ts +4 -0
  163. package/src/mcp/tools/authenticate/issue.ts +50 -0
  164. package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
  165. package/src/mcp/tools/index.ts +6 -0
  166. package/src/mcp/tools/verification/build.ts +16 -0
  167. package/src/mcp/tools/verification/index.ts +2 -0
  168. package/src/mcp/tools/verification/result.ts +155 -0
  169. package/src/old/client.ts +3 -0
  170. package/src/old/instructions.ts +10 -25
  171. package/src/old/to-register.ts +62 -27
  172. package/src/old/tools/publish.ts +17 -1
  173. package/src/proof/attestor.ts +112 -71
  174. package/src/proof/index.ts +21 -0
  175. package/src/proof/proof-core.ts +109 -0
  176. package/src/provider/index.ts +20 -0
  177. package/src/provider/to-version.ts +52 -11
  178. package/src/provider/verification-checks.ts +36 -0
  179. package/lib/mcp/tools/credentials/build.d.ts +0 -16
  180. package/lib/mcp/tools/credentials/build.js +0 -33
  181. package/lib/mcp/tools/credentials/status.js +0 -62
  182. package/src/mcp/tools/credentials/build.ts +0 -37
  183. package/src/mcp/tools/credentials/cache.ts +0 -161
  184. package/src/mcp/tools/credentials/env-file.ts +0 -101
  185. package/src/mcp/tools/credentials/import.ts +0 -72
  186. package/src/mcp/tools/credentials/issue.ts +0 -107
  187. package/src/mcp/tools/credentials/list-cached.ts +0 -66
  188. package/src/mcp/tools/credentials/register.ts +0 -49
  189. package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
  190. package/src/mcp/tools/credentials/status.ts +0 -82
  191. package/src/types/openapi.ts +0 -7
  192. /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
  193. /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
  194. /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
  195. /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
  196. /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
  197. /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
  198. /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
  199. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
  200. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
  201. /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
@@ -0,0 +1,53 @@
1
+ import { join } from 'node:path';
2
+ import { findProjectRoot } from "../../../paths.js";
3
+ import { defineTool } from "../../server.js";
4
+ import { ENV_FILE, resolveEthKey } from "./eth-key.js";
5
+ /**
6
+ * Decide which eth proof-owner key `run_proof` should sign with, BEFORE
7
+ * calling it. The key is a raw 0x-hex Ethereum private key, resolved (no
8
+ * `~/.reclaim` cache) from:
9
+ * 1. `RECLAIM_PRIVATE_KEY` in the MCP env
10
+ * 2. a `RECLAIM_PRIVATE_KEY=0x…` line in the project `.env`
11
+ * 3. a file at `RECLAIM_PRIVATE_KEY_FILE` holding the raw hex
12
+ * 4. none → ask the dev to generate (issue_credentials) or provide one
13
+ * (import_credentials), then call again.
14
+ * Never returns the private key — only the derived address.
15
+ */
16
+ export function resolveOwnerKeyTool() {
17
+ return defineTool({
18
+ name: 'resolve_owner_key',
19
+ description: 'Resolve which eth proof-owner key run_proof should sign with — ' +
20
+ 'call this BEFORE run_proof. Checks, in order: RECLAIM_PRIVATE_KEY ' +
21
+ 'in the MCP env, a RECLAIM_PRIVATE_KEY=0x… line in the project .env, ' +
22
+ 'then a file at RECLAIM_PRIVATE_KEY_FILE holding the raw hex. ' +
23
+ 'Returns { ready: true, address, source } when one is ' +
24
+ 'available — pass `address` to run_proof as `ownerAddress`. ' +
25
+ 'Returns { ready: false } ' +
26
+ 'when none exists: then ask the dev to generate one ' +
27
+ '(issue_credentials) or import one they already hold ' +
28
+ '(import_credentials, accepts 0x-hex or a key-file path), and call ' +
29
+ 'resolve_owner_key again. Never exposes the private key.',
30
+ inputSchema: { type: 'object', properties: {} },
31
+ }, async () => {
32
+ const projectDir = findProjectRoot(process.cwd());
33
+ const resolved = resolveEthKey(projectDir);
34
+ if (resolved) {
35
+ return {
36
+ ready: true,
37
+ address: resolved.address,
38
+ source: resolved.source,
39
+ ...(resolved.path ? { path: resolved.path } : {}),
40
+ };
41
+ }
42
+ return {
43
+ ready: false,
44
+ message: 'No eth proof-owner key available — no RECLAIM_PRIVATE_KEY in the ' +
45
+ `env, no RECLAIM_PRIVATE_KEY in ${join(projectDir, ENV_FILE)}, and ` +
46
+ 'no RECLAIM_PRIVATE_KEY_FILE. Ask the dev to generate one via ' +
47
+ 'issue_credentials, or import one they already hold via ' +
48
+ 'import_credentials (0x-hex or a key-file path). Then call ' +
49
+ 'resolve_owner_key again and pass its address to run_proof as ' +
50
+ 'ownerAddress.',
51
+ };
52
+ });
53
+ }
@@ -0,0 +1,10 @@
1
+ import { type CaptureSession } from '../../cdp/capture.ts';
2
+ import { type RegisteredTool } from '../server.ts';
3
+ import type { AttachState } from './attach.ts';
4
+ export interface CaptureStore {
5
+ sessions: Map<string, CaptureSession>;
6
+ activeTab?: string;
7
+ }
8
+ export declare function captureTools(attachRef: {
9
+ current?: AttachState;
10
+ }, captures: CaptureStore): RegisteredTool[];
@@ -0,0 +1,142 @@
1
+ import { startCapture } from "../../cdp/capture.js";
2
+ import { defineTool } from "../server.js";
3
+ export function captureTools(attachRef, captures) {
4
+ const requireAttached = () => {
5
+ if (!attachRef.current) {
6
+ throw new Error('Not attached. Call attach_chrome first.');
7
+ }
8
+ return attachRef.current;
9
+ };
10
+ const startTool = defineTool({
11
+ name: 'start_capture',
12
+ description: 'Begin recording network requests on the specified tab. ' +
13
+ 'Returns a captureId.',
14
+ inputSchema: {
15
+ type: 'object',
16
+ properties: { tabId: { type: 'string' } },
17
+ required: ['tabId'],
18
+ },
19
+ }, async ({ tabId }) => {
20
+ const attached = requireAttached();
21
+ const tabClient = await attached.handles.attachToTab(tabId);
22
+ const session = await startCapture(tabClient);
23
+ captures.sessions.set(session.captureId, session);
24
+ captures.activeTab = tabId;
25
+ return { captureId: session.captureId };
26
+ });
27
+ const stopTool = defineTool({
28
+ name: 'stop_capture',
29
+ description: 'Stop recording on the given capture. ' +
30
+ 'Captured data remains queryable until reset_session.',
31
+ inputSchema: {
32
+ type: 'object',
33
+ properties: { captureId: { type: 'string' } },
34
+ required: ['captureId'],
35
+ },
36
+ }, async ({ captureId }) => {
37
+ const session = captures.sessions.get(captureId);
38
+ if (!session) {
39
+ throw new Error(`no capture ${captureId}`);
40
+ }
41
+ await session.stop();
42
+ return { stopped: true, requestCount: session.requests.size };
43
+ });
44
+ const listTool = defineTool({
45
+ name: 'list_requests',
46
+ description: 'List metadata for captured requests. ' +
47
+ 'Filter by method, URL glob, status, content-type, ' +
48
+ 'or graphqlOp. Returns only metadata, never bodies — ' +
49
+ 'use get_request for those.',
50
+ inputSchema: {
51
+ type: 'object',
52
+ properties: {
53
+ captureId: { type: 'string' },
54
+ filter: {
55
+ type: 'object',
56
+ properties: {
57
+ method: { type: 'string' },
58
+ urlGlob: { type: 'string' },
59
+ statusMin: { type: 'number' },
60
+ statusMax: { type: 'number' },
61
+ contentType: { type: 'string' },
62
+ graphqlOp: { type: 'string' },
63
+ },
64
+ },
65
+ },
66
+ required: ['captureId'],
67
+ },
68
+ }, async ({ captureId, filter }) => {
69
+ const session = captures.sessions.get(captureId);
70
+ if (!session) {
71
+ throw new Error(`no capture ${captureId}`);
72
+ }
73
+ const out = [];
74
+ for (const r of session.requests.values()) {
75
+ if (filter?.method && r.method !== filter.method.toUpperCase()) {
76
+ continue;
77
+ }
78
+ if (filter?.urlGlob && !globMatch(filter.urlGlob, r.url)) {
79
+ continue;
80
+ }
81
+ if (filter?.statusMin !== undefined && r.status < filter.statusMin) {
82
+ continue;
83
+ }
84
+ if (filter?.statusMax !== undefined && r.status > filter.statusMax) {
85
+ continue;
86
+ }
87
+ if (filter?.contentType &&
88
+ !r.contentType.includes(filter.contentType)) {
89
+ continue;
90
+ }
91
+ if (filter?.graphqlOp && r.graphqlOp !== filter.graphqlOp) {
92
+ continue;
93
+ }
94
+ const item = {
95
+ requestId: r.requestId,
96
+ method: r.method,
97
+ url: r.url,
98
+ status: r.status,
99
+ contentType: r.contentType,
100
+ size: r.size,
101
+ };
102
+ if (r.graphqlOp !== undefined) {
103
+ item.graphqlOp = r.graphqlOp;
104
+ }
105
+ out.push(item);
106
+ }
107
+ return { requests: out };
108
+ });
109
+ const getTool = defineTool({
110
+ name: 'get_request',
111
+ description: 'Return full headers + bodies for a specific captured request.',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ captureId: { type: 'string' },
116
+ requestId: { type: 'string' },
117
+ },
118
+ required: ['captureId', 'requestId'],
119
+ },
120
+ }, async ({ captureId, requestId }) => {
121
+ const session = captures.sessions.get(captureId);
122
+ if (!session) {
123
+ throw new Error(`no capture ${captureId}`);
124
+ }
125
+ const r = session.requests.get(requestId);
126
+ if (!r) {
127
+ throw new Error(`no request ${requestId} in capture ${captureId}`);
128
+ }
129
+ const body = session.bodies.get(requestId);
130
+ if (!body.available) {
131
+ return { ...r, bodyAvailable: false, reason: body.reason };
132
+ }
133
+ return { ...r, responseBody: body.body, bodyAvailable: true };
134
+ });
135
+ return [startTool, stopTool, listTool, getTool];
136
+ }
137
+ function globMatch(pattern, str) {
138
+ const re = new RegExp('^' +
139
+ pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') +
140
+ '$');
141
+ return re.test(str);
142
+ }
@@ -0,0 +1,5 @@
1
+ import { type RegisteredTool } from '../server.ts';
2
+ import type { AttachState } from './attach.ts';
3
+ export declare function browserTools(attachRef: {
4
+ current?: AttachState;
5
+ }): RegisteredTool[];
@@ -0,0 +1,127 @@
1
+ import { listTabs } from "../../cdp/tabs.js";
2
+ import { defineTool } from "../server.js";
3
+ export function browserTools(attachRef) {
4
+ const requireAttached = () => {
5
+ if (!attachRef.current) {
6
+ throw new Error('Not attached. Call attach_chrome first.');
7
+ }
8
+ return attachRef.current;
9
+ };
10
+ return [
11
+ defineTool({
12
+ name: 'list_tabs',
13
+ description: 'List open Chrome tabs.',
14
+ inputSchema: { type: 'object', properties: {} },
15
+ }, async () => {
16
+ const attached = requireAttached();
17
+ return { tabs: await listTabs(attached.port) };
18
+ }),
19
+ defineTool({
20
+ name: 'eval_in_page',
21
+ description: 'Run a JS expression in a tab via Runtime.evaluate ' +
22
+ 'and return the result. ' +
23
+ 'Useful for reading visible values from the DOM.',
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ tabId: { type: 'string' },
28
+ expression: { type: 'string' },
29
+ },
30
+ required: ['tabId', 'expression'],
31
+ },
32
+ }, async ({ tabId, expression }) => {
33
+ const attached = requireAttached();
34
+ const { Runtime } = await attached.handles.attachToTab(tabId);
35
+ const result = await Runtime.evaluate({
36
+ expression,
37
+ returnByValue: true,
38
+ });
39
+ if (result.exceptionDetails) {
40
+ return { error: result.exceptionDetails.text };
41
+ }
42
+ return { value: result.result.value };
43
+ }),
44
+ defineTool({
45
+ name: 'navigate',
46
+ description: 'Navigate a tab to a URL via Page.navigate, ' +
47
+ 'waiting for the load event. ' +
48
+ 'Use this to drive the browser yourself ' +
49
+ 'instead of asking the developer to navigate. ' +
50
+ 'Returns the final URL after navigation ' +
51
+ '(which may differ from the requested URL due to redirects).',
52
+ inputSchema: {
53
+ type: 'object',
54
+ properties: {
55
+ tabId: { type: 'string' },
56
+ url: { type: 'string' },
57
+ timeoutMs: { type: 'number' },
58
+ },
59
+ required: ['tabId', 'url'],
60
+ },
61
+ }, async ({ tabId, url, timeoutMs }) => {
62
+ const attached = requireAttached();
63
+ const { Page, Runtime } = await attached.handles.attachToTab(tabId);
64
+ await Page.enable();
65
+ const loadPromise = new Promise((resolve) => {
66
+ Page.loadEventFired(() => resolve());
67
+ });
68
+ const nav = await Page.navigate({ url });
69
+ if (nav.errorText) {
70
+ return { ok: false, error: nav.errorText };
71
+ }
72
+ const t = timeoutMs ?? 30_000;
73
+ const raced = await Promise.race([
74
+ loadPromise.then(() => 'loaded'),
75
+ new Promise((resolve) => setTimeout(() => resolve('timeout'), t)),
76
+ ]);
77
+ const final = await Runtime.evaluate({
78
+ expression: 'location.href',
79
+ returnByValue: true,
80
+ });
81
+ return {
82
+ ok: true,
83
+ loadStatus: raced,
84
+ finalUrl: final.result.value,
85
+ };
86
+ }),
87
+ defineTool({
88
+ name: 'wait_for_page',
89
+ description: 'Poll a JS expression in a tab until it ' +
90
+ 'returns truthy (or timeout). ' +
91
+ 'Use this for steps that require the ' +
92
+ 'developer to do something in the browser — ' +
93
+ 'most commonly waiting for them to finish logging in. ' +
94
+ 'Pass an expression that ' +
95
+ 'evaluates true once the desired state is reached, e.g. ' +
96
+ '`!!document.querySelector' +
97
+ '(\'summary[aria-label*="View profile"]\')`' +
98
+ ' for GitHub post-login.',
99
+ inputSchema: {
100
+ type: 'object',
101
+ properties: {
102
+ tabId: { type: 'string' },
103
+ expression: { type: 'string' },
104
+ timeoutMs: { type: 'number' },
105
+ pollMs: { type: 'number' },
106
+ },
107
+ required: ['tabId', 'expression'],
108
+ },
109
+ }, async ({ tabId, expression, timeoutMs, pollMs }) => {
110
+ const attached = requireAttached();
111
+ const { Runtime } = await attached.handles.attachToTab(tabId);
112
+ const deadline = Date.now() + (timeoutMs ?? 120_000);
113
+ const interval = pollMs ?? 1000;
114
+ while (Date.now() < deadline) {
115
+ const r = await Runtime.evaluate({ expression, returnByValue: true });
116
+ if (r.exceptionDetails) {
117
+ return { matched: false, error: r.exceptionDetails.text };
118
+ }
119
+ if (r.result.value) {
120
+ return { matched: true, value: r.result.value };
121
+ }
122
+ await new Promise((resolve) => setTimeout(resolve, interval));
123
+ }
124
+ return { matched: false, reason: 'timeout' };
125
+ }),
126
+ ];
127
+ }
@@ -0,0 +1,3 @@
1
+ import { type RegisteredTool } from '../server.ts';
2
+ import type { CaptureStore } from './capture.ts';
3
+ export declare function findTool(captures: CaptureStore): RegisteredTool;
@@ -0,0 +1,60 @@
1
+ import { normalizeCandidates } from "../../provider/normalize.js";
2
+ import { defineTool } from "../server.js";
3
+ export function findTool(captures) {
4
+ return defineTool({
5
+ name: 'find_requests_containing',
6
+ description: 'Search captured responses for any encoding of `value`.' +
7
+ 'Returns a ranked candidate list ' +
8
+ 'with the JSON path (when applicable), score, and a short snippet.' +
9
+ 'Server-side; bodies stay here.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ captureId: { type: 'string' },
14
+ value: { type: 'string' },
15
+ limit: { type: 'number' },
16
+ },
17
+ required: ['captureId', 'value'],
18
+ },
19
+ }, async ({ captureId, value, limit }) => {
20
+ const session = captures.sessions.get(captureId);
21
+ if (!session) {
22
+ throw new Error(`no capture ${captureId}`);
23
+ }
24
+ const variants = normalizeCandidates(value);
25
+ const ranked = [];
26
+ for (const r of session.requests.values()) {
27
+ if (!r.responseBody) {
28
+ continue;
29
+ }
30
+ let hit;
31
+ for (const v of variants) {
32
+ const idx = r.responseBody.indexOf(v);
33
+ if (idx >= 0) {
34
+ const start = Math.max(0, idx - 40);
35
+ const end = Math.min(r.responseBody.length, idx + v.length + 40);
36
+ hit = { snippet: r.responseBody.slice(start, end), variant: v };
37
+ break;
38
+ }
39
+ }
40
+ if (!hit) {
41
+ continue;
42
+ }
43
+ // Score: prefer JSON responses + smaller bodies (likely API endpoints).
44
+ const score = (r.contentType.includes('json') ? 10 : 0) +
45
+ Math.max(0, 5 - Math.log10(Math.max(r.size, 1)));
46
+ ranked.push({
47
+ requestId: r.requestId,
48
+ url: r.url,
49
+ method: r.method,
50
+ status: r.status,
51
+ contentType: r.contentType,
52
+ matchedVariant: hit.variant,
53
+ snippet: hit.snippet,
54
+ score,
55
+ });
56
+ }
57
+ ranked.sort((a, b) => b.score - a.score);
58
+ return { candidates: ranked.slice(0, limit ?? 10) };
59
+ });
60
+ }
@@ -0,0 +1,3 @@
1
+ export * from './agent/index.ts';
2
+ export * from './authenticate/index.ts';
3
+ export * from './verification/index.ts';
@@ -0,0 +1,6 @@
1
+ // Top-level barrel for every MCP tool group. The MCP server (start.ts) and the
2
+ // package entry (src/index.ts) import tool builders from here, never from the
3
+ // individual tool files.
4
+ export * from "./agent/index.js";
5
+ export * from "./authenticate/index.js";
6
+ export * from "./verification/index.js";
@@ -0,0 +1,2 @@
1
+ import { type RegisteredTool } from '../server.ts';
2
+ export declare function ownerKeyTool(): RegisteredTool;
@@ -0,0 +1,63 @@
1
+ import { generateOwnerKey, ownerKeyEnvOverrideActive, ownerKeyPath, readOwnerKey, } from "../credentials/owner-key.js";
2
+ import { defineTool } from "../server.js";
3
+ export function ownerKeyTool() {
4
+ return defineTool({
5
+ name: 'generate_owner_key',
6
+ description: 'Generate the owner private key that `run_proof` needs '
7
+ + '(RECLAIM_AGENT_OWNER_PRIVATE_KEY) and save it to '
8
+ + '~/.reclaim/owner-key.json (mode 0600). `run_proof` reads it '
9
+ + 'from there automatically — no env var and no server restart '
10
+ + 'needed. Call this when `run_proof` reports the owner key is '
11
+ + 'missing. If a key already exists it is reused; pass '
12
+ + '`force: true` to replace it (this changes the claim owner '
13
+ + 'identity for future proofs). An explicit '
14
+ + 'RECLAIM_AGENT_OWNER_PRIVATE_KEY env var always takes '
15
+ + 'precedence over the saved file. The private key is never '
16
+ + 'returned in the response — the saved file is the only copy.',
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: {
20
+ force: {
21
+ type: 'boolean',
22
+ description: 'Replace an existing saved owner key with a new one. '
23
+ + 'Default false (reuse the existing key).',
24
+ },
25
+ },
26
+ },
27
+ }, async (args) => {
28
+ const envActive = ownerKeyEnvOverrideActive();
29
+ const existing = readOwnerKey();
30
+ if (existing && !args.force) {
31
+ return {
32
+ created: false,
33
+ address: existing.address,
34
+ publicKey: existing.publicKey,
35
+ path: ownerKeyPath(),
36
+ envOverrideActive: envActive,
37
+ note: 'An owner key already exists and was reused. run_proof '
38
+ + 'will use it automatically. Pass force:true to replace it.'
39
+ + (envActive
40
+ ? ' NOTE: RECLAIM_AGENT_OWNER_PRIVATE_KEY is set in the '
41
+ + 'environment and takes precedence over this file.'
42
+ : ''),
43
+ };
44
+ }
45
+ const key = generateOwnerKey();
46
+ return {
47
+ created: true,
48
+ replaced: Boolean(existing),
49
+ address: key.address,
50
+ publicKey: key.publicKey,
51
+ path: ownerKeyPath(),
52
+ envOverrideActive: envActive,
53
+ note: 'Owner key saved to ~/.reclaim/owner-key.json (0600). '
54
+ + 'run_proof will use it automatically — no restart needed. '
55
+ + 'The private key is intentionally omitted from this response.'
56
+ + (envActive
57
+ ? ' NOTE: RECLAIM_AGENT_OWNER_PRIVATE_KEY is set in the '
58
+ + 'environment and takes precedence over this file, so the '
59
+ + 'saved key will not be used until that env var is unset.'
60
+ : ''),
61
+ };
62
+ });
63
+ }
@@ -0,0 +1,3 @@
1
+ import { type RegisteredTool } from '../server.ts';
2
+ import type { SecretStore } from './propose.ts';
3
+ export declare function proofTool(secrets: SecretStore): RegisteredTool;