@tabai/sdk 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.
Files changed (204) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +401 -0
  3. package/bin/tab.mjs +23 -0
  4. package/dist/_shared/abi.d.ts +150 -0
  5. package/dist/_shared/abi.d.ts.map +1 -0
  6. package/dist/_shared/abi.js +197 -0
  7. package/dist/_shared/abi.js.map +1 -0
  8. package/dist/_shared/chains.d.ts +118 -0
  9. package/dist/_shared/chains.d.ts.map +1 -0
  10. package/dist/_shared/chains.js +89 -0
  11. package/dist/_shared/chains.js.map +1 -0
  12. package/dist/_shared/hex.d.ts +35 -0
  13. package/dist/_shared/hex.d.ts.map +1 -0
  14. package/dist/_shared/hex.js +40 -0
  15. package/dist/_shared/hex.js.map +1 -0
  16. package/dist/_shared/index.d.ts +14 -0
  17. package/dist/_shared/index.d.ts.map +1 -0
  18. package/dist/_shared/index.js +14 -0
  19. package/dist/_shared/index.js.map +1 -0
  20. package/dist/_shared/keccak256.d.ts +29 -0
  21. package/dist/_shared/keccak256.d.ts.map +1 -0
  22. package/dist/_shared/keccak256.js +145 -0
  23. package/dist/_shared/keccak256.js.map +1 -0
  24. package/dist/_shared/result.d.ts +78 -0
  25. package/dist/_shared/result.d.ts.map +1 -0
  26. package/dist/_shared/result.js +61 -0
  27. package/dist/_shared/result.js.map +1 -0
  28. package/dist/cli/client-config.d.ts +155 -0
  29. package/dist/cli/client-config.d.ts.map +1 -0
  30. package/dist/cli/client-config.js +382 -0
  31. package/dist/cli/client-config.js.map +1 -0
  32. package/dist/cli/connect.d.ts +76 -0
  33. package/dist/cli/connect.d.ts.map +1 -0
  34. package/dist/cli/connect.js +158 -0
  35. package/dist/cli/connect.js.map +1 -0
  36. package/dist/cli/doctor.d.ts +57 -0
  37. package/dist/cli/doctor.d.ts.map +1 -0
  38. package/dist/cli/doctor.js +253 -0
  39. package/dist/cli/doctor.js.map +1 -0
  40. package/dist/cli/index.d.ts +13 -0
  41. package/dist/cli/index.d.ts.map +1 -0
  42. package/dist/cli/index.js +13 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/cli/main.d.ts +45 -0
  45. package/dist/cli/main.d.ts.map +1 -0
  46. package/dist/cli/main.js +371 -0
  47. package/dist/cli/main.js.map +1 -0
  48. package/dist/errors.d.ts +29 -0
  49. package/dist/errors.d.ts.map +1 -0
  50. package/dist/errors.js +37 -0
  51. package/dist/errors.js.map +1 -0
  52. package/dist/http/client-402.d.ts +243 -0
  53. package/dist/http/client-402.d.ts.map +1 -0
  54. package/dist/http/client-402.js +515 -0
  55. package/dist/http/client-402.js.map +1 -0
  56. package/dist/http/headers.d.ts +173 -0
  57. package/dist/http/headers.d.ts.map +1 -0
  58. package/dist/http/headers.js +284 -0
  59. package/dist/http/headers.js.map +1 -0
  60. package/dist/http/index.d.ts +15 -0
  61. package/dist/http/index.d.ts.map +1 -0
  62. package/dist/http/index.js +15 -0
  63. package/dist/http/index.js.map +1 -0
  64. package/dist/http/metering-claim.d.ts +82 -0
  65. package/dist/http/metering-claim.d.ts.map +1 -0
  66. package/dist/http/metering-claim.js +99 -0
  67. package/dist/http/metering-claim.js.map +1 -0
  68. package/dist/index.d.ts +48 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +51 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/logger.d.ts +40 -0
  73. package/dist/logger.d.ts.map +1 -0
  74. package/dist/logger.js +50 -0
  75. package/dist/logger.js.map +1 -0
  76. package/dist/mcp/assets.d.ts +31 -0
  77. package/dist/mcp/assets.d.ts.map +1 -0
  78. package/dist/mcp/assets.js +78 -0
  79. package/dist/mcp/assets.js.map +1 -0
  80. package/dist/mcp/index.d.ts +19 -0
  81. package/dist/mcp/index.d.ts.map +1 -0
  82. package/dist/mcp/index.js +19 -0
  83. package/dist/mcp/index.js.map +1 -0
  84. package/dist/mcp/json-schema.d.ts +86 -0
  85. package/dist/mcp/json-schema.d.ts.map +1 -0
  86. package/dist/mcp/json-schema.js +215 -0
  87. package/dist/mcp/json-schema.js.map +1 -0
  88. package/dist/mcp/json.d.ts +43 -0
  89. package/dist/mcp/json.d.ts.map +1 -0
  90. package/dist/mcp/json.js +69 -0
  91. package/dist/mcp/json.js.map +1 -0
  92. package/dist/mcp/registry-client.d.ts +88 -0
  93. package/dist/mcp/registry-client.d.ts.map +1 -0
  94. package/dist/mcp/registry-client.js +158 -0
  95. package/dist/mcp/registry-client.js.map +1 -0
  96. package/dist/mcp/schemas.d.ts +82 -0
  97. package/dist/mcp/schemas.d.ts.map +1 -0
  98. package/dist/mcp/schemas.js +493 -0
  99. package/dist/mcp/schemas.js.map +1 -0
  100. package/dist/mcp/server.d.ts +97 -0
  101. package/dist/mcp/server.d.ts.map +1 -0
  102. package/dist/mcp/server.js +285 -0
  103. package/dist/mcp/server.js.map +1 -0
  104. package/dist/mcp/settings.d.ts +90 -0
  105. package/dist/mcp/settings.d.ts.map +1 -0
  106. package/dist/mcp/settings.js +160 -0
  107. package/dist/mcp/settings.js.map +1 -0
  108. package/dist/mcp/toolset.d.ts +231 -0
  109. package/dist/mcp/toolset.d.ts.map +1 -0
  110. package/dist/mcp/toolset.js +760 -0
  111. package/dist/mcp/toolset.js.map +1 -0
  112. package/dist/payments/abi.d.ts +9 -0
  113. package/dist/payments/abi.d.ts.map +1 -0
  114. package/dist/payments/abi.js +17 -0
  115. package/dist/payments/abi.js.map +1 -0
  116. package/dist/payments/config.d.ts +199 -0
  117. package/dist/payments/config.d.ts.map +1 -0
  118. package/dist/payments/config.js +259 -0
  119. package/dist/payments/config.js.map +1 -0
  120. package/dist/payments/index.d.ts +13 -0
  121. package/dist/payments/index.d.ts.map +1 -0
  122. package/dist/payments/index.js +13 -0
  123. package/dist/payments/index.js.map +1 -0
  124. package/dist/payments/kuru.d.ts +191 -0
  125. package/dist/payments/kuru.d.ts.map +1 -0
  126. package/dist/payments/kuru.js +377 -0
  127. package/dist/payments/kuru.js.map +1 -0
  128. package/dist/payments/monad.d.ts +69 -0
  129. package/dist/payments/monad.d.ts.map +1 -0
  130. package/dist/payments/monad.js +306 -0
  131. package/dist/payments/monad.js.map +1 -0
  132. package/dist/payments/permit2.d.ts +118 -0
  133. package/dist/payments/permit2.d.ts.map +1 -0
  134. package/dist/payments/permit2.js +366 -0
  135. package/dist/payments/permit2.js.map +1 -0
  136. package/dist/payments/registry.d.ts +119 -0
  137. package/dist/payments/registry.d.ts.map +1 -0
  138. package/dist/payments/registry.js +199 -0
  139. package/dist/payments/registry.js.map +1 -0
  140. package/dist/payments/strategy.d.ts +80 -0
  141. package/dist/payments/strategy.d.ts.map +1 -0
  142. package/dist/payments/strategy.js +103 -0
  143. package/dist/payments/strategy.js.map +1 -0
  144. package/dist/proxy/hooks.d.ts +90 -0
  145. package/dist/proxy/hooks.d.ts.map +1 -0
  146. package/dist/proxy/hooks.js +35 -0
  147. package/dist/proxy/hooks.js.map +1 -0
  148. package/dist/proxy/index.d.ts +9 -0
  149. package/dist/proxy/index.d.ts.map +1 -0
  150. package/dist/proxy/index.js +9 -0
  151. package/dist/proxy/index.js.map +1 -0
  152. package/dist/proxy/proxy.d.ts +156 -0
  153. package/dist/proxy/proxy.d.ts.map +1 -0
  154. package/dist/proxy/proxy.js +366 -0
  155. package/dist/proxy/proxy.js.map +1 -0
  156. package/dist/server/adapters/express.d.ts +89 -0
  157. package/dist/server/adapters/express.d.ts.map +1 -0
  158. package/dist/server/adapters/express.js +215 -0
  159. package/dist/server/adapters/express.js.map +1 -0
  160. package/dist/server/adapters/hono.d.ts +52 -0
  161. package/dist/server/adapters/hono.d.ts.map +1 -0
  162. package/dist/server/adapters/hono.js +61 -0
  163. package/dist/server/adapters/hono.js.map +1 -0
  164. package/dist/server/adapters/next.d.ts +52 -0
  165. package/dist/server/adapters/next.d.ts.map +1 -0
  166. package/dist/server/adapters/next.js +56 -0
  167. package/dist/server/adapters/next.js.map +1 -0
  168. package/dist/server/index.d.ts +30 -0
  169. package/dist/server/index.d.ts.map +1 -0
  170. package/dist/server/index.js +30 -0
  171. package/dist/server/index.js.map +1 -0
  172. package/dist/server/metering.d.ts +209 -0
  173. package/dist/server/metering.d.ts.map +1 -0
  174. package/dist/server/metering.js +365 -0
  175. package/dist/server/metering.js.map +1 -0
  176. package/dist/server/post-paid.d.ts +355 -0
  177. package/dist/server/post-paid.d.ts.map +1 -0
  178. package/dist/server/post-paid.js +512 -0
  179. package/dist/server/post-paid.js.map +1 -0
  180. package/dist/x402/client.d.ts +203 -0
  181. package/dist/x402/client.d.ts.map +1 -0
  182. package/dist/x402/client.js +337 -0
  183. package/dist/x402/client.js.map +1 -0
  184. package/dist/x402/hub.d.ts +79 -0
  185. package/dist/x402/hub.d.ts.map +1 -0
  186. package/dist/x402/hub.js +164 -0
  187. package/dist/x402/hub.js.map +1 -0
  188. package/dist/x402/index.d.ts +27 -0
  189. package/dist/x402/index.d.ts.map +1 -0
  190. package/dist/x402/index.js +27 -0
  191. package/dist/x402/index.js.map +1 -0
  192. package/dist/x402/proxy.d.ts +162 -0
  193. package/dist/x402/proxy.d.ts.map +1 -0
  194. package/dist/x402/proxy.js +198 -0
  195. package/dist/x402/proxy.js.map +1 -0
  196. package/dist/x402/server.d.ts +162 -0
  197. package/dist/x402/server.d.ts.map +1 -0
  198. package/dist/x402/server.js +306 -0
  199. package/dist/x402/server.js.map +1 -0
  200. package/dist/x402/wire.d.ts +104 -0
  201. package/dist/x402/wire.d.ts.map +1 -0
  202. package/dist/x402/wire.js +265 -0
  203. package/dist/x402/wire.js.map +1 -0
  204. package/package.json +61 -0
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Where the MCP server gets its settings, and the order it prefers them in.
3
+ *
4
+ * Three sources, most specific first:
5
+ *
6
+ * 1. the options handed to {@link resolveTabMcpSettings}, which is what a test
7
+ * and an embedding host use;
8
+ * 2. `tab.config.{ts,mts,mjs,js,cjs}`, discovered by walking up from the working
9
+ * directory -- the mechanism this package already has for consumer
10
+ * configuration, so the MCP surface adds no second one;
11
+ * 3. the environment, which is what the `mcpServers` stanza `tab connect` writes
12
+ * actually carries.
13
+ *
14
+ * Every environment variable read here is already declared in the tracked
15
+ * `.env.example` contract. That is not incidental: the repository's environment
16
+ * gate extracts every `process.env` read in the tree and fails the build when
17
+ * one has no declaration, so a new name would be a new line in a contract this
18
+ * surface has no business changing. The RPC endpoint is `MONAD_RPC_URL`, in the
19
+ * stanza and here.
20
+ *
21
+ * ## No key is a setting
22
+ *
23
+ * Nothing in this module reads a private key and nothing returns one. The
24
+ * settlement signing key is read from the environment at the moment a Settlement
25
+ * is signed, by the strategy that signs it, and never travels through a config
26
+ * file or an MCP client's `mcpServers` stanza. That is what makes `tab connect`
27
+ * safe to run against a file the client software rewrites.
28
+ *
29
+ * Requirements: 25.3, 25.5, 28.6
30
+ */
31
+ import { isAddress } from "../_shared/index.js";
32
+ import { loadTabConfig } from "../payments/config.js";
33
+ import { defaultLogger } from "../logger.js";
34
+ /** The public Monad Testnet explorer, used when nothing names one. */
35
+ export const DEFAULT_EXPLORER_URL = "https://testnet.monadvision.com";
36
+ /** Monad Testnet, used when nothing names a chain. */
37
+ export const DEFAULT_CHAIN_ID = 10143;
38
+ const trimmed = (value) => {
39
+ const text = value?.trim();
40
+ return text === undefined || text === "" ? undefined : text;
41
+ };
42
+ /**
43
+ * The registry read API the environment names.
44
+ *
45
+ * `NEXT_PUBLIC_REGISTRY_API_URL` is the deployment's own name for this value and
46
+ * is already in the environment contract, so it is what is read. When only
47
+ * `REGISTRY_PORT` is set the read API is taken to be local, which is exactly the
48
+ * developer case and saves a second variable that would say the same thing.
49
+ */
50
+ const registryUrlFromEnv = (env) => {
51
+ const declared = trimmed(env["NEXT_PUBLIC_REGISTRY_API_URL"]);
52
+ if (declared !== undefined)
53
+ return { url: declared, source: "env NEXT_PUBLIC_REGISTRY_API_URL" };
54
+ const port = trimmed(env["REGISTRY_PORT"]);
55
+ if (port !== undefined && /^[0-9]{1,5}$/.test(port)) {
56
+ return { url: `http://127.0.0.1:${port}`, source: "env REGISTRY_PORT" };
57
+ }
58
+ return undefined;
59
+ };
60
+ /** Keeps the first entry for each serviceId, so a more specific source wins. */
61
+ function mergeServices(...groups) {
62
+ const byId = new Map();
63
+ for (const group of groups) {
64
+ for (const entry of group) {
65
+ if (typeof entry?.serviceId !== "string" || typeof entry?.endpoint !== "string")
66
+ continue;
67
+ const key = entry.serviceId.toLowerCase();
68
+ if (!byId.has(key))
69
+ byId.set(key, { ...entry, serviceId: key });
70
+ }
71
+ }
72
+ return [...byId.values()];
73
+ }
74
+ /**
75
+ * Resolves the settings, loading `tab.config` unless one was handed in.
76
+ *
77
+ * Never fails. A config file that cannot be imported is logged and skipped
78
+ * rather than taking the server down: the tools each report their own missing
79
+ * settings by name, which is a better message than a startup failure that names
80
+ * a file the caller may not have known existed.
81
+ */
82
+ export async function resolveTabMcpSettings(options = {}) {
83
+ const env = options.env ?? process.env;
84
+ const logger = options.logger ?? defaultLogger;
85
+ const sources = {};
86
+ let config = {};
87
+ if (options.config === undefined) {
88
+ const loaded = await loadTabConfig({
89
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
90
+ registry: false,
91
+ logger,
92
+ });
93
+ if (loaded.ok) {
94
+ config = loaded.value.config;
95
+ if (loaded.value.path !== undefined)
96
+ sources["config"] = loaded.value.path;
97
+ }
98
+ else {
99
+ logger.warn("tab config could not be loaded; continuing without it", {
100
+ code: loaded.error.code,
101
+ message: loaded.error.message,
102
+ });
103
+ }
104
+ }
105
+ else if (options.config !== false) {
106
+ config = options.config;
107
+ sources["config"] = "supplied";
108
+ }
109
+ const pick = (key, explicit, fromConfig, fromEnv) => {
110
+ if (trimmed(explicit) !== undefined) {
111
+ sources[key] = "options";
112
+ return trimmed(explicit);
113
+ }
114
+ if (trimmed(fromConfig) !== undefined) {
115
+ sources[key] = "tab.config";
116
+ return trimmed(fromConfig);
117
+ }
118
+ if (fromEnv !== undefined) {
119
+ sources[key] = fromEnv.source;
120
+ return fromEnv.value;
121
+ }
122
+ return undefined;
123
+ };
124
+ const rawAgent = pick("agent", options.agent, config.agent, undefined);
125
+ const agent = rawAgent !== undefined && isAddress(rawAgent) ? rawAgent.toLowerCase() : undefined;
126
+ if (rawAgent !== undefined && agent === undefined) {
127
+ logger.warn("the configured agent is not a 20-byte address and was ignored", { agent: rawAgent });
128
+ delete sources["agent"];
129
+ }
130
+ const envRegistry = registryUrlFromEnv(env);
131
+ const registryUrl = pick("registryUrl", options.registryUrl, config.registryUrl, envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source });
132
+ const envRpc = trimmed(env["MONAD_RPC_URL"]);
133
+ const rpcUrl = pick("rpcUrl", options.rpcUrl, undefined, envRpc === undefined ? undefined : { value: envRpc, source: "env MONAD_RPC_URL" });
134
+ const envChain = trimmed(env["MONAD_CHAIN_ID"]);
135
+ const chainIdText = pick("chainId", options.chainId === undefined ? undefined : String(options.chainId), undefined, envChain === undefined ? undefined : { value: envChain, source: "env MONAD_CHAIN_ID" });
136
+ const chainId = chainIdText !== undefined && /^[0-9]+$/.test(chainIdText) ? Number(chainIdText) : DEFAULT_CHAIN_ID;
137
+ const envExplorer = trimmed(env["MONAD_EXPLORER_URL"]);
138
+ const explorerUrl = pick("explorerUrl", options.explorerUrl, undefined, envExplorer === undefined ? undefined : { value: envExplorer, source: "env MONAD_EXPLORER_URL" }) ?? DEFAULT_EXPLORER_URL;
139
+ const services = mergeServices(options.services ?? [], config.services ?? []);
140
+ if (services.length > 0)
141
+ sources["services"] = options.services === undefined ? "tab.config" : "options";
142
+ const strategyId = trimmed(options.strategyId);
143
+ if (strategyId !== undefined)
144
+ sources["strategyId"] = "options";
145
+ const x402 = options.x402 ?? (typeof config.x402 === "function" ? config.x402 : undefined);
146
+ if (x402 !== undefined)
147
+ sources["x402"] = options.x402 === undefined ? "tab.config" : "options";
148
+ return {
149
+ agent,
150
+ registryUrl,
151
+ rpcUrl,
152
+ chainId,
153
+ explorerUrl,
154
+ services,
155
+ strategyId,
156
+ x402,
157
+ sources,
158
+ };
159
+ }
160
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/mcp/settings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Where the MCP server gets its settings, and the order it prefers them in.\n *\n * Three sources, most specific first:\n *\n * 1. the options handed to {@link resolveTabMcpSettings}, which is what a test\n * and an embedding host use;\n * 2. `tab.config.{ts,mts,mjs,js,cjs}`, discovered by walking up from the working\n * directory -- the mechanism this package already has for consumer\n * configuration, so the MCP surface adds no second one;\n * 3. the environment, which is what the `mcpServers` stanza `tab connect` writes\n * actually carries.\n *\n * Every environment variable read here is already declared in the tracked\n * `.env.example` contract. That is not incidental: the repository's environment\n * gate extracts every `process.env` read in the tree and fails the build when\n * one has no declaration, so a new name would be a new line in a contract this\n * surface has no business changing. The RPC endpoint is `MONAD_RPC_URL`, in the\n * stanza and here.\n *\n * ## No key is a setting\n *\n * Nothing in this module reads a private key and nothing returns one. The\n * settlement signing key is read from the environment at the moment a Settlement\n * is signed, by the strategy that signs it, and never travels through a config\n * file or an MCP client's `mcpServers` stanza. That is what makes `tab connect`\n * safe to run against a file the client software rewrites.\n *\n * Requirements: 25.3, 25.5, 28.6\n */\n\nimport type { Address } from \"../_shared/index.js\";\nimport { isAddress } from \"../_shared/index.js\";\n\nimport type { TabServiceEntry } from \"../payments/config.js\";\nimport { loadTabConfig, type TabConfig } from \"../payments/config.js\";\nimport { defaultLogger, type Logger } from \"../logger.js\";\nimport type { X402SignerFactory } from \"../x402/client.js\";\n\n/** The settings every tool reads. Each field is resolved or explicitly absent. */\nexport interface TabMcpSettings {\n /** Whose Open Tab a metered call lands on. Undefined until one is configured. */\n readonly agent: Address | undefined;\n /** Absolute base URL of the registry read API, or undefined when none is configured. */\n readonly registryUrl: string | undefined;\n /** The Monad JSON-RPC endpoint, used by `doctor` and by nothing that signs. */\n readonly rpcUrl: string | undefined;\n /** The EVM chain id every Asset is named against: 143 for Mainnet, 10143 for Testnet. */\n readonly chainId: number;\n /** Where a Monad transaction is linked. Always resolved; a default is fine for a link. */\n readonly explorerUrl: string;\n /** The endpoint directory, keyed by lower-case serviceId. */\n readonly services: readonly TabServiceEntry[];\n /** Which strategy `tab_settle` settles through when the call names none. */\n readonly strategyId: string | undefined;\n /**\n * The x402 signer factory, for `tab_call`'s prepaid fallback. Never called\n * while settings are resolved; only when a refused call carries an offer.\n */\n readonly x402: X402SignerFactory | undefined;\n /** Where each setting came from, so `doctor` can print it. */\n readonly sources: Readonly<Record<string, string>>;\n}\n\n/** Explicit settings, which beat both the config file and the environment. */\nexport interface TabMcpSettingsOptions {\n readonly agent?: string;\n readonly chainId?: number;\n readonly registryUrl?: string;\n readonly rpcUrl?: string;\n readonly explorerUrl?: string;\n readonly services?: readonly TabServiceEntry[];\n readonly strategyId?: string;\n readonly x402?: X402SignerFactory;\n /** Where the `tab.config` walk starts. Defaults to the working directory. */\n readonly cwd?: string;\n /** `false` skips config discovery entirely, which is what a hermetic test wants. */\n readonly config?: TabConfig | false;\n readonly env?: NodeJS.ProcessEnv;\n readonly logger?: Logger;\n}\n\n/** The public Monad Testnet explorer, used when nothing names one. */\nexport const DEFAULT_EXPLORER_URL = \"https://testnet.monadvision.com\";\n\n/** Monad Testnet, used when nothing names a chain. */\nexport const DEFAULT_CHAIN_ID = 10143;\n\nconst trimmed = (value: string | undefined): string | undefined => {\n const text = value?.trim();\n return text === undefined || text === \"\" ? undefined : text;\n};\n\n/**\n * The registry read API the environment names.\n *\n * `NEXT_PUBLIC_REGISTRY_API_URL` is the deployment's own name for this value and\n * is already in the environment contract, so it is what is read. When only\n * `REGISTRY_PORT` is set the read API is taken to be local, which is exactly the\n * developer case and saves a second variable that would say the same thing.\n */\nconst registryUrlFromEnv = (env: NodeJS.ProcessEnv): { url: string; source: string } | undefined => {\n const declared = trimmed(env[\"NEXT_PUBLIC_REGISTRY_API_URL\"]);\n if (declared !== undefined) return { url: declared, source: \"env NEXT_PUBLIC_REGISTRY_API_URL\" };\n const port = trimmed(env[\"REGISTRY_PORT\"]);\n if (port !== undefined && /^[0-9]{1,5}$/.test(port)) {\n return { url: `http://127.0.0.1:${port}`, source: \"env REGISTRY_PORT\" };\n }\n return undefined;\n};\n\n/** Keeps the first entry for each serviceId, so a more specific source wins. */\nfunction mergeServices(...groups: readonly (readonly TabServiceEntry[])[]): readonly TabServiceEntry[] {\n const byId = new Map<string, TabServiceEntry>();\n for (const group of groups) {\n for (const entry of group) {\n if (typeof entry?.serviceId !== \"string\" || typeof entry?.endpoint !== \"string\") continue;\n const key = entry.serviceId.toLowerCase();\n if (!byId.has(key)) byId.set(key, { ...entry, serviceId: key });\n }\n }\n return [...byId.values()];\n}\n\n/**\n * Resolves the settings, loading `tab.config` unless one was handed in.\n *\n * Never fails. A config file that cannot be imported is logged and skipped\n * rather than taking the server down: the tools each report their own missing\n * settings by name, which is a better message than a startup failure that names\n * a file the caller may not have known existed.\n */\nexport async function resolveTabMcpSettings(\n options: TabMcpSettingsOptions = {},\n): Promise<TabMcpSettings> {\n const env = options.env ?? process.env;\n const logger = options.logger ?? defaultLogger;\n const sources: Record<string, string> = {};\n\n let config: TabConfig = {};\n if (options.config === undefined) {\n const loaded = await loadTabConfig({\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n registry: false,\n logger,\n });\n if (loaded.ok) {\n config = loaded.value.config;\n if (loaded.value.path !== undefined) sources[\"config\"] = loaded.value.path;\n } else {\n logger.warn(\"tab config could not be loaded; continuing without it\", {\n code: loaded.error.code,\n message: loaded.error.message,\n });\n }\n } else if (options.config !== false) {\n config = options.config;\n sources[\"config\"] = \"supplied\";\n }\n\n const pick = (\n key: string,\n explicit: string | undefined,\n fromConfig: string | undefined,\n fromEnv: { value: string; source: string } | undefined,\n ): string | undefined => {\n if (trimmed(explicit) !== undefined) {\n sources[key] = \"options\";\n return trimmed(explicit);\n }\n if (trimmed(fromConfig) !== undefined) {\n sources[key] = \"tab.config\";\n return trimmed(fromConfig);\n }\n if (fromEnv !== undefined) {\n sources[key] = fromEnv.source;\n return fromEnv.value;\n }\n return undefined;\n };\n\n const rawAgent = pick(\"agent\", options.agent, config.agent, undefined);\n const agent = rawAgent !== undefined && isAddress(rawAgent) ? (rawAgent.toLowerCase() as Address) : undefined;\n if (rawAgent !== undefined && agent === undefined) {\n logger.warn(\"the configured agent is not a 20-byte address and was ignored\", { agent: rawAgent });\n delete sources[\"agent\"];\n }\n\n const envRegistry = registryUrlFromEnv(env);\n const registryUrl = pick(\n \"registryUrl\",\n options.registryUrl,\n config.registryUrl,\n envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source },\n );\n\n const envRpc = trimmed(env[\"MONAD_RPC_URL\"]);\n const rpcUrl = pick(\n \"rpcUrl\",\n options.rpcUrl,\n undefined,\n envRpc === undefined ? undefined : { value: envRpc, source: \"env MONAD_RPC_URL\" },\n );\n\n const envChain = trimmed(env[\"MONAD_CHAIN_ID\"]);\n const chainIdText = pick(\n \"chainId\",\n options.chainId === undefined ? undefined : String(options.chainId),\n undefined,\n envChain === undefined ? undefined : { value: envChain, source: \"env MONAD_CHAIN_ID\" },\n );\n const chainId = chainIdText !== undefined && /^[0-9]+$/.test(chainIdText) ? Number(chainIdText) : DEFAULT_CHAIN_ID;\n\n const envExplorer = trimmed(env[\"MONAD_EXPLORER_URL\"]);\n const explorerUrl =\n pick(\n \"explorerUrl\",\n options.explorerUrl,\n undefined,\n envExplorer === undefined ? undefined : { value: envExplorer, source: \"env MONAD_EXPLORER_URL\" },\n ) ?? DEFAULT_EXPLORER_URL;\n\n const services = mergeServices(options.services ?? [], config.services ?? []);\n if (services.length > 0) sources[\"services\"] = options.services === undefined ? \"tab.config\" : \"options\";\n\n const strategyId = trimmed(options.strategyId);\n if (strategyId !== undefined) sources[\"strategyId\"] = \"options\";\n\n const x402 = options.x402 ?? (typeof config.x402 === \"function\" ? config.x402 : undefined);\n if (x402 !== undefined) sources[\"x402\"] = options.x402 === undefined ? \"tab.config\" : \"options\";\n\n return {\n agent,\n registryUrl,\n rpcUrl,\n chainId,\n explorerUrl,\n services,\n strategyId,\n x402,\n sources,\n };\n}\n"]}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * The four Tab tools, as functions.
3
+ *
4
+ * The MCP protocol wiring lives next door in `server.ts`. This file is the
5
+ * behaviour, and it is separate so the tools can be exercised without a
6
+ * transport: every test in `test/mcp-tools.test.mjs` calls these directly, which
7
+ * is what lets task 16.3 validate every output against its declared schema
8
+ * without standing a server up.
9
+ *
10
+ * ## Nothing here throws, including into the transport
11
+ *
12
+ * A tool that throws over stdio does not produce a bad answer, it produces no
13
+ * answer: the MCP client sees a protocol error, the model sees nothing it can
14
+ * reason about, and a long-running server can lose its transport to one
15
+ * malformed argument. So every entry point below returns a value that validates
16
+ * against the tool's declared output schema, on every path, including the paths
17
+ * where the work failed. A failure is `error: { category, code, message }` in
18
+ * the payload, and for `tab_call` and `tab_settle` it is `ok: false` beside it.
19
+ *
20
+ * `LIMIT_EXCEEDED` is the case that earns the discipline. An Agent out of
21
+ * headroom is not an error in the Agent, the Service, or the call -- it is the
22
+ * credit facility working. The tool answers `ok: false` with
23
+ * `requiredBaseUnits` and `headroomBaseUnits` both filled in, so the model can
24
+ * settle the difference and call again instead of retrying into the same wall.
25
+ * (R21.5)
26
+ *
27
+ * ## Every input is validated against the schema that was published
28
+ *
29
+ * Not a hand-written check that resembles it. {@link applyJsonDefaults} fills in
30
+ * the declared defaults and {@link validateJsonValue} enforces the same document
31
+ * `tools/list` served, so a `limit` of 500 is refused with the same bound the
32
+ * model was shown.
33
+ *
34
+ * Requirements: 21.5, 25.1, 25.2, 25.3, 25.4
35
+ */
36
+ import type { Result, TabError } from "../_shared/index.js";
37
+ import { type Tab402Fetch, type Tab402Response } from "../http/client-402.js";
38
+ import { type Logger } from "../logger.js";
39
+ import { type StrategyRegistry } from "../payments/registry.js";
40
+ import { type RegistryFetch, type RegistryReadClient } from "./registry-client.js";
41
+ import { type HubFetch } from "../x402/hub.js";
42
+ import type { TabMcpSettings } from "./settings.js";
43
+ /** The error block every output can carry. */
44
+ export interface TabToolError {
45
+ readonly category: TabError["category"];
46
+ readonly code: string;
47
+ readonly message: string;
48
+ readonly retryable: boolean;
49
+ readonly requiredBaseUnits?: string;
50
+ readonly headroomBaseUnits?: string;
51
+ }
52
+ export interface DiscoveredAsset {
53
+ readonly chainId: number;
54
+ readonly address: string;
55
+ readonly symbol: string | null;
56
+ readonly decimals: number | null;
57
+ readonly collectionAddress: string | null;
58
+ readonly curatedAsset: boolean;
59
+ }
60
+ export interface DiscoveredTool {
61
+ readonly tool: string;
62
+ readonly toolName: string | null;
63
+ readonly asset: string;
64
+ readonly priceBaseUnits: string;
65
+ }
66
+ export interface DiscoveredBond {
67
+ readonly asset: string;
68
+ readonly stakedBaseUnits: string;
69
+ readonly freeBaseUnits: string;
70
+ }
71
+ export interface DiscoveredHubEndpoint {
72
+ readonly endpoint: string;
73
+ readonly name: string | null;
74
+ readonly description: string | null;
75
+ readonly priceType: string;
76
+ readonly priceUsd: string | null;
77
+ readonly priceBaseUnits: string | null;
78
+ readonly networks: readonly string[];
79
+ }
80
+ /** The API Hub provider a Service fronts, with its endpoints as the Service's tools. */
81
+ export interface DiscoveredHub {
82
+ readonly provider: string;
83
+ readonly prefix: string;
84
+ readonly endpoints: readonly DiscoveredHubEndpoint[];
85
+ readonly total: number;
86
+ /** Present when the manifest could not be read; `endpoints` is then empty. */
87
+ readonly error?: TabToolError;
88
+ }
89
+ export interface DiscoveredService {
90
+ readonly serviceId: string;
91
+ readonly name: string | null;
92
+ readonly endpoint: string | null;
93
+ readonly tier: "curated" | "permissionless" | "unknown";
94
+ readonly settlementWindowSeconds: number;
95
+ readonly assets: readonly DiscoveredAsset[];
96
+ readonly tools: readonly DiscoveredTool[];
97
+ readonly bonds: readonly DiscoveredBond[];
98
+ readonly pendingChange: {
99
+ readonly changeId: string;
100
+ readonly kind: string | null;
101
+ readonly etaIso: string | null;
102
+ } | null;
103
+ readonly hub?: DiscoveredHub;
104
+ }
105
+ export interface TabDiscoverOutput {
106
+ readonly services: readonly DiscoveredService[];
107
+ readonly error?: TabToolError;
108
+ }
109
+ /** The prepaid receipt a call carries when x402 paid for it instead of the Open Tab. */
110
+ export interface TabCallX402Block {
111
+ readonly txHash: string;
112
+ readonly network: string;
113
+ readonly amountBaseUnits: string;
114
+ readonly asset: string;
115
+ readonly payTo: string;
116
+ readonly payer: string;
117
+ readonly explorerUrl: string | null;
118
+ }
119
+ export interface TabCallOutput {
120
+ readonly ok: boolean;
121
+ readonly result?: unknown;
122
+ readonly charge?: {
123
+ readonly amountBaseUnits: string;
124
+ readonly asset: string;
125
+ readonly tool: string;
126
+ };
127
+ readonly tab?: {
128
+ readonly openTabBaseUnits: string;
129
+ readonly headroomBaseUnits: string;
130
+ readonly creditLimitBaseUnits?: string;
131
+ readonly asset: string;
132
+ readonly settlementDueIso?: string | null;
133
+ };
134
+ readonly x402?: TabCallX402Block;
135
+ readonly error?: TabToolError;
136
+ }
137
+ export interface TabStatusOutput {
138
+ readonly agent: string;
139
+ /**
140
+ * The Monad block every figure here is as at, from the index that served them.
141
+ *
142
+ * A Settlement in a later block is not yet reflected; the index reaches it
143
+ * within a few blocks. Null when the index has never ticked or the read failed.
144
+ */
145
+ readonly indexedBlock: number | null;
146
+ readonly perAsset: readonly {
147
+ readonly asset: string;
148
+ readonly creditLimitBaseUnits: string | null;
149
+ readonly openTabBaseUnits: string;
150
+ readonly prepaidBaseUnits: string | null;
151
+ readonly headroomBaseUnits: string | null;
152
+ readonly delinquent: boolean;
153
+ readonly tabs: readonly {
154
+ readonly tabId: string | null;
155
+ readonly serviceId: string;
156
+ readonly openBaseUnits: string;
157
+ readonly dueIso: string | null;
158
+ }[];
159
+ }[];
160
+ readonly settlements?: readonly {
161
+ readonly settlementId: string;
162
+ readonly txHash: string;
163
+ readonly serviceId: string;
164
+ readonly asset: string;
165
+ readonly amountBaseUnits: string;
166
+ readonly appliedBaseUnits: string;
167
+ readonly prepaidBaseUnits: string;
168
+ readonly explorerUrl: string | null;
169
+ }[];
170
+ readonly error?: TabToolError;
171
+ }
172
+ export interface TabSettleOutput {
173
+ readonly ok: boolean;
174
+ readonly dryRun: boolean;
175
+ readonly txHash?: string | null;
176
+ readonly chainId?: number | null;
177
+ readonly amountBaseUnits: string;
178
+ readonly settlementId?: string | null;
179
+ readonly appliedBaseUnits?: string | null;
180
+ readonly prepaidBaseUnits?: string | null;
181
+ readonly explorerUrl?: string | null;
182
+ readonly error?: TabToolError;
183
+ }
184
+ export interface TabToolsetOptions {
185
+ readonly settings: TabMcpSettings;
186
+ /** Overrides the client built from `settings.registryUrl`. A test hands in a stub. */
187
+ readonly registry?: RegistryReadClient;
188
+ /** The `fetch` `tab_call` sends Service requests with. Defaults to the host's. */
189
+ readonly fetchImpl?: Tab402Fetch<Tab402Response>;
190
+ /**
191
+ * The `fetch` the registry read client uses, when one is built from settings.
192
+ *
193
+ * Separate from {@link TabToolsetOptions.fetchImpl} because the two talk to
194
+ * different things: one to a third party's Service, one to the read API. A
195
+ * test that stubs a Service should not silently start answering registry
196
+ * reads too.
197
+ */
198
+ readonly registryFetch?: RegistryFetch;
199
+ /** The `fetch` `tab_discover` reads API Hub manifests with. Defaults to the host's. */
200
+ readonly hubFetch?: HubFetch;
201
+ /**
202
+ * Where `tab_settle` resolves a strategy.
203
+ *
204
+ * Absent, the module-level registry is used, and `tab_settle` fills it from
205
+ * `tab.config` the first time it is called. See {@link TabToolset.settle} for
206
+ * why that load is deferred rather than done at startup.
207
+ */
208
+ readonly strategies?: StrategyRegistry;
209
+ /** Where the deferred `tab.config` load walks from. Defaults to the working directory. */
210
+ readonly cwd?: string;
211
+ readonly logger?: Logger;
212
+ readonly now?: () => number;
213
+ /**
214
+ * The environment the Asset table is read from: on Testnet `MOCK_USDC_ADDRESS`
215
+ * names the token this deployment settles in. Defaults to the process
216
+ * environment; a test passes its own so a machine's configuration cannot
217
+ * change a result.
218
+ */
219
+ readonly env?: NodeJS.ProcessEnv;
220
+ }
221
+ /** The four tools, plus a dispatcher the MCP server calls by name. */
222
+ export interface TabToolset {
223
+ discover(input: unknown): Promise<TabDiscoverOutput>;
224
+ call(input: unknown): Promise<TabCallOutput>;
225
+ status(input: unknown): Promise<TabStatusOutput>;
226
+ settle(input: unknown): Promise<TabSettleOutput>;
227
+ /** Dispatches by MCP tool name. `NOT_FOUND` for a name this package does not declare. */
228
+ invoke(name: string, input: unknown): Promise<Result<unknown>>;
229
+ }
230
+ export declare function createTabToolset(options: TabToolsetOptions): TabToolset;
231
+ //# sourceMappingURL=toolset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolset.d.ts","sourceRoot":"","sources":["../../src/mcp/toolset.ts"],"names":[],"mappings":"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"}