opentool 0.5.0 → 0.6.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 (60) hide show
  1. package/README.md +84 -22
  2. package/dist/ai/index.d.ts +237 -0
  3. package/dist/ai/index.js +759 -0
  4. package/dist/ai/index.js.map +1 -0
  5. package/dist/cli/index.d.ts +38 -5
  6. package/dist/cli/index.js +2218 -67
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/index-D3DaM5Rs.d.ts +1693 -0
  9. package/dist/index.d.ts +33 -5
  10. package/dist/index.js +3258 -25
  11. package/dist/index.js.map +1 -1
  12. package/dist/payment/index.d.ts +2 -0
  13. package/dist/payment/index.js +969 -0
  14. package/dist/payment/index.js.map +1 -0
  15. package/dist/{types/metadata.d.ts → validate-DiIOFUU5.d.ts} +262 -415
  16. package/dist/wallets/index.d.ts +117 -0
  17. package/dist/wallets/index.js +337 -0
  18. package/dist/wallets/index.js.map +1 -0
  19. package/package.json +35 -4
  20. package/dist/cli/build.d.ts +0 -23
  21. package/dist/cli/build.d.ts.map +0 -1
  22. package/dist/cli/build.js +0 -223
  23. package/dist/cli/build.js.map +0 -1
  24. package/dist/cli/dev.d.ts +0 -6
  25. package/dist/cli/dev.d.ts.map +0 -1
  26. package/dist/cli/dev.js +0 -123
  27. package/dist/cli/dev.js.map +0 -1
  28. package/dist/cli/generate-metadata.d.ts +0 -15
  29. package/dist/cli/generate-metadata.d.ts.map +0 -1
  30. package/dist/cli/generate-metadata.js +0 -90
  31. package/dist/cli/generate-metadata.js.map +0 -1
  32. package/dist/cli/index.d.ts.map +0 -1
  33. package/dist/cli/shared/metadata.d.ts +0 -19
  34. package/dist/cli/shared/metadata.d.ts.map +0 -1
  35. package/dist/cli/shared/metadata.js +0 -283
  36. package/dist/cli/shared/metadata.js.map +0 -1
  37. package/dist/cli/validate.d.ts +0 -12
  38. package/dist/cli/validate.d.ts.map +0 -1
  39. package/dist/cli/validate.js +0 -237
  40. package/dist/cli/validate.js.map +0 -1
  41. package/dist/index.d.ts.map +0 -1
  42. package/dist/runtime/index.d.ts +0 -12
  43. package/dist/runtime/index.d.ts.map +0 -1
  44. package/dist/runtime/index.js +0 -241
  45. package/dist/runtime/index.js.map +0 -1
  46. package/dist/types/index.d.ts +0 -33
  47. package/dist/types/index.d.ts.map +0 -1
  48. package/dist/types/index.js +0 -3
  49. package/dist/types/index.js.map +0 -1
  50. package/dist/types/metadata.d.ts.map +0 -1
  51. package/dist/types/metadata.js +0 -108
  52. package/dist/types/metadata.js.map +0 -1
  53. package/dist/utils/esbuild.d.ts +0 -13
  54. package/dist/utils/esbuild.d.ts.map +0 -1
  55. package/dist/utils/esbuild.js +0 -95
  56. package/dist/utils/esbuild.js.map +0 -1
  57. package/dist/utils/module-loader.d.ts +0 -3
  58. package/dist/utils/module-loader.d.ts.map +0 -1
  59. package/dist/utils/module-loader.js +0 -49
  60. package/dist/utils/module-loader.js.map +0 -1
