@arcnow/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.
Files changed (71) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +624 -0
  3. package/dist/client-options.d.ts +16 -0
  4. package/dist/client-options.d.ts.map +1 -0
  5. package/dist/client-options.js +22 -0
  6. package/dist/client-options.js.map +1 -0
  7. package/dist/config.d.ts +223 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +516 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/format.d.ts +79 -0
  12. package/dist/format.d.ts.map +1 -0
  13. package/dist/format.js +164 -0
  14. package/dist/format.js.map +1 -0
  15. package/dist/index.d.ts +17 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +50 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/sdk-port.d.ts +227 -0
  20. package/dist/sdk-port.d.ts.map +1 -0
  21. package/dist/sdk-port.js +144 -0
  22. package/dist/sdk-port.js.map +1 -0
  23. package/dist/server.d.ts +25 -0
  24. package/dist/server.d.ts.map +1 -0
  25. package/dist/server.js +103 -0
  26. package/dist/server.js.map +1 -0
  27. package/dist/tools/errors.d.ts +44 -0
  28. package/dist/tools/errors.d.ts.map +1 -0
  29. package/dist/tools/errors.js +231 -0
  30. package/dist/tools/errors.js.map +1 -0
  31. package/dist/tools/index.d.ts +35 -0
  32. package/dist/tools/index.d.ts.map +1 -0
  33. package/dist/tools/index.js +59 -0
  34. package/dist/tools/index.js.map +1 -0
  35. package/dist/tools/launch-params.d.ts +27 -0
  36. package/dist/tools/launch-params.d.ts.map +1 -0
  37. package/dist/tools/launch-params.js +29 -0
  38. package/dist/tools/launch-params.js.map +1 -0
  39. package/dist/tools/pool.d.ts +84 -0
  40. package/dist/tools/pool.d.ts.map +1 -0
  41. package/dist/tools/pool.js +249 -0
  42. package/dist/tools/pool.js.map +1 -0
  43. package/dist/tools/quote.d.ts +53 -0
  44. package/dist/tools/quote.d.ts.map +1 -0
  45. package/dist/tools/quote.js +85 -0
  46. package/dist/tools/quote.js.map +1 -0
  47. package/dist/tools/read.d.ts +26 -0
  48. package/dist/tools/read.d.ts.map +1 -0
  49. package/dist/tools/read.js +920 -0
  50. package/dist/tools/read.js.map +1 -0
  51. package/dist/tools/resolve.d.ts +45 -0
  52. package/dist/tools/resolve.d.ts.map +1 -0
  53. package/dist/tools/resolve.js +75 -0
  54. package/dist/tools/resolve.js.map +1 -0
  55. package/dist/tools/schema.d.ts +98 -0
  56. package/dist/tools/schema.d.ts.map +1 -0
  57. package/dist/tools/schema.js +143 -0
  58. package/dist/tools/schema.js.map +1 -0
  59. package/dist/tools/spend.d.ts +45 -0
  60. package/dist/tools/spend.d.ts.map +1 -0
  61. package/dist/tools/spend.js +99 -0
  62. package/dist/tools/spend.js.map +1 -0
  63. package/dist/tools/venue.d.ts +67 -0
  64. package/dist/tools/venue.d.ts.map +1 -0
  65. package/dist/tools/venue.js +110 -0
  66. package/dist/tools/venue.js.map +1 -0
  67. package/dist/tools/write.d.ts +56 -0
  68. package/dist/tools/write.d.ts.map +1 -0
  69. package/dist/tools/write.js +950 -0
  70. package/dist/tools/write.js.map +1 -0
  71. package/package.json +55 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The options the SDK client is built from, out of a {@link ServerConfig}.
