@reclaimprotocol/agent 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/cdp/capture-engine.d.ts +66 -0
- package/lib/cdp/capture-engine.js +153 -0
- package/lib/cdp/capture.d.ts +9 -20
- package/lib/cdp/capture.js +14 -138
- package/lib/cdp/index.d.ts +3 -0
- package/lib/cdp/index.js +6 -0
- package/lib/config/store.d.ts +7 -6
- package/lib/config/store.js +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/mcp/api/operations.gen.d.ts +101 -45
- package/lib/mcp/api/operations.gen.js +996 -126
- package/lib/mcp/api/to-zod.d.ts +24 -0
- package/lib/mcp/api/to-zod.js +94 -0
- package/lib/mcp/api/tools.js +1 -1
- package/lib/mcp/credentials/authenticate.d.ts +3 -0
- package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
- package/lib/mcp/credentials/build.d.ts +5 -0
- package/lib/mcp/credentials/build.js +18 -0
- package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
- package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
- package/lib/mcp/credentials/import.d.ts +2 -0
- package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
- package/lib/mcp/credentials/issue.d.ts +2 -0
- package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
- package/lib/mcp/credentials/keypair.d.ts +17 -0
- package/lib/mcp/credentials/keypair.js +48 -0
- package/lib/mcp/credentials/link.d.ts +3 -0
- package/lib/mcp/credentials/link.js +107 -0
- package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
- package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
- package/lib/mcp/credentials/owner-key.d.ts +23 -0
- package/lib/mcp/credentials/owner-key.js +58 -0
- package/lib/mcp/credentials/paths.d.ts +12 -0
- package/lib/mcp/credentials/paths.js +35 -0
- package/lib/mcp/credentials/poll.d.ts +27 -0
- package/lib/mcp/credentials/poll.js +61 -0
- package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
- package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
- package/lib/mcp/credentials/session-cache.d.ts +14 -0
- package/lib/mcp/credentials/session-cache.js +42 -0
- package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
- package/lib/mcp/credentials/status.js +76 -0
- package/lib/mcp/instructions.d.ts +1 -0
- package/lib/mcp/instructions.js +11 -0
- package/lib/mcp/register.d.ts +38 -0
- package/lib/mcp/register.js +80 -0
- package/lib/mcp/server.d.ts +2 -2
- package/lib/mcp/server.js +3 -3
- package/lib/mcp/start.js +10 -4
- package/lib/mcp/tools/agent/build.js +2 -15
- package/lib/mcp/tools/agent/index.d.ts +2 -0
- package/lib/mcp/tools/agent/index.js +3 -0
- package/lib/mcp/tools/agent/proof.js +1 -6
- package/lib/mcp/tools/agent/propose.js +13 -2
- package/lib/mcp/tools/agent/publish.js +10 -2
- package/lib/mcp/tools/agent/replay.js +0 -5
- package/lib/mcp/tools/analyze.d.ts +3 -0
- package/lib/mcp/tools/analyze.js +26 -0
- package/lib/mcp/tools/attach.d.ts +11 -0
- package/lib/mcp/tools/attach.js +72 -0
- package/lib/mcp/tools/authenticate/authenticate.js +107 -0
- package/lib/mcp/tools/authenticate/build.d.ts +15 -0
- package/lib/mcp/tools/authenticate/build.js +28 -0
- package/lib/mcp/tools/authenticate/decrypt-key.d.ts +32 -0
- package/lib/mcp/tools/authenticate/decrypt-key.js +49 -0
- package/lib/mcp/tools/authenticate/eth-key.d.ts +38 -0
- package/lib/mcp/tools/authenticate/eth-key.js +130 -0
- package/lib/mcp/tools/authenticate/import.js +57 -0
- package/lib/mcp/tools/authenticate/index.d.ts +2 -0
- package/lib/mcp/tools/authenticate/index.js +4 -0
- package/lib/mcp/tools/authenticate/issue.js +42 -0
- package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
- package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
- package/lib/mcp/tools/capture.d.ts +10 -0
- package/lib/mcp/tools/capture.js +142 -0
- package/lib/mcp/tools/eval.d.ts +5 -0
- package/lib/mcp/tools/eval.js +127 -0
- package/lib/mcp/tools/find.d.ts +3 -0
- package/lib/mcp/tools/find.js +60 -0
- package/lib/mcp/tools/index.d.ts +3 -0
- package/lib/mcp/tools/index.js +6 -0
- package/lib/mcp/tools/owner-key.d.ts +2 -0
- package/lib/mcp/tools/owner-key.js +63 -0
- package/lib/mcp/tools/proof.d.ts +3 -0
- package/lib/mcp/tools/proof.js +214 -0
- package/lib/mcp/tools/propose.d.ts +9 -0
- package/lib/mcp/tools/propose.js +75 -0
- package/lib/mcp/tools/publish.d.ts +3 -0
- package/lib/mcp/tools/publish.js +59 -0
- package/lib/mcp/tools/replay.d.ts +3 -0
- package/lib/mcp/tools/replay.js +46 -0
- package/lib/mcp/tools/session.d.ts +10 -0
- package/lib/mcp/tools/session.js +29 -0
- package/lib/mcp/tools/verification/build.d.ts +12 -0
- package/lib/mcp/tools/verification/build.js +14 -0
- package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
- package/lib/mcp/tools/verification/diagnose.js +132 -0
- package/lib/mcp/tools/verification/index.d.ts +1 -0
- package/lib/mcp/tools/verification/index.js +2 -0
- package/lib/mcp/tools/verification/result.d.ts +12 -0
- package/lib/mcp/tools/verification/result.js +126 -0
- package/lib/mcp/verifications/build.d.ts +5 -0
- package/lib/mcp/verifications/build.js +14 -0
- package/lib/mcp/verifications/create.d.ts +3 -0
- package/lib/mcp/verifications/create.js +57 -0
- package/lib/mcp/verifications/find.d.ts +3 -0
- package/lib/mcp/verifications/find.js +37 -0
- package/lib/mcp/verifications/get.d.ts +3 -0
- package/lib/mcp/verifications/get.js +26 -0
- package/lib/mcp/verifications/update.d.ts +3 -0
- package/lib/mcp/verifications/update.js +78 -0
- package/lib/old/client.d.ts +3 -0
- package/lib/old/instructions.d.ts +0 -6
- package/lib/old/instructions.js +6 -24
- package/lib/old/to-register.d.ts +3 -0
- package/lib/old/to-register.js +35 -7
- package/lib/old/tools/publish.js +13 -1
- package/lib/proof/attestor.d.ts +33 -1
- package/lib/proof/attestor.js +67 -61
- package/lib/proof/index.d.ts +5 -0
- package/lib/proof/index.js +6 -0
- package/lib/proof/proof-core.d.ts +35 -0
- package/lib/proof/proof-core.js +73 -0
- package/lib/proof/zk-files.d.ts +14 -0
- package/lib/proof/zk-files.js +73 -0
- package/lib/provider/index.d.ts +5 -0
- package/lib/provider/index.js +9 -0
- package/lib/provider/to-version.d.ts +9 -12
- package/lib/provider/to-version.js +38 -4
- package/lib/provider/verification-checks.d.ts +12 -0
- package/lib/provider/verification-checks.js +30 -0
- package/lib/routes.gen.d.ts +271 -0
- package/lib/routes.gen.js +73 -0
- package/lib/types/openapi.gen.d.ts +3967 -0
- package/lib/types/openapi.gen.js +5 -0
- package/package.json +18 -10
- package/skill/SKILL.md +35 -14
- package/skill/builder-mode.md +9 -0
- package/skill/old-mode.md +13 -0
- package/src/cdp/capture-engine.ts +256 -0
- package/src/cdp/capture.ts +25 -185
- package/src/cdp/index.ts +6 -0
- package/src/config/store.ts +7 -6
- package/src/index.ts +2 -4
- package/src/mcp/api/operations.gen.ts +1023 -121
- package/src/mcp/api/to-zod.ts +115 -0
- package/src/mcp/api/tools.ts +9 -3
- package/src/mcp/instructions.ts +15 -0
- package/src/mcp/server.ts +5 -4
- package/src/mcp/start.ts +14 -4
- package/src/mcp/tools/agent/build.ts +2 -18
- package/src/mcp/tools/agent/index.ts +4 -0
- package/src/mcp/tools/agent/proof.ts +1 -7
- package/src/mcp/tools/agent/propose.ts +13 -2
- package/src/mcp/tools/agent/publish.ts +10 -2
- package/src/mcp/tools/agent/replay.ts +0 -5
- package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
- package/src/mcp/tools/authenticate/build.ts +32 -0
- package/src/mcp/tools/authenticate/decrypt-key.ts +64 -0
- package/src/mcp/tools/authenticate/eth-key.ts +182 -0
- package/src/mcp/tools/authenticate/import.ts +73 -0
- package/src/mcp/tools/authenticate/index.ts +4 -0
- package/src/mcp/tools/authenticate/issue.ts +50 -0
- package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
- package/src/mcp/tools/index.ts +6 -0
- package/src/mcp/tools/verification/build.ts +16 -0
- package/src/mcp/tools/verification/index.ts +2 -0
- package/src/mcp/tools/verification/result.ts +155 -0
- package/src/old/client.ts +3 -0
- package/src/old/instructions.ts +10 -25
- package/src/old/to-register.ts +62 -27
- package/src/old/tools/publish.ts +17 -1
- package/src/proof/attestor.ts +115 -69
- package/src/proof/index.ts +21 -0
- package/src/proof/proof-core.ts +109 -0
- package/src/proof/zk-files.ts +83 -0
- package/src/provider/index.ts +20 -0
- package/src/provider/to-version.ts +52 -11
- package/src/provider/verification-checks.ts +36 -0
- package/lib/mcp/tools/credentials/build.d.ts +0 -16
- package/lib/mcp/tools/credentials/build.js +0 -33
- package/lib/mcp/tools/credentials/status.js +0 -62
- package/src/mcp/tools/credentials/build.ts +0 -37
- package/src/mcp/tools/credentials/cache.ts +0 -161
- package/src/mcp/tools/credentials/env-file.ts +0 -101
- package/src/mcp/tools/credentials/import.ts +0 -72
- package/src/mcp/tools/credentials/issue.ts +0 -107
- package/src/mcp/tools/credentials/list-cached.ts +0 -66
- package/src/mcp/tools/credentials/register.ts +0 -49
- package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
- package/src/mcp/tools/credentials/status.ts +0 -82
- package/src/types/openapi.ts +0 -7
- /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
- /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
- /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
- /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the Reclaim cache directory (`~/.reclaim`). Honours the
|
|
3
|
+
* `RECLAIM_HOME` env var as an override so tests can sandbox writes.
|
|
4
|
+
*/
|
|
5
|
+
export declare function reclaimHome(): string;
|
|
6
|
+
export declare function credentialsCachePath(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Walk up from `start` until we find a directory containing one of
|
|
9
|
+
* the project-root markers, then return that directory. Falls back
|
|
10
|
+
* to `start` if no marker is found within 8 levels.
|
|
11
|
+
*/
|
|
12
|
+
export declare function findProjectRoot(start?: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the Reclaim cache directory (`~/.reclaim`). Honours the
|
|
6
|
+
* `RECLAIM_HOME` env var as an override so tests can sandbox writes.
|
|
7
|
+
*/
|
|
8
|
+
export function reclaimHome() {
|
|
9
|
+
return process.env.RECLAIM_HOME || join(homedir(), '.reclaim');
|
|
10
|
+
}
|
|
11
|
+
export function credentialsCachePath() {
|
|
12
|
+
return join(reclaimHome(), 'credentials.json');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Walk up from `start` until we find a directory containing one of
|
|
16
|
+
* the project-root markers, then return that directory. Falls back
|
|
17
|
+
* to `start` if no marker is found within 8 levels.
|
|
18
|
+
*/
|
|
19
|
+
export function findProjectRoot(start = process.cwd()) {
|
|
20
|
+
const markers = ['.git', 'package.json', 'pyproject.toml', 'Cargo.toml'];
|
|
21
|
+
let dir = resolve(start);
|
|
22
|
+
for (let i = 0; i < 8; i++) {
|
|
23
|
+
for (const m of markers) {
|
|
24
|
+
if (existsSync(join(dir, m))) {
|
|
25
|
+
return dir;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const parent = dirname(dir);
|
|
29
|
+
if (parent === dir) {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
dir = parent;
|
|
33
|
+
}
|
|
34
|
+
return start;
|
|
35
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReclaimClient } from '@reclaimprotocol/client';
|
|
2
|
+
import type { components } from '../../types/openapi.gen.ts';
|
|
3
|
+
type Session = components['schemas']['CredentialAttachSession'];
|
|
4
|
+
type PollResult = {
|
|
5
|
+
outcome: 'linked';
|
|
6
|
+
token?: string;
|
|
7
|
+
orgId?: string;
|
|
8
|
+
} | {
|
|
9
|
+
outcome: 'expired';
|
|
10
|
+
} | {
|
|
11
|
+
outcome: 'timeout';
|
|
12
|
+
elapsed: number;
|
|
13
|
+
attachUrl: string;
|
|
14
|
+
} | {
|
|
15
|
+
outcome: 'error';
|
|
16
|
+
message: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Poll GET /credentials/attach/sessions/{code} until the session is
|
|
20
|
+
* LINKED or we give up, whichever comes first.
|
|
21
|
+
*
|
|
22
|
+
* Errors inside the loop are surfaced immediately after MAX_CONSECUTIVE_ERRORS
|
|
23
|
+
* rather than being silently swallowed — this is what tells the agent that
|
|
24
|
+
* e.g. the confirmation POST failed or the server restarted.
|
|
25
|
+
*/
|
|
26
|
+
export declare function pollUntilLinked(client: ReclaimClient, session: Pick<Session, 'code' | 'attachUrl' | 'expiresAt'>, onToken?: (token: string) => void): Promise<PollResult>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// How long to poll before giving up and telling the user what to do.
|
|
2
|
+
// Shorter than the 15-min server TTL on purpose — agents can't block long.
|
|
3
|
+
const POLL_TIMEOUT_MS = 3 * 60_000; // 3 minutes
|
|
4
|
+
const POLL_INTERVAL_MS = 5_000; // 5 seconds
|
|
5
|
+
const MAX_CONSECUTIVE_ERRORS = 5;
|
|
6
|
+
/**
|
|
7
|
+
* Poll GET /credentials/attach/sessions/{code} until the session is
|
|
8
|
+
* LINKED or we give up, whichever comes first.
|
|
9
|
+
*
|
|
10
|
+
* Errors inside the loop are surfaced immediately after MAX_CONSECUTIVE_ERRORS
|
|
11
|
+
* rather than being silently swallowed — this is what tells the agent that
|
|
12
|
+
* e.g. the confirmation POST failed or the server restarted.
|
|
13
|
+
*/
|
|
14
|
+
export async function pollUntilLinked(client, session, onToken) {
|
|
15
|
+
const sessionExpiry = new Date(session.expiresAt).getTime();
|
|
16
|
+
const deadline = Math.min(sessionExpiry, Date.now() + POLL_TIMEOUT_MS);
|
|
17
|
+
const startedAt = Date.now();
|
|
18
|
+
let consecutiveErrors = 0;
|
|
19
|
+
while (Date.now() < deadline) {
|
|
20
|
+
await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));
|
|
21
|
+
let polled;
|
|
22
|
+
try {
|
|
23
|
+
polled = await client.call('GetAttachSession', {
|
|
24
|
+
params: { code: session.code },
|
|
25
|
+
query: {}, body: {},
|
|
26
|
+
});
|
|
27
|
+
consecutiveErrors = 0;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
consecutiveErrors++;
|
|
31
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
32
|
+
return {
|
|
33
|
+
outcome: 'error',
|
|
34
|
+
message: `Polling failed ${consecutiveErrors} times in a row: `
|
|
35
|
+
+ err.message
|
|
36
|
+
+ '. The session confirmation may have failed — try opening '
|
|
37
|
+
+ session.attachUrl
|
|
38
|
+
+ ' again and confirming, then retry.',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
continue; // transient error, retry
|
|
42
|
+
}
|
|
43
|
+
if (polled.status === 'LINKED') {
|
|
44
|
+
const token = polled.token?.trim();
|
|
45
|
+
if (token) {
|
|
46
|
+
onToken?.(token);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
outcome: 'linked',
|
|
50
|
+
token,
|
|
51
|
+
orgId: polled.linkedOrgId,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (polled.status === 'EXPIRED') {
|
|
55
|
+
return { outcome: 'expired' };
|
|
56
|
+
}
|
|
57
|
+
// status === 'PENDING' → keep polling
|
|
58
|
+
}
|
|
59
|
+
const elapsed = Math.round((Date.now() - startedAt) / 60_000);
|
|
60
|
+
return { outcome: 'timeout', elapsed, attachUrl: session.attachUrl };
|
|
61
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { deriveFromPrivateKey } from '@reclaimprotocol/client';
|
|
2
|
-
import { findProjectRoot } from "
|
|
3
|
-
import { defineTool } from "
|
|
2
|
+
import { findProjectRoot } from "../../paths.js";
|
|
3
|
+
import { defineTool } from "../server.js";
|
|
4
4
|
import { suggestCredentialForDir } from "./cache.js";
|
|
5
5
|
import { readPrivateKeyFromEnvFile } from "./env-file.js";
|
|
6
6
|
/**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type CachedSession = {
|
|
2
|
+
token: string;
|
|
3
|
+
/** ISO timestamp when the token expires (2 days from issue). */
|
|
4
|
+
expiresAt: string;
|
|
5
|
+
/** Email of the user who authorized (if available). */
|
|
6
|
+
email?: string;
|
|
7
|
+
};
|
|
8
|
+
/** Persist a session token to ~/.reclaim/session.json (0600). */
|
|
9
|
+
export declare function writeSession(session: CachedSession): void;
|
|
10
|
+
/**
|
|
11
|
+
* Read the cached session, returning it only if the token is still
|
|
12
|
+
* valid (not yet expired). Returns undefined on any error.
|
|
13
|
+
*/
|
|
14
|
+
export declare function readSession(): CachedSession | undefined;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { reclaimHomeDirPath } from "../../paths.js";
|
|
4
|
+
// Separate from credentials.json — sessions expire, credentials don't.
|
|
5
|
+
function sessionCachePath() {
|
|
6
|
+
return join(reclaimHomeDirPath(), 'session.json');
|
|
7
|
+
}
|
|
8
|
+
/** Persist a session token to ~/.reclaim/session.json (0600). */
|
|
9
|
+
export function writeSession(session) {
|
|
10
|
+
const dir = reclaimHomeDirPath();
|
|
11
|
+
if (!existsSync(dir)) {
|
|
12
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
13
|
+
}
|
|
14
|
+
chmodSync(dir, 0o700);
|
|
15
|
+
const path = sessionCachePath();
|
|
16
|
+
writeFileSync(path, JSON.stringify(session, null, 2) + '\n', { mode: 0o600 });
|
|
17
|
+
chmodSync(path, 0o600);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read the cached session, returning it only if the token is still
|
|
21
|
+
* valid (not yet expired). Returns undefined on any error.
|
|
22
|
+
*/
|
|
23
|
+
export function readSession() {
|
|
24
|
+
const path = sessionCachePath();
|
|
25
|
+
if (!existsSync(path)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const raw = readFileSync(path, 'utf8');
|
|
30
|
+
const s = JSON.parse(raw);
|
|
31
|
+
if (!s.token || !s.expiresAt) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
if (new Date(s.expiresAt) <= new Date()) {
|
|
35
|
+
return undefined; // expired
|
|
36
|
+
}
|
|
37
|
+
return s;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { deriveFromPrivateKey, } from '@reclaimprotocol/client';
|
|
2
|
+
import { findProjectRoot } from "../../paths.js";
|
|
3
|
+
import { defineTool } from "../server.js";
|
|
4
|
+
import { findCached, suggestCredentialForDir } from "./cache.js";
|
|
5
|
+
export function statusTool(client) {
|
|
6
|
+
return defineTool({
|
|
7
|
+
name: 'reclaim_status',
|
|
8
|
+
description: 'Report the live mode (SANDBOX | PRODUCTION | REVOKED) ' +
|
|
9
|
+
'of a Reclaim app credential. Pass `address` — or omit it ' +
|
|
10
|
+
'to derive the address from RECLAIM_PRIVATE_KEY, falling ' +
|
|
11
|
+
'back to the best cached credential for this directory. ' +
|
|
12
|
+
'Useful to confirm a credential is linked to an org ' +
|
|
13
|
+
'with billing before running a production flow.',
|
|
14
|
+
inputSchema: {
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: {
|
|
17
|
+
address: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
pattern: '^0x[0-9a-fA-F]{40}$',
|
|
20
|
+
description: 'Lowercase ETH address. Defaults to the address ' +
|
|
21
|
+
'derived from RECLAIM_PRIVATE_KEY, then the cached ' +
|
|
22
|
+
'credential suggested for the current directory.',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}, async (args) => {
|
|
27
|
+
let address = args.address?.toLowerCase();
|
|
28
|
+
if (!address && process.env.RECLAIM_PRIVATE_KEY) {
|
|
29
|
+
address = deriveFromPrivateKey(process.env.RECLAIM_PRIVATE_KEY).address;
|
|
30
|
+
}
|
|
31
|
+
if (!address) {
|
|
32
|
+
address = suggestCredentialForDir(findProjectRoot(process.cwd()))
|
|
33
|
+
?.credential.address;
|
|
34
|
+
}
|
|
35
|
+
if (!address) {
|
|
36
|
+
throw new Error('No address given, RECLAIM_PRIVATE_KEY is not set, and the ' +
|
|
37
|
+
'cache is empty. Run issue_credentials or import_credentials ' +
|
|
38
|
+
'first.');
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const credResult = (await client.call('GetCredentialByAddress', {
|
|
42
|
+
params: { address },
|
|
43
|
+
}));
|
|
44
|
+
const cred = credResult.data;
|
|
45
|
+
return {
|
|
46
|
+
address: cred.address,
|
|
47
|
+
mode: cred.mode,
|
|
48
|
+
orgId: cred.orgId,
|
|
49
|
+
label: cred.label,
|
|
50
|
+
revokedAt: cred.revokedAt,
|
|
51
|
+
lastUsedAt: cred.lastUsedAt,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
// Anonymous credentials are not registered server-side, so a
|
|
56
|
+
// 404 just means "local-only" — which is SANDBOX. Report what
|
|
57
|
+
// the local cache knows. Other errors propagate. The client
|
|
58
|
+
// throws a Boom-style ProblemError, so the status lives on
|
|
59
|
+
// `output.statusCode` / `problem.status`, not `status`.
|
|
60
|
+
const e = err;
|
|
61
|
+
const code = e.status ?? e.output?.statusCode ?? e.problem?.status;
|
|
62
|
+
if (code !== 404) {
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
const cached = findCached(address);
|
|
66
|
+
return {
|
|
67
|
+
address,
|
|
68
|
+
mode: 'SANDBOX',
|
|
69
|
+
...(cached?.label ? { label: cached.label } : {}),
|
|
70
|
+
note: 'Local-only credential — not registered with the server. ' +
|
|
71
|
+
'It operates in SANDBOX. Link it to an org with billing ' +
|
|
72
|
+
'(via link_credential) to reach PRODUCTION.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BUILDER_MODE_INSTRUCTIONS: string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server instructions shown to the LLM when running in BUILDER mode
|
|
3
|
+
* (`USE_OLD_DEVTOOLS=false`). The prose lives in `skill/builder-mode.md`
|
|
4
|
+
* (published via the `files` array) so it can be edited as markdown without
|
|
5
|
+
* touching code. The path resolves identically from `src/mcp` (dev) and
|
|
6
|
+
* `lib/mcp` (published) — both are two levels below the package root.
|
|
7
|
+
* Old-devtools mode has its own reduced set in `../old/instructions.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync } from 'node:fs';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
export const BUILDER_MODE_INSTRUCTIONS = readFileSync(fileURLToPath(new URL('../../skill/builder-mode.md', import.meta.url)), 'utf8').trim();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory entry-point for embedding the reclaim-agent's MCP tools into
|
|
3
|
+
* a host MCP server. Two consumers:
|
|
4
|
+
*
|
|
5
|
+
* - The agent's own standalone `src/index.ts` (uses `ReclaimMcpServer`,
|
|
6
|
+
* the low-level wrapper around `@modelcontextprotocol/sdk`'s Server).
|
|
7
|
+
* - `@reclaimprotocol/client`'s MCP server (uses `McpServer`, the
|
|
8
|
+
* high-level SDK wrapper). Calls `registerAgentTools` to fold the
|
|
9
|
+
* agent's 16 tools alongside its auto-generated API tools.
|
|
10
|
+
*
|
|
11
|
+
* Shared state — Chrome attach state, capture store, secret store — is
|
|
12
|
+
* built once per server and threaded through every tool factory.
|
|
13
|
+
*/
|
|
14
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
15
|
+
import type { ReclaimClient } from '@reclaimprotocol/client';
|
|
16
|
+
import { ConfigStore } from '../config/store.ts';
|
|
17
|
+
import { type AttachState } from './tools/attach.ts';
|
|
18
|
+
import { type CaptureStore } from './tools/capture.ts';
|
|
19
|
+
import { type SecretStore } from './tools/propose.ts';
|
|
20
|
+
import { type RegisteredTool } from './server.ts';
|
|
21
|
+
export interface AgentState {
|
|
22
|
+
attach: {
|
|
23
|
+
current?: AttachState;
|
|
24
|
+
config: ConfigStore;
|
|
25
|
+
};
|
|
26
|
+
captures: CaptureStore;
|
|
27
|
+
secrets: SecretStore;
|
|
28
|
+
}
|
|
29
|
+
export declare function buildAgentState(): AgentState;
|
|
30
|
+
/** Build the flat list of `RegisteredTool` entries. Useful when the host
|
|
31
|
+
* uses our internal `ReclaimMcpServer` interface (`.register(tool)`).
|
|
32
|
+
* Pass `client` to include `create_provider_version_from_capture`. */
|
|
33
|
+
export declare function buildAgentTools(state: AgentState, client?: ReclaimClient): RegisteredTool[];
|
|
34
|
+
/** Register agent tools on `@reclaimprotocol/client`'s McpServer. Mirrors
|
|
35
|
+
* the same shape as builder's auto-generated `registerTools(server, client)`
|
|
36
|
+
* in `mcp/api/tools.ts`.
|
|
37
|
+
* Pass `client` to include `create_provider_version_from_capture`. */
|
|
38
|
+
export declare function registerAgentTools(server: McpServer, state?: AgentState, client?: ReclaimClient): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory entry-point for embedding the reclaim-agent's MCP tools into
|
|
3
|
+
* a host MCP server. Two consumers:
|
|
4
|
+
*
|
|
5
|
+
* - The agent's own standalone `src/index.ts` (uses `ReclaimMcpServer`,
|
|
6
|
+
* the low-level wrapper around `@modelcontextprotocol/sdk`'s Server).
|
|
7
|
+
* - `@reclaimprotocol/client`'s MCP server (uses `McpServer`, the
|
|
8
|
+
* high-level SDK wrapper). Calls `registerAgentTools` to fold the
|
|
9
|
+
* agent's 16 tools alongside its auto-generated API tools.
|
|
10
|
+
*
|
|
11
|
+
* Shared state — Chrome attach state, capture store, secret store — is
|
|
12
|
+
* built once per server and threaded through every tool factory.
|
|
13
|
+
*/
|
|
14
|
+
import { setCryptoImplementation } from '@reclaimprotocol/tls';
|
|
15
|
+
import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto';
|
|
16
|
+
import { ConfigStore } from "../config/store.js";
|
|
17
|
+
import { analyzeTool } from "./tools/analyze.js";
|
|
18
|
+
import { attachTool } from "./tools/attach.js";
|
|
19
|
+
import { captureTools } from "./tools/capture.js";
|
|
20
|
+
import { browserTools } from "./tools/eval.js";
|
|
21
|
+
import { findTool } from "./tools/find.js";
|
|
22
|
+
import { proofTool } from "./tools/proof.js";
|
|
23
|
+
import { makeSecretStore, proposeTool, } from "./tools/propose.js";
|
|
24
|
+
import { createVersionFromCaptureTool } from "./tools/publish.js";
|
|
25
|
+
import { replayTool } from "./tools/replay.js";
|
|
26
|
+
import { sessionTools } from "./tools/session.js";
|
|
27
|
+
import { registerToolList } from "./server.js";
|
|
28
|
+
let cryptoInitialized = false;
|
|
29
|
+
/** One-time crypto backend init for @reclaimprotocol/tls. The package
|
|
30
|
+
* ships with an empty `crypto = {}` and defers backend choice to the
|
|
31
|
+
* caller; without this, the first proof call dies inside the SDK with
|
|
32
|
+
* `crypto.randomBytes is not a function`. */
|
|
33
|
+
function ensureCryptoInit() {
|
|
34
|
+
if (cryptoInitialized) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
setCryptoImplementation(webcryptoCrypto);
|
|
38
|
+
cryptoInitialized = true;
|
|
39
|
+
}
|
|
40
|
+
export function buildAgentState() {
|
|
41
|
+
return {
|
|
42
|
+
attach: { config: new ConfigStore() },
|
|
43
|
+
captures: { sessions: new Map() },
|
|
44
|
+
secrets: makeSecretStore(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Build the flat list of `RegisteredTool` entries. Useful when the host
|
|
48
|
+
* uses our internal `ReclaimMcpServer` interface (`.register(tool)`).
|
|
49
|
+
* Pass `client` to include `create_provider_version_from_capture`. */
|
|
50
|
+
export function buildAgentTools(state, client) {
|
|
51
|
+
ensureCryptoInit();
|
|
52
|
+
const tools = [];
|
|
53
|
+
tools.push(attachTool(state.attach));
|
|
54
|
+
for (const t of captureTools(state.attach, state.captures)) {
|
|
55
|
+
tools.push(t);
|
|
56
|
+
}
|
|
57
|
+
tools.push(findTool(state.captures));
|
|
58
|
+
for (const t of browserTools(state.attach)) {
|
|
59
|
+
tools.push(t);
|
|
60
|
+
}
|
|
61
|
+
for (const t of sessionTools(state.attach, state.captures, state.secrets)) {
|
|
62
|
+
tools.push(t);
|
|
63
|
+
}
|
|
64
|
+
tools.push(analyzeTool(state.captures));
|
|
65
|
+
tools.push(proposeTool(state.captures, state.secrets));
|
|
66
|
+
tools.push(replayTool(state.secrets));
|
|
67
|
+
tools.push(proofTool(state.secrets));
|
|
68
|
+
if (client) {
|
|
69
|
+
tools.push(createVersionFromCaptureTool(client));
|
|
70
|
+
}
|
|
71
|
+
return tools;
|
|
72
|
+
}
|
|
73
|
+
/** Register agent tools on `@reclaimprotocol/client`'s McpServer. Mirrors
|
|
74
|
+
* the same shape as builder's auto-generated `registerTools(server, client)`
|
|
75
|
+
* in `mcp/api/tools.ts`.
|
|
76
|
+
* Pass `client` to include `create_provider_version_from_capture`. */
|
|
77
|
+
export function registerAgentTools(server, state, client) {
|
|
78
|
+
const s = state ?? buildAgentState();
|
|
79
|
+
registerToolList(server, buildAgentTools(s, client));
|
|
80
|
+
}
|
package/lib/mcp/server.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { JSONSchema } from 'zod/v4/core';
|
|
3
3
|
export interface ToolDefinition {
|
|
4
4
|
name: string;
|
|
5
5
|
description: string;
|
|
6
|
-
inputSchema: JSONSchema;
|
|
6
|
+
inputSchema: JSONSchema.ObjectSchema;
|
|
7
7
|
}
|
|
8
8
|
export interface RegisteredTool {
|
|
9
9
|
definition: ToolDefinition;
|
package/lib/mcp/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
-
import {
|
|
4
|
+
import { toZod } from "./api/to-zod.js";
|
|
5
5
|
import { remapErrorAsResponse } from "./remap_errors.js";
|
|
6
6
|
/**
|
|
7
7
|
* Define a tool with a single inputSchema (JSON Schema) used as the
|
|
@@ -11,7 +11,7 @@ import { remapErrorAsResponse } from "./remap_errors.js";
|
|
|
11
11
|
* to inbound args cannot drift.
|
|
12
12
|
*/
|
|
13
13
|
export function defineTool(definition, handler) {
|
|
14
|
-
const schema =
|
|
14
|
+
const schema = toZod(definition.inputSchema);
|
|
15
15
|
return {
|
|
16
16
|
definition,
|
|
17
17
|
handler: async (raw) => {
|
|
@@ -29,7 +29,7 @@ export function registerToolList(server, tools) {
|
|
|
29
29
|
for (const tool of tools) {
|
|
30
30
|
server.registerTool(tool.definition.name, {
|
|
31
31
|
description: tool.definition.description,
|
|
32
|
-
inputSchema:
|
|
32
|
+
inputSchema: toZod(tool.definition.inputSchema),
|
|
33
33
|
}, async (args) => {
|
|
34
34
|
try {
|
|
35
35
|
return {
|
package/lib/mcp/start.js
CHANGED
|
@@ -8,13 +8,16 @@ import { OLD_MODE_INSTRUCTIONS } from "../old/instructions.js";
|
|
|
8
8
|
import { buildOldBackendTools } from "../old/tools/build.js";
|
|
9
9
|
import { NAME, VERSION } from "../pkg.js";
|
|
10
10
|
import { registerTools } from "./api/tools.js";
|
|
11
|
-
import { buildAgentTools } from "./tools/
|
|
12
|
-
import {
|
|
13
|
-
import { readSession } from "./tools/credentials/session-cache.js";
|
|
11
|
+
import { buildAgentTools, buildCredentialTools, buildLocalCredentialTools, buildVerificationTools, readSession, } from "./tools/index.js";
|
|
12
|
+
import { BUILDER_MODE_INSTRUCTIONS } from "./instructions.js";
|
|
14
13
|
import { registerToolList } from "./server.js";
|
|
15
14
|
export async function startMcpServer() {
|
|
16
15
|
const oldMode = useOldDevtools();
|
|
17
|
-
const server = new McpServer({ name: NAME, version: VERSION },
|
|
16
|
+
const server = new McpServer({ name: NAME, version: VERSION }, {
|
|
17
|
+
instructions: oldMode
|
|
18
|
+
? OLD_MODE_INSTRUCTIONS
|
|
19
|
+
: BUILDER_MODE_INSTRUCTIONS,
|
|
20
|
+
});
|
|
18
21
|
// Agent tools (Chrome CDP capture, provider synthesis, replay, proof) are
|
|
19
22
|
// backend-independent and registered in both modes. Skipped in hosted
|
|
20
23
|
// deployments — set RECLAIM_AGENT_DISABLED=1 to register only the API
|
|
@@ -51,6 +54,9 @@ export async function startMcpServer() {
|
|
|
51
54
|
// collision instead of one tool silently shadowing the other.
|
|
52
55
|
// Register credential tools for ETH credential management.
|
|
53
56
|
registerToolList(server, buildCredentialTools(client));
|
|
57
|
+
// Higher-level verification orchestrations (e.g. fetch + decrypt result).
|
|
58
|
+
// Authenticates with RECLAIM_ORG_SECRET, not the session client.
|
|
59
|
+
registerToolList(server, buildVerificationTools());
|
|
54
60
|
// Add auto-generated tools with snake_case wrappers
|
|
55
61
|
// for every MCP-tagged operation.
|
|
56
62
|
registerTools(server, client);
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
* Shared state — Chrome attach state, capture store, secret store — is
|
|
12
12
|
* built once per server and threaded through every tool factory.
|
|
13
13
|
*/
|
|
14
|
-
import { setCryptoImplementation } from '@reclaimprotocol/tls';
|
|
15
|
-
import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto';
|
|
16
14
|
import { ConfigStore } from "../../../config/store.js";
|
|
15
|
+
import { ensureAttestorCrypto } from "../../../proof/proof-core.js";
|
|
17
16
|
import { analyzeTool } from "./analyze.js";
|
|
18
17
|
import { attachTool } from "./attach.js";
|
|
19
18
|
import { captureTools } from "./capture.js";
|
|
@@ -24,18 +23,6 @@ import { makeSecretStore, proposeTool, } from "./propose.js";
|
|
|
24
23
|
import { createVersionFromCaptureTool } from "./publish.js";
|
|
25
24
|
import { replayTool } from "./replay.js";
|
|
26
25
|
import { sessionTools } from "./session.js";
|
|
27
|
-
let cryptoInitialized = false;
|
|
28
|
-
/** One-time crypto backend init for @reclaimprotocol/tls. The package
|
|
29
|
-
* ships with an empty `crypto = {}` and defers backend choice to the
|
|
30
|
-
* caller; without this, the first proof call dies inside the SDK with
|
|
31
|
-
* `crypto.randomBytes is not a function`. */
|
|
32
|
-
function ensureCryptoInit() {
|
|
33
|
-
if (cryptoInitialized) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
setCryptoImplementation(webcryptoCrypto);
|
|
37
|
-
cryptoInitialized = true;
|
|
38
|
-
}
|
|
39
26
|
function buildAgentState() {
|
|
40
27
|
return {
|
|
41
28
|
attach: { config: new ConfigStore() },
|
|
@@ -50,7 +37,7 @@ function buildAgentState() {
|
|
|
50
37
|
* capture/proof tools — old mode supplies its own publish tool. */
|
|
51
38
|
export function buildAgentTools(client) {
|
|
52
39
|
const state = buildAgentState();
|
|
53
|
-
|
|
40
|
+
ensureAttestorCrypto();
|
|
54
41
|
const tools = [];
|
|
55
42
|
tools.push(attachTool(state.attach));
|
|
56
43
|
for (const t of captureTools(state.attach, state.captures)) {
|
|
@@ -103,11 +103,6 @@ export function proofTool(secrets) {
|
|
|
103
103
|
inputSchema: {
|
|
104
104
|
type: 'object',
|
|
105
105
|
properties: {
|
|
106
|
-
// `type: 'object'` is required so MCP clients (the LLM)
|
|
107
|
-
// serialize the value as an object, not a JSON-stringified
|
|
108
|
-
// string. `properties: {}` is required so zod-from-json-schema
|
|
109
|
-
// compiles to a passthrough instead of strict-strip — leaving
|
|
110
|
-
// it off makes the server receive `{}`.
|
|
111
106
|
provider: { type: 'object', properties: {} },
|
|
112
107
|
secretParamsRef: { type: 'string' },
|
|
113
108
|
attestorUrl: { type: 'string' },
|
|
@@ -132,7 +127,7 @@ export function proofTool(secrets) {
|
|
|
132
127
|
}
|
|
133
128
|
resolved = r;
|
|
134
129
|
}
|
|
135
|
-
const result = await runAttestorProof(provider, resolved, attestorUrl, ownerAddress);
|
|
130
|
+
const result = await runAttestorProof(provider, resolved, { attestorUrl, ownerAddress });
|
|
136
131
|
// Persist the full claim to disk for the dev to inspect/share.
|
|
137
132
|
let claimPath;
|
|
138
133
|
if (result.proof !== undefined && result.proof !== null) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { draftProvider } from "../../../provider/draft.js";
|
|
3
3
|
import { OPRF_MAX_BYTES } from "../../../provider/matcher.js";
|
|
4
|
+
import { verificationWarnings } from "../../../provider/verification-checks.js";
|
|
4
5
|
import { defineTool } from "../../server.js";
|
|
5
6
|
export function makeSecretStore() {
|
|
6
7
|
const map = new Map();
|
|
@@ -27,7 +28,11 @@ export function proposeTool(captures, secrets) {
|
|
|
27
28
|
'cleartext. Skill should ask the dev first. `oprf-raw` ' +
|
|
28
29
|
'is the only variant that runs ' +
|
|
29
30
|
'without external deps; `oprf` needs gnark (Linux/macOS), ' +
|
|
30
|
-
'`oprf-mpc` needs a TEE attestor.'
|
|
31
|
+
'`oprf-mpc` needs a TEE attestor. ' +
|
|
32
|
+
'The response may include `verificationWarnings` — advisory ' +
|
|
33
|
+
'author-only decisions (e.g. a user-specific URL part needing ' +
|
|
34
|
+
'the {{context.<name>}}-vs-bare call). Surface each to the ' +
|
|
35
|
+
'dev verbatim and resolve before publishing.',
|
|
31
36
|
inputSchema: {
|
|
32
37
|
type: 'object',
|
|
33
38
|
properties: {
|
|
@@ -70,6 +75,12 @@ export function proposeTool(captures, secrets) {
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
const secretParamsRef = secrets.put(realSecrets);
|
|
73
|
-
|
|
78
|
+
const warnings = verificationWarnings(provider);
|
|
79
|
+
return {
|
|
80
|
+
provider,
|
|
81
|
+
secretRefs,
|
|
82
|
+
secretParamsRef,
|
|
83
|
+
...(warnings.length ? { verificationWarnings: warnings } : {}),
|
|
84
|
+
};
|
|
74
85
|
});
|
|
75
86
|
}
|
|
@@ -10,8 +10,16 @@ export function createVersionFromCaptureTool(client) {
|
|
|
10
10
|
'hand-construct that shape or call create_provider_version directly. ' +
|
|
11
11
|
'Omit `version` to have the tool auto-select the next available ' +
|
|
12
12
|
'version (it lists existing versions and bumps past the highest). ' +
|
|
13
|
-
'
|
|
14
|
-
'
|
|
13
|
+
'The version lands on the draft branch — to go live, call ' +
|
|
14
|
+
'`publish_provider_version` (PRIVATE) or ' +
|
|
15
|
+
'`submit_provider_version_for_review` (PUBLIC) afterwards. ' +
|
|
16
|
+
'`requiredContext` is derived from any {{context.<name>}} ' +
|
|
17
|
+
'placeholders and returned on the created version — when ' +
|
|
18
|
+
'present, tell the dev verbatim which context fields consumers ' +
|
|
19
|
+
'MUST send when creating sessions (verification matches those ' +
|
|
20
|
+
'values exactly; a missing field is a 400 at session create). ' +
|
|
21
|
+
'Refine types/descriptions via `update_provider_version` while ' +
|
|
22
|
+
'still on draft.',
|
|
15
23
|
inputSchema: {
|
|
16
24
|
type: 'object',
|
|
17
25
|
properties: {
|
|
@@ -11,11 +11,6 @@ export function replayTool(secrets) {
|
|
|
11
11
|
inputSchema: {
|
|
12
12
|
type: 'object',
|
|
13
13
|
properties: {
|
|
14
|
-
// `type: 'object'` is required so MCP clients (the LLM)
|
|
15
|
-
// serialize the value as an object, not a JSON-stringified
|
|
16
|
-
// string. `properties: {}` is required so zod-from-json-schema
|
|
17
|
-
// compiles to a passthrough instead of strict-strip — leaving
|
|
18
|
-
// it off makes the server receive `{}`.
|
|
19
14
|
provider: { type: 'object', properties: {} },
|
|
20
15
|
secretParamsRef: { type: 'string' },
|
|
21
16
|
},
|