@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.
Files changed (126) hide show
  1. package/README.md +5 -5
  2. package/lib/authoring/backend.d.ts +71 -0
  3. package/lib/authoring/backend.js +24 -0
  4. package/lib/authoring/find.d.ts +3 -0
  5. package/lib/authoring/find.js +54 -0
  6. package/lib/authoring/index.d.ts +4 -0
  7. package/lib/authoring/index.js +6 -0
  8. package/lib/authoring/propose.d.ts +3 -0
  9. package/lib/authoring/propose.js +109 -0
  10. package/lib/authoring/replay.d.ts +10 -0
  11. package/lib/authoring/replay.js +34 -0
  12. package/lib/authoring/tools.d.ts +16 -0
  13. package/lib/authoring/tools.js +193 -0
  14. package/lib/authoring/util.d.ts +27 -0
  15. package/lib/authoring/util.js +21 -0
  16. package/lib/cdp/capture-engine.js +1 -1
  17. package/lib/consts.d.ts +6 -1
  18. package/lib/consts.js +9 -2
  19. package/lib/mcp/api/operations.gen.js +46 -18
  20. package/lib/mcp/server.d.ts +2 -25
  21. package/lib/mcp/server.js +4 -17
  22. package/lib/mcp/start.js +4 -2
  23. package/lib/mcp/tools/agent/analyze.js +3 -3
  24. package/lib/mcp/tools/agent/build.d.ts +4 -4
  25. package/lib/mcp/tools/agent/build.js +13 -15
  26. package/lib/mcp/tools/agent/capture.d.ts +13 -1
  27. package/lib/mcp/tools/agent/capture.js +18 -85
  28. package/lib/mcp/tools/agent/eval.d.ts +5 -2
  29. package/lib/mcp/tools/agent/eval.js +11 -121
  30. package/lib/mcp/tools/agent/find.d.ts +10 -3
  31. package/lib/mcp/tools/agent/find.js +25 -31
  32. package/lib/mcp/tools/agent/proof.d.ts +13 -3
  33. package/lib/mcp/tools/agent/proof.js +81 -132
  34. package/lib/mcp/tools/agent/propose.d.ts +10 -9
  35. package/lib/mcp/tools/agent/propose.js +87 -64
  36. package/lib/mcp/tools/agent/publish.js +2 -2
  37. package/lib/mcp/tools/agent/replay.d.ts +10 -3
  38. package/lib/mcp/tools/agent/replay.js +29 -36
  39. package/lib/mcp/tools/agent/session.d.ts +1 -3
  40. package/lib/mcp/tools/agent/session.js +5 -5
  41. package/lib/mcp/tools/agent/shared.d.ts +8 -0
  42. package/lib/mcp/tools/agent/shared.js +125 -0
  43. package/lib/old/client.d.ts +35 -0
  44. package/lib/old/client.js +18 -0
  45. package/lib/old/login-cdp.d.ts +24 -0
  46. package/lib/old/login-cdp.js +28 -3
  47. package/lib/old/sdk-client.d.ts +39 -0
  48. package/lib/old/sdk-client.js +85 -0
  49. package/lib/old/to-register.d.ts +69 -0
  50. package/lib/old/to-register.js +52 -2
  51. package/lib/old/tools/build.d.ts +6 -1
  52. package/lib/old/tools/build.js +11 -1
  53. package/lib/old/tools/get-provider-info.d.ts +16 -0
  54. package/lib/old/tools/get-provider-info.js +73 -0
  55. package/lib/old/tools/get-version-config.d.ts +17 -0
  56. package/lib/old/tools/get-version-config.js +47 -0
  57. package/lib/old/tools/publish.js +189 -2
  58. package/lib/old/tools/update-provider-metadata.d.ts +16 -0
  59. package/lib/old/tools/update-provider-metadata.js +61 -0
  60. package/lib/proof/attestor.d.ts +6 -3
  61. package/lib/proof/attestor.js +10 -1
  62. package/lib/proof/debug-response-dump.d.ts +4 -0
  63. package/lib/proof/debug-response-dump.js +55 -0
  64. package/lib/proof/patch-domhandler.d.ts +1 -0
  65. package/lib/proof/patch-domhandler.js +59 -0
  66. package/lib/proof/proof-core.d.ts +1 -1
  67. package/lib/proof/proof-core.js +1 -1
  68. package/lib/proof/zk-files.js +7 -6
  69. package/lib/provider/dom-xpath.d.ts +17 -0
  70. package/lib/provider/dom-xpath.js +187 -0
  71. package/lib/provider/draft.d.ts +30 -2
  72. package/lib/provider/draft.js +117 -28
  73. package/lib/provider/index.d.ts +4 -0
  74. package/lib/provider/index.js +7 -0
  75. package/lib/provider/injection-doc.js +6 -0
  76. package/lib/provider/matcher.d.ts +17 -20
  77. package/lib/provider/matcher.js +394 -280
  78. package/lib/provider/schema.d.ts +7 -5
  79. package/lib/tools/registry.d.ts +50 -0
  80. package/lib/tools/registry.js +49 -0
  81. package/package.json +9 -1
  82. package/skill/SKILL.builder.md +55 -32
  83. package/skill/SKILL.old.md +20 -12
  84. package/skill/builder-mode.md +1 -1
  85. package/skill/injection-api.md +117 -0
  86. package/src/authoring/backend.ts +98 -0
  87. package/src/authoring/index.ts +20 -0
  88. package/src/authoring/tools.ts +273 -0
  89. package/src/authoring/util.ts +42 -0
  90. package/src/cdp/capture-engine.ts +1 -1
  91. package/src/consts.ts +15 -2
  92. package/src/mcp/api/operations.gen.ts +46 -18
  93. package/src/mcp/server.ts +9 -39
  94. package/src/mcp/start.ts +4 -1
  95. package/src/mcp/tools/agent/analyze.ts +3 -3
  96. package/src/mcp/tools/agent/build.ts +13 -21
  97. package/src/mcp/tools/agent/capture.ts +31 -115
  98. package/src/mcp/tools/agent/eval.ts +19 -155
  99. package/src/mcp/tools/agent/find.ts +33 -36
  100. package/src/mcp/tools/agent/proof.ts +87 -160
  101. package/src/mcp/tools/agent/propose.ts +93 -85
  102. package/src/mcp/tools/agent/publish.ts +2 -2
  103. package/src/mcp/tools/agent/replay.ts +32 -42
  104. package/src/mcp/tools/agent/session.ts +4 -5
  105. package/src/mcp/tools/agent/shared.ts +152 -0
  106. package/src/old/client.ts +56 -0
  107. package/src/old/login-cdp.ts +28 -3
  108. package/src/old/sdk-client.ts +105 -0
  109. package/src/old/to-register.ts +98 -6
  110. package/src/old/tools/build.ts +12 -0
  111. package/src/old/tools/get-provider-info.ts +91 -0
  112. package/src/old/tools/get-version-config.ts +56 -0
  113. package/src/old/tools/publish.ts +244 -1
  114. package/src/old/tools/update-provider-metadata.ts +72 -0
  115. package/src/proof/attestor.ts +16 -4
  116. package/src/proof/debug-response-dump.ts +70 -0
  117. package/src/proof/patch-domhandler.ts +68 -0
  118. package/src/proof/proof-core.ts +1 -1
  119. package/src/proof/zk-files.ts +7 -6
  120. package/src/provider/dom-xpath.ts +225 -0
  121. package/src/provider/draft.ts +168 -35
  122. package/src/provider/index.ts +8 -0
  123. package/src/provider/injection-doc.ts +6 -0
  124. package/src/provider/matcher.ts +477 -357
  125. package/src/provider/schema.ts +7 -5
  126. package/src/tools/registry.ts +92 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Default origin of the PUBLIC production read API that the Reclaim
