@reclaimprotocol/agent 0.1.0-dev.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.
- package/README.md +287 -0
- package/lib/cdp/capture.d.ts +22 -0
- package/lib/cdp/capture.js +159 -0
- package/lib/cdp/client.d.ts +9 -0
- package/lib/cdp/client.js +11 -0
- package/lib/cdp/eviction.d.ts +16 -0
- package/lib/cdp/eviction.js +38 -0
- package/lib/cdp/launcher.d.ts +14 -0
- package/lib/cdp/launcher.js +102 -0
- package/lib/cdp/tabs.d.ts +6 -0
- package/lib/cdp/tabs.js +10 -0
- package/lib/cli/args.d.ts +14 -0
- package/lib/cli/args.js +19 -0
- package/lib/cli/commands.d.ts +1 -0
- package/lib/cli/commands.js +19 -0
- package/lib/cli.d.ts +1 -0
- package/lib/cli.js +7 -0
- package/lib/config/store.d.ts +45 -0
- package/lib/config/store.js +46 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +7 -0
- package/lib/logger.d.ts +2 -0
- package/lib/logger.js +7 -0
- package/lib/mcp/api/operations.gen.d.ts +152 -0
- package/lib/mcp/api/operations.gen.js +2300 -0
- package/lib/mcp/api/tools.d.ts +3 -0
- package/lib/mcp/api/tools.js +36 -0
- package/lib/mcp/remap_errors.d.ts +2 -0
- package/lib/mcp/remap_errors.js +27 -0
- package/lib/mcp/server.d.ts +38 -0
- package/lib/mcp/server.js +76 -0
- package/lib/mcp/start.d.ts +1 -0
- package/lib/mcp/start.js +63 -0
- package/lib/mcp/tools/agent/analyze.d.ts +3 -0
- package/lib/mcp/tools/agent/analyze.js +26 -0
- package/lib/mcp/tools/agent/attach.d.ts +11 -0
- package/lib/mcp/tools/agent/attach.js +72 -0
- package/lib/mcp/tools/agent/build.d.ts +33 -0
- package/lib/mcp/tools/agent/build.js +74 -0
- package/lib/mcp/tools/agent/capture.d.ts +10 -0
- package/lib/mcp/tools/agent/capture.js +142 -0
- package/lib/mcp/tools/agent/eval.d.ts +5 -0
- package/lib/mcp/tools/agent/eval.js +127 -0
- package/lib/mcp/tools/agent/find.d.ts +3 -0
- package/lib/mcp/tools/agent/find.js +60 -0
- package/lib/mcp/tools/agent/proof.d.ts +3 -0
- package/lib/mcp/tools/agent/proof.js +214 -0
- package/lib/mcp/tools/agent/propose.d.ts +9 -0
- package/lib/mcp/tools/agent/propose.js +75 -0
- package/lib/mcp/tools/agent/publish.d.ts +3 -0
- package/lib/mcp/tools/agent/publish.js +122 -0
- package/lib/mcp/tools/agent/replay.d.ts +3 -0
- package/lib/mcp/tools/agent/replay.js +46 -0
- package/lib/mcp/tools/agent/session.d.ts +10 -0
- package/lib/mcp/tools/agent/session.js +29 -0
- package/lib/mcp/tools/credentials/authenticate.d.ts +3 -0
- package/lib/mcp/tools/credentials/authenticate.js +108 -0
- package/lib/mcp/tools/credentials/build.d.ts +16 -0
- package/lib/mcp/tools/credentials/build.js +33 -0
- package/lib/mcp/tools/credentials/cache.d.ts +70 -0
- package/lib/mcp/tools/credentials/cache.js +114 -0
- package/lib/mcp/tools/credentials/env-file.d.ts +25 -0
- package/lib/mcp/tools/credentials/env-file.js +71 -0
- package/lib/mcp/tools/credentials/import.d.ts +2 -0
- package/lib/mcp/tools/credentials/import.js +52 -0
- package/lib/mcp/tools/credentials/issue.d.ts +2 -0
- package/lib/mcp/tools/credentials/issue.js +84 -0
- package/lib/mcp/tools/credentials/list-cached.d.ts +2 -0
- package/lib/mcp/tools/credentials/list-cached.js +55 -0
- package/lib/mcp/tools/credentials/register.d.ts +18 -0
- package/lib/mcp/tools/credentials/register.js +30 -0
- package/lib/mcp/tools/credentials/resolve-owner-key.d.ts +12 -0
- package/lib/mcp/tools/credentials/resolve-owner-key.js +68 -0
- package/lib/mcp/tools/credentials/session-cache.d.ts +14 -0
- package/lib/mcp/tools/credentials/session-cache.js +19 -0
- package/lib/mcp/tools/credentials/status.d.ts +3 -0
- package/lib/mcp/tools/credentials/status.js +62 -0
- package/lib/mcp-bin.d.ts +1 -0
- package/lib/mcp-bin.js +7 -0
- package/lib/old/client.d.ts +67 -0
- package/lib/old/client.js +146 -0
- package/lib/old/flag.d.ts +11 -0
- package/lib/old/flag.js +13 -0
- package/lib/old/identity.d.ts +22 -0
- package/lib/old/identity.js +47 -0
- package/lib/old/instructions.d.ts +7 -0
- package/lib/old/instructions.js +29 -0
- package/lib/old/login-cdp.d.ts +23 -0
- package/lib/old/login-cdp.js +125 -0
- package/lib/old/to-register.d.ts +47 -0
- package/lib/old/to-register.js +133 -0
- package/lib/old/tools/authenticate.d.ts +18 -0
- package/lib/old/tools/authenticate.js +127 -0
- package/lib/old/tools/build.d.ts +9 -0
- package/lib/old/tools/build.js +16 -0
- package/lib/old/tools/me-providers.d.ts +10 -0
- package/lib/old/tools/me-providers.js +32 -0
- package/lib/old/tools/publish.d.ts +16 -0
- package/lib/old/tools/publish.js +97 -0
- package/lib/paths.d.ts +11 -0
- package/lib/paths.js +32 -0
- package/lib/pkg.d.ts +3 -0
- package/lib/pkg.js +13 -0
- package/lib/proof/attestor.d.ts +39 -0
- package/lib/proof/attestor.js +207 -0
- package/lib/proof/replay.d.ts +8 -0
- package/lib/proof/replay.js +73 -0
- package/lib/provider/constraints.d.ts +2 -0
- package/lib/provider/constraints.js +122 -0
- package/lib/provider/draft.d.ts +6 -0
- package/lib/provider/draft.js +68 -0
- package/lib/provider/graphql.d.ts +2 -0
- package/lib/provider/graphql.js +35 -0
- package/lib/provider/matcher.d.ts +36 -0
- package/lib/provider/matcher.js +436 -0
- package/lib/provider/normalize.d.ts +4 -0
- package/lib/provider/normalize.js +51 -0
- package/lib/provider/schema.d.ts +76 -0
- package/lib/provider/schema.js +1 -0
- package/lib/provider/secrets.d.ts +5 -0
- package/lib/provider/secrets.js +22 -0
- package/lib/provider/to-version.d.ts +22 -0
- package/lib/provider/to-version.js +68 -0
- package/lib/types/openapi.d.ts +4 -0
- package/lib/types/openapi.js +1 -0
- package/package.json +88 -0
- package/scripts/download-zk-files.ts +42 -0
- package/scripts/prepend-shebang.ts +17 -0
- package/skill/SKILL.md +248 -0
- package/src/cdp/capture.ts +215 -0
- package/src/cdp/client.ts +20 -0
- package/src/cdp/eviction.ts +52 -0
- package/src/cdp/launcher.ts +133 -0
- package/src/cdp/tabs.ts +22 -0
- package/src/cli/args.ts +20 -0
- package/src/cli/commands.ts +27 -0
- package/src/cli.ts +7 -0
- package/src/config/store.ts +86 -0
- package/src/index.ts +12 -0
- package/src/logger.ts +8 -0
- package/src/mcp/api/operations.gen.ts +2397 -0
- package/src/mcp/api/tools.ts +45 -0
- package/src/mcp/remap_errors.ts +35 -0
- package/src/mcp/server.ts +119 -0
- package/src/mcp/start.ts +78 -0
- package/src/mcp/tools/agent/analyze.ts +34 -0
- package/src/mcp/tools/agent/attach.ts +95 -0
- package/src/mcp/tools/agent/build.ts +99 -0
- package/src/mcp/tools/agent/capture.ts +202 -0
- package/src/mcp/tools/agent/eval.ts +161 -0
- package/src/mcp/tools/agent/find.ts +73 -0
- package/src/mcp/tools/agent/proof.ts +272 -0
- package/src/mcp/tools/agent/propose.ts +111 -0
- package/src/mcp/tools/agent/publish.ts +155 -0
- package/src/mcp/tools/agent/replay.ts +58 -0
- package/src/mcp/tools/agent/session.ts +46 -0
- package/src/mcp/tools/credentials/authenticate.ts +135 -0
- package/src/mcp/tools/credentials/build.ts +37 -0
- package/src/mcp/tools/credentials/cache.ts +161 -0
- package/src/mcp/tools/credentials/env-file.ts +101 -0
- package/src/mcp/tools/credentials/import.ts +72 -0
- package/src/mcp/tools/credentials/issue.ts +107 -0
- package/src/mcp/tools/credentials/list-cached.ts +66 -0
- package/src/mcp/tools/credentials/register.ts +49 -0
- package/src/mcp/tools/credentials/resolve-owner-key.ts +78 -0
- package/src/mcp/tools/credentials/session-cache.ts +31 -0
- package/src/mcp/tools/credentials/status.ts +82 -0
- package/src/mcp-bin.ts +7 -0
- package/src/old/client.ts +236 -0
- package/src/old/flag.ts +13 -0
- package/src/old/identity.ts +56 -0
- package/src/old/instructions.ts +30 -0
- package/src/old/login-cdp.ts +153 -0
- package/src/old/to-register.ts +234 -0
- package/src/old/tools/authenticate.ts +152 -0
- package/src/old/tools/build.ts +21 -0
- package/src/old/tools/me-providers.ts +42 -0
- package/src/old/tools/publish.ts +135 -0
- package/src/paths.ts +37 -0
- package/src/pkg.ts +24 -0
- package/src/proof/attestor.ts +286 -0
- package/src/proof/replay.ts +102 -0
- package/src/provider/constraints.ts +150 -0
- package/src/provider/draft.ts +105 -0
- package/src/provider/graphql.ts +42 -0
- package/src/provider/matcher.ts +616 -0
- package/src/provider/normalize.ts +65 -0
- package/src/provider/schema.ts +92 -0
- package/src/provider/secrets.ts +29 -0
- package/src/provider/to-version.ts +90 -0
- package/src/types/openapi.ts +7 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { deriveFromPrivateKey } from '@reclaimprotocol/client';
|
|
2
|
+
import { ConfigStore } from "../config/store.js";
|
|
3
|
+
/** Normalize an eth uid input to `eth:<lowercase-address>`. Accepts a bare
|
|
4
|
+
* `0x…` address or an already-prefixed `eth:0x…`. */
|
|
5
|
+
export function toEthUid(addressOrUid) {
|
|
6
|
+
const lower = addressOrUid.trim().toLowerCase();
|
|
7
|
+
const uid = lower.startsWith('eth:') ? lower : `eth:${lower}`;
|
|
8
|
+
return { kind: 'eth', uid };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a caller identity from the environment, in priority order:
|
|
12
|
+
* 1. `RECLAIM_OLD_API_TOKEN` — a dashboard Firebase bearer token.
|
|
13
|
+
* 2. `RECLAIM_OLD_ETH_UID` — an `eth:<addr>` (or bare `0x…`) uid.
|
|
14
|
+
* 3. `RECLAIM_PRIVATE_KEY` — derive the eth uid from the local app key.
|
|
15
|
+
* Returns undefined when none is set.
|
|
16
|
+
*/
|
|
17
|
+
export function resolveIdentityFromEnv() {
|
|
18
|
+
const token = process.env.RECLAIM_OLD_API_TOKEN?.trim();
|
|
19
|
+
if (token) {
|
|
20
|
+
return { kind: 'bearer', token };
|
|
21
|
+
}
|
|
22
|
+
const ethUid = process.env.RECLAIM_OLD_ETH_UID?.trim();
|
|
23
|
+
if (ethUid) {
|
|
24
|
+
return toEthUid(ethUid);
|
|
25
|
+
}
|
|
26
|
+
const privateKey = process.env.RECLAIM_PRIVATE_KEY?.trim();
|
|
27
|
+
if (privateKey) {
|
|
28
|
+
return toEthUid(deriveFromPrivateKey(privateKey).address);
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Read the identity persisted by a prior `reclaim_authenticate` call. */
|
|
33
|
+
export function loadPersistedIdentity() {
|
|
34
|
+
return new ConfigStore().read()?.old_devtools;
|
|
35
|
+
}
|
|
36
|
+
/** Persist the identity so it survives an MCP-server restart. */
|
|
37
|
+
export function persistIdentity(identity) {
|
|
38
|
+
new ConfigStore().write({ old_devtools: identity });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The identity the client should start with: an explicit env var wins
|
|
42
|
+
* (useful for headless / CI), otherwise fall back to whatever the dev
|
|
43
|
+
* authenticated with last time.
|
|
44
|
+
*/
|
|
45
|
+
export function resolveInitialIdentity() {
|
|
46
|
+
return resolveIdentityFromEnv() ?? loadPersistedIdentity();
|
|
47
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server instructions shown to the LLM when running in OLD-devtools mode
|
|
3
|
+
* (`USE_OLD_DEVTOOLS` unset or not `false`). Describes the REDUCED tool
|
|
4
|
+
* surface — there are no org/credential-link/review flows and no generated
|
|
5
|
+
* API tools here. Must not mention disabled tools.
|
|
6
|
+
*/
|
|
7
|
+
export declare const OLD_MODE_INSTRUCTIONS: string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server instructions shown to the LLM when running in OLD-devtools mode
|
|
3
|
+
* (`USE_OLD_DEVTOOLS` unset or not `false`). Describes the REDUCED tool
|
|
4
|
+
* surface — there are no org/credential-link/review flows and no generated
|
|
5
|
+
* API tools here. Must not mention disabled tools.
|
|
6
|
+
*/
|
|
7
|
+
export const OLD_MODE_INSTRUCTIONS = 'This server is running against the LEGACY Reclaim devtools backend ' +
|
|
8
|
+
'(temporary, while the new builder backend is in development), so its ' +
|
|
9
|
+
'capabilities are intentionally limited.\n\n' +
|
|
10
|
+
'Provider-authoring flow:\n' +
|
|
11
|
+
'1. `reclaim_authenticate` — by default opens the dashboard in Chrome, ' +
|
|
12
|
+
'waits for you to sign in, captures the token automatically, and closes ' +
|
|
13
|
+
'the tab (or paste a `token` / pass an eth `ethAddress` to skip the ' +
|
|
14
|
+
'browser). Do this once before publishing or listing.\n' +
|
|
15
|
+
'2. `attach_chrome` → `start_capture` → drive the page (`navigate`, ' +
|
|
16
|
+
'`wait_for_page`) → inspect (`list_requests`, `get_request`, ' +
|
|
17
|
+
'`find_requests_containing`).\n' +
|
|
18
|
+
'3. `propose_provider` to draft a provider, `replay_request` to ' +
|
|
19
|
+
'pre-flight, `run_proof` to verify with the attestor. OPRF/`hash` ' +
|
|
20
|
+
'redactions are optional and supported.\n' +
|
|
21
|
+
'4. `create_provider_version_from_capture` to publish. With NO ' +
|
|
22
|
+
'`providerId` it REGISTERS A NEW provider (re-running creates a ' +
|
|
23
|
+
'duplicate); pass a ' +
|
|
24
|
+
'`providerId` from `get_me_providers` to add a new version to an existing ' +
|
|
25
|
+
'provider instead.\n' +
|
|
26
|
+
'5. `get_me_providers` lists the providers you own (the only ' +
|
|
27
|
+
'provider-listing tool available in this mode).\n\n' +
|
|
28
|
+
'Only GET/POST endpoints can be captured into providers here. There is no ' +
|
|
29
|
+
'organization, credential-linking, or public-review workflow in this mode.';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** The devtools dashboard login page. Override per-call or via
|
|
2
|
+
* `RECLAIM_OLD_LOGIN_URL`. */
|
|
3
|
+
export declare const DEFAULT_LOGIN_URL = "https://dev.reclaimprotocol.org";
|
|
4
|
+
export interface CdpLoginResult {
|
|
5
|
+
token: string;
|
|
6
|
+
/** True when we launched (and then closed) a dedicated Chrome just for
|
|
7
|
+
* login; false when we attached to an already-running browser and only
|
|
8
|
+
* closed the tab we opened. */
|
|
9
|
+
closedBrowser: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Open the dashboard login page in Chrome via CDP, wait for the developer to
|
|
13
|
+
* finish signing in, read the resulting Firebase ID token from page storage,
|
|
14
|
+
* then clean up. If we had to launch a dedicated Chrome for this, we close the
|
|
15
|
+
* whole browser afterwards; if we attached to a Chrome that was already up
|
|
16
|
+
* (e.g. the capture flow's), we only close the tab we opened so we don't
|
|
17
|
+
* disrupt it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function captureFirebaseTokenViaCdp(opts: {
|
|
20
|
+
loginUrl?: string;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
pollMs?: number;
|
|
23
|
+
}): Promise<CdpLoginResult>;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { connectCdp } from "../cdp/client.js";
|
|
2
|
+
import { defaultProfileDir, launchChrome, waitForCdpReady, } from "../cdp/launcher.js";
|
|
3
|
+
import { ConfigStore } from "../config/store.js";
|
|
4
|
+
/** The devtools dashboard login page. Override per-call or via
|
|
5
|
+
* `RECLAIM_OLD_LOGIN_URL`. */
|
|
6
|
+
export const DEFAULT_LOGIN_URL = 'https://dev.reclaimprotocol.org';
|
|
7
|
+
/**
|
|
8
|
+
* Read the Firebase ID token the dashboard persisted after login.
|
|
9
|
+
*
|
|
10
|
+
* The frontend uses `browserLocalPersistence`, which the Firebase JS SDK
|
|
11
|
+
* implements on `localStorage` under a `firebase:authUser:<apiKey>:[DEFAULT]`
|
|
12
|
+
* key whose JSON value carries `stsTokenManager.accessToken`. We scan for any
|
|
13
|
+
* such key (so we never hard-code the project apiKey) and fall back to the
|
|
14
|
+
* IndexedDB persistence layout (`firebaseLocalStorageDb` /
|
|
15
|
+
* `firebaseLocalStorage`) in case a build switches persistence. Returns the
|
|
16
|
+
* token string, or null when the user has not finished logging in yet.
|
|
17
|
+
*
|
|
18
|
+
* Evaluated in-page with `awaitPromise` so the async IndexedDB branch resolves.
|
|
19
|
+
*/
|
|
20
|
+
const EXTRACT_TOKEN_JS = `(async () => {
|
|
21
|
+
try {
|
|
22
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
23
|
+
const k = localStorage.key(i)
|
|
24
|
+
if (k && k.indexOf('firebase:authUser:') === 0) {
|
|
25
|
+
const v = JSON.parse(localStorage.getItem(k) || 'null')
|
|
26
|
+
const t = v && v.stsTokenManager && v.stsTokenManager.accessToken
|
|
27
|
+
if (t) return t
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {}
|
|
31
|
+
try {
|
|
32
|
+
return await new Promise((resolve) => {
|
|
33
|
+
const req = indexedDB.open('firebaseLocalStorageDb')
|
|
34
|
+
req.onerror = () => resolve(null)
|
|
35
|
+
req.onsuccess = () => {
|
|
36
|
+
try {
|
|
37
|
+
const db = req.result
|
|
38
|
+
if (!db.objectStoreNames.contains('firebaseLocalStorage')) {
|
|
39
|
+
resolve(null); return
|
|
40
|
+
}
|
|
41
|
+
const store = db
|
|
42
|
+
.transaction('firebaseLocalStorage', 'readonly')
|
|
43
|
+
.objectStore('firebaseLocalStorage')
|
|
44
|
+
const all = store.getAll()
|
|
45
|
+
all.onerror = () => resolve(null)
|
|
46
|
+
all.onsuccess = () => {
|
|
47
|
+
for (const row of (all.result || [])) {
|
|
48
|
+
const m = row && row.value && row.value.stsTokenManager
|
|
49
|
+
if (m && m.accessToken) { resolve(m.accessToken); return }
|
|
50
|
+
}
|
|
51
|
+
resolve(null)
|
|
52
|
+
}
|
|
53
|
+
} catch (e) { resolve(null) }
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
} catch (e) { return null }
|
|
57
|
+
})()`;
|
|
58
|
+
/**
|
|
59
|
+
* Open the dashboard login page in Chrome via CDP, wait for the developer to
|
|
60
|
+
* finish signing in, read the resulting Firebase ID token from page storage,
|
|
61
|
+
* then clean up. If we had to launch a dedicated Chrome for this, we close the
|
|
62
|
+
* whole browser afterwards; if we attached to a Chrome that was already up
|
|
63
|
+
* (e.g. the capture flow's), we only close the tab we opened so we don't
|
|
64
|
+
* disrupt it.
|
|
65
|
+
*/
|
|
66
|
+
export async function captureFirebaseTokenViaCdp(opts) {
|
|
67
|
+
const loginUrl = opts.loginUrl || process.env.RECLAIM_OLD_LOGIN_URL || DEFAULT_LOGIN_URL;
|
|
68
|
+
const timeoutMs = opts.timeoutMs ?? 180_000;
|
|
69
|
+
const pollMs = opts.pollMs ?? 1000;
|
|
70
|
+
const cfg = new ConfigStore().read()?.browser_agent;
|
|
71
|
+
const mode = cfg?.attachMode ?? 'dedicated';
|
|
72
|
+
const port = cfg?.port ?? 9222;
|
|
73
|
+
// Ensure something is answering CDP. In dedicated mode we may launch it.
|
|
74
|
+
let launchedByUs = false;
|
|
75
|
+
try {
|
|
76
|
+
await waitForCdpReady(port, 500);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
if (mode !== 'dedicated') {
|
|
80
|
+
throw new Error(`attach mode: nothing answering CDP on port ${port}. Launch Chrome ` +
|
|
81
|
+
`with --remote-debugging-port=${port} AND a non-default ` +
|
|
82
|
+
'--user-data-dir, or switch to dedicated mode (attach_chrome).');
|
|
83
|
+
}
|
|
84
|
+
launchChrome({ port, profileDir: defaultProfileDir() });
|
|
85
|
+
await waitForCdpReady(port, 10_000);
|
|
86
|
+
launchedByUs = true;
|
|
87
|
+
}
|
|
88
|
+
const handles = await connectCdp(port);
|
|
89
|
+
const { Target } = handles.browser;
|
|
90
|
+
const { targetId } = await Target.createTarget({ url: loginUrl });
|
|
91
|
+
try {
|
|
92
|
+
const session = await handles.attachToTab(targetId);
|
|
93
|
+
const { Runtime } = session;
|
|
94
|
+
const deadline = Date.now() + timeoutMs;
|
|
95
|
+
while (Date.now() < deadline) {
|
|
96
|
+
const r = await Runtime.evaluate({
|
|
97
|
+
expression: EXTRACT_TOKEN_JS,
|
|
98
|
+
awaitPromise: true,
|
|
99
|
+
returnByValue: true,
|
|
100
|
+
});
|
|
101
|
+
const value = r.result?.value;
|
|
102
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
103
|
+
return { token: value, closedBrowser: launchedByUs };
|
|
104
|
+
}
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
106
|
+
}
|
|
107
|
+
throw new Error('Timed out waiting for login. Finish signing in at the opened ' +
|
|
108
|
+
'page, or re-run reclaim_authenticate with a longer timeoutMs.');
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
// Best-effort cleanup — never mask the real result/error.
|
|
112
|
+
try {
|
|
113
|
+
if (launchedByUs) {
|
|
114
|
+
await handles.browser.Browser.close();
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
await handles.browser.Target.closeTarget({ targetId });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// ignore
|
|
122
|
+
}
|
|
123
|
+
await handles.close().catch(() => { });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReclaimProvider } from '../provider/schema.ts';
|
|
2
|
+
import type { RegisterProviderBody, UpdateProviderConfigBody } from './client.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Translate a drafted `ReclaimProvider` (from `propose_provider`) into the
|
|
5
|
+
* OLD devtools backend shapes. Deliberately a SEPARATE module from
|
|
6
|
+
* `provider/to-version.ts` (the builder translator) — the two backends have
|
|
7
|
+
* structurally different bodies:
|
|
8
|
+
*
|
|
9
|
+
* - builder NESTS each redaction into its match's `extract`;
|
|
10
|
+
* - old devtools keeps `responseMatches` and `responseRedactions` as
|
|
11
|
+
* PARALLEL arrays on each `requestData` entry.
|
|
12
|
+
*
|
|
13
|
+
* Old-devtools limit we enforce here (a clear error beats a confusing
|
|
14
|
+
* server-side 400): only `GET` / `POST` methods. OPRF redactions are passed
|
|
15
|
+
* through unchanged — the backend's `hash` field accepts them.
|
|
16
|
+
*/
|
|
17
|
+
export interface OldProviderOpts {
|
|
18
|
+
initialUrl: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
geoLocation?: string;
|
|
21
|
+
providerType?: 'PRIVATE' | 'PUBLIC';
|
|
22
|
+
}
|
|
23
|
+
/** Body for `POST /api/providers/register` — new provider + v1.0.0. */
|
|
24
|
+
export declare function providerToRegisterBody(provider: ReclaimProvider, opts: OldProviderOpts): RegisterProviderBody;
|
|
25
|
+
/** Body for `POST /api/providers/:providerId/config` — adds a new version to
|
|
26
|
+
* an EXISTING provider. `version` must not already exist; `versionInfo` is
|
|
27
|
+
* required and must be ≥10 chars (enforced by the backend). */
|
|
28
|
+
export declare function providerToConfigBody(provider: ReclaimProvider, opts: OldProviderOpts, version: string, versionInfo: string): UpdateProviderConfigBody;
|
|
29
|
+
/** Minimal version triplet as the old backend stores it. */
|
|
30
|
+
export interface SemverTriplet {
|
|
31
|
+
major: number;
|
|
32
|
+
minor: number;
|
|
33
|
+
patch: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pull `{major,minor,patch}` triplets out of a `/versions` response, tolerant
|
|
37
|
+
* of the exact envelope (array, `{ providerVersions: [...] }`, `{ items }`,
|
|
38
|
+
* etc.). Each entry's `version` is the triplet.
|
|
39
|
+
*/
|
|
40
|
+
export declare function extractVersions(resp: unknown): SemverTriplet[];
|
|
41
|
+
/**
|
|
42
|
+
* Next version string for an update: the highest existing triplet with its
|
|
43
|
+
* patch bumped, as `"major.minor.patch"`. Falls back to `"1.0.1"` when no
|
|
44
|
+
* versions are found (a provider being updated always has ≥1, but stay safe
|
|
45
|
+
* rather than collide with the guaranteed 1.0.0).
|
|
46
|
+
*/
|
|
47
|
+
export declare function bumpPatchString(versions: SemverTriplet[]): string;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** Build the single `requestData` entry shared by register + update. */
|
|
2
|
+
function requestDataFromProvider(provider) {
|
|
3
|
+
const method = String(provider.method).toUpperCase();
|
|
4
|
+
if (method !== 'GET' && method !== 'POST') {
|
|
5
|
+
throw new Error('Old devtools supports only GET/POST requests; got ' +
|
|
6
|
+
`"${provider.method}". Re-capture against a GET/POST endpoint.`);
|
|
7
|
+
}
|
|
8
|
+
const responseMatches = provider.responseMatches.map((m, i) => ({
|
|
9
|
+
value: m.value,
|
|
10
|
+
type: m.type ?? 'contains',
|
|
11
|
+
isOptional: false,
|
|
12
|
+
order: i,
|
|
13
|
+
}));
|
|
14
|
+
const responseRedactions = (provider.responseRedactions ?? []).map((r, i) => {
|
|
15
|
+
const out = { order: i };
|
|
16
|
+
if (r.xPath !== undefined) {
|
|
17
|
+
out.xPath = r.xPath;
|
|
18
|
+
}
|
|
19
|
+
if (r.jsonPath !== undefined) {
|
|
20
|
+
out.jsonPath = r.jsonPath;
|
|
21
|
+
}
|
|
22
|
+
if (r.regex !== undefined) {
|
|
23
|
+
out.regex = r.regex;
|
|
24
|
+
}
|
|
25
|
+
// OPRF redactions are supported — pass the mode through unchanged.
|
|
26
|
+
if (r.hash !== undefined) {
|
|
27
|
+
out.hash = r.hash;
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
});
|
|
31
|
+
const requestData = {
|
|
32
|
+
url: provider.url,
|
|
33
|
+
// `{{param}}` placeholders → TEMPLATE so the backend templates them;
|
|
34
|
+
// otherwise a fixed CONSTANT url. (REGEX is never drafted.)
|
|
35
|
+
urlType: provider.url.includes('{{') ? 'TEMPLATE' : 'CONSTANT',
|
|
36
|
+
method: method,
|
|
37
|
+
responseMatches,
|
|
38
|
+
responseRedactions,
|
|
39
|
+
// The verification client re-supplies cookies/auth at runtime; secrets
|
|
40
|
+
// are never persisted (propose_provider already stripped them).
|
|
41
|
+
credentials: 'include',
|
|
42
|
+
};
|
|
43
|
+
if (provider.body !== undefined) {
|
|
44
|
+
requestData.bodySniff = { enabled: true, template: provider.body };
|
|
45
|
+
}
|
|
46
|
+
// NOTE: `responseVariables` is intentionally omitted — the old backend
|
|
47
|
+
// auto-extracts it from `{{var}}` placeholders in responseMatches. Sending
|
|
48
|
+
// it ourselves would risk drifting from the server's own extraction.
|
|
49
|
+
return requestData;
|
|
50
|
+
}
|
|
51
|
+
/** Body for `POST /api/providers/register` — new provider + v1.0.0. */
|
|
52
|
+
export function providerToRegisterBody(provider, opts) {
|
|
53
|
+
const body = {
|
|
54
|
+
name: provider.name,
|
|
55
|
+
loginUrl: opts.initialUrl,
|
|
56
|
+
providerType: opts.providerType ?? 'PRIVATE',
|
|
57
|
+
requestData: [requestDataFromProvider(provider)],
|
|
58
|
+
};
|
|
59
|
+
if (opts.description !== undefined) {
|
|
60
|
+
body.description = opts.description;
|
|
61
|
+
}
|
|
62
|
+
if (opts.geoLocation !== undefined) {
|
|
63
|
+
body.geoLocation = opts.geoLocation;
|
|
64
|
+
}
|
|
65
|
+
return body;
|
|
66
|
+
}
|
|
67
|
+
/** Body for `POST /api/providers/:providerId/config` — adds a new version to
|
|
68
|
+
* an EXISTING provider. `version` must not already exist; `versionInfo` is
|
|
69
|
+
* required and must be ≥10 chars (enforced by the backend). */
|
|
70
|
+
export function providerToConfigBody(provider, opts, version, versionInfo) {
|
|
71
|
+
const providerConfig = {
|
|
72
|
+
loginUrl: opts.initialUrl,
|
|
73
|
+
requestData: [requestDataFromProvider(provider)],
|
|
74
|
+
};
|
|
75
|
+
if (opts.geoLocation !== undefined) {
|
|
76
|
+
providerConfig.geoLocation = opts.geoLocation;
|
|
77
|
+
}
|
|
78
|
+
return { providerConfig, version, versionInfo };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Pull `{major,minor,patch}` triplets out of a `/versions` response, tolerant
|
|
82
|
+
* of the exact envelope (array, `{ providerVersions: [...] }`, `{ items }`,
|
|
83
|
+
* etc.). Each entry's `version` is the triplet.
|
|
84
|
+
*/
|
|
85
|
+
export function extractVersions(resp) {
|
|
86
|
+
const list = pickArray(resp);
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const item of list) {
|
|
89
|
+
const v = item.version ?? item;
|
|
90
|
+
if (v && typeof v === 'object' &&
|
|
91
|
+
typeof v.major === 'number' &&
|
|
92
|
+
typeof v.minor === 'number' &&
|
|
93
|
+
typeof v.patch === 'number') {
|
|
94
|
+
const t = v;
|
|
95
|
+
out.push({ major: t.major, minor: t.minor, patch: t.patch });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Next version string for an update: the highest existing triplet with its
|
|
102
|
+
* patch bumped, as `"major.minor.patch"`. Falls back to `"1.0.1"` when no
|
|
103
|
+
* versions are found (a provider being updated always has ≥1, but stay safe
|
|
104
|
+
* rather than collide with the guaranteed 1.0.0).
|
|
105
|
+
*/
|
|
106
|
+
export function bumpPatchString(versions) {
|
|
107
|
+
if (versions.length === 0) {
|
|
108
|
+
return '1.0.1';
|
|
109
|
+
}
|
|
110
|
+
let hi = versions[0];
|
|
111
|
+
for (const v of versions) {
|
|
112
|
+
if (v.major > hi.major ||
|
|
113
|
+
(v.major === hi.major && v.minor > hi.minor) ||
|
|
114
|
+
(v.major === hi.major && v.minor === hi.minor && v.patch > hi.patch)) {
|
|
115
|
+
hi = v;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return `${hi.major}.${hi.minor}.${hi.patch + 1}`;
|
|
119
|
+
}
|
|
120
|
+
function pickArray(resp) {
|
|
121
|
+
if (Array.isArray(resp)) {
|
|
122
|
+
return resp;
|
|
123
|
+
}
|
|
124
|
+
if (resp && typeof resp === 'object') {
|
|
125
|
+
const obj = resp;
|
|
126
|
+
for (const key of ['providerVersions', 'versions', 'items', 'data']) {
|
|
127
|
+
if (Array.isArray(obj[key])) {
|
|
128
|
+
return obj[key];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type RegisteredTool } from '../../mcp/server.ts';
|
|
2
|
+
import type { ReclaimOldClient } from '../client.ts';
|
|
3
|
+
/**
|
|
4
|
+
* OLD-devtools authenticate. The default, zero-arg flow drives Chrome via CDP:
|
|
5
|
+
* it opens the devtools dashboard, waits for the developer to sign in, reads
|
|
6
|
+
* the Firebase ID token straight from page storage, then closes the tab (or
|
|
7
|
+
* the browser, if it launched one just for this). Two manual overrides remain:
|
|
8
|
+
*
|
|
9
|
+
* - `token`: paste a Firebase ID token yourself (skips the browser).
|
|
10
|
+
* - `ethAddress`: an `eth:<addr>`/`0x…` uid for an already-provisioned eth
|
|
11
|
+
* user (header carries no signature, so the uid must already exist).
|
|
12
|
+
*
|
|
13
|
+
* The chosen identity is attached to the shared client and persisted to
|
|
14
|
+
* `~/.reclaim/config.json` so later calls and future restarts reuse it. A
|
|
15
|
+
* zero-arg call reuses a still-valid stored identity before falling back to
|
|
16
|
+
* the browser flow.
|
|
17
|
+
*/
|
|
18
|
+
export declare function authenticateTool(client: ReclaimOldClient): RegisteredTool;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { defineTool } from "../../mcp/server.js";
|
|
2
|
+
import { persistIdentity, toEthUid } from "../identity.js";
|
|
3
|
+
import { captureFirebaseTokenViaCdp } from "../login-cdp.js";
|
|
4
|
+
/**
|
|
5
|
+
* OLD-devtools authenticate. The default, zero-arg flow drives Chrome via CDP:
|
|
6
|
+
* it opens the devtools dashboard, waits for the developer to sign in, reads
|
|
7
|
+
* the Firebase ID token straight from page storage, then closes the tab (or
|
|
8
|
+
* the browser, if it launched one just for this). Two manual overrides remain:
|
|
9
|
+
*
|
|
10
|
+
* - `token`: paste a Firebase ID token yourself (skips the browser).
|
|
11
|
+
* - `ethAddress`: an `eth:<addr>`/`0x…` uid for an already-provisioned eth
|
|
12
|
+
* user (header carries no signature, so the uid must already exist).
|
|
13
|
+
*
|
|
14
|
+
* The chosen identity is attached to the shared client and persisted to
|
|
15
|
+
* `~/.reclaim/config.json` so later calls and future restarts reuse it. A
|
|
16
|
+
* zero-arg call reuses a still-valid stored identity before falling back to
|
|
17
|
+
* the browser flow.
|
|
18
|
+
*/
|
|
19
|
+
export function authenticateTool(client) {
|
|
20
|
+
/** Validate an identity against the backend (throws on failure). */
|
|
21
|
+
const validate = async (identity) => {
|
|
22
|
+
client.setIdentity(identity);
|
|
23
|
+
if (identity.kind === 'bearer') {
|
|
24
|
+
await client.loginWithToken();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
await client.getMyProviders({ pageSize: 1 });
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return defineTool({
|
|
31
|
+
name: 'reclaim_authenticate',
|
|
32
|
+
description: 'Authenticate against the OLD Reclaim devtools backend. \n\n' +
|
|
33
|
+
'Default (no args): opens the devtools dashboard in Chrome via CDP, ' +
|
|
34
|
+
'waits for you to sign in, grabs the Firebase token automatically, ' +
|
|
35
|
+
'and closes the tab. A previously stored identity that is still ' +
|
|
36
|
+
'valid is reused first (pass `useBrowser: true` to force a fresh ' +
|
|
37
|
+
'login). \n\n' +
|
|
38
|
+
'Manual overrides:\n' +
|
|
39
|
+
'- `token`: paste a Firebase ID token (skips the browser).\n' +
|
|
40
|
+
'- `ethAddress`: an `eth:0x…` / `0x…` uid for an already-provisioned ' +
|
|
41
|
+
'eth user (returns 401 "ETH user not found" if unknown).\n\n' +
|
|
42
|
+
'The identity is cached locally for subsequent publish / ' +
|
|
43
|
+
'get_me_providers calls. Firebase tokens are short-lived (~1h) — ' +
|
|
44
|
+
're-run this when calls start returning 401.',
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: 'object',
|
|
47
|
+
properties: {
|
|
48
|
+
token: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'Firebase ID token (skips the browser flow).',
|
|
51
|
+
},
|
|
52
|
+
ethAddress: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'eth uid (`eth:0x…`) or bare `0x…` address.',
|
|
55
|
+
},
|
|
56
|
+
loginUrl: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Dashboard URL to open for the browser flow ' +
|
|
59
|
+
'(default https://dev.reclaimprotocol.org).',
|
|
60
|
+
},
|
|
61
|
+
timeoutMs: {
|
|
62
|
+
type: 'number',
|
|
63
|
+
description: 'How long to wait for sign-in, in ms (default 180000).',
|
|
64
|
+
},
|
|
65
|
+
useBrowser: {
|
|
66
|
+
type: 'boolean',
|
|
67
|
+
description: 'Force the browser login even if a stored identity exists.',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
}, async ({ token, ethAddress, loginUrl, timeoutMs, useBrowser }) => {
|
|
72
|
+
if (token && ethAddress) {
|
|
73
|
+
throw new Error('Provide only ONE of `token` or `ethAddress`, not both.');
|
|
74
|
+
}
|
|
75
|
+
// Explicit credential paths skip the browser entirely.
|
|
76
|
+
if (token || ethAddress) {
|
|
77
|
+
const identity = token
|
|
78
|
+
? { kind: 'bearer', token: token.trim() }
|
|
79
|
+
: toEthUid(ethAddress);
|
|
80
|
+
await validate(identity);
|
|
81
|
+
persistIdentity(identity);
|
|
82
|
+
return {
|
|
83
|
+
authenticated: true,
|
|
84
|
+
method: identity.kind === 'bearer' ? 'token' : 'eth',
|
|
85
|
+
identity: identity.kind === 'bearer'
|
|
86
|
+
? { kind: 'bearer' }
|
|
87
|
+
: { kind: 'eth', uid: identity.uid },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// Reuse a still-valid stored/env identity before opening a browser.
|
|
91
|
+
if (!useBrowser) {
|
|
92
|
+
const existing = client.getIdentity();
|
|
93
|
+
if (existing) {
|
|
94
|
+
try {
|
|
95
|
+
await validate(existing);
|
|
96
|
+
persistIdentity(existing);
|
|
97
|
+
return {
|
|
98
|
+
authenticated: true,
|
|
99
|
+
method: 'reused',
|
|
100
|
+
identity: existing.kind === 'bearer'
|
|
101
|
+
? { kind: 'bearer' }
|
|
102
|
+
: { kind: 'eth', uid: existing.uid },
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Stale/expired — fall through to the browser flow.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// CDP browser login (the default headline flow).
|
|
111
|
+
if (process.env.RECLAIM_AGENT_DISABLED === '1') {
|
|
112
|
+
throw new Error('Browser login is unavailable (RECLAIM_AGENT_DISABLED=1). Pass a ' +
|
|
113
|
+
'`token` (Firebase ID token) or `ethAddress` instead.');
|
|
114
|
+
}
|
|
115
|
+
const result = await captureFirebaseTokenViaCdp({ loginUrl, timeoutMs });
|
|
116
|
+
const identity = { kind: 'bearer', token: result.token };
|
|
117
|
+
await validate(identity);
|
|
118
|
+
persistIdentity(identity);
|
|
119
|
+
return {
|
|
120
|
+
authenticated: true,
|
|
121
|
+
method: 'browser',
|
|
122
|
+
closedBrowser: result.closedBrowser,
|
|
123
|
+
note: 'Signed in via the dashboard; Firebase token captured and cached. ' +
|
|
124
|
+
'Tokens expire (~1h) — re-run reclaim_authenticate on 401.',
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RegisteredTool } from '../../mcp/server.ts';
|
|
2
|
+
import type { ReclaimOldClient } from '../client.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The backend-facing tools for OLD-devtools mode. Mirrors
|
|
5
|
+
* `buildCredentialTools` / `buildAgentTools`: returns a flat `RegisteredTool`
|
|
6
|
+
* list for `registerToolList`. These three replace the builder credential +
|
|
7
|
+
* publish tools and the (disabled) generated provider tools.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildOldBackendTools(client: ReclaimOldClient): RegisteredTool[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { authenticateTool } from "./authenticate.js";
|
|
2
|
+
import { getMeProvidersTool } from "./me-providers.js";
|
|
3
|
+
import { createVersionFromCaptureTool } from "./publish.js";
|
|
4
|
+
/**
|
|
5
|
+
* The backend-facing tools for OLD-devtools mode. Mirrors
|
|
6
|
+
* `buildCredentialTools` / `buildAgentTools`: returns a flat `RegisteredTool`
|
|
7
|
+
* list for `registerToolList`. These three replace the builder credential +
|
|
8
|
+
* publish tools and the (disabled) generated provider tools.
|
|
9
|
+
*/
|
|
10
|
+
export function buildOldBackendTools(client) {
|
|
11
|
+
return [
|
|
12
|
+
authenticateTool(client),
|
|
13
|
+
createVersionFromCaptureTool(client),
|
|
14
|
+
getMeProvidersTool(client),
|
|
15
|
+
];
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type RegisteredTool } from '../../mcp/server.ts';
|
|
2
|
+
import type { ReclaimOldClient } from '../client.ts';
|
|
3
|
+
/**
|
|
4
|
+
* List the authenticated user's OWN providers on the old devtools backend
|
|
5
|
+
* (`GET /api/providers/user/paginated`, filtered server-side to the caller's
|
|
6
|
+
* uid). This exists ONLY in old mode: the generated provider-listing tools
|
|
7
|
+
* are disabled there, so this is the way to discover a `providerId` to pass
|
|
8
|
+
* back into `create_provider_version_from_capture` for a version update.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getMeProvidersTool(client: ReclaimOldClient): RegisteredTool;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineTool } from "../../mcp/server.js";
|
|
2
|
+
/**
|
|
3
|
+
* List the authenticated user's OWN providers on the old devtools backend
|
|
4
|
+
* (`GET /api/providers/user/paginated`, filtered server-side to the caller's
|
|
5
|
+
* uid). This exists ONLY in old mode: the generated provider-listing tools
|
|
6
|
+
* are disabled there, so this is the way to discover a `providerId` to pass
|
|
7
|
+
* back into `create_provider_version_from_capture` for a version update.
|
|
8
|
+
*/
|
|
9
|
+
export function getMeProvidersTool(client) {
|
|
10
|
+
return defineTool({
|
|
11
|
+
name: 'get_me_providers',
|
|
12
|
+
description: 'List the providers YOU own on the old devtools backend (newest ' +
|
|
13
|
+
'first). Returns provider metadata including each `providerId` — ' +
|
|
14
|
+
'pass one back to create_provider_version_from_capture to publish a ' +
|
|
15
|
+
'new version of that provider instead of creating a duplicate. ' +
|
|
16
|
+
'Requires reclaim_authenticate first.',
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
pageKey: { type: 'number', description: 'Page index (default 0).' },
|
|
21
|
+
pageSize: {
|
|
22
|
+
type: 'number',
|
|
23
|
+
description: 'Page size (default 20).',
|
|
24
|
+
},
|
|
25
|
+
searchQuery: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'Filter by name or providerId.',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}, async (args) => client.getMyProviders(args));
|
|
32
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type RegisteredTool } from '../../mcp/server.ts';
|
|
2
|
+
import type { ReclaimOldClient } from '../client.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Publish a drafted provider to the OLD devtools backend. Keeps the builder
|
|
5
|
+
* tool NAME (`create_provider_version_from_capture`) so the skill flow is
|
|
6
|
+
* unchanged, but the behaviour differs:
|
|
7
|
+
*
|
|
8
|
+
* - WITHOUT `providerId` → `POST /api/providers/register`: creates a
|
|
9
|
+
* brand-new provider + version 1.0.0. Re-running creates a DUPLICATE.
|
|
10
|
+
* - WITH `providerId` → `POST /api/providers/:providerId/config`: adds a
|
|
11
|
+
* new version to an existing provider (auto-bumps the patch above the
|
|
12
|
+
* highest existing version).
|
|
13
|
+
*
|
|
14
|
+
* Get a `providerId` from `get_me_providers`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createVersionFromCaptureTool(client: ReclaimOldClient): RegisteredTool;
|