3
+ *
4
+ * Its own module, rather than three lines in `index.ts`, so the one thing that
5
+ * decides which deployment the server talks to — the preset or the network
6
+ * file, the endpoint override, the signer — is testable without starting a
7
+ * process.
8
+ *
9
+ * @module
10
+ */
11
+ export function clientOptionsFor(config) {
12
+ const rpcUrl = config.rpcUrlForClient();
13
+ const account = config.account();
14
+ return {
15
+ // Already resolved by the SDK in loadConfig: the caps were checked against
16
+ // this same list of quote tokens, so the client must not resolve another.
17
+ network: config.networkConfig,
18
+ ...(rpcUrl === undefined ? {} : { rpcUrl }),
19
+ ...(account === undefined ? {} : { account }),
20
+ };
21
+ }
22
+ //# sourceMappingURL=client-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-options.js","sourceRoot":"","sources":["../src/client-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,UAAU,gBAAgB,CAC9B,MAAoB;IAEpB,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,OAAO;QACL,2EAA2E;QAC3E,0EAA0E;QAC1E,OAAO,EAAE,MAAM,CAAC,aAAa;QAC7B,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;KAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * How this server is configured, and the one decision that matters.
3
+ *
4
+ * # A private key is never a tool argument
5
+ *
6
+ * Every write this server can do needs a key. That key is read **here**, from
7
+ * the process environment or from a file the operator names, and from nowhere
8
+ * else. No tool takes one, no tool schema has a field for one, and
9
+ * `test/unit/no-key-arguments.test.ts` walks every published schema to keep it
10
+ * that way.
11
+ *
12
+ * The reason is not that arguments are less secure than environment variables
13
+ * in general. It is that a tool argument is **written by a model, into a
14
+ * transcript**. It goes to the model provider, into whatever log the client
15
+ * keeps, into the context of every later turn, and into the bug report someone
16
+ * pastes into an issue. A key that has been through a tool call is a key that
17
+ * has been published, and there is no way to un-publish it. The environment is
18
+ * read by one process, in one place, at startup.
19
+ *
20
+ * The key never leaves this module either: {@link ServerConfig} holds a viem
21
+ * `Account` behind a private field and its `toJSON` is the redacted
22
+ * description, so a config object that ends up in a log line or an error dump
23
+ * carries an address and not a secret.
24
+ *
25
+ * # Read-only is the default, and writing is the operator's decision
26
+ *
27
+ * A key being present is **not** consent to spend it. Writing requires
28
+ * `--allow-writes` (or `ARCNOW_MCP_ALLOW_WRITES=1`) from whoever starts the
29
+ * process — a person editing a config file, not a model mid-conversation — and
30
+ * the mode is printed on stderr at startup and reported by the
31
+ * `arcnow_network` tool, so neither the operator nor the model has to guess.
32
+ *
33
+ * A key with no opt-in starts read-only and says so loudly. An opt-in with no
34
+ * key refuses to start: the operator asked for something this process cannot
35
+ * do, and a server that quietly downgrades is a server whose failures arrive
36
+ * later, as "why did it not buy".
37
+ *
38
+ * # Spend caps are per quote token, and a quote with no cap is refused
39
+ *
40
+ * A curve is priced in native USDC or an allowlisted ERC-20 such as EURC, and
41
+ * one number in USDC cannot cap a spend in EURC. So the operator sets one cap
42
+ * per quote token, each in that quote's own units:
43
+ *
44
+ * - `ARCNOW_MCP_MAX_SPEND_USDC` caps native USDC, and defaults to 100.
45
+ * - `ARCNOW_MCP_MAX_SPEND_<SYMBOL>` caps every other quote: `ARCNOW_MCP_MAX_SPEND_EURC=50`.
46
+ * The symbol is the quote's symbol upper-cased, with anything but a letter
47
+ * or a digit written as `_`.
48
+ *
49
+ * Fail-closed, in four ways. A quote with **no** cap is refused for every
50
+ * spending write — launch and buy — and non-native quotes get no default, so a
51
+ * cap can never be got round by switching quote. A symbol resolves **only**
52
+ * against the network's own `quoteTokens` (the SDK's `networks.json`, or the
53
+ * network file), never against a token's on-chain `symbol()`, so a token cannot
54
+ * call itself EURC and borrow EURC's cap; a quote the network does not list can
55
+ * have no cap and is always refused. A cap variable naming no quote token of
56
+ * the network is a startup error, which catches typos. And two quote tokens of
57
+ * the network sharing a symbol is a startup error, because their two caps would
58
+ * be one variable.
59
+ *
60
+ * # A network the SDK has no preset for
61
+ *
62
+ * `ARCNOW_MCP_NETWORK_FILE` names a JSON document in the SDK's `CustomNetwork`
63
+ * shape — `rpcUrl`, `chainId`, `contracts`, and optionally `quoteTokens` and
64
+ * `quoteAllowanceSlots` — for a local anvil stack or a fork. It is validated by
65
+ * the SDK's own `resolveNetwork`, and is mutually exclusive with a preset name.
66
+ *
67
+ * @module
68
+ */
69
+ import type { Account, Address } from "viem";
70
+ import type { NetworkConfig, QuoteTokenInfo } from "@arcnow/sdk";
71
+ import { QuoteAmount } from "@arcnow/sdk";
72
+ /** Bad configuration, phrased for the person who wrote it. */
73
+ export declare class ConfigError extends Error {
74
+ readonly name = "ConfigError";
75
+ }
76
+ /** Read-only, or writing. There is no third state and nothing in between. */
77
+ export type ServerMode = "read-only" | "write";
78
+ /** How far back the launch-log scan is allowed to reach in one tool call. */
79
+ export interface LogScanLimits {
80
+ readonly chunkBlocks: bigint;
81
+ readonly maxChunks: number;
82
+ }
83
+ /** The environment variable that caps native USDC. */
84
+ export declare const NATIVE_CAP_VARIABLE = "ARCNOW_MCP_MAX_SPEND_USDC";
85
+ /** Every per-quote cap variable starts with this. */
86
+ export declare const CAP_VARIABLE_PREFIX = "ARCNOW_MCP_MAX_SPEND_";
87
+ /** One quote token's cap, as the operator set it. */
88
+ export interface SpendCap {
89
+ /** The quote, from the network's `quoteTokens`. */
90
+ readonly token: QuoteTokenInfo;
91
+ /** The environment variable that sets it. */
92
+ readonly variable: string;
93
+ /** The most one write call may spend in this quote. `undefined`: no cap, every spend refused. */
94
+ readonly cap: QuoteAmount | undefined;
95
+ }
96
+ /** The variable capping `token`: `ARCNOW_MCP_MAX_SPEND_USDC` if native, else `…_<SYMBOL>`. */
97
+ export declare function capVariableFor(token: QuoteTokenInfo): string;
98
+ /** The redacted view: everything about this server except the secret. */
99
+ export interface ConfigDescription {
100
+ readonly network: string;
101
+ /** The network file the network came from, or null for a preset. */
102
+ readonly networkFile: string | null;
103
+ readonly rpcUrl: string;
104
+ readonly mode: ServerMode;
105
+ readonly signerAddress: Address | null;
106
+ /** The native USDC cap, as a decimal. */
107
+ readonly maxSpendPerCallUsdc: string;
108
+ /** Every quote token's cap by symbol, in its own units; `null` where none is set (refused). */
109
+ readonly maxSpendPerCall: Readonly<Record<string, string | null>>;
110
+ readonly logScan: {
111
+ readonly chunkBlocks: string;
112
+ readonly maxChunks: number;
113
+ };
114
+ readonly warnings: readonly string[];
115
+ }
116
+ /**
117
+ * The resolved configuration.
118
+ *
119
+ * Deliberately a class and not a plain object: the signing account lives in a
120
+ * `#` field that nothing can enumerate, and `toJSON` is the redacted
121
+ * description. Anything that stringifies this — a log line, an error cause, a
122
+ * crash dump — gets an address.
123
+ */
124
+ export declare class ServerConfig {
125
+ #private;
126
+ /** The network's name: the preset's, or the network file's. */
127
+ readonly network: string;
128
+ /** The network, resolved by the SDK: what the client is built on and caps resolve against. */
129
+ readonly networkConfig: NetworkConfig;
130
+ /** The network file it came from, when it did. */
131
+ readonly networkFile: string | undefined;
132
+ /** Already redacted of any credential: this is the value that gets printed. */
133
+ readonly rpcUrl: string;
134
+ readonly mode: ServerMode;
135
+ readonly signerAddress: Address | undefined;
136
+ /**
137
+ * The ceiling this process will spend in any one write call, per quote token,
138
+ * whatever a tool argument asks for. The operator's numbers, not the model's.
139
+ */
140
+ readonly spendCaps: readonly SpendCap[];
141
+ readonly logScan: LogScanLimits;
142
+ /** Things worth saying at startup that are not fatal. */
143
+ readonly warnings: readonly string[];
144
+ constructor(init: {
145
+ network: string;
146
+ networkConfig: NetworkConfig;
147
+ networkFile: string | undefined;
148
+ rpcUrlRaw: string | undefined;
149
+ rpcUrlDisplay: string;
150
+ mode: ServerMode;
151
+ account: Account | undefined;
152
+ spendCaps: readonly SpendCap[];
153
+ logScan: LogScanLimits;
154
+ warnings: readonly string[];
155
+ });
156
+ /** The signer, when this server is in write mode. `undefined` otherwise. */
157
+ account(): Account | undefined;
158
+ /** The endpoint to actually connect to, credential and all. */
159
+ rpcUrlForClient(): string | undefined;
160
+ /**
161
+ * The cap for a quote token, by ADDRESS — never by symbol, so a token that
162
+ * calls itself EURC is not EURC. `undefined` for a quote the network does not
163
+ * list, which no variable can cap.
164
+ */
165
+ spendCapFor(token: QuoteTokenInfo | string): SpendCap | undefined;
166
+ /** The native USDC cap, which always exists: it defaults to 100. */
167
+ get maxSpendPerCallUsdc(): QuoteAmount;
168
+ /** True when write tools are published and callable. */
169
+ get canWrite(): boolean;
170
+ describe(): ConfigDescription;
171
+ /** Redacted by construction: whatever stringifies a config gets this. */
172
+ toJSON(): ConfigDescription;
173
+ }
174
+ /** Defaults, named so they can be quoted in documentation and in tests. */
175
+ export declare const DEFAULTS: {
176
+ readonly network: "arc-testnet";
177
+ /**
178
+ * 100 USDC a call. Low enough that a prompt-injected "buy everything" is a
179
+ * bounded accident and not a bounded-by-your-balance one; high enough that
180
+ * the shipped 2 USDC launch fee plus a real first buy fits under it. An
181
+ * operator who means to spend more says so once, at startup, on purpose.
182
+ *
183
+ * Native USDC only. Every other quote has NO default: spending it is refused
184
+ * until the operator names a cap for it.
185
+ */
186
+ readonly maxSpendPerCallUsdc: "100";
187
+ /**
188
+ * Arc's public endpoint has not documented a `eth_getLogs` range limit, so
189
+ * the scan is chunked rather than asking for six million blocks and finding
190
+ * out. 10,000 blocks a request, twenty requests: a bounded amount of work for
191
+ * a tool call, and the result says how far back it actually reached instead
192
+ * of implying it saw everything.
193
+ */
194
+ readonly logChunkBlocks: 10000n;
195
+ readonly logMaxChunks: 20;
196
+ };
197
+ /**
198
+ * Strip anything secret out of an endpoint before it is ever printed.
199
+ *
200
+ * A private RPC endpoint is very often `https://host/v2/<api-key>` or
201
+ * `https://user:pass@host`. This server prints its endpoint at startup and in
202
+ * `arcnow_network`, and a model reads that output — so the path and the
203
+ * userinfo go, and what is left is the origin plus a marker saying something
204
+ * was there.
205
+ */
206
+ export declare function redactUrl(raw: string): string;
207
+ /**
208
+ * Turn an environment and a command line into a {@link ServerConfig}.
209
+ *
210
+ * Pure apart from the `readFile` it is handed, so the whole configuration
211
+ * surface — including every refusal — is testable without a process, a file or
212
+ * a key that is worth anything.
213
+ */
214
+ export declare function loadConfig(env: Readonly<Record<string, string | undefined>>, argv?: readonly string[], readFile?: (path: string) => string): ServerConfig;
215
+ /**
216
+ * The startup banner, on **stderr**.
217
+ *
218
+ * stdout belongs to the MCP transport and a stray byte there corrupts the
219
+ * protocol frame, so nothing in this server ever writes to it. The banner says
220
+ * the mode first, because that is the fact an operator is checking for.
221
+ */
222
+ export declare function startupBanner(config: ServerConfig): string;
223
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}