3
+ * verification SDK/attestor itself calls at runtime to fetch a provider's
4
+ * recipe — a DIFFERENT service from the old-devtools dashboard backend
5
+ * (`ReclaimOldClient`, `devapi.reclaimprotocol.org`). Both endpoints below are
6
+ * unauthenticated reads (no `authenticateToken` middleware on this backend's
7
+ * routes), so this client needs no identity. Override with
8
+ * `RECLAIM_SDK_API_URL`.
9
+ */
10
+ export declare const DEFAULT_SDK_API_URL = "https://api.reclaimprotocol.org";
11
+ /**
12
+ * Minimal read-only client for the public provider-info endpoints on the SDK
13
+ * backend (`reclaim-sdk-backend`). Two distinct reads, on purpose:
14
+ *
15
+ * - `getProvider` (`GET /providers/:id`) — the full provider row merged
16
+ * with its version's WHOLE providerConfig, `customInjection` included.
17
+ * - `getProviderConfigs` (`GET /providers/:id/configs`) — the trimmed
18
+ * recipe the attestor actually consumes at verification time: a fixed
19
+ * field projection that explicitly OMITS `customInjection` and adds a
20
+ * computed `isScriptRequestingClaim` flag instead.
21
+ *
22
+ * Errors are thrown as `@hapi/boom` so `remapErrorAsResponse` renders them
23
+ * the same way as every other tool in this package.
24
+ */
25
+ export declare class ReclaimSdkClient {
26
+ #private;
27
+ readonly baseUrl: string;
28
+ constructor(opts?: {
29
+ baseUrl?: string;
30
+ fetch?: typeof fetch;
31
+ });
32
+ /** Full provider + providerConfig (includes `customInjection`). Latest
33
+ * version when `versionNumber` is omitted. */
34
+ getProvider(providerId: string, versionNumber?: string): Promise<unknown>;
35
+ /** Trimmed runtime recipe (no `customInjection`; adds
36
+ * `isScriptRequestingClaim`). Latest version when `versionNumber` is
37
+ * omitted. */
38
+ getProviderConfigs(providerId: string, versionNumber?: string): Promise<unknown>;
39
+ }
@@ -0,0 +1,85 @@
1
+ import { Boom } from '@hapi/boom';
2
+ import { NAME, VERSION } from "../pkg.js";
3
+ /**
4
+ * Default origin of the PUBLIC production read API that the Reclaim
5
+ * verification SDK/attestor itself calls at runtime to fetch a provider's
6
+ * recipe — a DIFFERENT service from the old-devtools dashboard backend
7
+ * (`ReclaimOldClient`, `devapi.reclaimprotocol.org`). Both endpoints below are
8
+ * unauthenticated reads (no `authenticateToken` middleware on this backend's
9
+ * routes), so this client needs no identity. Override with
10
+ * `RECLAIM_SDK_API_URL`.
11
+ */
12
+ export const DEFAULT_SDK_API_URL = 'https://api.reclaimprotocol.org';
13
+ /**
14
+ * Minimal read-only client for the public provider-info endpoints on the SDK
15
+ * backend (`reclaim-sdk-backend`). Two distinct reads, on purpose:
16
+ *
17
+ * - `getProvider` (`GET /providers/:id`) — the full provider row merged
18
+ * with its version's WHOLE providerConfig, `customInjection` included.
19
+ * - `getProviderConfigs` (`GET /providers/:id/configs`) — the trimmed
20
+ * recipe the attestor actually consumes at verification time: a fixed
21
+ * field projection that explicitly OMITS `customInjection` and adds a
22
+ * computed `isScriptRequestingClaim` flag instead.
23
+ *
24
+ * Errors are thrown as `@hapi/boom` so `remapErrorAsResponse` renders them
25
+ * the same way as every other tool in this package.
26
+ */
27
+ export class ReclaimSdkClient {
28
+ baseUrl;
29
+ #fetch;
30
+ constructor(opts = {}) {
31
+ this.baseUrl = (opts.baseUrl || DEFAULT_SDK_API_URL).replace(/\/+$/, '');
32
+ this.#fetch = opts.fetch ?? fetch;
33
+ }
34
+ /** Full provider + providerConfig (includes `customInjection`). Latest
35
+ * version when `versionNumber` is omitted. */
36
+ getProvider(providerId, versionNumber) {
37
+ return this.#get(`/providers/${encodeURIComponent(providerId)}`, versionNumber);
38
+ }
39
+ /** Trimmed runtime recipe (no `customInjection`; adds
40
+ * `isScriptRequestingClaim`). Latest version when `versionNumber` is
41
+ * omitted. */
42
+ getProviderConfigs(providerId, versionNumber) {
43
+ return this.#get(`/providers/${encodeURIComponent(providerId)}/configs`, versionNumber);
44
+ }
45
+ async #get(path, versionNumber) {
46
+ let url = `${this.baseUrl}/api${path}`;
47
+ if (versionNumber) {
48
+ url += `?versionNumber=${encodeURIComponent(versionNumber)}`;
49
+ }
50
+ const res = await this.#fetch(url, {
51
+ method: 'GET',
52
+ headers: {
53
+ Accept: 'application/json',
54
+ 'User-Agent': `${NAME}/${VERSION}`,
55
+ },
56
+ });
57
+ let json;
58
+ try {
59
+ json = await res.json();
60
+ }
61
+ catch {
62
+ json = undefined;
63
+ }
64
+ const failed = !res.ok ||
65
+ (json !== undefined &&
66
+ typeof json === 'object' &&
67
+ json.isSuccess === false);
68
+ if (failed) {
69
+ const message = (json && typeof json === 'object' &&
70
+ typeof json.message === 'string'
71
+ ? json.message
72
+ : undefined) || res.statusText || 'SDK backend request failed';
73
+ throw new Boom(message, {
74
+ statusCode: res.ok ? 502 : res.status,
75
+ data: {
76
+ status: res.status,
77
+ title: message,
78
+ detail: message,
79
+ body: json,
80
+ },
81
+ });
82
+ }
83
+ return json;
84
+ }
85
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ReclaimProvider } from '../provider/schema.ts';
2
+ import type { AllowedJsRequest } from '../provider/to-version.ts';
2
3
  import type { RegisterProviderBody, UpdateProviderConfigBody } from './client.ts';
