@reclaimprotocol/agent 0.1.4 → 0.1.6
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 +5 -5
- package/lib/authoring/backend.d.ts +71 -0
- package/lib/authoring/backend.js +24 -0
- package/lib/authoring/find.d.ts +3 -0
- package/lib/authoring/find.js +54 -0
- package/lib/authoring/index.d.ts +4 -0
- package/lib/authoring/index.js +6 -0
- package/lib/authoring/propose.d.ts +3 -0
- package/lib/authoring/propose.js +109 -0
- package/lib/authoring/replay.d.ts +10 -0
- package/lib/authoring/replay.js +34 -0
- package/lib/authoring/tools.d.ts +16 -0
- package/lib/authoring/tools.js +193 -0
- package/lib/authoring/util.d.ts +27 -0
- package/lib/authoring/util.js +21 -0
- package/lib/cdp/capture-engine.js +1 -1
- package/lib/consts.d.ts +6 -1
- package/lib/consts.js +9 -2
- package/lib/mcp/api/operations.gen.js +46 -18
- package/lib/mcp/server.d.ts +2 -25
- package/lib/mcp/server.js +4 -17
- package/lib/mcp/start.js +4 -2
- package/lib/mcp/tools/agent/analyze.js +3 -3
- package/lib/mcp/tools/agent/build.d.ts +4 -4
- package/lib/mcp/tools/agent/build.js +13 -15
- package/lib/mcp/tools/agent/capture.d.ts +13 -1
- package/lib/mcp/tools/agent/capture.js +18 -85
- package/lib/mcp/tools/agent/eval.d.ts +5 -2
- package/lib/mcp/tools/agent/eval.js +11 -121
- package/lib/mcp/tools/agent/find.d.ts +10 -3
- package/lib/mcp/tools/agent/find.js +25 -31
- package/lib/mcp/tools/agent/proof.d.ts +13 -3
- package/lib/mcp/tools/agent/proof.js +81 -132
- package/lib/mcp/tools/agent/propose.d.ts +10 -9
- package/lib/mcp/tools/agent/propose.js +87 -64
- package/lib/mcp/tools/agent/publish.js +2 -2
- package/lib/mcp/tools/agent/replay.d.ts +10 -3
- package/lib/mcp/tools/agent/replay.js +29 -36
- package/lib/mcp/tools/agent/session.d.ts +1 -3
- package/lib/mcp/tools/agent/session.js +5 -5
- package/lib/mcp/tools/agent/shared.d.ts +8 -0
- package/lib/mcp/tools/agent/shared.js +125 -0
- package/lib/old/client.d.ts +35 -0
- package/lib/old/client.js +18 -0
- package/lib/old/login-cdp.d.ts +24 -0
- package/lib/old/login-cdp.js +28 -3
- package/lib/old/sdk-client.d.ts +39 -0
- package/lib/old/sdk-client.js +85 -0
- package/lib/old/to-register.d.ts +69 -0
- package/lib/old/to-register.js +52 -2
- package/lib/old/tools/build.d.ts +6 -1
- package/lib/old/tools/build.js +11 -1
- package/lib/old/tools/get-provider-info.d.ts +16 -0
- package/lib/old/tools/get-provider-info.js +73 -0
- package/lib/old/tools/get-version-config.d.ts +17 -0
- package/lib/old/tools/get-version-config.js +47 -0
- package/lib/old/tools/publish.js +189 -2
- package/lib/old/tools/update-provider-metadata.d.ts +16 -0
- package/lib/old/tools/update-provider-metadata.js +61 -0
- package/lib/proof/attestor.d.ts +6 -3
- package/lib/proof/attestor.js +10 -1
- package/lib/proof/debug-response-dump.d.ts +4 -0
- package/lib/proof/debug-response-dump.js +55 -0
- package/lib/proof/patch-domhandler.d.ts +1 -0
- package/lib/proof/patch-domhandler.js +59 -0
- package/lib/proof/proof-core.d.ts +1 -1
- package/lib/proof/proof-core.js +1 -1
- package/lib/proof/zk-files.js +7 -6
- package/lib/provider/dom-xpath.d.ts +17 -0
- package/lib/provider/dom-xpath.js +187 -0
- package/lib/provider/draft.d.ts +30 -2
- package/lib/provider/draft.js +117 -28
- package/lib/provider/index.d.ts +4 -0
- package/lib/provider/index.js +7 -0
- package/lib/provider/injection-doc.js +6 -0
- package/lib/provider/matcher.d.ts +17 -20
- package/lib/provider/matcher.js +394 -280
- package/lib/provider/schema.d.ts +7 -5
- package/lib/tools/registry.d.ts +50 -0
- package/lib/tools/registry.js +49 -0
- package/package.json +9 -1
- package/skill/SKILL.builder.md +55 -32
- package/skill/SKILL.old.md +20 -12
- package/skill/builder-mode.md +1 -1
- package/skill/injection-api.md +117 -0
- package/src/authoring/backend.ts +98 -0
- package/src/authoring/index.ts +20 -0
- package/src/authoring/tools.ts +273 -0
- package/src/authoring/util.ts +42 -0
- package/src/cdp/capture-engine.ts +1 -1
- package/src/consts.ts +15 -2
- package/src/mcp/api/operations.gen.ts +46 -18
- package/src/mcp/server.ts +9 -39
- package/src/mcp/start.ts +4 -1
- package/src/mcp/tools/agent/analyze.ts +3 -3
- package/src/mcp/tools/agent/build.ts +13 -21
- package/src/mcp/tools/agent/capture.ts +31 -115
- package/src/mcp/tools/agent/eval.ts +19 -155
- package/src/mcp/tools/agent/find.ts +33 -36
- package/src/mcp/tools/agent/proof.ts +87 -160
- package/src/mcp/tools/agent/propose.ts +93 -85
- package/src/mcp/tools/agent/publish.ts +2 -2
- package/src/mcp/tools/agent/replay.ts +32 -42
- package/src/mcp/tools/agent/session.ts +4 -5
- package/src/mcp/tools/agent/shared.ts +152 -0
- package/src/old/client.ts +56 -0
- package/src/old/login-cdp.ts +28 -3
- package/src/old/sdk-client.ts +105 -0
- package/src/old/to-register.ts +98 -6
- package/src/old/tools/build.ts +12 -0
- package/src/old/tools/get-provider-info.ts +91 -0
- package/src/old/tools/get-version-config.ts +56 -0
- package/src/old/tools/publish.ts +244 -1
- package/src/old/tools/update-provider-metadata.ts +72 -0
- package/src/proof/attestor.ts +16 -4
- package/src/proof/debug-response-dump.ts +70 -0
- package/src/proof/patch-domhandler.ts +68 -0
- package/src/proof/proof-core.ts +1 -1
- package/src/proof/zk-files.ts +7 -6
- package/src/provider/dom-xpath.ts +225 -0
- package/src/provider/draft.ts +168 -35
- package/src/provider/index.ts +8 -0
- package/src/provider/injection-doc.ts +6 -0
- package/src/provider/matcher.ts +477 -357
- package/src/provider/schema.ts +7 -5
- package/src/tools/registry.ts +92 -0
|
@@ -98,7 +98,7 @@ export const MCP_TOOLS = {
|
|
|
98
98
|
}),
|
|
99
99
|
},
|
|
100
100
|
"AdminProviders": {
|
|
101
|
-
description: "All
|
|
101
|
+
description: "All providers (admin-only)\n\nAdmin only. Lists all providers across all organizations. Supports filtering by visibility, status, and free-text search on title/domain/slug.",
|
|
102
102
|
inputSchema: toZod({
|
|
103
103
|
"type": "object",
|
|
104
104
|
"properties": {
|
|
@@ -485,7 +485,7 @@ export const MCP_TOOLS = {
|
|
|
485
485
|
}),
|
|
486
486
|
},
|
|
487
487
|
"CreateProvider": {
|
|
488
|
-
description: "Create a
|
|
488
|
+
description: "Create a provider\n\nCreate a new Reclaim provider. Use this only after `providers` returned nothing useful for the domain. The caller must be an active member of the target organization.\nCreates a new provider in the specified organization. `visibility` is coerced to `PRIVATE` at creation regardless of what's sent; the author may toggle to `PUBLIC` later via `PATCH /providers/{id}`. While `PRIVATE`, versions go to the go live freely; once `PUBLIC`, non-admin versions need admin review. See `Provider.visibility`.\nThe server also seeds an initial `0.1.0` version on the `draft` branch in the same transaction so the provider is immediately editable. Its `initialUrl` defaults to `https://<domain>`; all other version fields fall back to their schema-declared defaults (a `structured` verificationType, empty requests, empty web settings). `Provider.latestVersion` stays `null` until the draft is promoted to the live channel.",
|
|
489
489
|
inputSchema: toZod({
|
|
490
490
|
"type": "object",
|
|
491
491
|
"properties": {
|
|
@@ -618,7 +618,7 @@ export const MCP_TOOLS = {
|
|
|
618
618
|
}),
|
|
619
619
|
},
|
|
620
620
|
"CreateProviderVersion": {
|
|
621
|
-
description: "Create a new
|
|
621
|
+
description: "Create a new provider version\n\nCreates a new version of the provider. The starting branch\ndepends on the provider's `visibility` and the caller's role:\n\n- `PRIVATE` provider (any caller): the live channel (no review).\n\n- `PUBLIC` provider, admin caller (Reclaim staff): the live channel\n (no review).\n\n- `PUBLIC` provider, non-admin caller: `draft` (or `ai` if\n authored by the AI assistant). Must pass review (see\n `POST /providers/{id}/versions/{version}/review`) before\n reaching the live channel.\n",
|
|
622
622
|
inputSchema: toZod({
|
|
623
623
|
"type": "object",
|
|
624
624
|
"properties": {
|
|
@@ -644,7 +644,7 @@ export const MCP_TOOLS = {
|
|
|
644
644
|
"body": {
|
|
645
645
|
"type": "object",
|
|
646
646
|
"additionalProperties": false,
|
|
647
|
-
"description": "Body for creating a new version of a provider. Every new version starts on the `draft` branch — see `CreateProviderVersion`. The request body never sets `branch` directly; going live is a separate, explicit step (publish for PRIVATE, submit-for-review → approve for PUBLIC).
|
|
647
|
+
"description": "Body for creating a new version of a provider. Every new version starts on the `draft` branch — see `CreateProviderVersion`. The request body never sets `branch` directly; going live is a separate, explicit step (publish for PRIVATE, submit-for-review → approve for PUBLIC). `verificationType` defaults to `structured`; pass `llm` with a `prompt` to author an AI-verification provider.",
|
|
648
648
|
"required": [
|
|
649
649
|
"initialUrl",
|
|
650
650
|
"requests",
|
|
@@ -652,6 +652,20 @@ export const MCP_TOOLS = {
|
|
|
652
652
|
"webSettings"
|
|
653
653
|
],
|
|
654
654
|
"properties": {
|
|
655
|
+
"verificationType": {
|
|
656
|
+
"type": "string",
|
|
657
|
+
"description": "How a provider version verifies a claim. `structured` uses the explicit match rules on this version (the `matches` / `allowedJsMatches` and related settings). `llm` defers the verification decision to a language model and requires `prompt` to be set.",
|
|
658
|
+
"enum": [
|
|
659
|
+
"llm",
|
|
660
|
+
"structured"
|
|
661
|
+
]
|
|
662
|
+
},
|
|
663
|
+
"prompt": {
|
|
664
|
+
"type": "string",
|
|
665
|
+
"description": "Extraction prompt, used (and required) when `verificationType` is `llm`.",
|
|
666
|
+
"minLength": 0,
|
|
667
|
+
"maxLength": 1000000
|
|
668
|
+
},
|
|
655
669
|
"version": {
|
|
656
670
|
"type": "object",
|
|
657
671
|
"additionalProperties": false,
|
|
@@ -1211,7 +1225,7 @@ export const MCP_TOOLS = {
|
|
|
1211
1225
|
}),
|
|
1212
1226
|
},
|
|
1213
1227
|
"DecideProviderVersionReview": {
|
|
1214
|
-
description: "Record a decision on a
|
|
1228
|
+
description: "Record a decision on a provider version review\n\nAdmin only (Reclaim staff). Approves or rejects a provider version currently on the `in_review` branch. `APPROVED` clears the branch tag and promotes the version to the live channel; `REJECTED` moves it to the `rejected` branch where the author can address feedback and resubmit. A rejected version stays rejected — the author either fixes and resubmits, or abandons it.\nUntil RBAC is designed, \"admin\" is detected via the user's email domain (`@reclaimprotocol.org`). Non-admin callers receive a 403.",
|
|
1215
1229
|
inputSchema: toZod({
|
|
1216
1230
|
"type": "object",
|
|
1217
1231
|
"properties": {
|
|
@@ -1384,7 +1398,7 @@ export const MCP_TOOLS = {
|
|
|
1384
1398
|
}),
|
|
1385
1399
|
},
|
|
1386
1400
|
"DeleteProvider": {
|
|
1387
|
-
description: "Delete a
|
|
1401
|
+
description: "Delete a provider\n\nOwner of the provider's organization only. Soft-archives the provider (sets `status` to `ARCHIVED`) so historical references remain resolvable. Supports optimistic concurrency via `If-Match`.",
|
|
1388
1402
|
inputSchema: toZod({
|
|
1389
1403
|
"type": "object",
|
|
1390
1404
|
"properties": {
|
|
@@ -1429,7 +1443,7 @@ export const MCP_TOOLS = {
|
|
|
1429
1443
|
}),
|
|
1430
1444
|
},
|
|
1431
1445
|
"DeleteProviderVersion": {
|
|
1432
|
-
description: "Delete a
|
|
1446
|
+
description: "Delete a provider version\n\nSoft-archives a version on the `draft`, `ai`, or `rejected` branch — sets `status` to `ARCHIVED` so history is preserved. Trunk (live) and `in_review` versions cannot be archived this way; archive the parent provider instead. Supports optimistic concurrency via `If-Match`.",
|
|
1433
1447
|
inputSchema: toZod({
|
|
1434
1448
|
"type": "object",
|
|
1435
1449
|
"properties": {
|
|
@@ -1521,7 +1535,7 @@ export const MCP_TOOLS = {
|
|
|
1521
1535
|
}),
|
|
1522
1536
|
},
|
|
1523
1537
|
"DiscoverResolve": {
|
|
1524
|
-
description: "Resolve a website + data points to
|
|
1538
|
+
description: "Resolve a website + data points to providers\n\nProvider resolution: given a website and the data points the user wants their users to prove, return the smallest set of existing providers whose data points COVER the selection (greedy combine), the `requiredContext` inputs the consumer must supply, and any `uncovered` points no provider exposes yet (`needsCreation` is true then — author a provider with the agent tools). When the chosen providers can be fused into one (same start page, no clashing page scripts) `merge.mergeable` is true.\n\nAgent flow: pick a website (`GET /discover/data-points` lists what's verifiable there), confirm the data points with the user, call this to get the `providers` + `requiredContext`, collect those context values from the user, then `POST /verifications/sessions` with `providers` (pass every id) and `context` to mint a verification.",
|
|
1525
1539
|
inputSchema: toZod({
|
|
1526
1540
|
"type": "object",
|
|
1527
1541
|
"properties": {
|
|
@@ -1792,7 +1806,7 @@ export const MCP_TOOLS = {
|
|
|
1792
1806
|
}),
|
|
1793
1807
|
},
|
|
1794
1808
|
"GetProvider": {
|
|
1795
|
-
description: "Get a
|
|
1809
|
+
description: "Get a provider\n\nFetch a single Reclaim provider by id. Returns every field needed\nto integrate it into a flow: domain, the live version (initialUrl + requests),\nand the data points it can prove. Use `providers` first if you only\nhave a query string.\n\nReturns the provider record.\n\n**Canonical URL.** For SEO and stable sharing, the canonical\nHTML URL for a provider is `/providers/{providerId}/{slug}`\n(see `GetProviderBySlug`). HTML callers (`Accept: text/html`)\nthat hit this route — which omits the slug — receive a `301`\nredirect to the slugged URL. JSON callers\n(`Accept: application/json`) receive the body directly without\nredirect; the slug is on the response.\n",
|
|
1796
1810
|
inputSchema: toZod({
|
|
1797
1811
|
"type": "object",
|
|
1798
1812
|
"properties": {
|
|
@@ -1827,7 +1841,7 @@ export const MCP_TOOLS = {
|
|
|
1827
1841
|
}),
|
|
1828
1842
|
},
|
|
1829
1843
|
"GetProviderVersion": {
|
|
1830
|
-
description: "Get a specific
|
|
1844
|
+
description: "Get a specific provider version",
|
|
1831
1845
|
inputSchema: toZod({
|
|
1832
1846
|
"type": "object",
|
|
1833
1847
|
"properties": {
|
|
@@ -2165,7 +2179,7 @@ export const MCP_TOOLS = {
|
|
|
2165
2179
|
}),
|
|
2166
2180
|
},
|
|
2167
2181
|
"ListProviderVersions": {
|
|
2168
|
-
description: "List a
|
|
2182
|
+
description: "List a provider's versions\n\nLists versions visible to the caller. Non-public branches (`ai`, `draft`, `in_review`, `rejected`) are only visible to members of the provider's owning organization.",
|
|
2169
2183
|
inputSchema: toZod({
|
|
2170
2184
|
"type": "object",
|
|
2171
2185
|
"properties": {
|
|
@@ -2320,7 +2334,7 @@ export const MCP_TOOLS = {
|
|
|
2320
2334
|
}),
|
|
2321
2335
|
},
|
|
2322
2336
|
"Providers": {
|
|
2323
|
-
description: "Search
|
|
2337
|
+
description: "Search providers\n\nSearch published Reclaim providers by domain or data point. A provider is the recipe an end-user follows to prove something about themselves (e.g. \"I have N followers on Twitter\"). Returns a list of matches. Call this BEFORE `create_provider` — most popular domains already have a public provider you can reuse.\nCatalog page listing all providers. Returns a paginated list of providers the caller can see. Public providers are visible to everyone; private providers are only visible to org members.",
|
|
2324
2338
|
inputSchema: toZod({
|
|
2325
2339
|
"type": "object",
|
|
2326
2340
|
"properties": {
|
|
@@ -2366,7 +2380,7 @@ export const MCP_TOOLS = {
|
|
|
2366
2380
|
}),
|
|
2367
2381
|
},
|
|
2368
2382
|
"PublishProviderVersion": {
|
|
2369
|
-
description: "Publish a draft version directly (PRIVATE providers only)\n\nPublishes a
|
|
2383
|
+
description: "Publish a draft version directly (PRIVATE providers only)\n\nPublishes a provider version on the `draft` branch directly to the live channel (trunk). Only allowed for PRIVATE providers — PUBLIC providers must use the review flow (`POST .../review` → admin decision). On success the version's branch transitions from `draft` to `null` (trunk/live).",
|
|
2370
2384
|
inputSchema: toZod({
|
|
2371
2385
|
"type": "object",
|
|
2372
2386
|
"properties": {
|
|
@@ -2615,7 +2629,7 @@ export const MCP_TOOLS = {
|
|
|
2615
2629
|
}),
|
|
2616
2630
|
},
|
|
2617
2631
|
"SubmitProviderVersionForReview": {
|
|
2618
|
-
description: "Submit a
|
|
2632
|
+
description: "Submit a provider version for review\n\nSubmits a provider version (currently on the `draft` or `rejected` branch) for admin review. On success the version's branch transitions to `in_review`. Callable by any authenticated member of the provider's owning org. Meaningful only on `PUBLIC` providers — on `PRIVATE` providers new versions go to the live channel directly and never need review.",
|
|
2619
2633
|
inputSchema: toZod({
|
|
2620
2634
|
"type": "object",
|
|
2621
2635
|
"properties": {
|
|
@@ -2666,7 +2680,7 @@ export const MCP_TOOLS = {
|
|
|
2666
2680
|
}),
|
|
2667
2681
|
},
|
|
2668
2682
|
"TransferProvider": {
|
|
2669
|
-
description: "Transfer a
|
|
2683
|
+
description: "Transfer a provider to a different workspace\n\nAdmin-only. Moves the provider's `orgId` to the supplied workspace; preserves slug, versions, members. SQL function `builder.transfer_provider` enforces the admin gate and target existence atomically.",
|
|
2670
2684
|
inputSchema: toZod({
|
|
2671
2685
|
"type": "object",
|
|
2672
2686
|
"properties": {
|
|
@@ -2825,7 +2839,7 @@ export const MCP_TOOLS = {
|
|
|
2825
2839
|
}),
|
|
2826
2840
|
},
|
|
2827
2841
|
"UpdateProvider": {
|
|
2828
|
-
description: "Update a
|
|
2842
|
+
description: "Update a provider\n\nUpdate a Reclaim provider's metadata. Partial PATCH — pass only fields you want to change. The caller must be an active member of the owning organization. To change the provider's recipe (initialUrl, requests, …) cut a new version via the dashboard. Use `seo` to control how the provider appears in search results and social shares; omit a subfield to keep the server default.\nCaller must be a member of the provider's owning organization. `id`, `orgId`, and `slug` are immutable. Supports optimistic concurrency via `If-Match`.",
|
|
2829
2843
|
inputSchema: toZod({
|
|
2830
2844
|
"type": "object",
|
|
2831
2845
|
"properties": {
|
|
@@ -2962,7 +2976,7 @@ export const MCP_TOOLS = {
|
|
|
2962
2976
|
}),
|
|
2963
2977
|
},
|
|
2964
2978
|
"UpdateProviderVersion": {
|
|
2965
|
-
description: "Update a
|
|
2979
|
+
description: "Update a provider version\n\nMutable only while the version is on the `draft` or `rejected` branch. Versions on `in_review` or the live channel reject all writes here. Caller must be a member of the provider's owning organization. Supports optimistic concurrency via `If-Match`.",
|
|
2966
2980
|
inputSchema: toZod({
|
|
2967
2981
|
"type": "object",
|
|
2968
2982
|
"properties": {
|
|
@@ -3004,13 +3018,27 @@ export const MCP_TOOLS = {
|
|
|
3004
3018
|
"body": {
|
|
3005
3019
|
"type": "object",
|
|
3006
3020
|
"additionalProperties": false,
|
|
3007
|
-
"description": "Partial update of a provider version. Mutable only while the version is on the `draft` or `rejected` branch; versions on `in_review` or the live channel reject all writes here. The semver does not change on update — `build_number` increments instead, giving callers a monotonic revision counter without touching the (major, minor, patch) PK. `verificationType`
|
|
3021
|
+
"description": "Partial update of a provider version. Mutable only while the version is on the `draft` or `rejected` branch; versions on `in_review` or the live channel reject all writes here. The semver does not change on update — `build_number` increments instead, giving callers a monotonic revision counter without touching the (major, minor, patch) PK. `verificationType` and `prompt` may be updated; omit either to carry the prior build's value forward.",
|
|
3008
3022
|
"properties": {
|
|
3009
3023
|
"initialUrl": {
|
|
3010
3024
|
"type": "string",
|
|
3011
3025
|
"format": "uri",
|
|
3012
3026
|
"maxLength": 300
|
|
3013
3027
|
},
|
|
3028
|
+
"verificationType": {
|
|
3029
|
+
"type": "string",
|
|
3030
|
+
"description": "How a provider version verifies a claim. `structured` uses the explicit match rules on this version (the `matches` / `allowedJsMatches` and related settings). `llm` defers the verification decision to a language model and requires `prompt` to be set.",
|
|
3031
|
+
"enum": [
|
|
3032
|
+
"llm",
|
|
3033
|
+
"structured"
|
|
3034
|
+
]
|
|
3035
|
+
},
|
|
3036
|
+
"prompt": {
|
|
3037
|
+
"type": "string",
|
|
3038
|
+
"description": "Extraction prompt, used when `verificationType` is `llm`.",
|
|
3039
|
+
"minLength": 0,
|
|
3040
|
+
"maxLength": 1000000
|
|
3041
|
+
},
|
|
3014
3042
|
"requests": {
|
|
3015
3043
|
"type": "array",
|
|
3016
3044
|
"minItems": 0,
|
package/src/mcp/server.ts
CHANGED
|
@@ -1,46 +1,16 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
2
|
-
import type
|
|
2
|
+
import { type RegisteredTool } from '../tools/registry.ts'
|
|
3
3
|
import { toZod } from './api/to-zod.ts'
|
|
4
4
|
import { remapErrorAsResponse } from './remap_errors.ts'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param args Tool arguments
|
|
16
|
-
* @returns A JSON stringifiable content to be returned to the llm
|
|
17
|
-
* @throws Any error encountered during tool execution will be caught and
|
|
18
|
-
* returned as a response using
|
|
19
|
-
* [remapErrorAsResponse](./src/mcp/remap_errors.ts).
|
|
20
|
-
*/
|
|
21
|
-
handler: (args: unknown) => Promise<unknown>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Define a tool with a single inputSchema (JSON Schema) used as the
|
|
26
|
-
* source of truth. The handler receives args already parsed and
|
|
27
|
-
* type-narrowed via a Zod schema derived from that same JSON Schema —
|
|
28
|
-
* so the description sent to the MCP client and the validation applied
|
|
29
|
-
* to inbound args cannot drift.
|
|
30
|
-
*/
|
|
31
|
-
export function defineTool<TArgs>(
|
|
32
|
-
definition: ToolDefinition,
|
|
33
|
-
handler: (args: TArgs) => Promise<unknown>,
|
|
34
|
-
): RegisteredTool {
|
|
35
|
-
const schema = toZod(definition.inputSchema)
|
|
36
|
-
return {
|
|
37
|
-
definition,
|
|
38
|
-
handler: async(raw) => {
|
|
39
|
-
const args = schema.parse(raw) as TArgs
|
|
40
|
-
return await handler(args)
|
|
41
|
-
},
|
|
42
|
-
}
|
|
43
|
-
}
|
|
6
|
+
// The tool primitive lives in `../tools/registry.ts` (SDK-free, so the cloud
|
|
7
|
+
// loop can use it too). Re-exported here so the MCP-side tool files can keep
|
|
8
|
+
// importing `defineTool`/`RegisteredTool` from the server module.
|
|
9
|
+
export {
|
|
10
|
+
defineTool,
|
|
11
|
+
type RegisteredTool,
|
|
12
|
+
type ToolDefinition,
|
|
13
|
+
} from '../tools/registry.ts'
|
|
44
14
|
|
|
45
15
|
/**
|
|
46
16
|
* Registers a list of RegisteredTool entries on a high-level McpServer.
|
package/src/mcp/start.ts
CHANGED
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
apiUrl,
|
|
8
8
|
oldApiUrl,
|
|
9
9
|
oldLogsUrl,
|
|
10
|
+
sdkApiUrl,
|
|
10
11
|
useOldDevtools,
|
|
11
12
|
} from '../consts.ts'
|
|
12
13
|
import { ReclaimOldClient } from '../old/client.ts'
|
|
13
14
|
import { resolveInitialIdentity } from '../old/identity.ts'
|
|
14
15
|
import { OLD_MODE_INSTRUCTIONS } from '../old/instructions.ts'
|
|
16
|
+
import { ReclaimSdkClient } from '../old/sdk-client.ts'
|
|
15
17
|
import { buildOldBackendTools } from '../old/tools/build.ts'
|
|
16
18
|
import { NAME, VERSION } from '../pkg.ts'
|
|
17
19
|
import { registerTools } from './api/tools.ts'
|
|
@@ -53,9 +55,10 @@ export async function startMcpServer() {
|
|
|
53
55
|
logsBaseUrl: oldLogsUrl(),
|
|
54
56
|
identity: resolveInitialIdentity(),
|
|
55
57
|
})
|
|
58
|
+
const sdkClient = new ReclaimSdkClient({ baseUrl: sdkApiUrl() })
|
|
56
59
|
|
|
57
60
|
registerToolList(server, buildLocalCredentialTools())
|
|
58
|
-
registerToolList(server, buildOldBackendTools(oldClient))
|
|
61
|
+
registerToolList(server, buildOldBackendTools(oldClient, sdkClient))
|
|
59
62
|
if(agentToolsEnabled) {
|
|
60
63
|
// No builder client → no builder publish tool (old mode has its own).
|
|
61
64
|
registerToolList(server, buildAgentTools())
|
|
@@ -18,12 +18,12 @@ export function analyzeTool(captures: CaptureStore): RegisteredTool {
|
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
async({ captureId, requestId }) => {
|
|
21
|
-
const
|
|
22
|
-
if(!
|
|
21
|
+
const entry = captures.sessions.get(captureId)
|
|
22
|
+
if(!entry) {
|
|
23
23
|
throw new Error(`no capture ${captureId}`)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const r = session.requests.get(requestId)
|
|
26
|
+
const r = entry.session.requests.get(requestId)
|
|
27
27
|
if(!r) {
|
|
28
28
|
throw new Error(`no request ${requestId} in capture ${captureId}`)
|
|
29
29
|
}
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* `@modelcontextprotocol/sdk` `McpServer`. Folds the agent's tools
|
|
5
5
|
* alongside the auto-generated API tools.
|
|
6
6
|
*
|
|
7
|
-
* Shared state — Chrome attach state
|
|
8
|
-
*
|
|
7
|
+
* Shared state — Chrome attach state + capture store — is built once per
|
|
8
|
+
* server and threaded through every tool factory. Per-capture drafts (and the
|
|
9
|
+
* secrets they hold) live inside each capture entry, so a capture IS the
|
|
10
|
+
* session for the shared authoring tools.
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
import type { ReclaimClient } from '@reclaimprotocol/client'
|
|
@@ -15,30 +17,21 @@ import { type RegisteredTool } from '../../server.ts'
|
|
|
15
17
|
import { analyzeTool } from './analyze.ts'
|
|
16
18
|
import { type AttachState, attachTool } from './attach.ts'
|
|
17
19
|
import { type CaptureStore, captureTools } from './capture.ts'
|
|
18
|
-
import {
|
|
19
|
-
import { findTool } from './find.ts'
|
|
20
|
+
import { listTabsTool } from './eval.ts'
|
|
20
21
|
import { howItWorksTool } from './how-it-works.ts'
|
|
21
|
-
import { proofTool } from './proof.ts'
|
|
22
|
-
import {
|
|
23
|
-
makeSecretStore,
|
|
24
|
-
proposeTool,
|
|
25
|
-
type SecretStore,
|
|
26
|
-
} from './propose.ts'
|
|
27
22
|
import { createVersionFromCaptureTool } from './publish.ts'
|
|
28
|
-
import { replayTool } from './replay.ts'
|
|
29
23
|
import { sessionTools } from './session.ts'
|
|
24
|
+
import { sharedAuthoringTools } from './shared.ts'
|
|
30
25
|
|
|
31
26
|
export interface AgentState {
|
|
32
27
|
attach: { current?: AttachState, config: ConfigStore }
|
|
33
28
|
captures: CaptureStore
|
|
34
|
-
secrets: SecretStore
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
function buildAgentState(): AgentState {
|
|
38
32
|
return {
|
|
39
33
|
attach: { config: new ConfigStore() },
|
|
40
34
|
captures: { sessions: new Map() },
|
|
41
|
-
secrets: makeSecretStore(),
|
|
42
35
|
}
|
|
43
36
|
}
|
|
44
37
|
|
|
@@ -57,24 +50,23 @@ export function buildAgentTools(
|
|
|
57
50
|
// client. No `client` ⇒ old-devtools mode (see `mcp/start.ts`).
|
|
58
51
|
tools.push(howItWorksTool(!client))
|
|
59
52
|
tools.push(attachTool(state.attach))
|
|
53
|
+
tools.push(listTabsTool(state.attach))
|
|
60
54
|
for(const t of captureTools(state.attach, state.captures)) {
|
|
61
55
|
tools.push(t)
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
for(const t of browserTools(state.attach)) {
|
|
58
|
+
for(const t of sessionTools(state.attach, state.captures)) {
|
|
66
59
|
tools.push(t)
|
|
67
60
|
}
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
tools.push(analyzeTool(state.captures))
|
|
63
|
+
// navigate / eval_in_page / wait_for_page / get_cookies / list_requests /
|
|
64
|
+
// find_requests_containing / propose_provider / replay_request / run_proof —
|
|
65
|
+
// shared with the cloud loop, bound to each capture's local backend.
|
|
66
|
+
for(const t of sharedAuthoringTools(state.captures)) {
|
|
70
67
|
tools.push(t)
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
tools.push(analyzeTool(state.captures))
|
|
74
|
-
tools.push(proposeTool(state.captures, state.secrets))
|
|
75
|
-
tools.push(replayTool(state.secrets))
|
|
76
|
-
tools.push(proofTool(state.secrets))
|
|
77
|
-
|
|
78
70
|
if(client) {
|
|
79
71
|
tools.push(createVersionFromCaptureTool(client))
|
|
80
72
|
}
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
import { type DraftStore, makeDraftStore } from '../../../authoring/index.ts'
|
|
1
2
|
import { type CaptureSession, startCapture } from '../../../cdp/capture.ts'
|
|
2
3
|
import { defineTool, type RegisteredTool } from '../../server.ts'
|
|
3
4
|
import type { AttachState } from './attach.ts'
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* One capture == a session (network requests) + the tab CDP client it runs on +
|
|
8
|
+
* a draft store. Bundling the tab client is what lets the shared authoring
|
|
9
|
+
* tools treat a `captureId` as a full session (drive the browser AND read
|
|
10
|
+
* capture AND hold drafts) behind one id.
|
|
11
|
+
*/
|
|
12
|
+
export interface CaptureEntry {
|
|
13
|
+
session: CaptureSession
|
|
14
|
+
tabClient: Awaited<ReturnType<AttachState['handles']['attachToTab']>>
|
|
15
|
+
drafts: DraftStore
|
|
16
|
+
}
|
|
17
|
+
|
|
5
18
|
export interface CaptureStore {
|
|
6
|
-
sessions: Map<string,
|
|
19
|
+
sessions: Map<string, CaptureEntry>
|
|
7
20
|
activeTab?: string
|
|
8
21
|
}
|
|
9
22
|
|
|
@@ -23,8 +36,9 @@ export function captureTools(
|
|
|
23
36
|
{
|
|
24
37
|
name: 'start_capture',
|
|
25
38
|
description:
|
|
26
|
-
'Begin recording network requests on the specified tab. '
|
|
27
|
-
'Returns a captureId
|
|
39
|
+
'Begin recording network requests on the specified tab. '
|
|
40
|
+
+ 'Returns a captureId — the session handle the authoring tools '
|
|
41
|
+
+ '(navigate, propose_provider, run_proof, …) all take.',
|
|
28
42
|
inputSchema: {
|
|
29
43
|
type: 'object',
|
|
30
44
|
properties: { tabId: { type: 'string' } },
|
|
@@ -35,7 +49,9 @@ export function captureTools(
|
|
|
35
49
|
const attached = requireAttached()
|
|
36
50
|
const tabClient = await attached.handles.attachToTab(tabId)
|
|
37
51
|
const session = await startCapture(tabClient)
|
|
38
|
-
captures.sessions.set(session.captureId,
|
|
52
|
+
captures.sessions.set(session.captureId, {
|
|
53
|
+
session, tabClient, drafts: makeDraftStore(),
|
|
54
|
+
})
|
|
39
55
|
captures.activeTab = tabId
|
|
40
56
|
return { captureId: session.captureId }
|
|
41
57
|
},
|
|
@@ -45,8 +61,8 @@ export function captureTools(
|
|
|
45
61
|
{
|
|
46
62
|
name: 'stop_capture',
|
|
47
63
|
description:
|
|
48
|
-
'Stop recording on the given capture. '
|
|
49
|
-
'Captured data remains queryable until reset_session.',
|
|
64
|
+
'Stop recording on the given capture. '
|
|
65
|
+
+ 'Captured data remains queryable until reset_session.',
|
|
50
66
|
inputSchema: {
|
|
51
67
|
type: 'object',
|
|
52
68
|
properties: { captureId: { type: 'string' } },
|
|
@@ -54,104 +70,13 @@ export function captureTools(
|
|
|
54
70
|
},
|
|
55
71
|
},
|
|
56
72
|
async({ captureId }) => {
|
|
57
|
-
const
|
|
58
|
-
if(!
|
|
73
|
+
const entry = captures.sessions.get(captureId)
|
|
74
|
+
if(!entry) {
|
|
59
75
|
throw new Error(`no capture ${captureId}`)
|
|
60
76
|
}
|
|
61
77
|
|
|
62
|
-
await session.stop()
|
|
63
|
-
return { stopped: true, requestCount: session.requests.size }
|
|
64
|
-
},
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
const listTool = defineTool<{
|
|
68
|
-
captureId: string
|
|
69
|
-
filter?: {
|
|
70
|
-
method?: string
|
|
71
|
-
urlGlob?: string
|
|
72
|
-
statusMin?: number
|
|
73
|
-
statusMax?: number
|
|
74
|
-
contentType?: string
|
|
75
|
-
graphqlOp?: string
|
|
76
|
-
}
|
|
77
|
-
}>(
|
|
78
|
-
{
|
|
79
|
-
name: 'list_requests',
|
|
80
|
-
description:
|
|
81
|
-
'List metadata for captured requests. ' +
|
|
82
|
-
'Filter by method, URL glob, status, content-type, ' +
|
|
83
|
-
'or graphqlOp. Returns only metadata, never bodies — ' +
|
|
84
|
-
'use get_request for those.',
|
|
85
|
-
inputSchema: {
|
|
86
|
-
type: 'object',
|
|
87
|
-
properties: {
|
|
88
|
-
captureId: { type: 'string' },
|
|
89
|
-
filter: {
|
|
90
|
-
type: 'object',
|
|
91
|
-
properties: {
|
|
92
|
-
method: { type: 'string' },
|
|
93
|
-
urlGlob: { type: 'string' },
|
|
94
|
-
statusMin: { type: 'number' },
|
|
95
|
-
statusMax: { type: 'number' },
|
|
96
|
-
contentType: { type: 'string' },
|
|
97
|
-
graphqlOp: { type: 'string' },
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
required: ['captureId'],
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
async({ captureId, filter }) => {
|
|
105
|
-
const session = captures.sessions.get(captureId)
|
|
106
|
-
if(!session) {
|
|
107
|
-
throw new Error(`no capture ${captureId}`)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const out = []
|
|
111
|
-
for(const r of session.requests.values()) {
|
|
112
|
-
if(filter?.method && r.method !== filter.method.toUpperCase()) {
|
|
113
|
-
continue
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if(filter?.urlGlob && !globMatch(filter.urlGlob, r.url)) {
|
|
117
|
-
continue
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if(filter?.statusMin !== undefined && r.status < filter.statusMin) {
|
|
121
|
-
continue
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if(filter?.statusMax !== undefined && r.status > filter.statusMax) {
|
|
125
|
-
continue
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if(
|
|
129
|
-
filter?.contentType &&
|
|
130
|
-
!r.contentType.includes(filter.contentType)
|
|
131
|
-
) {
|
|
132
|
-
continue
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if(filter?.graphqlOp && r.graphqlOp !== filter.graphqlOp) {
|
|
136
|
-
continue
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const item: Record<string, unknown> = {
|
|
140
|
-
requestId: r.requestId,
|
|
141
|
-
method: r.method,
|
|
142
|
-
url: r.url,
|
|
143
|
-
status: r.status,
|
|
144
|
-
contentType: r.contentType,
|
|
145
|
-
size: r.size,
|
|
146
|
-
}
|
|
147
|
-
if(r.graphqlOp !== undefined) {
|
|
148
|
-
item.graphqlOp = r.graphqlOp
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
out.push(item)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return { requests: out }
|
|
78
|
+
await entry.session.stop()
|
|
79
|
+
return { stopped: true, requestCount: entry.session.requests.size }
|
|
155
80
|
},
|
|
156
81
|
)
|
|
157
82
|
|
|
@@ -170,17 +95,17 @@ export function captureTools(
|
|
|
170
95
|
},
|
|
171
96
|
},
|
|
172
97
|
async({ captureId, requestId }) => {
|
|
173
|
-
const
|
|
174
|
-
if(!
|
|
98
|
+
const entry = captures.sessions.get(captureId)
|
|
99
|
+
if(!entry) {
|
|
175
100
|
throw new Error(`no capture ${captureId}`)
|
|
176
101
|
}
|
|
177
102
|
|
|
178
|
-
const r = session.requests.get(requestId)
|
|
103
|
+
const r = entry.session.requests.get(requestId)
|
|
179
104
|
if(!r) {
|
|
180
105
|
throw new Error(`no request ${requestId} in capture ${captureId}`)
|
|
181
106
|
}
|
|
182
107
|
|
|
183
|
-
const body = session.bodies.get(requestId)
|
|
108
|
+
const body = entry.session.bodies.get(requestId)
|
|
184
109
|
if(!body.available) {
|
|
185
110
|
return { ...r, bodyAvailable: false, reason: body.reason }
|
|
186
111
|
}
|
|
@@ -189,14 +114,5 @@ export function captureTools(
|
|
|
189
114
|
},
|
|
190
115
|
)
|
|
191
116
|
|
|
192
|
-
return [startTool, stopTool,
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function globMatch(pattern: string, str: string): boolean {
|
|
196
|
-
const re = new RegExp(
|
|
197
|
-
'^' +
|
|
198
|
-
pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') +
|
|
199
|
-
'$',
|
|
200
|
-
)
|
|
201
|
-
return re.test(str)
|
|
117
|
+
return [startTool, stopTool, getTool]
|
|
202
118
|
}
|