@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
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom'
|
|
2
|
+
import { NAME, VERSION } from '../pkg.ts'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default origin of the PUBLIC production read API that the Reclaim
|
|
6
|
+
* verification SDK/attestor itself calls at runtime to fetch a provider's
|
|
7
|
+
* recipe — a DIFFERENT service from the old-devtools dashboard backend
|
|
8
|
+
* (`ReclaimOldClient`, `devapi.reclaimprotocol.org`). Both endpoints below are
|
|
9
|
+
* unauthenticated reads (no `authenticateToken` middleware on this backend's
|
|
10
|
+
* routes), so this client needs no identity. Override with
|
|
11
|
+
* `RECLAIM_SDK_API_URL`.
|
|
12
|
+
*/
|
|
13
|
+
export const DEFAULT_SDK_API_URL = 'https://api.reclaimprotocol.org'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Minimal read-only client for the public provider-info endpoints on the SDK
|
|
17
|
+
* backend (`reclaim-sdk-backend`). Two distinct reads, on purpose:
|
|
18
|
+
*
|
|
19
|
+
* - `getProvider` (`GET /providers/:id`) — the full provider row merged
|
|
20
|
+
* with its version's WHOLE providerConfig, `customInjection` included.
|
|
21
|
+
* - `getProviderConfigs` (`GET /providers/:id/configs`) — the trimmed
|
|
22
|
+
* recipe the attestor actually consumes at verification time: a fixed
|
|
23
|
+
* field projection that explicitly OMITS `customInjection` and adds a
|
|
24
|
+
* computed `isScriptRequestingClaim` flag instead.
|
|
25
|
+
*
|
|
26
|
+
* Errors are thrown as `@hapi/boom` so `remapErrorAsResponse` renders them
|
|
27
|
+
* the same way as every other tool in this package.
|
|
28
|
+
*/
|
|
29
|
+
export class ReclaimSdkClient {
|
|
30
|
+
readonly baseUrl: string
|
|
31
|
+
#fetch: typeof fetch
|
|
32
|
+
|
|
33
|
+
constructor(opts: { baseUrl?: string, fetch?: typeof fetch } = {}) {
|
|
34
|
+
this.baseUrl = (opts.baseUrl || DEFAULT_SDK_API_URL).replace(/\/+$/, '')
|
|
35
|
+
this.#fetch = opts.fetch ?? fetch
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Full provider + providerConfig (includes `customInjection`). Latest
|
|
39
|
+
* version when `versionNumber` is omitted. */
|
|
40
|
+
getProvider(providerId: string, versionNumber?: string): Promise<unknown> {
|
|
41
|
+
return this.#get(
|
|
42
|
+
`/providers/${encodeURIComponent(providerId)}`,
|
|
43
|
+
versionNumber,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Trimmed runtime recipe (no `customInjection`; adds
|
|
48
|
+
* `isScriptRequestingClaim`). Latest version when `versionNumber` is
|
|
49
|
+
* omitted. */
|
|
50
|
+
getProviderConfigs(
|
|
51
|
+
providerId: string,
|
|
52
|
+
versionNumber?: string,
|
|
53
|
+
): Promise<unknown> {
|
|
54
|
+
return this.#get(
|
|
55
|
+
`/providers/${encodeURIComponent(providerId)}/configs`,
|
|
56
|
+
versionNumber,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async #get(path: string, versionNumber?: string): Promise<unknown> {
|
|
61
|
+
let url = `${this.baseUrl}/api${path}`
|
|
62
|
+
if(versionNumber) {
|
|
63
|
+
url += `?versionNumber=${encodeURIComponent(versionNumber)}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const res = await this.#fetch(url, {
|
|
67
|
+
method: 'GET',
|
|
68
|
+
headers: {
|
|
69
|
+
Accept: 'application/json',
|
|
70
|
+
'User-Agent': `${NAME}/${VERSION}`,
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
let json: unknown
|
|
75
|
+
try {
|
|
76
|
+
json = await res.json()
|
|
77
|
+
} catch{
|
|
78
|
+
json = undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const failed =
|
|
82
|
+
!res.ok ||
|
|
83
|
+
(json !== undefined &&
|
|
84
|
+
typeof json === 'object' &&
|
|
85
|
+
(json as { isSuccess?: unknown }).isSuccess === false)
|
|
86
|
+
if(failed) {
|
|
87
|
+
const message =
|
|
88
|
+
(json && typeof json === 'object' &&
|
|
89
|
+
typeof (json as { message?: unknown }).message === 'string'
|
|
90
|
+
? (json as { message: string }).message
|
|
91
|
+
: undefined) || res.statusText || 'SDK backend request failed'
|
|
92
|
+
throw new Boom(message, {
|
|
93
|
+
statusCode: res.ok ? 502 : res.status,
|
|
94
|
+
data: {
|
|
95
|
+
status: res.status,
|
|
96
|
+
title: message,
|
|
97
|
+
detail: message,
|
|
98
|
+
body: json,
|
|
99
|
+
},
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return json
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/old/to-register.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReclaimProvider } from '../provider/schema.ts'
|
|
2
|
+
import type { AllowedJsRequest, DraftRequest } from '../provider/to-version.ts'
|
|
2
3
|
import type {
|
|
3
4
|
RegisterProviderBody,
|
|
4
5
|
UpdateProviderConfigBody,
|
|
@@ -34,6 +35,30 @@ export interface OldProviderOpts {
|
|
|
34
35
|
/** Defaults to `true` when omitted. Register only (Provider-level flag). */
|
|
35
36
|
useProxy?: boolean
|
|
36
37
|
providerType?: 'PRIVATE' | 'PUBLIC'
|
|
38
|
+
/** Page-injection script — old-devtools' name for the builder's
|
|
39
|
+
* `webSettings.jsUserScripts`. Top-level on register, nested under
|
|
40
|
+
* `providerConfig` on config (add-version). The backend rejects a few
|
|
41
|
+
* deprecated injection APIs (e.g. `window.payloadData`) with a 400. */
|
|
42
|
+
customInjection?: string
|
|
43
|
+
/** Accepted at register too (unlike the four fields below, which the
|
|
44
|
+
* backend only accepts on config/add-version). */
|
|
45
|
+
userAgent?: { ios?: string, android?: string }
|
|
46
|
+
/** Accepted at register too. */
|
|
47
|
+
pageTitle?: string
|
|
48
|
+
/** Config (add-version) ONLY — the register endpoint hardcodes this to
|
|
49
|
+
* `[]` and ignores whatever is sent. Already old-backend-shaped: build
|
|
50
|
+
* fresh entries with {@link injectedRequestDataFrom}; a carried-forward
|
|
51
|
+
* value (read back from an existing version) passes through unchanged. */
|
|
52
|
+
allowedInjectedRequestData?: OldInjectedRequestData[]
|
|
53
|
+
/** Config (add-version) ONLY — the register endpoint never reads this
|
|
54
|
+
* field from the request body. */
|
|
55
|
+
stepsToFollow?: string
|
|
56
|
+
/** Config (add-version) ONLY — the register endpoint never reads this
|
|
57
|
+
* field from the request body. */
|
|
58
|
+
useIncognitoWebview?: boolean
|
|
59
|
+
/** Config (add-version) ONLY — the register endpoint never reads this
|
|
60
|
+
* field from the request body. Free-form JSON. */
|
|
61
|
+
extensionConfig?: unknown
|
|
37
62
|
}
|
|
38
63
|
|
|
39
64
|
interface OldResponseMatch {
|
|
@@ -63,8 +88,18 @@ interface OldRequestData {
|
|
|
63
88
|
bodySniff?: { enabled: boolean, template: string }
|
|
64
89
|
}
|
|
65
90
|
|
|
66
|
-
/**
|
|
67
|
-
|
|
91
|
+
/** One `allowedInjectedRequestData` entry — an `OldRequestData` plus the
|
|
92
|
+
* pagination/optionality flags the old backend stores alongside it. */
|
|
93
|
+
export interface OldInjectedRequestData extends OldRequestData {
|
|
94
|
+
required?: boolean
|
|
95
|
+
multiple?: boolean
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Build the single `requestData` entry shared by register + update. Takes
|
|
99
|
+
* the loose `DraftRequest` shape (not the full `ReclaimProvider`) so it can
|
|
100
|
+
* build BOTH the top-level `requestData` and `allowedInjectedRequestData`
|
|
101
|
+
* entries — a `ReclaimProvider` satisfies it structurally either way. */
|
|
102
|
+
function requestDataFromProvider(provider: DraftRequest): OldRequestData {
|
|
68
103
|
const method = String(provider.method).toUpperCase()
|
|
69
104
|
if(method !== 'GET' && method !== 'POST') {
|
|
70
105
|
throw new Error(
|
|
@@ -87,14 +122,13 @@ function requestDataFromProvider(provider: ReclaimProvider): OldRequestData {
|
|
|
87
122
|
)
|
|
88
123
|
}
|
|
89
124
|
|
|
90
|
-
const responseMatches: OldResponseMatch[] = provider.responseMatches
|
|
91
|
-
(m, i) => ({
|
|
125
|
+
const responseMatches: OldResponseMatch[] = (provider.responseMatches ?? [])
|
|
126
|
+
.map((m, i) => ({
|
|
92
127
|
value: m.value,
|
|
93
128
|
type: m.type ?? 'contains',
|
|
94
129
|
isOptional: false,
|
|
95
130
|
order: i,
|
|
96
|
-
})
|
|
97
|
-
)
|
|
131
|
+
}))
|
|
98
132
|
|
|
99
133
|
// Old devtools wants `responseMatches` and `responseRedactions` as PARALLEL
|
|
100
134
|
// arrays — same shape the builder uses, so pass them through directly. We do
|
|
@@ -157,6 +191,22 @@ function requestDataFrom(providers: ReclaimProvider[]): OldRequestData[] {
|
|
|
157
191
|
return providers.map(requestDataFromProvider)
|
|
158
192
|
}
|
|
159
193
|
|
|
194
|
+
/** Translate fresh `allowedInjectedRequestData` drafts (the author's input
|
|
195
|
+
* shape, `AllowedJsRequest[]` — same shape the builder translator uses for
|
|
196
|
+
* its own `allowedJsRequests`) into the old backend's shape. A
|
|
197
|
+
* carried-forward value read back from an existing version is ALREADY in
|
|
198
|
+
* this shape and should be passed straight through instead — don't run it
|
|
199
|
+
* through this a second time. */
|
|
200
|
+
export function injectedRequestDataFrom(
|
|
201
|
+
requests: AllowedJsRequest[],
|
|
202
|
+
): OldInjectedRequestData[] {
|
|
203
|
+
return requests.map((req) => ({
|
|
204
|
+
...requestDataFromProvider(req),
|
|
205
|
+
required: req.required ?? true,
|
|
206
|
+
multiple: req.multiple ?? true,
|
|
207
|
+
}))
|
|
208
|
+
}
|
|
209
|
+
|
|
160
210
|
/** Body for `POST /api/providers/register` — new provider + v1.0.0. Every
|
|
161
211
|
* drafted request becomes a `requestData` entry; provider-level fields (name)
|
|
162
212
|
* come from the first draft. */
|
|
@@ -177,6 +227,21 @@ export function providerToRegisterBody(
|
|
|
177
227
|
body.description = opts.description
|
|
178
228
|
}
|
|
179
229
|
|
|
230
|
+
if(opts.customInjection !== undefined) {
|
|
231
|
+
body.customInjection = opts.customInjection
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Register also accepts these two (unlike allowedInjectedRequestData /
|
|
235
|
+
// stepsToFollow / useIncognitoWebview / extensionConfig, which the
|
|
236
|
+
// register controller never reads from the body at all).
|
|
237
|
+
if(opts.userAgent !== undefined) {
|
|
238
|
+
body.userAgent = opts.userAgent
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if(opts.pageTitle !== undefined) {
|
|
242
|
+
body.pageTitle = opts.pageTitle
|
|
243
|
+
}
|
|
244
|
+
|
|
180
245
|
return body
|
|
181
246
|
}
|
|
182
247
|
|
|
@@ -197,6 +262,33 @@ export function providerToConfigBody(
|
|
|
197
262
|
geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
|
|
198
263
|
requestData: requestDataFrom(providers),
|
|
199
264
|
}
|
|
265
|
+
if(opts.customInjection !== undefined) {
|
|
266
|
+
providerConfig.customInjection = opts.customInjection
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if(opts.userAgent !== undefined) {
|
|
270
|
+
providerConfig.userAgent = opts.userAgent
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if(opts.pageTitle !== undefined) {
|
|
274
|
+
providerConfig.pageTitle = opts.pageTitle
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if(opts.allowedInjectedRequestData !== undefined) {
|
|
278
|
+
providerConfig.allowedInjectedRequestData = opts.allowedInjectedRequestData
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if(opts.stepsToFollow !== undefined) {
|
|
282
|
+
providerConfig.stepsToFollow = opts.stepsToFollow
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if(opts.useIncognitoWebview !== undefined) {
|
|
286
|
+
providerConfig.useIncognitoWebview = opts.useIncognitoWebview
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if(opts.extensionConfig !== undefined) {
|
|
290
|
+
providerConfig.extensionConfig = opts.extensionConfig
|
|
291
|
+
}
|
|
200
292
|
|
|
201
293
|
return { providerConfig, version, versionInfo }
|
|
202
294
|
}
|
package/src/old/tools/build.ts
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
import type { RegisteredTool } from '../../mcp/server.ts'
|
|
2
2
|
import type { ReclaimOldClient } from '../client.ts'
|
|
3
|
+
import type { ReclaimSdkClient } from '../sdk-client.ts'
|
|
3
4
|
import { authenticateTool } from './authenticate.ts'
|
|
5
|
+
import { getProviderInfoTool } from './get-provider-info.ts'
|
|
6
|
+
import { getProviderVersionConfigTool } from './get-version-config.ts'
|
|
4
7
|
import { getMeProvidersTool } from './me-providers.ts'
|
|
5
8
|
import { createVersionFromCaptureTool } from './publish.ts'
|
|
6
9
|
import { sessionAnalyticsLogsTool } from './session-analytics-logs.ts'
|
|
10
|
+
import { updateProviderMetadataTool } from './update-provider-metadata.ts'
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* The backend-facing tools for OLD-devtools mode. Mirrors
|
|
10
14
|
* `buildCredentialTools` / `buildAgentTools`: returns a flat `RegisteredTool`
|
|
11
15
|
* list for `registerToolList`. These replace the builder credential + publish
|
|
12
16
|
* tools and the (disabled) generated provider tools.
|
|
17
|
+
*
|
|
18
|
+
* `sdkClient` is a SEPARATE, unauthenticated client for the public
|
|
19
|
+
* production SDK backend (`api.reclaimprotocol.org`) — a different host from
|
|
20
|
+
* `client`'s old-devtools dashboard backend (`devapi.reclaimprotocol.org`).
|
|
13
21
|
*/
|
|
14
22
|
export function buildOldBackendTools(
|
|
15
23
|
client: ReclaimOldClient,
|
|
24
|
+
sdkClient: ReclaimSdkClient,
|
|
16
25
|
): RegisteredTool[] {
|
|
17
26
|
return [
|
|
18
27
|
authenticateTool(client),
|
|
19
28
|
createVersionFromCaptureTool(client),
|
|
20
29
|
getMeProvidersTool(client),
|
|
30
|
+
getProviderVersionConfigTool(client),
|
|
31
|
+
getProviderInfoTool(sdkClient),
|
|
32
|
+
updateProviderMetadataTool(client),
|
|
21
33
|
sessionAnalyticsLogsTool(client),
|
|
22
34
|
]
|
|
23
35
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { isBoom } from '@hapi/boom'
|
|
2
|
+
import { defineTool, type RegisteredTool } from '../../mcp/server.ts'
|
|
3
|
+
import type { ReclaimSdkClient } from '../sdk-client.ts'
|
|
4
|
+
|
|
5
|
+
/** Best-effort call: resolve to the response, or to an error string instead
|
|
6
|
+
* of throwing — one endpoint 404ing (e.g. a bad `versionNumber`) shouldn't
|
|
7
|
+
* hide a result the other endpoint DID have. */
|
|
8
|
+
async function attempt(
|
|
9
|
+
label: string,
|
|
10
|
+
call: () => Promise<unknown>,
|
|
11
|
+
): Promise<{ ok: true, value: unknown } | { ok: false, error: string }> {
|
|
12
|
+
try {
|
|
13
|
+
return { ok: true, value: await call() }
|
|
14
|
+
} catch(err) {
|
|
15
|
+
const message = isBoom(err) ? err.message : String(err)
|
|
16
|
+
return { ok: false, error: `${label}: ${message}` }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Read provider info from the PUBLIC production SDK backend
|
|
22
|
+
* (`api.reclaimprotocol.org`) — the service the verification SDK/attestor
|
|
23
|
+
* itself calls at runtime, NOT the old-devtools dashboard backend
|
|
24
|
+
* (`get_provider_version_config`, `devapi.reclaimprotocol.org`, requires
|
|
25
|
+
* auth). Both underlying reads are unauthenticated.
|
|
26
|
+
*
|
|
27
|
+
* Fetches BOTH shapes in one call, since they're complementary:
|
|
28
|
+
* - `provider`: full provider + providerConfig, `customInjection` included.
|
|
29
|
+
* - `configs`: the trimmed runtime recipe the attestor actually consumes —
|
|
30
|
+
* `customInjection` deliberately omitted, `isScriptRequestingClaim`
|
|
31
|
+
* computed instead.
|
|
32
|
+
*/
|
|
33
|
+
export function getProviderInfoTool(client: ReclaimSdkClient): RegisteredTool {
|
|
34
|
+
return defineTool<{ providerId: string, versionNumber?: string }>(
|
|
35
|
+
{
|
|
36
|
+
name: 'get_provider_info',
|
|
37
|
+
description:
|
|
38
|
+
'Read a PUBLISHED provider from the public production SDK backend ' +
|
|
39
|
+
'(api.reclaimprotocol.org — what the verification SDK/attestor ' +
|
|
40
|
+
'itself fetches at runtime), for ANY provider, no auth required. ' +
|
|
41
|
+
'Different from get_provider_version_config, which reads the old ' +
|
|
42
|
+
'devtools DASHBOARD backend and requires auth. \n\n' +
|
|
43
|
+
'Returns two complementary reads for the given version (latest ' +
|
|
44
|
+
'when `versionNumber` is omitted): `provider` (the full provider ' +
|
|
45
|
+
'+ providerConfig, including `customInjection`) and `configs` (the ' +
|
|
46
|
+
'trimmed recipe the attestor actually consumes — `customInjection` ' +
|
|
47
|
+
'is deliberately OMITTED there, replaced by a computed ' +
|
|
48
|
+
'`isScriptRequestingClaim` flag). One endpoint failing (e.g. an ' +
|
|
49
|
+
'invalid `versionNumber`) is reported under `errors` without ' +
|
|
50
|
+
'hiding a result the other endpoint did return.',
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
providerId: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'UUID of the provider.',
|
|
57
|
+
},
|
|
58
|
+
versionNumber: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description:
|
|
61
|
+
'Specific version, e.g. "1.0.2". Omit for the ' +
|
|
62
|
+
"provider's current latest version.",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ['providerId'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
async({ providerId, versionNumber }) => {
|
|
69
|
+
const [provider, configs] = await Promise.all([
|
|
70
|
+
attempt(
|
|
71
|
+
'provider',
|
|
72
|
+
() => client.getProvider(providerId, versionNumber),
|
|
73
|
+
),
|
|
74
|
+
attempt(
|
|
75
|
+
'configs',
|
|
76
|
+
() => client.getProviderConfigs(providerId, versionNumber),
|
|
77
|
+
),
|
|
78
|
+
])
|
|
79
|
+
|
|
80
|
+
const errors = [provider, configs]
|
|
81
|
+
.filter((r) => !r.ok)
|
|
82
|
+
.map((r) => (r as { error: string }).error)
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
...(provider.ok ? { provider: provider.value } : {}),
|
|
86
|
+
...(configs.ok ? { configs: configs.value } : {}),
|
|
87
|
+
...(errors.length ? { errors } : {}),
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { defineTool, type RegisteredTool } from '../../mcp/server.ts'
|
|
2
|
+
import type { ReclaimOldClient } from '../client.ts'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Read the full `providerConfig` (loginUrl, customInjection, requestData,
|
|
6
|
+
* geoLocation, ...) of one provider version on the old devtools backend —
|
|
7
|
+
* the latest version when `version` is omitted.
|
|
8
|
+
*
|
|
9
|
+
* Exists so a dev/agent can see what's CURRENTLY published before adding a
|
|
10
|
+
* new version with `create_provider_version_from_capture`. That tool always
|
|
11
|
+
* takes a FULL replacement `providerConfig` (no partial-patch endpoint on
|
|
12
|
+
* this backend), so a version added without knowing the current
|
|
13
|
+
* `customInjection` would silently publish it blank — wiping a working
|
|
14
|
+
* login script instead of preserving it. Read it here first, then pass it
|
|
15
|
+
* straight through (or omit `customInjection` on publish to have it carried
|
|
16
|
+
* forward automatically).
|
|
17
|
+
*/
|
|
18
|
+
export function getProviderVersionConfigTool(
|
|
19
|
+
client: ReclaimOldClient,
|
|
20
|
+
): RegisteredTool {
|
|
21
|
+
return defineTool<{ providerId: string, version?: string }>(
|
|
22
|
+
{
|
|
23
|
+
name: 'get_provider_version_config',
|
|
24
|
+
description:
|
|
25
|
+
'Fetch the full providerConfig (loginUrl, customInjection, ' +
|
|
26
|
+
'requestData, geoLocation, ...) of one version on the old devtools ' +
|
|
27
|
+
'backend — the latest version when `version` is omitted. Readable ' +
|
|
28
|
+
'for any non-archived provider, not just ones you own. Use this ' +
|
|
29
|
+
'BEFORE calling create_provider_version_from_capture with a ' +
|
|
30
|
+
'`providerId` to see the currently-published customInjection/' +
|
|
31
|
+
'requestData so you know what you would be changing — that tool ' +
|
|
32
|
+
'replaces the whole providerConfig, so a field you never see and ' +
|
|
33
|
+
"never pass comes out blank in the new version, even if it's set " +
|
|
34
|
+
'today.',
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
providerId: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'UUID of the provider (from get_me_providers).',
|
|
41
|
+
},
|
|
42
|
+
version: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description:
|
|
45
|
+
'Specific version to fetch, e.g. "1.0.2". Omit for the ' +
|
|
46
|
+
"provider's current latest version.",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['providerId'],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
async({ providerId, version }) => {
|
|
53
|
+
return client.getProviderConfig(providerId, version)
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
}
|