package/README.md CHANGED
@@ -3,20 +3,44 @@
3
3
  [![npm version](https://badge.fury.io/js/opentool.svg)](https://badge.fury.io/js/opentool)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- ## OpenPond Hosting launching August 2025
6
+ A comprehensive TypeScript framework for building, deploying, and monetizing serverless MCP (Model Context Protocol) tools with integrated AI, blockchain wallets, and crypto payments.
7
7
 
8
- (current openpond.ai site hasn't been updated yet)
8
+ ## Overview
9
9
 
10
- A TypeScript framework for building serverless MCP (Model Context Protocol) tools that automatically deploy to AWS Lambda using [OpenPond](https://openpond.ai) hosting.
10
+ OpenTool is a complete platform for creating intelligent, payment-enabled tools that run on AWS Lambda. It combines:
11
+
12
+ - **MCP Protocol** - Full Model Context Protocol implementation with stdio and HTTP transports
13
+ - **AI Integration** - Built-in AI client with text generation, streaming, and tool calling capabilities
14
+ - **Wallet System** - Multi-chain blockchain wallet support with Turnkey and private key providers
15
+ - **Payment Infrastructure** - Crypto payment integration for monetizing tools on-chain
16
+ - **Serverless Deployment** - Automatic AWS Lambda deployment via [OpenPond](https://openpond.ai)
17
+ - **Type Safety** - Full TypeScript support with Zod schema validation
11
18
 
12
19
  ## Features
13
20
 
14
- - **Serverless-first**: Tools automatically deploy to AWS Lambda
15
- - **Type-safe**: Full TypeScript support with Zod schema validation
16
- - **CLI Tools**: Build, develop, and validate your tools
17
- - **MCP Compatible**: Works with any MCP client
18
- - **Automatic Detection**: Detected by OpenPond hosting platform
19
- - **Local Development**: Test your tools locally before deployment
21
+ ### Core Framework
22
+ - **Serverless-first**: Tools automatically deploy to AWS Lambda with Function URLs
23
+ - **Type-safe**: Full TypeScript support with Zod schema validation and automatic JSON schema generation
24
+ - **CLI Tools**: Build, develop, validate, and generate metadata with comprehensive CLI
25
+ - **Hot Reloading**: Development server with optional watch mode for rapid iteration
26
+ - **MCP Compatible**: Works with any MCP client (Claude Desktop, MCP Inspector, etc.)
27
+
28
+ ### AI Capabilities
29
+ - **Multi-Model Support**: OpenAI, Anthropic, and compatible providers
30
+ - **Text Generation**: Simple and streaming text generation with tool calling
31
+ - **Built-in Tools**: Web search and custom tool integration
32
+ - **Model Management**: Automatic model normalization and capability detection
33
+
34
+ ### Blockchain & Payments
35
+ - **Multi-Chain Wallets**: Support for Ethereum, Base, Optimism, Arbitrum, Polygon, and more
36
+ - **Provider Flexibility**: Private key or Turnkey-managed signing
37
+ - **Crypto Payments**: On-chain payment integration with ERC-20 token support
38
+ - **Token Registry**: Built-in registry for common tokens (USDC, USDT, DAI, etc.)
39
+
40
+ ### Discovery & Metadata
41
+ - **Three-Tier Metadata**: Smart defaults, enhanced metadata, and per-tool overrides
42
+ - **On-Chain Registration**: Metadata formatted for blockchain discovery
43
+ - **Rich Annotations**: Icons, categories, tags, and custom branding
20
44
 
21
45
  ## Installation
22
46
 
@@ -47,8 +71,18 @@ export const schema = z.object({
47
71
  name: z.string().describe("The name of the user to greet"),
48
72
  });
49
73
 
50
- export async function TOOL({ name }: z.infer<typeof schema>) {
51
- return `Hello, ${name}! 👋`;
74
+ export const metadata = {
75
+ name: "greet",
76
+ description: "Simple greeting tool",
77
+ };
78
+
79
+ export async function POST(request: Request) {
80
+ const payload = await request.json();
81
+ const { name } = schema.parse(payload);
82
+
83
+ return Response.json({
84
+ message: `Hello, ${name}!`,
85
+ });
52
86
  }
53
87
  ```
54
88
 
@@ -62,6 +96,19 @@ npx opentool validate
62
96
  npx opentool dev
63
97
  ```
64
98
 
99
+ ### MCP Inspector
100
+
101
+ The `examples/full-metadata` project includes an `inspector.json` preset so you can exercise MCP tools with the official MCP Inspector:
102
+
103
+ ```bash
104
+ cd examples/full-metadata
105
+ npx mcp-inspector --config inspector.json --server opentool-dev
106
+ ```
107
+
108
+ Before starting the inspector, copy `examples/full-metadata/.env.example` to `examples/full-metadata/.env` and populate the Turnkey, 0x, and Alchemy secrets with your own credentials. The actual `.env` file is git-ignored so you can keep real keys out of version control.
109
+
110
+ The inspector spawns `opentool dev --stdio --no-watch --input tools`, so you don’t need a second terminal. Only tools that export `mcp = { enabled: true }` (for example `mcp_ping`) appear in the inspector’s tool list; HTTP-only tools like `calculate` and `hello` keep responding on the local HTTP port.
111
+
65
112
  ### 4. Build for deployment
66
113
 
67
114
  ```bash
@@ -134,11 +181,11 @@ This command generates the `metadata.json` file that contains all the informatio
134
181
 
135
182
  ## Tool Definition
136
183
 
137
- Each tool is defined by exporting three things:
184
+ Each tool is defined by exporting:
138
185
 
139
186
  1. **schema**: Zod schema for input validation
140
187
  2. **metadata**: Tool information and MCP annotations
141
- 3. **TOOL**: Async function that implements the tool logic
188
+ 3. **HTTP handler**: Async function that implements the tool logic (e.g., POST, GET, PUT, DELETE)
142
189
 
143
190
  ```typescript
144
191
  import { z } from "zod";
@@ -147,23 +194,39 @@ export const schema = z.object({
147
194
  // Define your input parameters here
148
195
  });
149
196
 
150
- export async function TOOL(params: z.infer<typeof schema>) {
197
+ export const metadata = {
198
+ name: "my_tool",
199
+ description: "Description of what this tool does",
200
+ };
201
+
202
+ export async function POST(request: Request) {
203
+ const payload = await request.json();
204
+ const params = schema.parse(payload);
205
+
151
206
  // Implement your tool logic here
152
- // Just return a string - it will be wrapped in MCP format automatically
153
- return "Tool response";
207
+ return Response.json({
208
+ result: "Tool response",
209
+ });
154
210
  }
155
211
  ```
156
212
 
157
213
  ## Error Handling
158
214
 
159
- Simply throw errors in your TOOL function - they will be automatically converted to MCP error responses:
215
+ Return appropriate HTTP status codes and error messages in your response:
160
216
 
161
217
  ```typescript
162
- export async function TOOL(params: z.infer<typeof schema>) {
218
+ export async function POST(request: Request) {
219
+ const payload = await request.json();
220
+ const params = schema.parse(payload);
221
+
163
222
  if (someCondition) {
164
- throw new Error("Something went wrong");
223
+ return Response.json(
224
+ { error: "Something went wrong" },
225
+ { status: 400 }
226
+ );
165
227
  }
166
- return "Success";
228
+
229
+ return Response.json({ result: "Success" });
167
230
  }
168
231
  ```
169
232
 
@@ -223,7 +286,7 @@ npm run examples:metadata # Regenerate metadata.json without rebuilding tools
223
286
  OpenTool features a sophisticated **three-tier metadata system**:
224
287
 
225
288
  1. **Smart Defaults** - Zero configuration, automatic generation from `package.json`
226
- 2. **Enhanced Metadata** - Optional `metadata.ts` for custom branding and crypto payments
289
+ 2. **Enhanced Metadata** - Optional `metadata.ts` for custom branding and crypto payments
227
290
  3. **Full Control** - Tool-level overrides for rich discovery metadata
228
291
 
229
292
  See [`METADATA.md`](./METADATA.md) for the complete guide to configuring metadata for on-chain registration and payments.
@@ -236,7 +299,6 @@ See [`METADATA.md`](./METADATA.md) for the complete guide to configuring metadat
236
299
 
237
300
  We welcome contributions! Please see our [Contributing Guide](https://github.com/openpond/opentool/blob/master/CONTRIBUTING.md) for details.
238
301
 
239
-
240
302
  ## License
241
303
 
242
304
  MIT © [OpenTool](https://opentool.dev)
@@ -0,0 +1,237 @@
1
+ type ChatMessageRole = "system" | "user" | "assistant" | "tool";
2
+ interface ChatMessageContentPartText {
3
+ type: "text";
4
+ text: string;
5
+ }
6
+ interface ChatMessageContentPartImageUrl {
7
+ type: "image_url";
8
+ image_url: {
9
+ url: string;
10
+ detail?: "auto" | "high" | "low";
11
+ };
12
+ }
13
+ type ChatMessageContentPart = ChatMessageContentPartText | ChatMessageContentPartImageUrl | Record<string, unknown>;
14
+ interface ChatMessage {
15
+ role: ChatMessageRole;
16
+ content: string | ChatMessageContentPart[];
17
+ name?: string;
18
+ tool_call_id?: string;
19
+ }
20
+ interface JsonSchema {
21
+ type?: string;
22
+ title?: string;
23
+ description?: string;
24
+ properties?: Record<string, JsonSchema>;
25
+ required?: string[];
26
+ items?: JsonSchema | JsonSchema[];
27
+ enum?: Array<string | number | boolean | null>;
28
+ additionalProperties?: boolean | JsonSchema;
29
+ [key: string]: unknown;
30
+ }
31
+ interface FunctionToolDefinition {
32
+ type: "function";
33
+ function: {
34
+ name: string;
35
+ description?: string;
36
+ parameters?: JsonSchema;
37
+ };
38
+ }
39
+ type ToolDefinition = FunctionToolDefinition;
40
+ type ToolChoice = "auto" | "required" | "none" | {
41
+ type: "function";
42
+ function: {
43
+ name: string;
44
+ };
45
+ };
46
+ interface GenerationParameters {
47
+ temperature?: number;
48
+ topP?: number;
49
+ maxTokens?: number;
50
+ stop?: string | string[];
51
+ frequencyPenalty?: number;
52
+ presencePenalty?: number;
53
+ responseFormat?: "json_object" | "text" | {
54
+ type: "json_schema";
55
+ json_schema: JsonSchema;
56
+ };
57
+ }
58
+ interface ToolExecutionPolicy {
59
+ enableTools?: boolean;
60
+ maxSteps?: number;
61
+ toolSources?: "internal" | "public" | "both";
62
+ webSearch?: WebSearchOptions | false;
63
+ }
64
+ interface WebSearchOptions {
65
+ limit?: number;
66
+ includeImages?: boolean;
67
+ }
68
+ interface AIRequestMetadata {
69
+ requestId?: string;
70
+ sessionId?: string;
71
+ tags?: string[];
72
+ openpond?: Record<string, unknown>;
73
+ [key: string]: unknown;
74
+ }
75
+ interface GenerateTextOptions {
76
+ messages: ChatMessage[];
77
+ model?: string;
78
+ generation?: GenerationParameters;
79
+ tools?: ToolDefinition[];
80
+ toolChoice?: ToolChoice;
81
+ toolExecution?: ToolExecutionPolicy;
82
+ metadata?: AIRequestMetadata;
83
+ timeoutMs?: number;
84
+ abortSignal?: AbortSignal;
85
+ headers?: Record<string, string>;
86
+ }
87
+ interface AIClientConfig {
88
+ baseUrl?: string;
89
+ apiKey?: string;
90
+ defaultModel?: string;
91
+ defaultHeaders?: Record<string, string>;
92
+ fetchImplementation?: typeof fetch;
93
+ timeoutMs?: number;
94
+ }
95
+ interface ResolvedAIClientConfig {
96
+ baseUrl: string;
97
+ apiKey?: string;
98
+ defaultModel: string;
99
+ defaultHeaders: Record<string, string>;
100
+ fetchImplementation: typeof fetch;
101
+ timeoutMs: number;
102
+ }
103
+ interface ChatCompletionResponse {
104
+ id: string;
105
+ object: string;
106
+ created: number;
107
+ model: string;
108
+ choices: ChatCompletionChoice[];
109
+ usage?: ChatCompletionUsage;
110
+ system_fingerprint?: string;
111
+ }
112
+ interface ChatCompletionChoice {
113
+ index: number;
114
+ message: ChatMessage;
115
+ finish_reason?: string;
116
+ logprobs?: ChatCompletionLogProbs;
117
+ }
118
+ interface ChatCompletionUsage {
119
+ prompt_tokens: number;
120
+ completion_tokens: number;
121
+ total_tokens: number;
122
+ [key: string]: unknown;
123
+ }
124
+ interface ChatCompletionLogProbs {
125
+ content?: Array<{
126
+ token: string;
127
+ logprob: number;
128
+ bytes?: number[];
129
+ }>;
130
+ }
131
+ interface GenerateTextResult {
132
+ id: string;
133
+ model: string;
134
+ message: ChatMessage;
135
+ finishReason?: string;
136
+ usage?: ChatCompletionUsage;
137
+ raw: ChatCompletionResponse;
138
+ }
139
+ interface StreamingEventHandlers {
140
+ onTextDelta?: (delta: string) => void;
141
+ onToolCallDelta?: (toolCall: unknown) => void;
142
+ onReasoningDelta?: (delta: string) => void;
143
+ onUsage?: (usage: ChatCompletionUsage) => void;
144
+ onError?: (error: unknown) => void;
145
+ onDone?: () => void;
146
+ }
147
+ interface StreamTextOptions extends GenerateTextOptions {
148
+ handlers?: StreamingEventHandlers;
149
+ sendReasoning?: boolean;
150
+ includeUsage?: boolean;
151
+ }
152
+ interface StreamTextResult {
153
+ abort: () => void;
154
+ finished: Promise<void>;
155
+ }
156
+
157
+ interface ErrorInit {
158
+ cause?: unknown;
159
+ }
160
+ declare class AIError extends Error {
161
+ constructor(message: string, options?: ErrorInit);
162
+ }
163
+ interface ResponseErrorDetails {
164
+ status: number;
165
+ statusText: string;
166
+ body?: unknown;
167
+ headers?: Record<string, string>;
168
+ }
169
+ declare class AIFetchError extends AIError {
170
+ constructor(message: string, options?: ErrorInit);
171
+ }
172
+ declare class AIResponseError extends AIError {
173
+ readonly status: number;
174
+ readonly statusText: string;
175
+ readonly body?: unknown;
176
+ readonly headers: Record<string, string>;
177
+ constructor(details: ResponseErrorDetails, message?: string);
178
+ }
179
+ declare class AIAbortError extends AIError {
180
+ constructor(message?: string);
181
+ }
182
+
183
+ type ModelProvider = "openai" | "anthropic" | "google" | "deepseek" | "custom";
184
+ interface ModelConfig {
185
+ name: string;
186
+ label: string;
187
+ provider: ModelProvider;
188
+ supportsStreaming: boolean;
189
+ supportsTools: boolean;
190
+ reasoning?: boolean;
191
+ aliases?: string[];
192
+ default?: boolean;
193
+ }
194
+ declare function listModels(): ModelConfig[];
195
+ declare function getModelConfig(modelName?: string): ModelConfig | undefined;
196
+ declare function normalizeModelName(modelName?: string): string;
197
+ declare function isStreamingSupported(modelName?: string): boolean;
198
+ declare function isToolCallingSupported(modelName?: string): boolean;
199
+
200
+ interface AIClient {
201
+ readonly config: ResolvedAIClientConfig;
202
+ generateText(options: GenerateTextOptions): Promise<GenerateTextResult>;
203
+ streamText(options: StreamTextOptions): Promise<StreamTextResult>;
204
+ listModels: typeof listModels;
205
+ }
206
+ declare function createAIClient(config?: AIClientConfig): AIClient;
207
+ declare function generateText(options: GenerateTextOptions, clientConfig?: AIClientConfig): Promise<GenerateTextResult>;
208
+ declare function streamText(options: StreamTextOptions, clientConfig?: AIClientConfig): Promise<StreamTextResult>;
209
+
210
+ declare const DEFAULT_BASE_URL = "https://gateway.openpond.dev";
211
+ declare const DEFAULT_TIMEOUT_MS = 60000;
212
+ declare const DEFAULT_MODEL = "openai/gpt-5-mini";
213
+ declare function resolveConfig(config?: AIClientConfig): ResolvedAIClientConfig;
214
+
215
+ declare const WEBSEARCH_TOOL_NAME = "websearch";
216
+ declare const WEBSEARCH_TOOL_DEFINITION: ToolDefinition;
217
+ declare function resolveToolset(tools: ToolDefinition[] | undefined, policy: ToolExecutionPolicy | undefined): ToolDefinition[] | undefined;
218
+
219
+ interface FlattenMessageContentOptions {
220
+ /**
221
+ * String used to join individual text segments when the content array contains multiple text parts.
222
+ * Defaults to an empty string.
223
+ */
224
+ separator?: string;
225
+ /**
226
+ * When true, JSON stringifies non-text segments instead of discarding them.
227
+ * Defaults to false (skip non-text parts).
228
+ */
229
+ includeUnknown?: boolean;
230
+ }
231
+ declare function flattenMessageContent(content: ChatMessage["content"], options?: FlattenMessageContentOptions): string | undefined;
232
+ interface EnsureTextContentOptions extends FlattenMessageContentOptions {
233
+ errorMessage?: string;
234
+ }
235
+ declare function ensureTextContent(message: ChatMessage, options?: EnsureTextContentOptions): string;
236
+
237
+ export { AIAbortError, type AIClientConfig, AIError, AIFetchError, type AIRequestMetadata, AIResponseError, type ChatCompletionChoice, type ChatCompletionLogProbs, type ChatCompletionResponse, type ChatCompletionUsage, type ChatMessage, type ChatMessageContentPart, type ChatMessageContentPartImageUrl, type ChatMessageContentPartText, type ChatMessageRole, DEFAULT_BASE_URL, DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, type FunctionToolDefinition, type GenerateTextOptions, type GenerateTextResult, type GenerationParameters, type JsonSchema, type ResolvedAIClientConfig, type ResponseErrorDetails, type StreamTextOptions, type StreamTextResult, type StreamingEventHandlers, type ToolChoice, type ToolDefinition, type ToolExecutionPolicy, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, type WebSearchOptions, createAIClient, ensureTextContent, flattenMessageContent, generateText, getModelConfig, isStreamingSupported, isToolCallingSupported, listModels, normalizeModelName, resolveConfig, resolveToolset, streamText };