@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.
- package/README.md +157 -0
- package/dist/cli.d.ts +44 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +314 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-write.d.ts +38 -0
- package/dist/config-write.d.ts.map +1 -0
- package/dist/config-write.js +80 -0
- package/dist/config-write.js.map +1 -0
- package/dist/config.d.ts +114 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +164 -0
- package/dist/config.js.map +1 -0
- package/dist/host-stdio.d.ts +27 -0
- package/dist/host-stdio.d.ts.map +1 -0
- package/dist/host-stdio.js +1001 -0
- package/dist/host-stdio.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/mint-local.d.ts +128 -0
- package/dist/mint-local.d.ts.map +1 -0
- package/dist/mint-local.js +267 -0
- package/dist/mint-local.js.map +1 -0
- package/dist/sandbox-api.d.ts +56 -0
- package/dist/sandbox-api.d.ts.map +1 -0
- package/dist/sandbox-api.js +38 -0
- package/dist/sandbox-api.js.map +1 -0
- package/dist/server.d.ts +131 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +502 -0
- package/dist/server.js.map +1 -0
- package/dist/signer.d.ts +54 -0
- package/dist/signer.d.ts.map +1 -0
- package/dist/signer.js +102 -0
- package/dist/signer.js.map +1 -0
- package/package.json +55 -0
|
@@ -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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"}
|
package/dist/config.d.ts
ADDED
|
@@ -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"}
|