opentool 0.7.7 → 0.7.9

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/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import { I as InternalToolDefinition, T as ToolResponse } from './validate-BrOwtVYW.js';
3
- export { B as BuildConfig, i as BuildMetadata, H as HTTP_METHODS, d as HttpHandlerDefinition, c as HttpMethod, M as McpConfig, h as Metadata, P as PaymentConfig, S as ServerConfig, e as Tool, b as ToolContent, f as ToolMetadataOverrides, g as generateMetadata, a as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand } from './validate-BrOwtVYW.js';
2
+ import { I as InternalToolDefinition, T as ToolResponse } from './validate-BBjyq5nS.js';
3
+ export { B as BuildConfig, k as BuildMetadata, H as HTTP_METHODS, f as HttpHandlerDefinition, e as HttpMethod, h as McpConfig, M as Metadata, P as PaymentConfig, S as ServerConfig, i as Tool, d as ToolContent, j as ToolMetadataOverrides, b as generateMetadata, g as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand } from './validate-BBjyq5nS.js';
4
+ import { z, ZodSchema } from 'zod';
4
5
  export { CurrencySpec, DEFAULT_FACILITATOR, DefineX402PaymentConfig, EIP3009Authorization, PAYMENT_HEADERS, RequireX402PaymentOptions, RequireX402PaymentOutcome, RequireX402PaymentSuccess, SUPPORTED_CURRENCIES, X402BrowserClient, X402BrowserClientConfig, X402Client, X402ClientConfig, X402FacilitatorConfig, X402PayRequest, X402PayResult, X402Payment, X402PaymentContext, X402PaymentDefinition, X402PaymentRequiredError, X402VerificationResult, defineX402Payment, getX402PaymentContext, payX402, payX402WithWallet, requireX402Payment, withX402Payment } from './x402/index.js';
5
6
  export { ChainMetadata, ChainReference, ChainTokenMap, DEFAULT_CHAIN, DEFAULT_TOKENS, Hex, HexAddress, RpcProviderOptions, RpcUrlResolver, TokenMetadata, TurnkeyOptions, TurnkeySignWith, WalletBaseContext, WalletContext, WalletFullContext, WalletOptions, WalletOptionsBase, WalletPrivateKeyOptions, WalletProviderType, WalletReadonlyContext, WalletReadonlyOptions, WalletRegistry, WalletSendTransactionParams, WalletSignerContext, WalletTransferParams, WalletTurnkeyOptions, chains, getRpcUrl, registry, tokens, wallet, walletToolkit } from './wallets/index.js';
6
7
  export { AIAbortError, AIClientConfig, AIError, AIFetchError, AIRequestMetadata, AIResponseError, ChatCompletionChoice, ChatCompletionLogProbs, ChatCompletionResponse, ChatCompletionUsage, ChatMessage, ChatMessageContentPart, ChatMessageContentPartImageUrl, ChatMessageContentPartText, ChatMessageRole, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, FunctionToolDefinition, GenerateTextOptions, GenerateTextResult, GenerationParameters, JsonSchema, ResolvedAIClientConfig, ResponseErrorDetails, StreamTextOptions, StreamTextResult, StreamingEventHandlers, ToolChoice, ToolDefinition, ToolExecutionPolicy, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, WebSearchOptions, createAIClient, ensureTextContent, flattenMessageContent, generateText, getModelConfig, isStreamingSupported, isToolCallingSupported, listModels, normalizeModelName, resolveConfig, resolveToolset, streamText } from './ai/index.js';
7
- import { ZodSchema } from 'zod';
8
8
  import 'viem';
9
9
  import 'viem/accounts';
10
10
 
@@ -18,6 +18,39 @@ declare function createDevServer(tools: InternalToolDefinition[]): Server;
18
18
  declare function createStdioServer(tools?: InternalToolDefinition[]): Promise<void>;
19
19
  declare function resolveRuntimePath(value: string): string;
20
20
 
