@leashmarket/mcp 0.1.0

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.
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Persist a freshly-registered agent (or a pending-register block) to
3
+ * `~/.config/leash/agent.json` with `chmod 600` so subsequent
4
+ * `leash-mcp` / `leash` CLI launches pick up the new identity
5
+ * automatically.
6
+ *
7
+ * Lives in its own module (separate from `./config.ts`) because the
8
+ * read path is browser-safe — `loadAgentConfig` only depends on
9
+ * `node:fs` types — while writing requires `node:fs/promises` and
10
+ * `node:os`. Keeping the boundaries clean lets the SDK reuse the
11
+ * read path in non-Node runtimes (Bun, Deno, edge) without dragging
12
+ * in the file-system writer.
13
+ */
14
+ import { mkdir, writeFile } from 'node:fs/promises';
15
+ import { dirname } from 'node:path';
16
+ import { defaultConfigPath } from './config.js';
17
+ /**
18
+ * Write a fully-registered `LeashAgentConfig` to disk. Creates parent
19
+ * directories with mode 0700, writes the file with mode 0600.
20
+ * Idempotent: overwrites in-place. Clears any `pending_register`
21
+ * block left over from the two-step registration flow.
22
+ */
23
+ export async function writeAgentConfig(args) {
24
+ const path = args.path ?? defaultConfigPath();
25
+ const file = {
26
+ version: 1,
27
+ agent_mint: args.config.agentMint,
28
+ executive_keypair: args.config.executiveSecretBase58,
29
+ network: args.config.network,
30
+ api_url: args.config.apiBaseUrl,
31
+ rpc_url: args.config.rpcUrl,
32
+ ...(args.config.explorerBaseUrl ? { explorer_url: args.config.explorerBaseUrl } : {}),
33
+ ...(args.config.apiKey ? { api_key: args.config.apiKey } : {}),
34
+ created_at: new Date().toISOString(),
35
+ };
36
+ return writeJson(path, file, args.pretty ?? true);
37
+ }
38
+ /**
39
+ * Persist a pending executive keypair while the user funds it with
40
+ * SOL. Subsequent `leash_register_agent` calls (or a fresh MCP boot)
41
+ * will pick this up via `loadAgentSession().pending`. The block is
42
+ * cleared once `writeAgentConfig` lands the registered config.
43
+ */
44
+ export async function writePendingRegister(args) {
45
+ const path = args.path ?? defaultConfigPath();
46
+ const meta = args.pending.meta;
47
+ const metaJson = meta &&
48
+ (meta.name || meta.description || meta.imageUrl || (meta.services && meta.services.length > 0))
49
+ ? {
50
+ ...(meta.name ? { name: meta.name } : {}),
51
+ ...(meta.description ? { description: meta.description } : {}),
52
+ ...(meta.imageUrl ? { image_url: meta.imageUrl } : {}),
53
+ ...(meta.services && meta.services.length > 0 ? { services: meta.services } : {}),
54
+ }
55
+ : null;
56
+ const file = {
57
+ version: 1,
58
+ network: args.defaults.network,
59
+ api_url: args.defaults.apiBaseUrl,
60
+ rpc_url: args.defaults.rpcUrl,
61
+ ...(args.defaults.explorerBaseUrl ? { explorer_url: args.defaults.explorerBaseUrl } : {}),
62
+ ...(args.defaults.apiKey ? { api_key: args.defaults.apiKey } : {}),
63
+ pending_register: {
64
+ executive_keypair: args.pending.executiveSecretBase58,
65
+ executive_pubkey: args.pending.executivePubkey,
66
+ network: args.pending.network,
67
+ created_at: args.pending.createdAt,
68
+ ...(metaJson ? { meta: metaJson } : {}),
69
+ },
70
+ created_at: new Date().toISOString(),
71
+ };
72
+ return writeJson(path, file, args.pretty ?? true);
73
+ }
74
+ async function writeJson(path, payload, pretty) {
75
+ const body = pretty ? `${JSON.stringify(payload, null, 2)}\n` : JSON.stringify(payload);
76
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
77
+ await writeFile(path, body, { mode: 0o600 });
78
+ return path;
79
+ }
80
+ //# sourceMappingURL=config-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-write.js","sourceRoot":"","sources":["../src/config-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Local agent configuration for the standalone Leash MCP server.
3
+ *
4
+ * Source of truth is `~/.config/leash/agent.json` (chmod 600). Same
5
+ * posture as `gcloud`, `gh`, `aws`. Each field can be overridden via
6
+ * an environment variable, which makes the MCP CI/CD-friendly without
7
+ * needing a config file at all:
8
+ *
9
+ * - LEASH_AGENT_MINT → agent_mint
10
+ * - LEASH_EXECUTIVE_KEY → executive_keypair (base58 OR JSON array)
11
+ * - LEASH_NETWORK → network ('solana-mainnet' | 'solana-devnet'). Defaults to `solana-mainnet`.
12
+ * - LEASH_API_URL → apiBaseUrl
13
+ * - LEASH_RPC_URL → rpcUrl override (otherwise picked per network)
14
+ * - LEASH_EXPLORER_URL → explorerBaseUrl (default explorer.leash.market)
15
+ * - LEASH_API_KEY → bearer token for legacy API-key endpoints
16
+ * (X-Leash-Sig auth is the long-term path)
17
+ *
18
+ * Loading rules:
19
+ * 1. Read `agent.json` if it exists.
20
+ * 2. Apply env-var overrides on top.
21
+ * 3. The host always boots — `loadAgentSession` returns a `defaults`
22
+ * block (network/rpc/api/explorer) even when no agent is
23
+ * provisioned, so `leash_register_agent` can run before the file
24
+ * exists. `config` is `null` until a mint is recorded; `pending`
25
+ * is set when the user has chosen a keypair but not yet funded
26
+ * it (the gap between the two `leash_register_agent` calls).
27
+ */
28
+ import type { SvmNetwork } from '@leashmarket/mcp-core';
29
+ /** Always-available host defaults. Resolvable without any agent state. */
30
+ export type LeashHostDefaults = {
31
+ network: SvmNetwork;
32
+ apiBaseUrl: string;
33
+ rpcUrl: string;
34
+ explorerBaseUrl: string;
35
+ apiKey: string | null;
36
+ };
37
+ /**
38
+ * Pending-register agent metadata persisted alongside the unfunded
39
+ * executive. Captured on the FIRST `leash_register_agent` call so the
40
+ * SECOND call (after funding) doesn't need the LLM to re-collect
41
+ * `name` / `description` / `image_url` / `services[]`.
42
+ */
43
+ export type PendingRegisterMeta = {
44
+ name?: string;
45
+ description?: string;
46
+ imageUrl?: string;
47
+ services?: {
48
+ name: string;
49
+ endpoint: string;
50
+ }[];
51
+ };
52
+ /**
53
+ * Persisted-but-unfunded executive keypair + agent draft. Written to
54
+ * `agent.json` on the FIRST `leash_register_agent` call; consumed
55
+ * (and cleared) on the SECOND call after the user has funded the
56
+ * executive with SOL.
57
+ */
58
+ export type PendingRegister = {
59
+ /** 64-byte ed25519 secret, base58. */
60
+ executiveSecretBase58: string;
61
+ /** Cached pubkey so doctor / status checks don't need to re-derive. */
62
+ executivePubkey: string;
63
+ network: SvmNetwork;
64
+ createdAt: string;
65
+ /**
66
+ * Agent metadata captured on Step 1 so the LLM doesn't need to
67
+ * repeat `name` / `services` / etc. on Step 2.
68
+ */
69
+ meta?: PendingRegisterMeta;
70
+ };
71
+ export type LeashAgentConfig = {
72
+ agentMint: string;
73
+ /** Raw base58 secret (length 64-byte ed25519 keypair). */
74
+ executiveSecretBase58: string;
75
+ network: SvmNetwork;
76
+ /** Base URL of the Leash API the host should talk to. */
77
+ apiBaseUrl: string;
78
+ /** Solana RPC URL used for direct chain reads + tx submission. */
79
+ rpcUrl: string;
80
+ /**
81
+ * Base URL of the Leash protocol explorer used to build
82
+ * `receipt_url` / `agent_url` deep-links. Defaults to
83
+ * `https://explorer.leash.market`.
84
+ */
85
+ explorerBaseUrl: string;
86
+ /** Optional legacy API-key bearer token. Goes away once X-Leash-Sig auth is in. */
87
+ apiKey: string | null;
88
+ };
89
+ /** Snapshot returned by {@link loadAgentSession}. */
90
+ export type AgentSession = {
91
+ config: LeashAgentConfig | null;
92
+ pending: PendingRegister | null;
93
+ defaults: LeashHostDefaults;
94
+ };
95
+ export declare function defaultRpcFor(network: SvmNetwork): string;
96
+ /** Path searched for the on-disk config. Exposed for tests. */
97
+ export declare function defaultConfigPath(): string;
98
+ /**
99
+ * Resolve the host's full session snapshot. Always returns `defaults`
100
+ * (so the host can boot and `leash_register_agent` is callable);
101
+ * `config` and `pending` are present only when previously persisted.
102
+ */
103
+ export declare function loadAgentSession(opts?: {
104
+ path?: string;
105
+ }): AgentSession;
106
+ /**
107
+ * Backwards-compat shim — same return as the v0.1 build (config-only,
108
+ * `null` when no mint persisted). Used by the test suite and any
109
+ * external callers that imported it.
110
+ */
111
+ export declare function loadAgentConfig(opts?: {
112
+ path?: string;
113
+ }): LeashAgentConfig | null;
114
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,0EAA0E;AAC1E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,sCAAsC;IACtC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,UAAU,CAAC;IACpB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,qDAAqD;AACrD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAwBF,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAEzD;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAsGD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAqBvE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,GAAG,IAAI,CAEjF"}
package/dist/config.js ADDED
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Local agent configuration for the standalone Leash MCP server.
3
+ *
4
+ * Source of truth is `~/.config/leash/agent.json` (chmod 600). Same
5
+ * posture as `gcloud`, `gh`, `aws`. Each field can be overridden via
6
+ * an environment variable, which makes the MCP CI/CD-friendly without
7
+ * needing a config file at all:
8
+ *
9
+ * - LEASH_AGENT_MINT → agent_mint
10
+ * - LEASH_EXECUTIVE_KEY → executive_keypair (base58 OR JSON array)
11
+ * - LEASH_NETWORK → network ('solana-mainnet' | 'solana-devnet'). Defaults to `solana-mainnet`.
12
+ * - LEASH_API_URL → apiBaseUrl
13
+ * - LEASH_RPC_URL → rpcUrl override (otherwise picked per network)
14
+ * - LEASH_EXPLORER_URL → explorerBaseUrl (default explorer.leash.market)
15
+ * - LEASH_API_KEY → bearer token for legacy API-key endpoints
16
+ * (X-Leash-Sig auth is the long-term path)
17
+ *
18
+ * Loading rules:
19
+ * 1. Read `agent.json` if it exists.
20
+ * 2. Apply env-var overrides on top.
21
+ * 3. The host always boots — `loadAgentSession` returns a `defaults`
22
+ * block (network/rpc/api/explorer) even when no agent is
23
+ * provisioned, so `leash_register_agent` can run before the file
24
+ * exists. `config` is `null` until a mint is recorded; `pending`
25
+ * is set when the user has chosen a keypair but not yet funded
26
+ * it (the gap between the two `leash_register_agent` calls).
27
+ */
28
+ import { readFileSync } from 'node:fs';
29
+ import { homedir } from 'node:os';
30
+ import { join } from 'node:path';
31
+ const DEFAULT_API_URL = 'https://api.leash.market';
32
+ const DEFAULT_EXPLORER_URL = 'https://explorer.leash.market';
33
+ /**
34
+ * Public Solana RPC fallbacks. Used only when `LEASH_RPC_URL` and
35
+ * `agent.json:rpc_url` are both unset.
36
+ *
37
+ * **These are slow.** They are public, heavily rate-limited
38
+ * (429s under load), and add 4-8s of latency to every
39
+ * `leash_pay_payment_link` call (each settlement makes 3-5 RPC
40
+ * round-trips). Production users should set `LEASH_RPC_URL` (or
41
+ * persist `rpc_url` in `~/.config/leash/agent.json`) to a Helius /
42
+ * Triton / QuickNode / Alchemy / self-hosted endpoint — settlement
43
+ * latency drops to sub-second and 429s disappear.
44
+ *
45
+ * The MCP and CLI docs surface this in a "Bring your own RPC"
46
+ * callout; keep this comment in sync if those move.
47
+ */
48
+ const DEFAULT_RPC = {
49
+ 'solana-devnet': 'https://api.devnet.solana.com',
50
+ 'solana-mainnet': 'https://api.mainnet-beta.solana.com',
51
+ };
52
+ export function defaultRpcFor(network) {
53
+ return DEFAULT_RPC[network];
54
+ }
55
+ /** Path searched for the on-disk config. Exposed for tests. */
56
+ export function defaultConfigPath() {
57
+ return join(homedir(), '.config', 'leash', 'agent.json');
58
+ }
59
+ /**
60
+ * Best-effort read of the on-disk config. Missing or malformed files
61
+ * yield `null`; we never throw because the MCP must boot regardless
62
+ * (so `tools/list` works and the LLM can call onboarding tools).
63
+ */
64
+ function tryReadFile(path) {
65
+ try {
66
+ const raw = readFileSync(path, 'utf8');
67
+ const parsed = JSON.parse(raw);
68
+ return parsed && typeof parsed === 'object' ? parsed : null;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ function pick(envVal, fileVal) {
75
+ const e = envVal?.trim();
76
+ if (e && e.length > 0)
77
+ return e;
78
+ const f = fileVal?.trim();
79
+ if (f && f.length > 0)
80
+ return f;
81
+ return undefined;
82
+ }
83
+ function normalizeNetwork(raw) {
84
+ const lower = raw?.toLowerCase().trim();
85
+ if (lower === 'solana-devnet' || lower === 'devnet')
86
+ return 'solana-devnet';
87
+ return 'solana-mainnet';
88
+ }
89
+ function resolveDefaults(file) {
90
+ const network = normalizeNetwork(process.env.LEASH_NETWORK ?? file?.network);
91
+ const apiBaseUrl = pick(process.env.LEASH_API_URL, file?.api_url) ?? DEFAULT_API_URL;
92
+ const rpcUrl = pick(process.env.LEASH_RPC_URL, file?.rpc_url) ?? DEFAULT_RPC[network];
93
+ const explorerBaseUrl = pick(process.env.LEASH_EXPLORER_URL, file?.explorer_url) ?? DEFAULT_EXPLORER_URL;
94
+ const apiKey = pick(process.env.LEASH_API_KEY, file?.api_key) ?? null;
95
+ return { network, apiBaseUrl, rpcUrl, explorerBaseUrl, apiKey };
96
+ }
97
+ function readPending(file, defaults) {
98
+ const block = file?.pending_register;
99
+ if (!block)
100
+ return null;
101
+ const secret = block.executive_keypair?.trim();
102
+ const pub = block.executive_pubkey?.trim();
103
+ if (!secret || !pub)
104
+ return null;
105
+ const meta = readPendingMeta(block.meta);
106
+ return {
107
+ executiveSecretBase58: secret,
108
+ executivePubkey: pub,
109
+ network: normalizeNetwork(block.network ?? defaults.network),
110
+ createdAt: block.created_at ?? new Date(0).toISOString(),
111
+ ...(meta ? { meta } : {}),
112
+ };
113
+ }
114
+ function readPendingMeta(raw) {
115
+ if (!raw)
116
+ return undefined;
117
+ const services = (raw.services ?? [])
118
+ .map((s) => ({ name: (s.name ?? '').trim(), endpoint: (s.endpoint ?? '').trim() }))
119
+ .filter((s) => s.name.length > 0 && s.endpoint.length > 0);
120
+ const meta = {};
121
+ if (raw.name?.trim())
122
+ meta.name = raw.name.trim();
123
+ if (raw.description?.trim())
124
+ meta.description = raw.description.trim();
125
+ if (raw.image_url?.trim())
126
+ meta.imageUrl = raw.image_url.trim();
127
+ if (services.length > 0)
128
+ meta.services = services;
129
+ return Object.keys(meta).length > 0 ? meta : undefined;
130
+ }
131
+ /**
132
+ * Resolve the host's full session snapshot. Always returns `defaults`
133
+ * (so the host can boot and `leash_register_agent` is callable);
134
+ * `config` and `pending` are present only when previously persisted.
135
+ */
136
+ export function loadAgentSession(opts) {
137
+ const path = opts?.path ?? defaultConfigPath();
138
+ const file = tryReadFile(path);
139
+ const defaults = resolveDefaults(file);
140
+ const agentMint = pick(process.env.LEASH_AGENT_MINT, file?.agent_mint);
141
+ const executiveSecret = pick(process.env.LEASH_EXECUTIVE_KEY, file?.executive_keypair);
142
+ const config = agentMint && executiveSecret
143
+ ? {
144
+ agentMint,
145
+ executiveSecretBase58: executiveSecret,
146
+ network: defaults.network,
147
+ apiBaseUrl: defaults.apiBaseUrl,
148
+ rpcUrl: defaults.rpcUrl,
149
+ explorerBaseUrl: defaults.explorerBaseUrl,
150
+ apiKey: defaults.apiKey,
151
+ }
152
+ : null;
153
+ const pending = readPending(file, defaults);
154
+ return { config, pending, defaults };
155
+ }
156
+ /**
157
+ * Backwards-compat shim — same return as the v0.1 build (config-only,
158
+ * `null` when no mint persisted). Used by the test suite and any
159
+ * external callers that imported it.
160
+ */
161
+ export function loadAgentConfig(opts) {
162
+ return loadAgentSession(opts).config;
163
+ }
164
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `LeashHost` implementation for the standalone STDIO MCP / CLI.
3
+ *
4
+ * Differs from the chat product in two important ways:
5
+ *
6
+ * 1. **Settlement happens in-process.** `pay` and `withdraw` actually
7
+ * sign + submit on Solana using the local executive keypair —
8
+ * no UI in the loop. The result blob carries a real `tx_signature`,
9
+ * not a "review-the-card" artifact. This is the killer demo path.
10
+ *
11
+ * 2. **No platform DB / Privy session.** Off-chain calls to the
12
+ * Leash API authenticate via a legacy `LEASH_API_KEY` bearer
13
+ * token until the X-Leash-Sig auth path lands in batch 4.
14
+ *
15
+ * The four host methods all `try/catch` aggressively and return a
16
+ * structured `{ status: 'ok' | 'error' }` blob — never throw — so
17
+ * the LLM never sees a tool exception, only a recoverable JSON
18
+ * response with a `message` it can surface.
19
+ */
20
+ import { type LeashHost } from '@leashmarket/mcp-core';
21
+ import type { LeashAgentConfig } from './config.js';
22
+ /**
23
+ * Build the standalone `LeashHost`. Captures the `LeashAgentConfig`
24
+ * + `LeashSigner` once so per-call methods can stay tight.
25
+ */
26
+ export declare function createStdioHost(config: LeashAgentConfig): LeashHost;
27
+ //# sourceMappingURL=host-stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-stdio.d.ts","sourceRoot":"","sources":["../src/host-stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAaH,OAAO,EAgBL,KAAK,SAAS,EAYf,MAAM,uBAAuB,CAAC;AAa/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAgCpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAGnE"}