@naulon/wayfarer-mcp 0.2.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 ADDED
@@ -0,0 +1,196 @@
1
+ # @naulon/wayfarer-mcp
2
+
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that lets any
4
+ LLM **discover, quote, pay, and cite** naulon-tolled sources — bring your own
5
+ wallet, local stdio, the [wayfarer](../wayfarer) brain running in-process.
6
+
7
+ Point any MCP-capable client at this server and the model gains tools to find
8
+ tolled articles, get a quote, pay the `402` toll from a wallet you control, and
9
+ cite what it bought — the same budgeted buying loop the CLI agent runs, exposed
10
+ as callable tools and slash commands.
11
+
12
+ Works with **any MCP client**: Claude Code, Claude Desktop, Cursor, Windsurf,
13
+ Cline, VS Code, or your own host. Setup for each is below.
14
+
15
+ ---
16
+
17
+ ## Quick start
18
+
19
+ ```bash
20
+ npx -y @naulon/wayfarer-mcp # runs the stdio MCP server
21
+ ```
22
+
23
+ The package is scoped (`@naulon/wayfarer-mcp`); the binary it installs is
24
+ `wayfarer-mcp`. It runs **offline against mock settlement by default** — safe to
25
+ try with zero config, no wallet, no spend. To pay real tolls, see
26
+ [Configuration](#configuration).
27
+
28
+ The canonical registration, which every client below is a variant of:
29
+
30
+ ```jsonc
31
+ {
32
+ "mcpServers": {
33
+ "naulon": { "command": "npx", "args": ["-y", "@naulon/wayfarer-mcp"] }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Slash commands (prompts)
41
+
42
+ Every prompts-capable client surfaces these as native, argument-taking slash
43
+ commands — no per-user config. In Claude Code / Desktop they appear as
44
+ `/mcp__naulon__<name>` (the `naulon` segment is whatever you named the server):
45
+
46
+ | Prompt | Argument | Does |
47
+ |--------|----------|------|
48
+ | `research` | `topic` | Discover sources, see prices, return a grounded cited answer within budget. |
49
+ | `discover` | `topic` | List candidate sources — **free**, no payment. |
50
+ | `verify` | `claim` | Fact-check a claim against tolled sources, citing what it paid for. |
51
+ | `ask`\* | `question` | Hosted reading agent: pays per citation, returns a grounded answer. |
52
+
53
+ \* `ask` is only present on the **hosted** endpoint (it drives the cloud
54
+ `naulon_ask` tool). The stdio server exposes `research` / `discover` / `verify`.
55
+
56
+ ---
57
+
58
+ ## Per-client setup
59
+
60
+ ### Claude Code
61
+
62
+ CLI (recommended — `--scope project` writes a shared `.mcp.json`, `user` makes it
63
+ global across your projects):
64
+
65
+ ```bash
66
+ claude mcp add naulon --scope user -- npx -y @naulon/wayfarer-mcp
67
+ ```
68
+
69
+ Then `/mcp` inside Claude Code to confirm it connected, and type `/` to see the
70
+ `research` / `discover` / `verify` prompts. Or add it by hand to `.mcp.json`
71
+ (project) using the canonical block above.
72
+
73
+ ### Claude Desktop
74
+
75
+ Edit `claude_desktop_config.json`
76
+ (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`):
77
+
78
+ ```jsonc
79
+ {
80
+ "mcpServers": {
81
+ "naulon": { "command": "npx", "args": ["-y", "@naulon/wayfarer-mcp"] }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Restart Claude Desktop. Prompts appear in the `+` / slash-command menu.
87
+
88
+ ### Cursor
89
+
90
+ `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project), key
91
+ `mcpServers` — same canonical block above.
92
+
93
+ ### Windsurf
94
+
95
+ `~/.codeium/windsurf/mcp_config.json`, key `mcpServers` — same canonical block.
96
+
97
+ ### VS Code (native MCP / Copilot agent)
98
+
99
+ `.vscode/mcp.json` (workspace). VS Code uses the `servers` key (not
100
+ `mcpServers`); the `type` is inferred as stdio from `command`, so it's optional:
101
+
102
+ ```jsonc
103
+ {
104
+ "servers": {
105
+ "naulon": { "command": "npx", "args": ["-y", "@naulon/wayfarer-mcp"] }
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### Cline
111
+
112
+ Cline → MCP Servers → Configure (`cline_mcp_settings.json`), key `mcpServers` —
113
+ same canonical block.
114
+
115
+ ### Any other MCP host
116
+
117
+ Spawn the stdio binary and speak MCP over its stdio transport:
118
+
119
+ ```
120
+ command: npx args: ["-y", "@naulon/wayfarer-mcp"]
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Hosted endpoint (no local wallet)
126
+
127
+ naulon-cloud exposes the same brain over **Streamable HTTP** at `/_naulon/mcp`,
128
+ authenticated with an agent token — tolls are signed by naulon's custody-free
129
+ session key, so **no private key ever touches your machine**. This endpoint also
130
+ adds the cloud-only `naulon_ask` tool + its `ask` prompt.
131
+
132
+ Clients that support remote/HTTP MCP with headers:
133
+
134
+ ```bash
135
+ # Claude Code
136
+ claude mcp add --transport http naulon \
137
+ https://<your-naulon-host>/_naulon/mcp \
138
+ --header "Authorization: Bearer <AGENT_TOKEN>"
139
+ ```
140
+
141
+ ```jsonc
142
+ // Generic HTTP MCP config
143
+ {
144
+ "mcpServers": {
145
+ "naulon": {
146
+ "type": "http",
147
+ "url": "https://<your-naulon-host>/_naulon/mcp",
148
+ "headers": { "Authorization": "Bearer <AGENT_TOKEN>" }
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ Mint the agent token from your naulon buyer wallet / dashboard. Spend is bounded
155
+ by the server budget **and** the token's sub-cap — the model can lower a run's
156
+ budget, never raise it past either.
157
+
158
+ ---
159
+
160
+ ## Configuration
161
+
162
+ Env read by the stdio server (all optional — omit for the offline mock):
163
+
164
+ | Var | Purpose |
165
+ |-----|---------|
166
+ | `PAYMENT_MODE` | `gateway` to pay real tolls over Circle Gateway on Arc Network (default: mock). |
167
+ | `BUYER_PRIVATE_KEY` | The wallet the toll is paid from. BYO-key path; a hosted deploy signs through a cloud signer instead. |
168
+ | `TOLLGATE_URL` | The gate every payment resolves against. Payments only ever flow here — a prompt-injected model cannot redirect them. |
169
+ | `WAYFARER_BUDGET_USDC` | The session spend ceiling. The model can never raise it. |
170
+ | `WAYFARER_ALLOW_DOMAINS` / `WAYFARER_DENY_DOMAINS` | Publisher allow/deny lists for `naulon_research`. |
171
+ | `WAYFARER_PER_DOMAIN_CAP` | Max paid reads per publisher per session. |
172
+ | `WAYFARER_KILL_SWITCH` | Hard stop — refuse all spend. |
173
+
174
+ Budget and wallet are **server config, never tool arguments** — the model plans
175
+ spend within the envelope but can't widen it.
176
+
177
+ ---
178
+
179
+ ## Tools
180
+
181
+ | Tool | Cost | Does |
182
+ |------|------|------|
183
+ | `naulon_discover` | free | Candidate teasers for a topic (slug, title, summary). Start here. |
184
+ | `naulon_appraise` | free | Relevance + rationale for teasers already held. |
185
+ | `naulon_quote` | free | The x402 `402` probe — real price + terms, **no spend**. |
186
+ | `naulon_pay_and_read` | **$** | Pays the toll, returns content + settlement ref + citation license. |
187
+ | `naulon_read_held` | free | Re-read a held live license (PoP-signed if cnf-bound). |
188
+ | `naulon_research` | **$** | One composite that runs the whole discover→quote→pay→ground loop. |
189
+ | `naulon_ask`\* | **$** | Hosted-only reading agent — grounded, numbered-citation answer. |
190
+
191
+ \* hosted endpoint only. All tools carry MCP annotations (`readOnlyHint` on the
192
+ free ones) so clients render safe-vs-spends correctly.
193
+
194
+ ---
195
+
196
+ MIT.
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The cloud MemoSigner (BUY-2). Wires the wayfarer memo buyer to naulon's hosted, grant-checked
3
+ * signer instead of a local private key: each EIP-3009 leg is POSTed to `/_naulon/buyer-wallet/
4
+ * sign-memo`, which holds the encrypted session key, enforces the grant (cap + TTL), and returns just
5
+ * the signature. So the MCP process never touches a private key — the custody-free hosted path.
6
+ *
7
+ * The endpoint + token are SERVER-CONFIG (env), never LLM tool args — the model cannot point the
8
+ * signer elsewhere or raise its own spend ceiling. The chainId is taken from the request's own domain,
9
+ * so it can never drift from what wayfarer is paying against.
10
+ */
11
+ import type { AgentWallet, MemoSigner } from "@naulon/wayfarer";
12
+ /** The grant CAP/budget refused the spend — funding the session is the remedy. The message STARTS with the
13
+ * raw code (`grant_exceeded`) so memo.ts's message-prefix classifier maps it to `needs_topup`, not a
14
+ * retryable `origin_error` (mirrors in-process-signer.ts, which already throws code-prefixed messages). */
15
+ export declare class GrantExceededError extends Error {
16
+ readonly remainingMicro?: number | undefined;
17
+ constructor(remainingMicro?: number | undefined);
18
+ }
19
+ /** The grant WINDOW lapsed though funds may be intact — RENEWING the session is the remedy, not a top-up.
20
+ * Distinct class + code-prefixed message so the hosted agent renews rather than funds. */
21
+ export declare class GrantExpiredError extends Error {
22
+ readonly remainingMicro?: number | undefined;
23
+ constructor(remainingMicro?: number | undefined);
24
+ }
25
+ /** Any other non-ok response from the signer BFF (bad_from, no_session, chain_mismatch, 5xx, …). */
26
+ export declare class SignerError extends Error {
27
+ readonly status: number;
28
+ readonly code?: string | undefined;
29
+ constructor(status: number, code?: string | undefined);
30
+ }
31
+ export interface CloudSignerOpts {
32
+ /** Cloud gate base URL, no trailing slash (e.g. https://gate.naulon.app). This is the
33
+ * naulon gate origin that serves the `/_naulon/*` routes — NOT the REST/API edge. */
34
+ endpoint: string;
35
+ /** Per-session bearer token — server-config, never a tool arg. */
36
+ token: string;
37
+ /** The provisioned session EOA address (the `from` every leg signs as). */
38
+ address: `0x${string}`;
39
+ /** Injectable for tests. */
40
+ fetchImpl?: typeof fetch;
41
+ }
42
+ /**
43
+ * Build the cloud signer from environment — the hosted path is opt-in via SERVER-CONFIG, never a tool
44
+ * arg. All three of NAULON_CLOUD_ENDPOINT / NAULON_CLOUD_TOKEN / NAULON_BUYER_SESSION_ADDRESS must be
45
+ * present (and the address well-formed) or we return undefined and the caller falls back to the
46
+ * BYO-key path. This keeps the OSS default (local key) exactly as-is when the cloud isn't configured.
47
+ */
48
+ export declare function cloudSignerFromEnv(env?: Record<string, string | undefined>): MemoSigner | undefined;
49
+ export declare function cloudMemoSigner(opts: CloudSignerOpts): MemoSigner;
50
+ /**
51
+ * The cloud PoP signer (Phase 4 / C2). A held re-read of a cnf-bound license must prove control of
52
+ * the paying wallet by signing an EIP-191 holder-of-key challenge. On the custody-free hosted path the
53
+ * paying identity is the session EOA, whose key lives encrypted in the cloud — so the proof is signed
54
+ * by `/_naulon/buyer-wallet/sign-pop` (the session key) rather than a local key. Returns an
55
+ * `AgentWallet` so `buildPopProof` consumes it exactly like the env wallet.
56
+ *
57
+ * Unlike `/sign-memo` this leg is GRANT-FREE: a PoP is a free re-read, not a spend, so there is no cap
58
+ * to debit. The BFF still authenticates the bearer, checks the `address` matches the session, AND
59
+ * constrains the signed bytes to a canonical `naulon-pop` challenge — the session key can never be
60
+ * coerced into signing an arbitrary message. The endpoint + token are SERVER-CONFIG, never a tool arg.
61
+ */
62
+ export declare function cloudPopSigner(opts: CloudSignerOpts): AgentWallet;
63
+ //# sourceMappingURL=cloud-signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-signer.d.ts","sourceRoot":"","sources":["../src/cloud-signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEhE;;4GAE4G;AAC5G,qBAAa,kBAAmB,SAAQ,KAAK;aACf,cAAc,CAAC,EAAE,MAAM;gBAAvB,cAAc,CAAC,EAAE,MAAM,YAAA;CAIpD;AAED;2FAC2F;AAC3F,qBAAa,iBAAkB,SAAQ,KAAK;aACd,cAAc,CAAC,EAAE,MAAM;gBAAvB,cAAc,CAAC,EAAE,MAAM,YAAA;CAIpD;AAED,oGAAoG;AACpG,qBAAa,WAAY,SAAQ,KAAK;aAElB,MAAM,EAAE,MAAM;aACd,IAAI,CAAC,EAAE,MAAM;gBADb,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED,MAAM,WAAW,eAAe;IAC9B;0FACsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,UAAU,GAAG,SAAS,CAOxB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,UAAU,CAwCjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,CAoBjE"}
@@ -0,0 +1,125 @@
1
+ /** The grant CAP/budget refused the spend — funding the session is the remedy. The message STARTS with the
2
+ * raw code (`grant_exceeded`) so memo.ts's message-prefix classifier maps it to `needs_topup`, not a
3
+ * retryable `origin_error` (mirrors in-process-signer.ts, which already throws code-prefixed messages). */
4
+ export class GrantExceededError extends Error {
5
+ remainingMicro;
6
+ constructor(remainingMicro) {
7
+ super(`grant_exceeded${remainingMicro !== undefined ? ` (remaining ${remainingMicro})` : ""}`);
8
+ this.remainingMicro = remainingMicro;
9
+ this.name = "GrantExceededError";
10
+ }
11
+ }
12
+ /** The grant WINDOW lapsed though funds may be intact — RENEWING the session is the remedy, not a top-up.
13
+ * Distinct class + code-prefixed message so the hosted agent renews rather than funds. */
14
+ export class GrantExpiredError extends Error {
15
+ remainingMicro;
16
+ constructor(remainingMicro) {
17
+ super(`grant_expired${remainingMicro !== undefined ? ` (remaining ${remainingMicro})` : ""}`);
18
+ this.remainingMicro = remainingMicro;
19
+ this.name = "GrantExpiredError";
20
+ }
21
+ }
22
+ /** Any other non-ok response from the signer BFF (bad_from, no_session, chain_mismatch, 5xx, …). */
23
+ export class SignerError extends Error {
24
+ status;
25
+ code;
26
+ constructor(status, code) {
27
+ super(`sign-memo failed: ${status}${code ? ` ${code}` : ""}`);
28
+ this.status = status;
29
+ this.code = code;
30
+ this.name = "SignerError";
31
+ }
32
+ }
33
+ /**
34
+ * Build the cloud signer from environment — the hosted path is opt-in via SERVER-CONFIG, never a tool
35
+ * arg. All three of NAULON_CLOUD_ENDPOINT / NAULON_CLOUD_TOKEN / NAULON_BUYER_SESSION_ADDRESS must be
36
+ * present (and the address well-formed) or we return undefined and the caller falls back to the
37
+ * BYO-key path. This keeps the OSS default (local key) exactly as-is when the cloud isn't configured.
38
+ */
39
+ export function cloudSignerFromEnv(env = process.env) {
40
+ const endpoint = env.NAULON_CLOUD_ENDPOINT;
41
+ const token = env.NAULON_CLOUD_TOKEN;
42
+ const address = env.NAULON_BUYER_SESSION_ADDRESS;
43
+ if (!endpoint || !token || !address)
44
+ return undefined;
45
+ if (!/^0x[0-9a-fA-F]{40}$/.test(address))
46
+ return undefined;
47
+ return cloudMemoSigner({ endpoint, token, address: address });
48
+ }
49
+ export function cloudMemoSigner(opts) {
50
+ const doFetch = opts.fetchImpl ?? fetch;
51
+ return {
52
+ address: opts.address,
53
+ async signTypedData(args) {
54
+ const m = args.message;
55
+ const res = await doFetch(`${opts.endpoint}/_naulon/buyer-wallet/sign-memo`, {
56
+ method: "POST",
57
+ headers: { authorization: `Bearer ${opts.token}`, "content-type": "application/json" },
58
+ // BigInt can't be JSON-serialized — send the EIP-3009 fields as decimal strings. The BFF
59
+ // rebuilds the domain + types authoritatively; we send only the leg's message primitives.
60
+ body: JSON.stringify({
61
+ chainId: Number(args.domain.chainId),
62
+ message: {
63
+ from: m.from,
64
+ to: m.to,
65
+ value: m.value.toString(),
66
+ validAfter: m.validAfter.toString(),
67
+ validBefore: m.validBefore.toString(),
68
+ nonce: m.nonce,
69
+ },
70
+ }),
71
+ });
72
+ if (res.status === 402) {
73
+ // The BFF returns 402 for BOTH grant stops (sign.ts:57/60). Read `error` to pick the remedy:
74
+ // grant_expired ⇒ renew (funds intact); grant_exceeded / anything else ⇒ top up (fund the session).
75
+ const body = (await res.json().catch(() => ({})));
76
+ throw body.error === "grant_expired"
77
+ ? new GrantExpiredError(body.remainingMicro)
78
+ : new GrantExceededError(body.remainingMicro);
79
+ }
80
+ if (!res.ok) {
81
+ const body = (await res.json().catch(() => ({})));
82
+ throw new SignerError(res.status, body.error);
83
+ }
84
+ const body = (await res.json().catch(() => ({})));
85
+ if (!body.signature)
86
+ throw new SignerError(res.status, "no_signature");
87
+ return body.signature;
88
+ },
89
+ };
90
+ }
91
+ /**
92
+ * The cloud PoP signer (Phase 4 / C2). A held re-read of a cnf-bound license must prove control of
93
+ * the paying wallet by signing an EIP-191 holder-of-key challenge. On the custody-free hosted path the
94
+ * paying identity is the session EOA, whose key lives encrypted in the cloud — so the proof is signed
95
+ * by `/_naulon/buyer-wallet/sign-pop` (the session key) rather than a local key. Returns an
96
+ * `AgentWallet` so `buildPopProof` consumes it exactly like the env wallet.
97
+ *
98
+ * Unlike `/sign-memo` this leg is GRANT-FREE: a PoP is a free re-read, not a spend, so there is no cap
99
+ * to debit. The BFF still authenticates the bearer, checks the `address` matches the session, AND
100
+ * constrains the signed bytes to a canonical `naulon-pop` challenge — the session key can never be
101
+ * coerced into signing an arbitrary message. The endpoint + token are SERVER-CONFIG, never a tool arg.
102
+ */
103
+ export function cloudPopSigner(opts) {
104
+ const doFetch = opts.fetchImpl ?? fetch;
105
+ return {
106
+ address: opts.address,
107
+ mock: false,
108
+ signMessage: async (message) => {
109
+ const res = await doFetch(`${opts.endpoint}/_naulon/buyer-wallet/sign-pop`, {
110
+ method: "POST",
111
+ headers: { authorization: `Bearer ${opts.token}`, "content-type": "application/json" },
112
+ body: JSON.stringify({ address: opts.address, message }),
113
+ });
114
+ if (!res.ok) {
115
+ const body = (await res.json().catch(() => ({})));
116
+ throw new SignerError(res.status, body.error);
117
+ }
118
+ const body = (await res.json().catch(() => ({})));
119
+ if (!body.signature)
120
+ throw new SignerError(res.status, "no_signature");
121
+ return body.signature;
122
+ },
123
+ };
124
+ }
125
+ //# sourceMappingURL=cloud-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-signer.js","sourceRoot":"","sources":["../src/cloud-signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * stdio entry point — an MCP client (Claude Desktop, Cursor, …) spawns this as a
4
+ * child process and speaks JSON-RPC over stdin/stdout.
5
+ *
6
+ * Hard rule for stdio servers: stdout is the protocol channel. Nothing but
7
+ * JSON-RPC may be written there — all diagnostics go to stderr, or they corrupt
8
+ * the stream.
9
+ */
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { buildServer } from "./server.js";
12
+ async function main() {
13
+ const server = buildServer();
14
+ const transport = new StdioServerTransport();
15
+ await server.connect(transport);
16
+ process.stderr.write("naulon-wayfarer-mcp: listening on stdio\n");
17
+ }
18
+ main().catch((err) => {
19
+ process.stderr.write(`naulon-wayfarer-mcp: failed to start — ${err instanceof Error ? err.message : String(err)}\n`);
20
+ process.exitCode = 1;
21
+ });
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;AACpE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrH,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
package/dist/lib.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @naulon/wayfarer-mcp — public library surface.
3
+ *
4
+ * The side-effect-free barrel the package.json `exports` map points at. `index.ts`
5
+ * (the stdio bin) is a thin consumer of `buildServer`, never the other way round —
6
+ * so the cloud can `buildServer()` and wrap it over its own authenticated transport
7
+ * without dragging in the stdio bootstrap.
8
+ */
9
+ export { buildServer, SERVER_NAME, SERVER_VERSION, type BuildServerOptions, type DecisionAuditEvent } from "./server.ts";
10
+ export { cloudMemoSigner, cloudPopSigner, cloudSignerFromEnv, GrantExceededError, SignerError, type CloudSignerOpts, } from "./cloud-signer.ts";
11
+ //# sourceMappingURL=lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzH,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC"}
package/dist/lib.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @naulon/wayfarer-mcp — public library surface.
3
+ *
4
+ * The side-effect-free barrel the package.json `exports` map points at. `index.ts`
5
+ * (the stdio bin) is a thin consumer of `buildServer`, never the other way round —
6
+ * so the cloud can `buildServer()` and wrap it over its own authenticated transport
7
+ * without dragging in the stdio bootstrap.
8
+ */
9
+ export { buildServer, SERVER_NAME, SERVER_VERSION } from "./server.js";
10
+ export { cloudMemoSigner, cloudPopSigner, cloudSignerFromEnv, GrantExceededError, SignerError, } from "./cloud-signer.js";
11
+ //# sourceMappingURL=lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAoD,MAAM,aAAa,CAAC;AACzH,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,GAEZ,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * @naulon/wayfarer-mcp — the MCP server factory.
3
+ *
4
+ * Exposes naulon's pay-per-citation pipeline to any MCP-capable LLM. The wayfarer
5
+ * brain runs IN-PROCESS here (no remote service, BYO wallet never leaves the
6
+ * machine) — the deliberate contrast to a thin client that pays a hosted brain.
7
+ *
8
+ * Tools are deliberately GRANULAR and quote-first: the host model sees prices and
9
+ * plans spend before any payment, rather than calling one black-box "research"
10
+ * verb. The §3.1 surface (BUY-1.2) is:
11
+ *
12
+ * naulon_discover free — candidate teasers for a topic
13
+ * naulon_appraise free — relevance + rationale for teasers the model holds
14
+ * naulon_quote free — the x402 402 probe: real price + terms, NO spend
15
+ * naulon_pay_and_read $ — pays, returns content + settlementRef + license jti
16
+ * naulon_read_held free — re-read a held live license (PoP-signed if cnf-bound)
17
+ * naulon_research $ — one composite that runs the whole loop for lazy clients
18
+ *
19
+ * Two deliberate shapes vs the spec's conceptual `url(...)` signatures:
20
+ * - Tools take a SLUG, never a raw URL. The server resolves it against the
21
+ * server-configured gate (TOLLGATE_URL), so a prompt-injected model can never
22
+ * redirect a payment to an attacker's endpoint — payment only ever flows to
23
+ * the configured gate. (Same "config, not tool args" principle BUY-1.3 applies
24
+ * to the budget + wallet.)
25
+ * - `kind` is pinned to "citation": the MCP's purpose is grounded, citable
26
+ * research, so every quote/pay/re-read asks for a citation license.
27
+ *
28
+ * Budget + wallet are SERVER-CONFIG, never tool args (BUY-1.3). The wallet comes
29
+ * from the env (`BUYER_PRIVATE_KEY` / the dev key) via `getWallet()`; the budget is
30
+ * a single ceiling (`WAYFARER_BUDGET_USDC`) the model cannot raise. Each server
31
+ * instance carries a SESSION SPEND ENVELOPE: every paid read debits a running total,
32
+ * the free tools report "$Y remaining", and a spend that would exceed the ceiling is
33
+ * refused (spending nothing). `naulon_research` accepts an optional `budgetUsdc` the
34
+ * server CLAMPS to what remains — the model can spend less, never more.
35
+ *
36
+ * The explicit toll-moved tolerance + validity-at-pay margin guards are BUY-1.4.
37
+ */
38
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
39
+ import type { AgentWallet, DecisionPolicy, GatewaySigner, HeldStore, MemoSigner, RailSigners } from "@naulon/wayfarer";
40
+ export declare const SERVER_NAME = "naulon-wayfarer-mcp";
41
+ /** Keep in step with this package's package.json `version` — it is what the MCP
42
+ * handshake reports as `serverInfo.version`. */
43
+ export declare const SERVER_VERSION = "0.2.0";
44
+ /**
45
+ * Per-session options for the HOSTED path (BUY-4). The stdio funnel reads the
46
+ * wallet, budget, and policy from process env (one process = one buyer). The cloud
47
+ * host authenticates MANY buyer sessions over one process, so it injects each
48
+ * session's config here — and each injected value WINS over env, which stays only
49
+ * the default when the option is absent (so the stdio funnel is unchanged). One
50
+ * `buildServer(opts)` per authed session gives per-session budget envelopes for
51
+ * free, since the envelope is a closure over this call.
52
+ */
53
+ /**
54
+ * One buyer spend DECISION, handed to a `BuildServerOptions.auditSink` (BUY-4.4). The
55
+ * hosted cloud injects a sink that writes each of these to its org-partitioned audit
56
+ * plane — the same immutable log the sell side uses. A PURE structured hook: the package
57
+ * never imports the cloud (the one-way dependency), so the sink is injected, not called.
58
+ *
59
+ * The four actions mirror the wayfarer decision engine exactly (pay · skip · approve ·
60
+ * cache). A kill-switch halt or a policy denial surfaces as a `skip` with the halt reason
61
+ * carried verbatim in `reason` — so nothing is lost to accountability even though it is
62
+ * not its own verb (the engine emits no distinct "kill"/"deny" action; adding one would
63
+ * be a decide.ts change, not an audit concern).
64
+ */
65
+ export interface DecisionAuditEvent {
66
+ /** The source slug the decision was about. */
67
+ slug: string;
68
+ /** The engine decision: paid · skipped (policy/budget/relevance) · flagged for human approval · re-read a held license free. */
69
+ action: "pay" | "skip" | "approve" | "cache";
70
+ /** The engine's human-readable reason (carries the kill-switch / deny / budget nuance verbatim). */
71
+ reason: string;
72
+ /** The candidate's 0..1 relevance for the topic (research decisions). */
73
+ relevance?: number;
74
+ /** The advertised author-leg price in USDC, when known. */
75
+ priceUsdc?: number;
76
+ /** The author leg actually paid, in USDC (pay decisions only). */
77
+ paidUsdc?: number;
78
+ /** The true total debited across all settlement legs, in USDC (pay_and_read pays only). */
79
+ costUsdc?: number;
80
+ /** The on-chain / settlement reference (pay decisions only). */
81
+ settlementRef?: string;
82
+ /** The Citation License jti (pay decisions only). */
83
+ licenseId?: string;
84
+ /** The policy's agent tag, if configured — audit attribution, not identity. */
85
+ agentId?: string;
86
+ }
87
+ export interface BuildServerOptions {
88
+ /**
89
+ * This session's custody-free cloud signer (else `cloudSignerFromEnv()`). A `MemoSigner`
90
+ * (memo/Arc rail) or a `GatewaySigner` (memo-less Circle rails — Base + every Gateway
91
+ * chain); the cloud injects the one matching the active settlement network's rail, and
92
+ * `buildServer` routes it to the matching buyer (`supportsMemo(activeNetwork())`).
93
+ */
94
+ signer?: MemoSigner | GatewaySigner;
95
+ /**
96
+ * A mixed-fleet session's BOTH rail signers (RAS-B): the cloud injects a memo AND a gateway
97
+ * signer wrapping the same sealed session key, and `buildServer` builds a `railBuyer` that picks
98
+ * the rail from each tenant's advertised 402 — so one process serves an Arc-default fleet with a
99
+ * Base tenant. Takes precedence over `signer` when present; the single-rail `signer` path stays for
100
+ * the stdio funnel and any host that settles on one network. Both wrap the same key, so the payer
101
+ * identity is either signer's `address` (they are equal).
102
+ */
103
+ railSigners?: RailSigners;
104
+ /** This session's spend ceiling in USDC (else `WAYFARER_BUDGET_USDC`). */
105
+ budgetUsdc?: number;
106
+ /** This session's decision policy (else the env-derived policy over DEFAULT_POLICY). */
107
+ policy?: DecisionPolicy;
108
+ /**
109
+ * Per-decision audit hook (BUY-4.4). Invoked once per buyer spend decision — a pay, a
110
+ * skip, an approval-gate, a free cache re-read — with a structured `DecisionAuditEvent`.
111
+ * The cloud host injects a sink that writes to its org-partitioned audit plane; the stdio
112
+ * funnel leaves it unset (no sink ⇒ the OSS path is simply unaudited). A pure hook (the
113
+ * package never imports the cloud), and it is fired best-effort — a throwing sink must
114
+ * never break a paid read.
115
+ */
116
+ auditSink?: (event: DecisionAuditEvent) => void;
117
+ /**
118
+ * This session's gate (base URL) — the fleet tenant it settles into (else the env
119
+ * `TOLLGATE_URL`). The cloud host injects it per authed session so one process can
120
+ * serve many buyers, each accountable to a specific publisher's 402 (BUY-4.2, the
121
+ * moat: own both ends of the receipt). Server-config, never a tool arg — a
122
+ * prompt-injected model can no more redirect the gate than raise the budget.
123
+ */
124
+ tollgateUrl?: string;
125
+ /**
126
+ * This session's held-license backend. The stdio funnel leaves it unset (the
127
+ * process-global file `fileHeldStore`). The cloud host MUST inject a per-session
128
+ * store (e.g. `memoryHeldStore()`) so one process serving many buyers can never
129
+ * let session B re-read the license session A paid for — the file store is keyed
130
+ * by slug alone and shared, so without this the hosted path leaks licenses across
131
+ * buyers. Server-config, never a tool arg.
132
+ */
133
+ heldStore?: HeldStore;
134
+ /**
135
+ * The wallet that signs proof-of-possession for a cnf-bound held re-read. On a
136
+ * custody-free hosted deploy the paying identity is the cloud session EOA, but
137
+ * `getWallet()` (the fallback) returns a throwaway dev key when no
138
+ * `BUYER_PRIVATE_KEY` is set — so a PoP signed by it can never satisfy a license
139
+ * cnf-bound to the session address. The cloud injects a signer backed by its
140
+ * `/sign-pop` BFF (the session key). Absent ⇒ `getWallet()` (unchanged OSS path).
141
+ * Server-config, never a tool arg — the model cannot point the signer elsewhere.
142
+ */
143
+ popWallet?: AgentWallet;
144
+ /**
145
+ * Where the agent (or its operator) tops up / renews the funding session — surfaced on a
146
+ * `needs_topup` / `grant_expired` pay refusal so the refusal is ACTIONABLE, not a dead end. On
147
+ * the hosted path the cloud injects its portal wallet URL; the stdio funnel leaves it at the
148
+ * `/buyer/wallet` default. Server-config, never a tool arg. */
149
+ buyerWalletUrl?: string;
150
+ }
151
+ /**
152
+ * Build a fresh, unconnected MCP server with the tool surface registered. The
153
+ * caller connects it to a transport (stdio for the OSS funnel; the cloud wraps it
154
+ * over an authenticated HTTP transport). A factory — not a singleton — so tests
155
+ * can stand up an isolated server per case. `opts` supplies per-session config for
156
+ * the hosted path (BUY-4); absent, every value falls back to process env.
157
+ */
158
+ export declare function buildServer(opts?: BuildServerOptions): McpServer;
159
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2BpE,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAgB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIrI,eAAO,MAAM,WAAW,wBAAwB,CAAC;AACjD;iDACiD;AACjD,eAAO,MAAM,cAAc,UAAU,CAAC;AAgGtC;;;;;;;;GAQG;AACH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,gIAAgI;IAChI,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IAC7C,oGAAoG;IACpG,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IACpC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAChD;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;;;mEAI+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,SAAS,CAuyBpE"}