3
4
  /**
4
5
  * Translate a drafted `ReclaimProvider` (from `propose_provider`) into the
@@ -22,7 +23,74 @@ export interface OldProviderOpts {
22
23
  /** Defaults to `true` when omitted. Register only (Provider-level flag). */
23
24
  useProxy?: boolean;
24
25
  providerType?: 'PRIVATE' | 'PUBLIC';
26
+ /** Page-injection script — old-devtools' name for the builder's
27
+ * `webSettings.jsUserScripts`. Top-level on register, nested under
28
+ * `providerConfig` on config (add-version). The backend rejects a few
29
+ * deprecated injection APIs (e.g. `window.payloadData`) with a 400. */
30
+ customInjection?: string;
31
+ /** Accepted at register too (unlike the four fields below, which the
32
+ * backend only accepts on config/add-version). */
33
+ userAgent?: {
34
+ ios?: string;
35
+ android?: string;
36
+ };
37
+ /** Accepted at register too. */
38
+ pageTitle?: string;
39
+ /** Config (add-version) ONLY — the register endpoint hardcodes this to
40
+ * `[]` and ignores whatever is sent. Already old-backend-shaped: build
41
+ * fresh entries with {@link injectedRequestDataFrom}; a carried-forward
42
+ * value (read back from an existing version) passes through unchanged. */
43
+ allowedInjectedRequestData?: OldInjectedRequestData[];
44
+ /** Config (add-version) ONLY — the register endpoint never reads this
45
+ * field from the request body. */
46
+ stepsToFollow?: string;
47
+ /** Config (add-version) ONLY — the register endpoint never reads this
48
+ * field from the request body. */
49
+ useIncognitoWebview?: boolean;
50
+ /** Config (add-version) ONLY — the register endpoint never reads this
51
+ * field from the request body. Free-form JSON. */
52
+ extensionConfig?: unknown;
25
53
  }