21
+ type CronSpec = {
22
+ cron: string;
23
+ enabled?: boolean;
24
+ };
25
+ type ToolProfileGET = {
26
+ description: string;
27
+ schedule: CronSpec;
28
+ fixedAmount?: string;
29
+ tokenSymbol?: string;
30
+ limits?: {
31
+ concurrency?: number;
32
+ dailyCap?: number;
33
+ };
34
+ };
35
+ type ToolProfilePOST = {
36
+ description?: string;
37
+ };
38
+ type GetHandler = (req: Request) => Promise<Response> | Response;
39
+ type PostHandler = (req: Request) => Promise<Response> | Response;
40
+ type ToolModuleGET = {
41
+ profile: ToolProfileGET;
42
+ GET: GetHandler;
43
+ POST?: never;
44
+ schema?: never;
45
+ };
46
+ type ToolModulePOST<B = unknown> = {
47
+ profile?: ToolProfilePOST;
48
+ POST: PostHandler;
49
+ schema: z.ZodType<B>;
50
+ GET?: never;
51
+ };
52
+ type ToolModule = ToolModuleGET | ToolModulePOST<any>;
53
+
21
54
  interface CreateMcpAdapterOptions {
22
55
  name: string;
23
56
  schema?: ZodSchema;
@@ -30,4 +63,4 @@ interface CreateMcpAdapterOptions {
30
63
  declare function createMcpAdapter(options: CreateMcpAdapterOptions): (rawArguments: unknown) => Promise<ToolResponse>;
31
64
  declare function responseToToolResponse(response: Response): Promise<ToolResponse>;
32
65
 
33
- export { InternalToolDefinition, ToolResponse, createDevServer, createMcpAdapter, createStdioServer, resolveRuntimePath, responseToToolResponse };
66
+ export { type CronSpec, type GetHandler, InternalToolDefinition, type PostHandler, type ToolModule, type ToolModuleGET, type ToolModulePOST, type ToolProfileGET, type ToolProfilePOST, ToolResponse, createDevServer, createMcpAdapter, createStdioServer, resolveRuntimePath, responseToToolResponse };
package/dist/index.js CHANGED
@@ -132,6 +132,7 @@ function extractX402Attempt(request) {
132
132
  }
133
133
  async function verifyX402Payment(attempt, definition, options = {}) {
134
134
  const fetchImpl = options.fetchImpl ?? fetch;
135
+ const timeout = options.timeout ?? 25e3;
135
136
  const facilitator = definition.facilitator;
136
137
  const verifierUrl = new URL(
137
138
  facilitator.verifyPath ?? "/verify",
@@ -147,13 +148,18 @@ async function verifyX402Payment(attempt, definition, options = {}) {
147
148
  };
148
149
  console.log("[x402] Calling facilitator /verify", {
149
150
  url: verifierUrl,
150
- bodyPreview: JSON.stringify(verifyBody).substring(0, 200)
151
- });
152
- const verifyResponse = await fetchImpl(verifierUrl, {
153
- method: "POST",
154
- headers,
155
- body: JSON.stringify(verifyBody)
151
+ fullBody: JSON.stringify(verifyBody, null, 2)
156
152
  });
153
+ const verifyResponse = await Promise.race([
154
+ fetchImpl(verifierUrl, {
155
+ method: "POST",
156
+ headers,
157
+ body: JSON.stringify(verifyBody)
158
+ }),
159
+ new Promise(
160
+ (_, reject) => setTimeout(() => reject(new Error(`Verification timeout after ${timeout}ms`)), timeout)
161
+ )
162
+ ]);
157
163
  console.log("[x402] Facilitator /verify response", { status: verifyResponse.status });
158
164
  if (!verifyResponse.ok) {
159
165
  const errorText = await verifyResponse.text().catch(() => "");
@@ -183,27 +189,39 @@ async function verifyX402Payment(attempt, definition, options = {}) {
183
189
  ensureTrailingSlash(facilitator.url)
184
190
  ).toString();
185
191
  try {
186
- console.log("[x402] Calling facilitator /settle", { url: settleUrl });
187
- const settleResponse = await fetchImpl(settleUrl, {
188
- method: "POST",
189
- headers,
190
- body: JSON.stringify({
191
- x402Version: attempt.payload.x402Version,
192
- paymentPayload: attempt.payload,
193
- paymentRequirements: requirement
194
- })
192
+ const settleBody = {
193
+ x402Version: attempt.payload.x402Version,
194
+ paymentPayload: attempt.payload,
195
+ paymentRequirements: requirement
196
+ };
197
+ console.log("[x402] Calling facilitator /settle", {
198
+ url: settleUrl,
199
+ bodyPreview: JSON.stringify(settleBody).substring(0, 300)
195
200
  });
201
+ const settleResponse = await Promise.race([
202
+ fetchImpl(settleUrl, {
203
+ method: "POST",
204
+ headers,
205
+ body: JSON.stringify(settleBody)
206
+ }),
207
+ new Promise(
208
+ (_, reject) => setTimeout(() => reject(new Error(`Settlement timeout after ${timeout}ms`)), timeout)
209
+ )
210
+ ]);
196
211
  console.log("[x402] Facilitator /settle response", { status: settleResponse.status });
197
212
  if (!settleResponse.ok) {
213
+ const errorText = await settleResponse.text().catch(() => "");
214
+ console.error("[x402] Facilitator /settle error", { status: settleResponse.status, body: errorText });
198
215
  return {
199
216
  success: false,
200
217
  failure: {
201
- reason: `Facilitator settlement failed: ${settleResponse.status}`,
218
+ reason: `Facilitator settlement failed: ${settleResponse.status}${errorText ? ` - ${errorText}` : ""}`,
202
219
  code: "settlement_failed"
203
220
  }
204
221
  };
205
222
  }
206
223
  const settlePayload = await settleResponse.json();
224
+ console.log("[x402] Facilitator /settle success", { txHash: settlePayload.txHash });
207
225
  if (settlePayload.txHash) {
208
226
  responseHeaders[HEADER_PAYMENT_RESPONSE] = JSON.stringify({
209
227
  settled: true,
@@ -211,6 +229,7 @@ async function verifyX402Payment(attempt, definition, options = {}) {
211
229
  });
212
230
  }
213
231
  } catch (error) {
232
+ console.error("[x402] Settlement exception", { error: error instanceof Error ? error.message : String(error) });
214
233
  return {
215
234
  success: false,
216
235
  failure: {
@@ -2718,6 +2737,12 @@ async function loadAndValidateTools(toolsDir, options = {}) {
2718
2737
  if (fs2.existsSync(tempDir)) {
2719
2738
  fs2.rmSync(tempDir, { recursive: true, force: true });
2720
2739
  }
2740
+ const kebabCase = /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z]+$/;
2741
+ for (const f of files) {
2742
+ if (!kebabCase.test(f)) {
2743
+ throw new Error(`Tool filename must be kebab-case: ${f}`);
2744
+ }
2745
+ }
2721
2746
  const entryPoints = files.map((file) => path5.join(toolsDir, file));
2722
2747
  const { outDir, cleanup } = await transpileWithEsbuild({
2723
2748
  entryPoints,
@@ -2742,6 +2767,30 @@ async function loadAndValidateTools(toolsDir, options = {}) {
2742
2767
  const inputSchemaRaw = schema ? toJsonSchema(toolName, schema) : void 0;
2743
2768
  const inputSchema = normalizeInputSchema2(inputSchemaRaw);
2744
2769
  const httpHandlersRaw = collectHttpHandlers2(toolModule, file);
2770
+ const hasGET = typeof toolModule.GET === "function";
2771
+ const hasPOST = typeof toolModule.POST === "function";
2772
+ const otherMethods = HTTP_METHODS2.filter((m) => m !== "GET" && m !== "POST").filter(
2773
+ (m) => typeof toolModule[m] === "function"
2774
+ );
2775
+ if (otherMethods.length > 0) {
2776
+ throw new Error(
2777
+ `${file} must not export ${otherMethods.join(", ")}. Only one of GET or POST is allowed.`
2778
+ );
2779
+ }
2780
+ if (hasGET === hasPOST) {
2781
+ throw new Error(`${file}: export exactly one of GET or POST`);
2782
+ }
2783
+ if (hasGET) {
2784
+ const schedule = toolModule?.profile?.schedule;
2785
+ if (!schedule || typeof schedule?.cron !== "string" || schedule.cron.trim().length === 0) {
2786
+ throw new Error(`${file}: GET tools require profile.schedule { cron }`);
2787
+ }
2788
+ }
2789
+ if (hasPOST) {
2790
+ if (!schema) {
2791
+ throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
2792
+ }
2793
+ }
2745
2794
  const httpHandlers = [...httpHandlersRaw];
2746
2795
  if (httpHandlers.length === 0) {
2747
2796
  throw new Error(