opentool 0.4.6 → 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 (49) hide show
  1. package/README.md +95 -30
  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/validate-DiIOFUU5.d.ts +828 -0
  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 +39 -4
  20. package/dist/cli/build.d.ts +0 -8
  21. package/dist/cli/build.d.ts.map +0 -1
  22. package/dist/cli/build.js +0 -508
  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 -168
  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 -291
  31. package/dist/cli/generate-metadata.js.map +0 -1
  32. package/dist/cli/index.d.ts.map +0 -1
  33. package/dist/cli/validate.d.ts +0 -8
  34. package/dist/cli/validate.d.ts.map +0 -1
  35. package/dist/cli/validate.js +0 -328
  36. package/dist/cli/validate.js.map +0 -1
  37. package/dist/index.d.ts.map +0 -1
  38. package/dist/runtime/index.d.ts +0 -11
  39. package/dist/runtime/index.d.ts.map +0 -1
  40. package/dist/runtime/index.js +0 -192
  41. package/dist/runtime/index.js.map +0 -1
  42. package/dist/types/index.d.ts +0 -50
  43. package/dist/types/index.d.ts.map +0 -1
  44. package/dist/types/index.js +0 -3
  45. package/dist/types/index.js.map +0 -1
  46. package/dist/types/metadata.d.ts +0 -65
  47. package/dist/types/metadata.d.ts.map +0 -1
  48. package/dist/types/metadata.js +0 -3
  49. package/dist/types/metadata.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
 
@@ -188,10 +251,9 @@ When you push a project with `opentool` dependency to GitHub and connect it to O
188
251
 
189
252
  ## Examples
190
253
 
191
- See the `examples/` directory for complete examples:
254
+ See the `examples/` directory for a comprehensive example:
192
255
 
193
- - **`examples/full-metadata/`** - Complete metadata configuration with payment and discovery features
194
- - **`examples/minimal/`** - Minimal setup demonstrating smart defaults
256
+ - **`examples/full-metadata/`** - Metadata configuration with payment and discovery features
195
257
 
196
258
  ### Testing Examples Locally
197
259
 
@@ -207,16 +269,16 @@ cd examples/full-metadata
207
269
  npm link opentool
208
270
  npm run build
209
271
 
210
- # Test the minimal example
211
- cd ../minimal
212
- npm link opentool
213
- npm run build
214
-
215
272
  # Examine generated output
216
273
  cat dist/metadata.json
217
274
 
218
275
  # Test the MCP server
219
276
  echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | node dist/mcp-server.js
277
+
278
+ # Quick regression helpers from the repo root
279
+ npm run examples:build # Build full metadata example (CJS+ESM)
280
+ npm run examples:validate # Validate example metadata and tools
281
+ npm run examples:metadata # Regenerate metadata.json without rebuilding tools
220
282
  ```
221
283
 
222
284
  ## Metadata System
@@ -224,16 +286,19 @@ echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | node dist/mcp-serve
224
286
  OpenTool features a sophisticated **three-tier metadata system**:
225
287
 
226
288
  1. **Smart Defaults** - Zero configuration, automatic generation from `package.json`
227
- 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
228
290
  3. **Full Control** - Tool-level overrides for rich discovery metadata
229
291
 
230
292
  See [`METADATA.md`](./METADATA.md) for the complete guide to configuring metadata for on-chain registration and payments.
231
293
 
294
+ ## Future Work
295
+
296
+ - Explore an esbuild-powered watch mode that keeps metadata and tool artifacts up to date for the dev server. This remains on the follow-up list once the new pipeline settles.
297
+
232
298
  ## Contributing
233
299
 
234
300
  We welcome contributions! Please see our [Contributing Guide](https://github.com/openpond/opentool/blob/master/CONTRIBUTING.md) for details.
235
301
 
236
-
237
302
  ## License
238
303
 
239
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 };