54
+ interface OldResponseMatch {
55
+ value: string;
56
+ type: string;
57
+ isOptional: boolean;
58
+ order: number;
59
+ }
60
+ interface OldResponseRedaction {
61
+ xPath?: string;
62
+ jsonPath?: string;
63
+ regex?: string;
64
+ /** OPRF mode (`oprf` / `oprf-raw` / `oprf-mpc`) — the backend stores it as
65
+ * a free-form string and the attestor interprets it at verification. */
66
+ hash?: string;
67
+ order: number;
68
+ }
69
+ interface OldRequestData {
70
+ url: string;
71
+ urlType: 'CONSTANT' | 'TEMPLATE';
72
+ method: 'GET' | 'POST';
73
+ responseMatches: OldResponseMatch[];
74
+ responseRedactions: OldResponseRedaction[];
75
+ credentials: 'include';
76
+ bodySniff?: {
77
+ enabled: boolean;
78
+ template: string;
79
+ };
80
+ }
81
+ /** One `allowedInjectedRequestData` entry — an `OldRequestData` plus the
82
+ * pagination/optionality flags the old backend stores alongside it. */
83
+ export interface OldInjectedRequestData extends OldRequestData {
84
+ required?: boolean;
85
+ multiple?: boolean;
86
+ }
87
+ /** Translate fresh `allowedInjectedRequestData` drafts (the author's input
88
+ * shape, `AllowedJsRequest[]` — same shape the builder translator uses for
89
+ * its own `allowedJsRequests`) into the old backend's shape. A
90
+ * carried-forward value read back from an existing version is ALREADY in
91
+ * this shape and should be passed straight through instead — don't run it
92
+ * through this a second time. */
93
+ export declare function injectedRequestDataFrom(requests: AllowedJsRequest[]): OldInjectedRequestData[];
26
94
  /** Body for `POST /api/providers/register` — new provider + v1.0.0. Every
27
95
  * drafted request becomes a `requestData` entry; provider-level fields (name)
28
96
  * come from the first draft. */
