@toon-protocol/client-mcp 0.10.9 → 0.12.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/dist/app/index.html +86 -81
- package/dist/{chunk-CS4B3GET.js → chunk-74KX5LXI.js} +150 -21
- package/dist/chunk-74KX5LXI.js.map +1 -0
- package/dist/{chunk-X4GKWZQP.js → chunk-LN64MLWP.js} +66 -16
- package/dist/chunk-LN64MLWP.js.map +1 -0
- package/dist/{chunk-UHITXU5V.js → chunk-W6T6ZK7U.js} +66 -3
- package/dist/chunk-W6T6ZK7U.js.map +1 -0
- package/dist/daemon.js +2 -2
- package/dist/index.d.ts +82 -10
- package/dist/index.js +3 -3
- package/dist/mcp.js +3 -3
- package/dist/mcp.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-CS4B3GET.js.map +0 -1
- package/dist/chunk-UHITXU5V.js.map +0 -1
- package/dist/chunk-X4GKWZQP.js.map +0 -1
package/dist/daemon.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ClientRunner,
|
|
5
5
|
registerRoutes,
|
|
6
6
|
scaffoldFirstRun
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-74KX5LXI.js";
|
|
8
8
|
import {
|
|
9
9
|
ControlClient,
|
|
10
10
|
ToonClient,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveConfig,
|
|
18
18
|
spawnDaemonDetached,
|
|
19
19
|
waitForReady
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-W6T6ZK7U.js";
|
|
21
21
|
import "./chunk-32QD72IL.js";
|
|
22
22
|
import "./chunk-DLYE6U2Z.js";
|
|
23
23
|
import "./chunk-LR7W2ISE.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NostrEvent, EventTemplate } from 'nostr-tools/pure';
|
|
2
2
|
import { SwapPair } from '@toon-protocol/core';
|
|
3
|
-
import { ToonClientConfig } from '@toon-protocol/client';
|
|
3
|
+
import { ToonClientConfig, FaucetChain } from '@toon-protocol/client';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
5
|
import { ViewSpec } from '@toon-protocol/views';
|
|
6
6
|
|
|
@@ -453,16 +453,42 @@ interface FundWalletRequest {
|
|
|
453
453
|
/** Address to fund (default: this client's own address for `chain`). */
|
|
454
454
|
address?: string;
|
|
455
455
|
}
|
|
456
|
-
/**
|
|
456
|
+
/**
|
|
457
|
+
* `POST /fund-wallet` result — a snapshot of an ASYNC faucet drip job.
|
|
458
|
+
*
|
|
459
|
+
* The drip is non-blocking: `POST /fund-wallet` launches the faucet call in the
|
|
460
|
+
* daemon background and returns immediately with `status: 'pending'`. This avoids
|
|
461
|
+
* the MCP host's ~60s tool-call timeout surfacing a still-working Mina drip
|
|
462
|
+
* (which legitimately settles in ~75s, native MINA + USDC) as a misleading
|
|
463
|
+
* relay/apex timeout (#199-class). Poll `GET /fund-wallet/status` (or just
|
|
464
|
+
* re-read balances) to observe the terminal `'success'` / `'error'` state.
|
|
465
|
+
*/
|
|
457
466
|
interface FundWalletResponse {
|
|
458
|
-
/** The chain
|
|
467
|
+
/** The chain being funded. */
|
|
459
468
|
chain: SettlementChain;
|
|
460
|
-
/** The address
|
|
469
|
+
/** The address being funded. */
|
|
461
470
|
address: string;
|
|
462
471
|
/** The faucet base URL the drip was requested from. */
|
|
463
472
|
faucetUrl: string;
|
|
464
|
-
/**
|
|
465
|
-
|
|
473
|
+
/**
|
|
474
|
+
* Lifecycle of the background drip. `'timeout'` is distinct from `'error'`:
|
|
475
|
+
* the faucet client gave up but the on-chain drip MAY still have settled
|
|
476
|
+
* (observed on a loaded EVM faucet) — treat it as "uncertain, re-check
|
|
477
|
+
* balances", not a definitive failure, to avoid a misleading double-fund.
|
|
478
|
+
*/
|
|
479
|
+
status: 'pending' | 'success' | 'error' | 'timeout';
|
|
480
|
+
/** Unix ms the drip was submitted. */
|
|
481
|
+
startedAt: number;
|
|
482
|
+
/** Unix ms the drip settled or failed (absent while `'pending'`). */
|
|
483
|
+
finishedAt?: number;
|
|
484
|
+
/** Raw parsed JSON body from the faucet on success (shape is faucet-defined). */
|
|
485
|
+
response?: unknown;
|
|
486
|
+
/** Error message on failure. */
|
|
487
|
+
error?: string;
|
|
488
|
+
}
|
|
489
|
+
/** `GET /fund-wallet/status` result — snapshots of tracked drip jobs. */
|
|
490
|
+
interface FundStatusResponse {
|
|
491
|
+
jobs: FundWalletResponse[];
|
|
466
492
|
}
|
|
467
493
|
/** Uniform error envelope returned with non-2xx responses. */
|
|
468
494
|
interface ErrorResponse {
|
|
@@ -543,6 +569,7 @@ declare class ControlClient {
|
|
|
543
569
|
addApex(body: AddApexRequest): Promise<AddApexResponse>;
|
|
544
570
|
removeApex(body: RemoveApexRequest): Promise<TargetsResponse>;
|
|
545
571
|
fundWallet(body?: FundWalletRequest): Promise<FundWalletResponse>;
|
|
572
|
+
fundStatus(chain?: SettlementChain): Promise<FundStatusResponse>;
|
|
546
573
|
/**
|
|
547
574
|
* Whether an HTTP method is safe to transparently retry. Idempotent reads
|
|
548
575
|
* (GET) and deletes can be replayed verbatim; a mutating POST cannot — the
|
|
@@ -979,6 +1006,15 @@ interface ToonClientLike {
|
|
|
979
1006
|
}>;
|
|
980
1007
|
getChannelCloseState(channelId: string): 'open' | 'closing' | 'settleable' | 'settled';
|
|
981
1008
|
getSettleableAt(channelId: string): bigint | undefined;
|
|
1009
|
+
/**
|
|
1010
|
+
* Re-read a resumed channel's on-chain deposit (persisted state omits it).
|
|
1011
|
+
* Optional so lightweight fakes need not implement it; the real ToonClient
|
|
1012
|
+
* does. Best-effort — callers await + catch.
|
|
1013
|
+
*/
|
|
1014
|
+
rehydrateChannelDeposit?(channelId: string, opts: {
|
|
1015
|
+
chain: string;
|
|
1016
|
+
tokenNetworkAddress: string;
|
|
1017
|
+
}): Promise<bigint | undefined>;
|
|
982
1018
|
sendSwapPacket(params: {
|
|
983
1019
|
destination: string;
|
|
984
1020
|
amount: bigint;
|
|
@@ -1028,11 +1064,29 @@ declare class ClientRunner {
|
|
|
1028
1064
|
private readonly createRelay;
|
|
1029
1065
|
private readonly log;
|
|
1030
1066
|
private readonly targetsPath?;
|
|
1067
|
+
/**
|
|
1068
|
+
* Identity-level chain-read client. Reading your OWN on-chain wallet balance is
|
|
1069
|
+
* a pure (wallet keys + chain RPC) operation that has nothing to do with the
|
|
1070
|
+
* ILP/payment peer, so it lives at the daemon level rather than inside an apex.
|
|
1071
|
+
* Built once from the daemon's own `toonClientConfig` (the same keys + chain
|
|
1072
|
+
* RPC config every apex shares) and REUSED as the default apex's client, so a
|
|
1073
|
+
* funded apex's `start()` (which derives Solana/Mina keys) also benefits this
|
|
1074
|
+
* reader. `getBalances` uses it directly, so balances work even with zero
|
|
1075
|
+
* apexes registered (follow-up to #199/#200).
|
|
1076
|
+
*/
|
|
1077
|
+
private readonly identityClient;
|
|
1031
1078
|
private readonly startedAt;
|
|
1032
1079
|
/** Apex write targets, keyed by btpUrl. */
|
|
1033
1080
|
private readonly apexes;
|
|
1034
1081
|
/** Relay read targets, keyed by relayUrl. */
|
|
1035
1082
|
private readonly relays;
|
|
1083
|
+
/**
|
|
1084
|
+
* Async faucet drip jobs, keyed by chain. A drip is launched in the background
|
|
1085
|
+
* (the Mina faucet legitimately takes ~75s — longer than the MCP host's ~60s
|
|
1086
|
+
* tool-call budget) and its terminal state is observed via {@link getFundStatus}
|
|
1087
|
+
* / re-reading balances rather than by blocking the caller.
|
|
1088
|
+
*/
|
|
1089
|
+
private readonly fundJobs;
|
|
1036
1090
|
/** Runner-level merged read buffer across all relays (de-duped by event.id). */
|
|
1037
1091
|
private merged;
|
|
1038
1092
|
private readonly mergedSeen;
|
|
@@ -1145,7 +1199,13 @@ declare class ClientRunner {
|
|
|
1145
1199
|
* (the typical "fund me before I open a channel" flow). The daemon holds the
|
|
1146
1200
|
* faucet URL + the keys, so the MCP caller never needs either.
|
|
1147
1201
|
*/
|
|
1148
|
-
fundWallet(req?: FundWalletRequest):
|
|
1202
|
+
fundWallet(req?: FundWalletRequest): FundWalletResponse;
|
|
1203
|
+
/**
|
|
1204
|
+
* Snapshots of tracked faucet drip jobs — all of them, or just the one for
|
|
1205
|
+
* `chain`. Lets a caller poll for the terminal state of an async drip without
|
|
1206
|
+
* re-dripping.
|
|
1207
|
+
*/
|
|
1208
|
+
getFundStatus(chain?: FaucetChain): FundStatusResponse;
|
|
1149
1209
|
/** Full registry of relay + apex targets with per-target status. */
|
|
1150
1210
|
getTargets(): TargetsResponse;
|
|
1151
1211
|
/** Pay-to-write a single event through the selected (or default) apex. */
|
|
@@ -1190,8 +1250,20 @@ declare class ClientRunner {
|
|
|
1190
1250
|
getChannels(): ChannelsResponse;
|
|
1191
1251
|
/**
|
|
1192
1252
|
* On-chain wallet balances. The wallet is identity-level (same keys across
|
|
1193
|
-
* apexes), so
|
|
1194
|
-
*
|
|
1253
|
+
* apexes), so this reads from the daemon's {@link identityClient} — NOT an apex
|
|
1254
|
+
* — and therefore works even with zero apexes / no payment peer configured
|
|
1255
|
+
* (reading your own balance is a pure wallet-keys + chain-RPC operation).
|
|
1256
|
+
* Per-chain reads are best-effort inside the client (a failing chain is simply
|
|
1257
|
+
* omitted).
|
|
1258
|
+
*
|
|
1259
|
+
* Each underlying read hits per-chain RPC providers that can stall
|
|
1260
|
+
* indefinitely on devnet (a provider being `detail: "configured"` in
|
|
1261
|
+
* toon_status means it is WIRED, not that its RPC is live). A stall here used
|
|
1262
|
+
* to block the whole control request until the client aborted, surfacing as a
|
|
1263
|
+
* misleading "relay/apex unreachable" timeout (#199). Bound each attempt well
|
|
1264
|
+
* under the control-plane timeout and retry once so a single transient
|
|
1265
|
+
* provider stall FAST-FAILS with an honest "balances handler / provider
|
|
1266
|
+
* stalled" error instead of hanging.
|
|
1195
1267
|
*/
|
|
1196
1268
|
getBalances(): Promise<BalancesResponse>;
|
|
1197
1269
|
/**
|
|
@@ -1402,4 +1474,4 @@ interface JourneyResult {
|
|
|
1402
1474
|
*/
|
|
1403
1475
|
declare function runJourney(plan: JourneyPlan, client: ControlClient): Promise<JourneyResult>;
|
|
1404
1476
|
|
|
1405
|
-
export { type AddApexRequest, type AddApexResponse, type AddRelayRequest, type ApexNegotiationConfig, type ApexTargetStatus, type BalanceInfo, type BalancesResponse, type ChainStatus, type ChannelDepositRequest, type ChannelDepositResponse, type ChannelInfo, type ChannelsResponse, ClientRunner, type ClientRunnerDeps, type CloseChannelRequest, type CloseChannelResponse, ControlApiError, ControlClient, type ControlClientOptions, DEFAULT_KEYSTORE_PASSWORD, type DaemonConfigFile, DaemonUnreachableError, type DrainResult, type ErrorResponse, type EventsQuery, type EventsResponse, type FundWalletRequest, type FundWalletResponse, type HttpFetchPaidRequest, type HttpFetchPaidResponse, type JourneyPlan, type JourneyResult, type JourneyState, type JourneyStep, type JourneyStepResult, type MinimalWebSocket, type NostrFilter, NotReadyError, type OpenChannelRequest, PublishRejectedError, type PublishRequest, type PublishResponse, type PublishUnsignedRequest, type QueryRequest, type QueryResponse, RelaySubscription, type RelaySubscriptionOptions, type RelayTargetStatus, type RemoveApexRequest, type RemoveRelayRequest, type ResolvedDaemonConfig, type SettleChannelRequest, type SettleChannelResponse, type SettlementChain, type StatusResponse, type SubscribeRequest, type SubscribeResponse, type SwapClaim, type SwapRequest, type SwapResponse, TOOL_DEFINITIONS, type TargetsResponse, type ToolDefinition, type ToolResult, type ToonClientLike, type UploadMediaRequest, type UploadMediaResponse, type WebSocketFactory, acquireLock, configDir, defaultConfigPath, defaultKeystorePath, dispatchTool, hasConfiguredIdentity, isDaemonRunning, isProcessAlive, readConfigFile, readPid, registerRoutes, releaseLock, resolveConfig, resolveMnemonic, runJourney, scaffoldFirstRun, spawnDaemonDetached, waitForReady };
|
|
1477
|
+
export { type AddApexRequest, type AddApexResponse, type AddRelayRequest, type ApexNegotiationConfig, type ApexTargetStatus, type BalanceInfo, type BalancesResponse, type ChainStatus, type ChannelDepositRequest, type ChannelDepositResponse, type ChannelInfo, type ChannelsResponse, ClientRunner, type ClientRunnerDeps, type CloseChannelRequest, type CloseChannelResponse, ControlApiError, ControlClient, type ControlClientOptions, DEFAULT_KEYSTORE_PASSWORD, type DaemonConfigFile, DaemonUnreachableError, type DrainResult, type ErrorResponse, type EventsQuery, type EventsResponse, type FundStatusResponse, type FundWalletRequest, type FundWalletResponse, type HttpFetchPaidRequest, type HttpFetchPaidResponse, type JourneyPlan, type JourneyResult, type JourneyState, type JourneyStep, type JourneyStepResult, type MinimalWebSocket, type NostrFilter, NotReadyError, type OpenChannelRequest, PublishRejectedError, type PublishRequest, type PublishResponse, type PublishUnsignedRequest, type QueryRequest, type QueryResponse, RelaySubscription, type RelaySubscriptionOptions, type RelayTargetStatus, type RemoveApexRequest, type RemoveRelayRequest, type ResolvedDaemonConfig, type SettleChannelRequest, type SettleChannelResponse, type SettlementChain, type StatusResponse, type SubscribeRequest, type SubscribeResponse, type SwapClaim, type SwapRequest, type SwapResponse, TOOL_DEFINITIONS, type TargetsResponse, type ToolDefinition, type ToolResult, type ToonClientLike, type UploadMediaRequest, type UploadMediaResponse, type WebSocketFactory, acquireLock, configDir, defaultConfigPath, defaultKeystorePath, dispatchTool, hasConfiguredIdentity, isDaemonRunning, isProcessAlive, readConfigFile, readPid, registerRoutes, releaseLock, resolveConfig, resolveMnemonic, runJourney, scaffoldFirstRun, spawnDaemonDetached, waitForReady };
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
hasConfiguredIdentity,
|
|
9
9
|
registerRoutes,
|
|
10
10
|
scaffoldFirstRun
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-74KX5LXI.js";
|
|
12
12
|
import {
|
|
13
13
|
PUBLISH_TOOL,
|
|
14
14
|
TOOL_DEFINITIONS,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
buildFollowListFilter,
|
|
19
19
|
buildProfileFilter,
|
|
20
20
|
dispatchTool
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-LN64MLWP.js";
|
|
22
22
|
import {
|
|
23
23
|
ControlApiError,
|
|
24
24
|
ControlClient,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
resolveMnemonic,
|
|
37
37
|
spawnDaemonDetached,
|
|
38
38
|
waitForReady
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-W6T6ZK7U.js";
|
|
40
40
|
import "./chunk-32QD72IL.js";
|
|
41
41
|
import "./chunk-DLYE6U2Z.js";
|
|
42
42
|
import "./chunk-LR7W2ISE.js";
|
package/dist/mcp.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
APP_RESOURCE_URI,
|
|
5
5
|
TOOL_DEFINITIONS,
|
|
6
6
|
dispatchTool
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LN64MLWP.js";
|
|
8
8
|
import {
|
|
9
9
|
ARWEAVE_GATEWAYS,
|
|
10
10
|
ControlClient,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readConfigFile,
|
|
14
14
|
spawnDaemonDetached,
|
|
15
15
|
waitForReady
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-W6T6ZK7U.js";
|
|
17
17
|
import "./chunk-32QD72IL.js";
|
|
18
18
|
import "./chunk-DLYE6U2Z.js";
|
|
19
19
|
import "./chunk-LR7W2ISE.js";
|
|
@@ -84,7 +84,7 @@ async function main() {
|
|
|
84
84
|
// Travels to EVERY host in the `initialize` result (incl. claude.ai chat,
|
|
85
85
|
// which never loads the Claude Code skill). Keep the render-first policy
|
|
86
86
|
// here so it governs all surfaces, not just Claude Code.
|
|
87
|
-
instructions: 'TOON is pay-to-write Nostr over Interledger; reads are free, writes are paid. RENDERING IS THE DEFAULT SURFACE: when the user asks to see/show/open/view/browse/render TOON events, profiles, feeds, threads, channels, or balances, call toon_atoms then toon_render (ui://toon/app) \u2014 do NOT route TOON data to a generic HTML/SVG/chart/widget tool or dump it as text. Always call toon_atoms before toon_render. On ANY intent to upload media or post/publish a picture/video/image (e.g. "I want to upload", "publish an image", "post a photo"), your FIRST action is toon_atoms then toon_render with the media view (media-uploader atom). The uploader has an in-app FILE PICKER, so do NOT ask whether a file is attached, where the image is, or for a URL, and do NOT recount upload-path history or known issues \u2014 just render the uploader and let the user pick a file. Writes (post/like/follow/upload/swap) spend a payment-channel claim; surface the fee and confirm before paying. Fall back to text only on explicit request or render failure.'
|
|
87
|
+
instructions: 'TOON is pay-to-write Nostr over Interledger; reads are free, writes are paid. RENDERING IS THE DEFAULT SURFACE: when the user asks to see/show/open/view/browse/render TOON events, profiles, feeds, threads, channels, or balances, call toon_atoms then toon_render (ui://toon/app) \u2014 do NOT route TOON data to a generic HTML/SVG/chart/widget tool or dump it as text. Always call toon_atoms before toon_render. The rendered card IS the response: for read-only views (feeds, profiles, threads, channels, balances, wallet) go STRAIGHT toon_atoms \u2192 toon_render \u2014 do NOT precede a render with daemon-health (toon_status), identity (toon_identity), or balance preflight, and do NOT narrate the tool calls or write a status report; at most a one-line caption after. On ANY intent to upload media or post/publish a picture/video/image (e.g. "I want to upload", "publish an image", "post a photo"), your FIRST action is toon_atoms then toon_render with the media view (media-uploader atom). The uploader has an in-app FILE PICKER, so do NOT ask whether a file is attached, where the image is, or for a URL, and do NOT recount upload-path history or known issues \u2014 just render the uploader and let the user pick a file. Writes (post/like/follow/upload/swap) spend a payment-channel claim; surface the fee and confirm before paying. Fall back to text only on explicit request or render failure.'
|
|
88
88
|
}
|
|
89
89
|
);
|
|
90
90
|
const appHtml = loadAppHtml();
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `toon-mcp` — a thin MCP stdio server exposing the TOON client to a Claude\n * agent (Desktop or Code). It holds NO chain keys and NO long-lived\n * connections: every tool maps to an HTTP call against the always-on\n * `toon-clientd` daemon, which it auto-spawns (detached) if it is not running.\n *\n * Works on both surfaces:\n * • Claude Desktop — `claude_desktop_config.json` mcpServers entry.\n * • Claude Code — `claude mcp add toon -- toon-mcp` (or `.mcp.json`).\n */\n\nimport { createRequire } from 'node:module';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n type CallToolResult,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { APP_RESOURCE_URI } from '@toon-protocol/views';\nimport { ARWEAVE_GATEWAYS } from '@toon-protocol/arweave';\nimport { ControlClient } from './control-client.js';\nimport { dispatchTool, TOOL_DEFINITIONS } from './mcp-tools.js';\n\n/** MIME marking the bundle as an MCP-app UI resource (ext-apps profile). */\nconst APP_MIME = 'text/html;profile=mcp-app';\n\n/** Load the prebuilt single-file MCP-app bundle served as `ui://toon/app`. */\nfunction loadAppHtml(): string {\n // 1. Prefer the copy shipped next to the built server (tsup onSuccess copies\n // it into dist/app). This is what a published client-mcp serves — no\n // dependency on the unpublished @toon-protocol/views package at runtime.\n try {\n return readFileSync(new URL('./app/index.html', import.meta.url), 'utf8');\n } catch {\n /* running from source / not yet copied — fall through to the dev resolve */\n }\n // 2. Dev fallback: resolve the bundle from the @toon-protocol/views workspace.\n try {\n const req = createRequire(import.meta.url);\n const entry = req.resolve('@toon-protocol/views'); // …/views/dist/index.js\n return readFileSync(join(dirname(entry), 'app', 'index.html'), 'utf8');\n } catch {\n return '<!doctype html><html><body><div id=\"root\">toon app bundle missing — run `pnpm --filter @toon-protocol/views build`</div></body></html>';\n }\n}\nimport { defaultConfigPath, readConfigFile } from './daemon/config.js';\nimport {\n isDaemonRunning,\n spawnDaemonDetached,\n waitForReady,\n} from './daemon/lifecycle.js';\n\n/** stdout carries the MCP protocol — all logging must go to stderr. */\nfunction log(msg: string): void {\n console.error(`[toon-mcp] ${msg}`);\n}\n\n/** Resolve the daemon control-plane URL without needing the mnemonic. */\nfunction controlPlaneUrl(): string {\n const file = readConfigFile(\n process.env['TOON_CLIENT_CONFIG'] ?? defaultConfigPath()\n );\n const port = Number(\n process.env['TOON_CLIENT_HTTP_PORT'] ?? file.httpPort ?? 8787\n );\n return `http://127.0.0.1:${port}`;\n}\n\n/**\n * Make sure the daemon is up: if the lock shows it running, return; otherwise\n * spawn it detached and wait until the control plane is reachable. Best-effort\n * — failures surface as readable tool errors rather than crashing the server.\n */\nasync function ensureDaemon(url: string): Promise<void> {\n if (isDaemonRunning()) return;\n const client = new ControlClient({ baseUrl: url });\n if (await client.ping()) return;\n log('daemon not running — spawning detached');\n try {\n const pid = spawnDaemonDetached();\n log(`spawned toon-clientd (pid ${pid}); waiting for control plane`);\n await waitForReady(url, 20_000);\n } catch (err) {\n log(\n `failed to spawn daemon: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n}\n\nasync function main(): Promise<void> {\n const url = controlPlaneUrl();\n const control = new ControlClient({ baseUrl: url });\n\n // Kick off daemon startup; don't block server init on it (BTP bootstrap can\n // take a moment). Tools report \"bootstrapping — retry\" until it is ready.\n void ensureDaemon(url);\n\n const server = new Server(\n { name: 'toon-client', version: '0.1.0' },\n {\n capabilities: { tools: {}, resources: {} },\n // Travels to EVERY host in the `initialize` result (incl. claude.ai chat,\n // which never loads the Claude Code skill). Keep the render-first policy\n // here so it governs all surfaces, not just Claude Code.\n instructions:\n 'TOON is pay-to-write Nostr over Interledger; reads are free, writes ' +\n 'are paid. RENDERING IS THE DEFAULT SURFACE: when the user asks to ' +\n 'see/show/open/view/browse/render TOON events, profiles, feeds, ' +\n 'threads, channels, or balances, call toon_atoms then toon_render ' +\n '(ui://toon/app) — do NOT route TOON data to a generic ' +\n 'HTML/SVG/chart/widget tool or dump it as text. Always call toon_atoms ' +\n 'before toon_render. On ANY intent to upload media or post/publish a ' +\n 'picture/video/image (e.g. \"I want to upload\", \"publish an image\", ' +\n '\"post a photo\"), your FIRST action is toon_atoms then toon_render with ' +\n 'the media view (media-uploader atom). The uploader has an in-app FILE ' +\n 'PICKER, so do NOT ask whether a file is attached, where the image is, ' +\n 'or for a URL, and do NOT recount upload-path history or known issues — ' +\n 'just render the uploader and let the user pick a file. Writes ' +\n '(post/like/follow/upload/swap) spend a ' +\n 'payment-channel claim; surface the fee and confirm before paying. ' +\n 'Fall back to text only on explicit request or render failure.',\n }\n );\n\n const appHtml = loadAppHtml();\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOL_DEFINITIONS,\n }));\n\n // The MCP-app UI resource the host renders for toon_render results.\n //\n // CSP: the rendered feed/uploader shows media stored on Arweave. Without an\n // explicit `resourceDomains`, the host iframe's default `img-src`/`media-src`\n // blocks those gateways and images never load (toon-client#127). Advertise the\n // Arweave gateways as both resource (img/media/static) and connect origins.\n // Per the ext-apps spec the host reads `_meta.ui.csp` from the `resources/read`\n // content item, with the `resources/list` entry as fallback — so set it on both.\n //\n // CRUCIAL: ar.io / arweave.net gateways serve a 302 from the apex\n // (`https://arweave.net/<txId>`) to a per-tx SANDBOX SUBDOMAIN\n // (`https://<base32>.arweave.net/<txId>`). CSP `img-src` is checked against the\n // REDIRECT TARGET, so an apex-only allowlist still blocks the image. Allow both\n // the apex (initial request) and a wildcard subdomain (where the bytes load).\n const arweaveCspDomains = ARWEAVE_GATEWAYS.flatMap((gateway) => {\n try {\n const host = new URL(gateway).host;\n return [gateway, `https://*.${host}`];\n } catch {\n return [gateway];\n }\n });\n const APP_CSP = {\n csp: {\n resourceDomains: arweaveCspDomains,\n connectDomains: arweaveCspDomains,\n },\n };\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: [\n { uri: APP_RESOURCE_URI, name: 'TOON', mimeType: APP_MIME, _meta: { ui: APP_CSP } },\n ],\n }));\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n if (request.params.uri !== APP_RESOURCE_URI) {\n throw new Error(`Unknown resource: ${request.params.uri}`);\n }\n return {\n contents: [\n { uri: APP_RESOURCE_URI, mimeType: APP_MIME, text: appHtml, _meta: { ui: APP_CSP } },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const name = request.params.name;\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n // If the daemon went away, try once to bring it back before dispatching.\n if (!(await control.ping())) await ensureDaemon(url);\n // Our ToolResult is a structural subset of CallToolResult (content + isError);\n // the SDK's handler union also carries a task-augmented variant we never use.\n return (await dispatchTool(control, name, args)) as CallToolResult;\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n log(`ready; proxying to ${url}`);\n}\n\nmain().catch((err) => {\n log(err instanceof Error ? (err.stack ?? err.message) : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `toon-mcp` — a thin MCP stdio server exposing the TOON client to a Claude\n * agent (Desktop or Code). It holds NO chain keys and NO long-lived\n * connections: every tool maps to an HTTP call against the always-on\n * `toon-clientd` daemon, which it auto-spawns (detached) if it is not running.\n *\n * Works on both surfaces:\n * • Claude Desktop — `claude_desktop_config.json` mcpServers entry.\n * • Claude Code — `claude mcp add toon -- toon-mcp` (or `.mcp.json`).\n */\n\nimport { createRequire } from 'node:module';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n type CallToolResult,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { APP_RESOURCE_URI } from '@toon-protocol/views';\nimport { ARWEAVE_GATEWAYS } from '@toon-protocol/arweave';\nimport { ControlClient } from './control-client.js';\nimport { dispatchTool, TOOL_DEFINITIONS } from './mcp-tools.js';\n\n/** MIME marking the bundle as an MCP-app UI resource (ext-apps profile). */\nconst APP_MIME = 'text/html;profile=mcp-app';\n\n/** Load the prebuilt single-file MCP-app bundle served as `ui://toon/app`. */\nfunction loadAppHtml(): string {\n // 1. Prefer the copy shipped next to the built server (tsup onSuccess copies\n // it into dist/app). This is what a published client-mcp serves — no\n // dependency on the unpublished @toon-protocol/views package at runtime.\n try {\n return readFileSync(new URL('./app/index.html', import.meta.url), 'utf8');\n } catch {\n /* running from source / not yet copied — fall through to the dev resolve */\n }\n // 2. Dev fallback: resolve the bundle from the @toon-protocol/views workspace.\n try {\n const req = createRequire(import.meta.url);\n const entry = req.resolve('@toon-protocol/views'); // …/views/dist/index.js\n return readFileSync(join(dirname(entry), 'app', 'index.html'), 'utf8');\n } catch {\n return '<!doctype html><html><body><div id=\"root\">toon app bundle missing — run `pnpm --filter @toon-protocol/views build`</div></body></html>';\n }\n}\nimport { defaultConfigPath, readConfigFile } from './daemon/config.js';\nimport {\n isDaemonRunning,\n spawnDaemonDetached,\n waitForReady,\n} from './daemon/lifecycle.js';\n\n/** stdout carries the MCP protocol — all logging must go to stderr. */\nfunction log(msg: string): void {\n console.error(`[toon-mcp] ${msg}`);\n}\n\n/** Resolve the daemon control-plane URL without needing the mnemonic. */\nfunction controlPlaneUrl(): string {\n const file = readConfigFile(\n process.env['TOON_CLIENT_CONFIG'] ?? defaultConfigPath()\n );\n const port = Number(\n process.env['TOON_CLIENT_HTTP_PORT'] ?? file.httpPort ?? 8787\n );\n return `http://127.0.0.1:${port}`;\n}\n\n/**\n * Make sure the daemon is up: if the lock shows it running, return; otherwise\n * spawn it detached and wait until the control plane is reachable. Best-effort\n * — failures surface as readable tool errors rather than crashing the server.\n */\nasync function ensureDaemon(url: string): Promise<void> {\n if (isDaemonRunning()) return;\n const client = new ControlClient({ baseUrl: url });\n if (await client.ping()) return;\n log('daemon not running — spawning detached');\n try {\n const pid = spawnDaemonDetached();\n log(`spawned toon-clientd (pid ${pid}); waiting for control plane`);\n await waitForReady(url, 20_000);\n } catch (err) {\n log(\n `failed to spawn daemon: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n}\n\nasync function main(): Promise<void> {\n const url = controlPlaneUrl();\n const control = new ControlClient({ baseUrl: url });\n\n // Kick off daemon startup; don't block server init on it (BTP bootstrap can\n // take a moment). Tools report \"bootstrapping — retry\" until it is ready.\n void ensureDaemon(url);\n\n const server = new Server(\n { name: 'toon-client', version: '0.1.0' },\n {\n capabilities: { tools: {}, resources: {} },\n // Travels to EVERY host in the `initialize` result (incl. claude.ai chat,\n // which never loads the Claude Code skill). Keep the render-first policy\n // here so it governs all surfaces, not just Claude Code.\n instructions:\n 'TOON is pay-to-write Nostr over Interledger; reads are free, writes ' +\n 'are paid. RENDERING IS THE DEFAULT SURFACE: when the user asks to ' +\n 'see/show/open/view/browse/render TOON events, profiles, feeds, ' +\n 'threads, channels, or balances, call toon_atoms then toon_render ' +\n '(ui://toon/app) — do NOT route TOON data to a generic ' +\n 'HTML/SVG/chart/widget tool or dump it as text. Always call toon_atoms ' +\n 'before toon_render. The rendered card IS the response: for read-only ' +\n 'views (feeds, profiles, threads, channels, balances, wallet) go ' +\n 'STRAIGHT toon_atoms → toon_render — do NOT precede a render with ' +\n 'daemon-health (toon_status), identity (toon_identity), or balance ' +\n 'preflight, and do NOT narrate the tool calls or write a status ' +\n 'report; at most a one-line caption after. On ANY intent to upload ' +\n 'media or post/publish a ' +\n 'picture/video/image (e.g. \"I want to upload\", \"publish an image\", ' +\n '\"post a photo\"), your FIRST action is toon_atoms then toon_render with ' +\n 'the media view (media-uploader atom). The uploader has an in-app FILE ' +\n 'PICKER, so do NOT ask whether a file is attached, where the image is, ' +\n 'or for a URL, and do NOT recount upload-path history or known issues — ' +\n 'just render the uploader and let the user pick a file. Writes ' +\n '(post/like/follow/upload/swap) spend a ' +\n 'payment-channel claim; surface the fee and confirm before paying. ' +\n 'Fall back to text only on explicit request or render failure.',\n }\n );\n\n const appHtml = loadAppHtml();\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: TOOL_DEFINITIONS,\n }));\n\n // The MCP-app UI resource the host renders for toon_render results.\n //\n // CSP: the rendered feed/uploader shows media stored on Arweave. Without an\n // explicit `resourceDomains`, the host iframe's default `img-src`/`media-src`\n // blocks those gateways and images never load (toon-client#127). Advertise the\n // Arweave gateways as both resource (img/media/static) and connect origins.\n // Per the ext-apps spec the host reads `_meta.ui.csp` from the `resources/read`\n // content item, with the `resources/list` entry as fallback — so set it on both.\n //\n // CRUCIAL: ar.io / arweave.net gateways serve a 302 from the apex\n // (`https://arweave.net/<txId>`) to a per-tx SANDBOX SUBDOMAIN\n // (`https://<base32>.arweave.net/<txId>`). CSP `img-src` is checked against the\n // REDIRECT TARGET, so an apex-only allowlist still blocks the image. Allow both\n // the apex (initial request) and a wildcard subdomain (where the bytes load).\n const arweaveCspDomains = ARWEAVE_GATEWAYS.flatMap((gateway) => {\n try {\n const host = new URL(gateway).host;\n return [gateway, `https://*.${host}`];\n } catch {\n return [gateway];\n }\n });\n const APP_CSP = {\n csp: {\n resourceDomains: arweaveCspDomains,\n connectDomains: arweaveCspDomains,\n },\n };\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: [\n { uri: APP_RESOURCE_URI, name: 'TOON', mimeType: APP_MIME, _meta: { ui: APP_CSP } },\n ],\n }));\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n if (request.params.uri !== APP_RESOURCE_URI) {\n throw new Error(`Unknown resource: ${request.params.uri}`);\n }\n return {\n contents: [\n { uri: APP_RESOURCE_URI, mimeType: APP_MIME, text: appHtml, _meta: { ui: APP_CSP } },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const name = request.params.name;\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n // If the daemon went away, try once to bring it back before dispatching.\n if (!(await control.ping())) await ensureDaemon(url);\n // Our ToolResult is a structural subset of CallToolResult (content + isError);\n // the SDK's handler union also carries a task-augmented variant we never use.\n return (await dispatchTool(control, name, args)) as CallToolResult;\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n log(`ready; proxying to ${url}`);\n}\n\nmain().catch((err) => {\n log(err instanceof Error ? (err.stack ?? err.message) : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toon-protocol/client-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Always-on local daemon + MCP server letting a Claude agent (Desktop or Code) act as a TOON Protocol client: pay-to-write publishing, free reads, channel/balance management, and swaps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jonathan Green",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"typescript": "^5.3.0",
|
|
50
50
|
"vitest": "^1.0.0",
|
|
51
51
|
"@toon-protocol/arweave": "0.1.1",
|
|
52
|
-
"@toon-protocol/client": "0.14.
|
|
53
|
-
"@toon-protocol/views": "0.
|
|
52
|
+
"@toon-protocol/client": "0.14.11",
|
|
53
|
+
"@toon-protocol/views": "0.12.0"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=20"
|