@@ -50,3 +118,4 @@ export declare function extractVersions(resp: unknown): SemverTriplet[];
50
118
  * rather than collide with the guaranteed 1.0.0).
51
119
  */
52
120
  export declare function bumpPatchString(versions: SemverTriplet[]): string;
121
+ export {};
@@ -4,7 +4,10 @@
4
4
  * is a Provider-level flag (register only). */
5
5
  const DEFAULT_GEO_LOCATION = '{{DYNAMIC_GEO}}';
6
6
  const DEFAULT_USE_PROXY = true;
7
- /** Build the single `requestData` entry shared by register + update. */
7
+ /** Build the single `requestData` entry shared by register + update. Takes
8
+ * the loose `DraftRequest` shape (not the full `ReclaimProvider`) so it can
9
+ * build BOTH the top-level `requestData` and `allowedInjectedRequestData`
10
+ * entries — a `ReclaimProvider` satisfies it structurally either way. */
8
11
  function requestDataFromProvider(provider) {
9
12
  const method = String(provider.method).toUpperCase();
10
13
  if (method !== 'GET' && method !== 'POST') {
@@ -22,7 +25,8 @@ function requestDataFromProvider(provider) {
22
25
  'consumer-supplied params to the {{context_<name>}} form ' +
23
26
  'for this backend.');
24
27
  }
25
- const responseMatches = provider.responseMatches.map((m, i) => ({
28
+ const responseMatches = (provider.responseMatches ?? [])
29
+ .map((m, i) => ({
26
30
  value: m.value,
27
31
  type: m.type ?? 'contains',
28
32
  isOptional: false,
@@ -78,6 +82,19 @@ function requestDataFromProvider(provider) {
78
82
  function requestDataFrom(providers) {
79
83
  return providers.map(requestDataFromProvider);
80
84
  }
85
+ /** Translate fresh `allowedInjectedRequestData` drafts (the author's input
86
+ * shape, `AllowedJsRequest[]` — same shape the builder translator uses for
87
+ * its own `allowedJsRequests`) into the old backend's shape. A
88
+ * carried-forward value read back from an existing version is ALREADY in
89
+ * this shape and should be passed straight through instead — don't run it
90
+ * through this a second time. */
91
+ export function injectedRequestDataFrom(requests) {
92
+ return requests.map((req) => ({
93
+ ...requestDataFromProvider(req),
94
+ required: req.required ?? true,
95
+ multiple: req.multiple ?? true,
96
+ }));
97
+ }
81
98
  /** Body for `POST /api/providers/register` — new provider + v1.0.0. Every
82
99
  * drafted request becomes a `requestData` entry; provider-level fields (name)
83
100
  * come from the first draft. */
@@ -94,6 +111,18 @@ export function providerToRegisterBody(providers, opts) {
94
111
  if (opts.description !== undefined) {
95
112
  body.description = opts.description;
96
113
  }
114
+ if (opts.customInjection !== undefined) {
115
+ body.customInjection = opts.customInjection;
116
+ }
117
+ // Register also accepts these two (unlike allowedInjectedRequestData /
118
+ // stepsToFollow / useIncognitoWebview / extensionConfig, which the
119
+ // register controller never reads from the body at all).
120
+ if (opts.userAgent !== undefined) {
121
+ body.userAgent = opts.userAgent;
122
+ }
123
+ if (opts.pageTitle !== undefined) {
124
+ body.pageTitle = opts.pageTitle;
125
+ }
97
126
  return body;
98
127
  }
99
128
  /** Body for `POST /api/providers/:providerId/config` — adds a new version to
@@ -108,6 +137,27 @@ export function providerToConfigBody(providers, opts, version, versionInfo) {
108
137
  geoLocation: opts.geoLocation ?? DEFAULT_GEO_LOCATION,
109
138
  requestData: requestDataFrom(providers),
110
139
  };
140
+ if (opts.customInjection !== undefined) {
141
+ providerConfig.customInjection = opts.customInjection;
142
+ }
143
+ if (opts.userAgent !== undefined) {
144
+ providerConfig.userAgent = opts.userAgent;
145
+ }
146
+ if (opts.pageTitle !== undefined) {
147
+ providerConfig.pageTitle = opts.pageTitle;
148
+ }
149
+ if (opts.allowedInjectedRequestData !== undefined) {
150
+ providerConfig.allowedInjectedRequestData = opts.allowedInjectedRequestData;
151
+ }
152
+ if (opts.stepsToFollow !== undefined) {
153
+ providerConfig.stepsToFollow = opts.stepsToFollow;
154
+ }
155
+ if (opts.useIncognitoWebview !== undefined) {
156
+ providerConfig.useIncognitoWebview = opts.useIncognitoWebview;
157
+ }
158
+ if (opts.extensionConfig !== undefined) {
159
+ providerConfig.extensionConfig = opts.extensionConfig;
160
+ }
111
161
  return { providerConfig, version, versionInfo };
112
162
  }
113
163
  /**
@@ -1,9 +1,14 @@
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
  /**
4
5
  * The backend-facing tools for OLD-devtools mode. Mirrors
5
6
  * `buildCredentialTools` / `buildAgentTools`: returns a flat `RegisteredTool`
6
7
  * list for `registerToolList`. These replace the builder credential + publish
7
8
  * tools and the (disabled) generated provider tools.
9
+ *
10
+ * `sdkClient` is a SEPARATE, unauthenticated client for the public
11
+ * production SDK backend (`api.reclaimprotocol.org`) — a different host from
12
+ * `client`'s old-devtools dashboard backend (`devapi.reclaimprotocol.org`).
8
13
  */
9
- export declare function buildOldBackendTools(client: ReclaimOldClient): RegisteredTool[];
14
+ export declare function buildOldBackendTools(client: ReclaimOldClient, sdkClient: ReclaimSdkClient): RegisteredTool[];
@@ -1,18 +1,28 @@
1
1
  import { authenticateTool } from "./authenticate.js";
2
+ import { getProviderInfoTool } from "./get-provider-info.js";
3
+ import { getProviderVersionConfigTool } from "./get-version-config.js";
2
4
  import { getMeProvidersTool } from "./me-providers.js";
3
5
  import { createVersionFromCaptureTool } from "./publish.js";
4
6
  import { sessionAnalyticsLogsTool } from "./session-analytics-logs.js";
7
+ import { updateProviderMetadataTool } from "./update-provider-metadata.js";
5
8
  /**
6
9
  * The backend-facing tools for OLD-devtools mode. Mirrors
7
10
  * `buildCredentialTools` / `buildAgentTools`: returns a flat `RegisteredTool`
8
11
  * list for `registerToolList`. These replace the builder credential + publish
9
12
  * tools and the (disabled) generated provider tools.
13
+ *
14
+ * `sdkClient` is a SEPARATE, unauthenticated client for the public
15
+ * production SDK backend (`api.reclaimprotocol.org`) — a different host from
16
+ * `client`'s old-devtools dashboard backend (`devapi.reclaimprotocol.org`).
10
17
  */
11
- export function buildOldBackendTools(client) {
18
+ export function buildOldBackendTools(client, sdkClient) {
12
19
  return [
13
20
  authenticateTool(client),
14
21
  createVersionFromCaptureTool(client),
15
22
  getMeProvidersTool(client),
23
+ getProviderVersionConfigTool(client),
24
+ getProviderInfoTool(sdkClient),
25
+ updateProviderMetadataTool(client),
16
26
  sessionAnalyticsLogsTool(client),
17
27
  ];
18
28
  }
@@ -0,0 +1,16 @@
1
+ import { type RegisteredTool } from '../../mcp/server.ts';
2
+ import type { ReclaimSdkClient } from '../sdk-client.ts';
3
+ /**
4
+ * Read provider info from the PUBLIC production SDK backend
5
+ * (`api.reclaimprotocol.org`) — the service the verification SDK/attestor
6
+ * itself calls at runtime, NOT the old-devtools dashboard backend
7
+ * (`get_provider_version_config`, `devapi.reclaimprotocol.org`, requires
8
+ * auth). Both underlying reads are unauthenticated.
9
+ *
10
+ * Fetches BOTH shapes in one call, since they're complementary:
11
+ * - `provider`: full provider + providerConfig, `customInjection` included.
12
+ * - `configs`: the trimmed runtime recipe the attestor actually consumes —
13
+ * `customInjection` deliberately omitted, `isScriptRequestingClaim`
14
+ * computed instead.
15
+ */
16
+ export declare function getProviderInfoTool(client: ReclaimSdkClient): RegisteredTool;
@@ -0,0 +1,73 @@
1
+ import { isBoom } from '@hapi/boom';
2
+ import { defineTool } from "../../mcp/server.js";
3
+ /** Best-effort call: resolve to the response, or to an error string instead
4
+ * of throwing — one endpoint 404ing (e.g. a bad `versionNumber`) shouldn't
5
+ * hide a result the other endpoint DID have. */
6
+ async function attempt(label, call) {
7
+ try {
8
+ return { ok: true, value: await call() };
9
+ }
10
+ catch (err) {
11
+ const message = isBoom(err) ? err.message : String(err);
12
+ return { ok: false, error: `${label}: ${message}` };
13
+ }
14
+ }
15
+ /**
16
+ * Read provider info from the PUBLIC production SDK backend
17
+ * (`api.reclaimprotocol.org`) — the service the verification SDK/attestor
18
+ * itself calls at runtime, NOT the old-devtools dashboard backend
19
+ * (`get_provider_version_config`, `devapi.reclaimprotocol.org`, requires
20
+ * auth). Both underlying reads are unauthenticated.
21
+ *
22
+ * Fetches BOTH shapes in one call, since they're complementary:
23
+ * - `provider`: full provider + providerConfig, `customInjection` included.
24
+ * - `configs`: the trimmed runtime recipe the attestor actually consumes —
25
+ * `customInjection` deliberately omitted, `isScriptRequestingClaim`
26
+ * computed instead.
27
+ */
28
+ export function getProviderInfoTool(client) {
29
+ return defineTool({
30
+ name: 'get_provider_info',
31
+ description: 'Read a PUBLISHED provider from the public production SDK backend ' +
32
+ '(api.reclaimprotocol.org — what the verification SDK/attestor ' +
33
+ 'itself fetches at runtime), for ANY provider, no auth required. ' +
34
+ 'Different from get_provider_version_config, which reads the old ' +
35
+ 'devtools DASHBOARD backend and requires auth. \n\n' +
36
+ 'Returns two complementary reads for the given version (latest ' +
37
+ 'when `versionNumber` is omitted): `provider` (the full provider ' +
38
+ '+ providerConfig, including `customInjection`) and `configs` (the ' +
39
+ 'trimmed recipe the attestor actually consumes — `customInjection` ' +
40
+ 'is deliberately OMITTED there, replaced by a computed ' +
41
+ '`isScriptRequestingClaim` flag). One endpoint failing (e.g. an ' +
42
+ 'invalid `versionNumber`) is reported under `errors` without ' +
43
+ 'hiding a result the other endpoint did return.',
44
+ inputSchema: {
45
+ type: 'object',
46
+ properties: {
47
+ providerId: {
48
+ type: 'string',
49
+ description: 'UUID of the provider.',
50
+ },
51
+ versionNumber: {
52
+ type: 'string',
53
+ description: 'Specific version, e.g. "1.0.2". Omit for the ' +
54
+ "provider's current latest version.",
55
+ },
56
+ },
57
+ required: ['providerId'],
58
+ },
59
+ }, async ({ providerId, versionNumber }) => {
60
+ const [provider, configs] = await Promise.all([
61
+ attempt('provider', () => client.getProvider(providerId, versionNumber)),
62
+ attempt('configs', () => client.getProviderConfigs(providerId, versionNumber)),
63
+ ]);
64
+ const errors = [provider, configs]
65
+ .filter((r) => !r.ok)
66
+ .map((r) => r.error);
67
+ return {
68
+ ...(provider.ok ? { provider: provider.value } : {}),
69
+ ...(configs.ok ? { configs: configs.value } : {}),
70
+ ...(errors.length ? { errors } : {}),
71
+ };
72
+ });
73
+ }
@@ -0,0 +1,17 @@
1
+ import { type RegisteredTool } from '../../mcp/server.ts';
2
+ import type { ReclaimOldClient } from '../client.ts';
3
+ /**
4
+ * Read the full `providerConfig` (loginUrl, customInjection, requestData,
5
+ * geoLocation, ...) of one provider version on the old devtools backend —
6
+ * the latest version when `version` is omitted.
7
+ *
8
+ * Exists so a dev/agent can see what's CURRENTLY published before adding a
9
+ * new version with `create_provider_version_from_capture`. That tool always
10
+ * takes a FULL replacement `providerConfig` (no partial-patch endpoint on
11
+ * this backend), so a version added without knowing the current
12
+ * `customInjection` would silently publish it blank — wiping a working
13
+ * login script instead of preserving it. Read it here first, then pass it
14
+ * straight through (or omit `customInjection` on publish to have it carried
15
+ * forward automatically).
16
+ */
17
+ export declare function getProviderVersionConfigTool(client: ReclaimOldClient): RegisteredTool;
@@ -0,0 +1,47 @@
1
+ import { defineTool } from "../../mcp/server.js";
2
+ /**
3
+ * Read the full `providerConfig` (loginUrl, customInjection, requestData,
4
+ * geoLocation, ...) of one provider version on the old devtools backend —
5
+ * the latest version when `version` is omitted.
6
+ *
7
+ * Exists so a dev/agent can see what's CURRENTLY published before adding a
8
+ * new version with `create_provider_version_from_capture`. That tool always
9
+ * takes a FULL replacement `providerConfig` (no partial-patch endpoint on
10
+ * this backend), so a version added without knowing the current
11
+ * `customInjection` would silently publish it blank — wiping a working
12
+ * login script instead of preserving it. Read it here first, then pass it
13
+ * straight through (or omit `customInjection` on publish to have it carried
14
+ * forward automatically).
15
+ */
16
+ export function getProviderVersionConfigTool(client) {
17
+ return defineTool({
18
+ name: 'get_provider_version_config',
19
+ description: 'Fetch the full providerConfig (loginUrl, customInjection, ' +
20
+ 'requestData, geoLocation, ...) of one version on the old devtools ' +
21
+ 'backend — the latest version when `version` is omitted. Readable ' +
22
+ 'for any non-archived provider, not just ones you own. Use this ' +
23
+ 'BEFORE calling create_provider_version_from_capture with a ' +
24
+ '`providerId` to see the currently-published customInjection/' +
25
+ 'requestData so you know what you would be changing — that tool ' +
26
+ 'replaces the whole providerConfig, so a field you never see and ' +
27
+ "never pass comes out blank in the new version, even if it's set " +
28
+ 'today.',
29
+ inputSchema: {
30
+ type: 'object',
31
+ properties: {
32
+ providerId: {
33
+ type: 'string',
34
+ description: 'UUID of the provider (from get_me_providers).',
35
+ },
36
+ version: {
37
+ type: 'string',
38
+ description: 'Specific version to fetch, e.g. "1.0.2". Omit for the ' +
39
+ "provider's current latest version.",
40
+ },
41
+ },
42
+ required: ['providerId'],
43
+ },
44
+ }, async ({ providerId, version }) => {
45
+ return client.getProviderConfig(providerId, version);
46
+ });
47
+ }