@ctxprotocol/sdk 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.
package/README.md ADDED
@@ -0,0 +1,281 @@
1
+ # @ctxprotocol/sdk
2
+
3
+ The official TypeScript SDK for the [Context Protocol](https://ctxprotocol.com) — the monetization layer for MCP. Discover and execute AI tools programmatically.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@ctxprotocol/sdk.svg)](https://www.npmjs.com/package/@ctxprotocol/sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @ctxprotocol/sdk
12
+ ```
13
+
14
+ ```bash
15
+ pnpm add @ctxprotocol/sdk
16
+ ```
17
+
18
+ ```bash
19
+ yarn add @ctxprotocol/sdk
20
+ ```
21
+
22
+ ## Prerequisites
23
+
24
+ Before using the API, you must complete setup via the web dashboard:
25
+
26
+ 1. **Sign in** at [ctxprotocol.com](https://ctxprotocol.com) — Creates your embedded wallet
27
+ 2. **Enable Auto Pay** — Approve USDC spending for tool payments
28
+ 3. **Fund wallet** — Add USDC for tool execution fees
29
+ 4. **Generate API key** — In Settings page
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { ContextClient } from "@ctxprotocol/sdk";
35
+
36
+ // Initialize the client with your API key
37
+ const client = new ContextClient({
38
+ apiKey: "sk_live_...",
39
+ });
40
+
41
+ // 1. Discover tools
42
+ const tools = await client.discovery.search("gas prices");
43
+ console.log(tools[0].name); // "Gas Price Oracle"
44
+ console.log(tools[0].mcpTools); // Available methods
45
+
46
+ // 2. Execute a tool method
47
+ const result = await client.tools.execute({
48
+ toolId: tools[0].id,
49
+ toolName: tools[0].mcpTools[0].name, // e.g., "get_gas_prices"
50
+ args: { chainId: 1 },
51
+ });
52
+
53
+ console.log(result.result); // Tool output data
54
+ console.log(result.durationMs); // Execution time in ms
55
+ ```
56
+
57
+ ## Configuration
58
+
59
+ ### Client Options
60
+
61
+ | Option | Type | Required | Default | Description |
62
+ | --------- | -------- | -------- | ------------------------ | ------------------------------ |
63
+ | `apiKey` | `string` | Yes | — | Your Context Protocol API key |
64
+ | `baseUrl` | `string` | No | `https://ctxprotocol.com`| API base URL (for development) |
65
+
66
+ ```typescript
67
+ // Production usage
68
+ const client = new ContextClient({
69
+ apiKey: process.env.CONTEXT_API_KEY!,
70
+ });
71
+
72
+ // Development/testing with local server
73
+ const devClient = new ContextClient({
74
+ apiKey: "sk_test_...",
75
+ baseUrl: "http://localhost:3000",
76
+ });
77
+ ```
78
+
79
+ ## API Reference
80
+
81
+ ### Discovery
82
+
83
+ #### `client.discovery.search(query, limit?)`
84
+
85
+ Search for tools matching a query string.
86
+
87
+ ```typescript
88
+ const tools = await client.discovery.search("gas prices", 10);
89
+
90
+ // Returns: Tool[]
91
+ // [
92
+ // {
93
+ // id: "uuid-string",
94
+ // name: "Gas Price Oracle",
95
+ // description: "Get current gas prices",
96
+ // price: "0.001",
97
+ // category: "defi",
98
+ // isVerified: true,
99
+ // kind: "mcp",
100
+ // mcpTools: [
101
+ // { name: "get_gas_prices", description: "Get gas prices for a chain" },
102
+ // { name: "get_supported_chains", description: "List supported chains" }
103
+ // ]
104
+ // }
105
+ // ]
106
+ ```
107
+
108
+ #### `client.discovery.getFeatured(limit?)`
109
+
110
+ Get featured/popular tools.
111
+
112
+ ```typescript
113
+ const featured = await client.discovery.getFeatured(5);
114
+ ```
115
+
116
+ ### Tools
117
+
118
+ #### `client.tools.execute(options)`
119
+
120
+ Execute a tool method with the provided arguments.
121
+
122
+ ```typescript
123
+ const result = await client.tools.execute({
124
+ toolId: "uuid-of-tool", // From search results
125
+ toolName: "get_gas_prices", // From tool's mcpTools array
126
+ args: { chainId: 1 }, // Tool-specific arguments
127
+ });
128
+
129
+ // Returns: ExecutionResult<T>
130
+ // {
131
+ // result: { gasPrice: "25.5", unit: "gwei", ... },
132
+ // tool: { id: "uuid", name: "Gas Price Oracle" },
133
+ // durationMs: 245
134
+ // }
135
+ ```
136
+
137
+ ## Types
138
+
139
+ All types are exported for full TypeScript autocomplete support:
140
+
141
+ ```typescript
142
+ import type {
143
+ ContextClientOptions,
144
+ Tool,
145
+ McpTool,
146
+ ExecuteOptions,
147
+ ExecutionResult,
148
+ ContextErrorCode,
149
+ } from "@ctxprotocol/sdk";
150
+ ```
151
+
152
+ ### Tool
153
+
154
+ ```typescript
155
+ interface Tool {
156
+ id: string;
157
+ name: string;
158
+ description: string;
159
+ price: string;
160
+ category?: string;
161
+ isVerified?: boolean;
162
+ kind?: string;
163
+ mcpTools?: McpTool[];
164
+ }
165
+
166
+ interface McpTool {
167
+ name: string;
168
+ description: string;
169
+ }
170
+ ```
171
+
172
+ ### ExecuteOptions
173
+
174
+ ```typescript
175
+ interface ExecuteOptions {
176
+ toolId: string; // UUID of the tool
177
+ toolName: string; // MCP method name from mcpTools array
178
+ args?: Record<string, unknown>;
179
+ }
180
+ ```
181
+
182
+ ### ExecutionResult
183
+
184
+ ```typescript
185
+ interface ExecutionResult<T = unknown> {
186
+ result: T;
187
+ tool: { id: string; name: string };
188
+ durationMs: number;
189
+ }
190
+ ```
191
+
192
+ ## Error Handling
193
+
194
+ The SDK throws `ContextError` for all API errors with specific error codes:
195
+
196
+ ```typescript
197
+ import { ContextClient, ContextError } from "@ctxprotocol/sdk";
198
+
199
+ try {
200
+ const result = await client.tools.execute({
201
+ toolId: "...",
202
+ toolName: "...",
203
+ args: {},
204
+ });
205
+ } catch (error) {
206
+ if (error instanceof ContextError) {
207
+ console.error("Error:", error.message);
208
+ console.error("Code:", error.code);
209
+ console.error("HTTP Status:", error.statusCode);
210
+
211
+ // Handle specific error cases
212
+ switch (error.code) {
213
+ case "no_wallet":
214
+ console.log("Please set up your wallet at", error.helpUrl);
215
+ break;
216
+ case "insufficient_allowance":
217
+ console.log("Please enable Auto Pay at", error.helpUrl);
218
+ break;
219
+ case "payment_failed":
220
+ console.log("Payment transaction failed");
221
+ break;
222
+ case "execution_failed":
223
+ console.log("Tool execution failed");
224
+ break;
225
+ }
226
+ }
227
+ }
228
+ ```
229
+
230
+ ### Error Codes
231
+
232
+ | Code | Description |
233
+ | ------------------------ | ---------------------------------------- |
234
+ | `unauthorized` | Missing or invalid API key |
235
+ | `no_wallet` | User hasn't set up wallet via dashboard |
236
+ | `insufficient_allowance` | Auto Pay not enabled or allowance too low|
237
+ | `payment_failed` | On-chain payment transaction failed |
238
+ | `execution_failed` | MCP tool execution error |
239
+
240
+ ## Authentication
241
+
242
+ All requests are automatically authenticated using the Bearer token scheme:
243
+
244
+ ```
245
+ Authorization: Bearer sk_live_...
246
+ ```
247
+
248
+ Your API key should be kept secret. Use environment variables in production:
249
+
250
+ ```typescript
251
+ const client = new ContextClient({
252
+ apiKey: process.env.CONTEXT_API_KEY!,
253
+ });
254
+ ```
255
+
256
+ ## Payment Flow
257
+
258
+ When you execute a tool:
259
+
260
+ 1. Your pre-approved USDC allowance is used for payment
261
+ 2. **90%** goes to the tool developer
262
+ 3. **10%** goes to the protocol
263
+ 4. Tool executes and returns results
264
+
265
+ Ensure your wallet has sufficient USDC balance before executing paid tools.
266
+
267
+ ## Links
268
+
269
+ - [Context Protocol](https://ctxprotocol.com) — Main website
270
+ - [GitHub](https://github.com/ctxprotocol/context) — Main project repository
271
+ - [SDK Repository](https://github.com/ctxprotocol/sdk) — This SDK
272
+ - [NPM Package](https://www.npmjs.com/package/@ctxprotocol/sdk)
273
+
274
+ ## Requirements
275
+
276
+ - Node.js 18.0.0 or later (for native `fetch` support)
277
+ - TypeScript 5.0+ (recommended)
278
+
279
+ ## License
280
+
281
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,194 @@
1
+ 'use strict';
2
+
3
+ // src/types.ts
4
+ var ContextError = class extends Error {
5
+ constructor(message, code, statusCode, helpUrl) {
6
+ super(message);
7
+ this.code = code;
8
+ this.statusCode = statusCode;
9
+ this.helpUrl = helpUrl;
10
+ this.name = "ContextError";
11
+ }
12
+ };
13
+
14
+ // src/resources/discovery.ts
15
+ var Discovery = class {
16
+ constructor(client) {
17
+ this.client = client;
18
+ }
19
+ /**
20
+ * Search for tools matching a query string
21
+ *
22
+ * @param query - The search query (e.g., "gas prices", "nft metadata")
23
+ * @param limit - Maximum number of results (1-50, default 10)
24
+ * @returns Array of matching tools
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const tools = await client.discovery.search("gas prices");
29
+ * console.log(tools[0].name); // "Gas Price Oracle"
30
+ * console.log(tools[0].mcpTools); // Available methods
31
+ * ```
32
+ */
33
+ async search(query, limit) {
34
+ const params = new URLSearchParams();
35
+ if (query) {
36
+ params.set("q", query);
37
+ }
38
+ if (limit !== void 0) {
39
+ params.set("limit", String(limit));
40
+ }
41
+ const queryString = params.toString();
42
+ const endpoint = `/api/v1/tools/search${queryString ? `?${queryString}` : ""}`;
43
+ const response = await this.client.fetch(endpoint);
44
+ return response.tools;
45
+ }
46
+ /**
47
+ * Get featured/popular tools (empty query search)
48
+ *
49
+ * @param limit - Maximum number of results (1-50, default 10)
50
+ * @returns Array of featured tools
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const featured = await client.discovery.getFeatured(5);
55
+ * ```
56
+ */
57
+ async getFeatured(limit) {
58
+ return this.search("", limit);
59
+ }
60
+ };
61
+
62
+ // src/resources/tools.ts
63
+ var Tools = class {
64
+ constructor(client) {
65
+ this.client = client;
66
+ }
67
+ /**
68
+ * Execute a tool with the provided arguments
69
+ *
70
+ * @param options - Execution options
71
+ * @param options.toolId - The UUID of the tool (from search results)
72
+ * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)
73
+ * @param options.args - Arguments to pass to the tool
74
+ * @returns The execution result with the tool's output data
75
+ *
76
+ * @throws {ContextError} With code `no_wallet` if wallet not set up
77
+ * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled
78
+ * @throws {ContextError} With code `payment_failed` if on-chain payment fails
79
+ * @throws {ContextError} With code `execution_failed` if tool execution fails
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * // First, search for a tool
84
+ * const tools = await client.discovery.search("gas prices");
85
+ * const tool = tools[0];
86
+ *
87
+ * // Execute a specific method from the tool's mcpTools
88
+ * const result = await client.tools.execute({
89
+ * toolId: tool.id,
90
+ * toolName: tool.mcpTools[0].name, // e.g., "get_gas_prices"
91
+ * args: { chainId: 1 }
92
+ * });
93
+ *
94
+ * console.log(result.result); // The tool's output
95
+ * console.log(result.durationMs); // Execution time
96
+ * ```
97
+ */
98
+ async execute(options) {
99
+ const { toolId, toolName, args } = options;
100
+ const response = await this.client.fetch(
101
+ "/api/v1/tools/execute",
102
+ {
103
+ method: "POST",
104
+ body: JSON.stringify({ toolId, toolName, args })
105
+ }
106
+ );
107
+ if ("error" in response) {
108
+ throw new ContextError(
109
+ response.error,
110
+ response.code,
111
+ 400,
112
+ response.helpUrl
113
+ );
114
+ }
115
+ if (response.success) {
116
+ return {
117
+ result: response.result,
118
+ tool: response.tool,
119
+ durationMs: response.durationMs
120
+ };
121
+ }
122
+ throw new ContextError("Unexpected response format from API");
123
+ }
124
+ };
125
+
126
+ // src/client.ts
127
+ var ContextClient = class {
128
+ apiKey;
129
+ baseUrl;
130
+ /**
131
+ * Discovery resource for searching tools
132
+ */
133
+ discovery;
134
+ /**
135
+ * Tools resource for executing tools
136
+ */
137
+ tools;
138
+ /**
139
+ * Creates a new Context Protocol client
140
+ *
141
+ * @param options - Client configuration options
142
+ * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
143
+ * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
144
+ */
145
+ constructor(options) {
146
+ if (!options.apiKey) {
147
+ throw new ContextError("API key is required");
148
+ }
149
+ this.apiKey = options.apiKey;
150
+ this.baseUrl = (options.baseUrl ?? "https://ctxprotocol.com").replace(/\/$/, "");
151
+ this.discovery = new Discovery(this);
152
+ this.tools = new Tools(this);
153
+ }
154
+ /**
155
+ * Internal method for making authenticated HTTP requests
156
+ * All requests include the Authorization header with the API key
157
+ *
158
+ * @internal
159
+ */
160
+ async fetch(endpoint, options = {}) {
161
+ const url = `${this.baseUrl}${endpoint}`;
162
+ const response = await fetch(url, {
163
+ ...options,
164
+ headers: {
165
+ "Content-Type": "application/json",
166
+ Authorization: `Bearer ${this.apiKey}`,
167
+ ...options.headers
168
+ }
169
+ });
170
+ if (!response.ok) {
171
+ let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
172
+ let errorCode;
173
+ let helpUrl;
174
+ try {
175
+ const errorBody = await response.json();
176
+ if (errorBody.error) {
177
+ errorMessage = errorBody.error;
178
+ errorCode = errorBody.code;
179
+ helpUrl = errorBody.helpUrl;
180
+ }
181
+ } catch {
182
+ }
183
+ throw new ContextError(errorMessage, errorCode, response.status, helpUrl);
184
+ }
185
+ return response.json();
186
+ }
187
+ };
188
+
189
+ exports.ContextClient = ContextClient;
190
+ exports.ContextError = ContextError;
191
+ exports.Discovery = Discovery;
192
+ exports.Tools = Tools;
193
+ //# sourceMappingURL=index.cjs.map
194
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/resources/discovery.ts","../src/resources/tools.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Configuration options for initializing the ContextClient\n */\nexport interface ContextClientOptions {\n /**\n * Your Context Protocol API key\n * @example \"sk_live_abc123...\"\n */\n apiKey: string;\n\n /**\n * Base URL for the Context Protocol API\n * @default \"https://ctxprotocol.com\"\n */\n baseUrl?: string;\n}\n\n/**\n * An individual MCP tool exposed by a tool listing\n */\nexport interface McpTool {\n /** Name of the MCP tool method */\n name: string;\n\n /** Description of what this method does */\n description: string;\n}\n\n/**\n * Represents a tool available on the Context Protocol marketplace\n */\nexport interface Tool {\n /** Unique identifier for the tool (UUID) */\n id: string;\n\n /** Human-readable name of the tool */\n name: string;\n\n /** Description of what the tool does */\n description: string;\n\n /** Price per execution in USDC */\n price: string;\n\n /** Tool category (e.g., \"defi\", \"nft\") */\n category?: string;\n\n /** Whether the tool is verified by Context Protocol */\n isVerified?: boolean;\n\n /** Type of tool (e.g., \"mcp\") */\n kind?: string;\n\n /**\n * Available MCP tool methods\n * Use items from this array as `toolName` when executing\n */\n mcpTools?: McpTool[];\n\n /** Creation timestamp */\n createdAt?: string;\n\n /** Last update timestamp */\n updatedAt?: string;\n}\n\n/**\n * Response from the tools search endpoint\n */\nexport interface SearchResponse {\n /** Array of matching tools */\n tools: Tool[];\n\n /** The search query that was used */\n query: string;\n\n /** Total number of results */\n count: number;\n}\n\n/**\n * Options for searching tools\n */\nexport interface SearchOptions {\n /** Search query (semantic search) */\n query?: string;\n\n /** Maximum number of results (1-50, default 10) */\n limit?: number;\n}\n\n/**\n * Options for executing a tool\n */\nexport interface ExecuteOptions {\n /** The UUID of the tool to execute (from search results) */\n toolId: string;\n\n /** The specific MCP tool name to call (from tool's mcpTools array) */\n toolName: string;\n\n /** Arguments to pass to the tool */\n args?: Record<string, unknown>;\n}\n\n/**\n * Successful execution response from the API\n */\nexport interface ExecuteApiSuccessResponse {\n success: true;\n\n /** The result data from the tool execution */\n result: unknown;\n\n /** Information about the executed tool */\n tool: {\n id: string;\n name: string;\n };\n\n /** Execution duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Error response from the API\n */\nexport interface ExecuteApiErrorResponse {\n /** Human-readable error message */\n error: string;\n\n /** Error code for programmatic handling */\n code?: ContextErrorCode;\n\n /** URL to help resolve the issue */\n helpUrl?: string;\n}\n\n/**\n * Raw API response from the execute endpoint\n */\nexport type ExecuteApiResponse = ExecuteApiSuccessResponse | ExecuteApiErrorResponse;\n\n/**\n * The resolved result returned to the user after SDK processing\n */\nexport interface ExecutionResult<T = unknown> {\n /** The data returned by the tool */\n result: T;\n\n /** Information about the executed tool */\n tool: {\n id: string;\n name: string;\n };\n\n /** Execution duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Specific error codes returned by the Context Protocol API\n */\nexport type ContextErrorCode =\n | \"unauthorized\"\n | \"no_wallet\"\n | \"insufficient_allowance\"\n | \"payment_failed\"\n | \"execution_failed\";\n\n/**\n * Error thrown by the Context Protocol client\n */\nexport class ContextError extends Error {\n constructor(\n message: string,\n public readonly code?: ContextErrorCode | string,\n public readonly statusCode?: number,\n public readonly helpUrl?: string\n ) {\n super(message);\n this.name = \"ContextError\";\n }\n}\n","import type { Tool, SearchResponse } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Discovery resource for searching and finding tools on the Context Protocol marketplace\n */\nexport class Discovery {\n constructor(private client: ContextClient) {}\n\n /**\n * Search for tools matching a query string\n *\n * @param query - The search query (e.g., \"gas prices\", \"nft metadata\")\n * @param limit - Maximum number of results (1-50, default 10)\n * @returns Array of matching tools\n *\n * @example\n * ```typescript\n * const tools = await client.discovery.search(\"gas prices\");\n * console.log(tools[0].name); // \"Gas Price Oracle\"\n * console.log(tools[0].mcpTools); // Available methods\n * ```\n */\n async search(query: string, limit?: number): Promise<Tool[]> {\n const params = new URLSearchParams();\n\n if (query) {\n params.set(\"q\", query);\n }\n\n if (limit !== undefined) {\n params.set(\"limit\", String(limit));\n }\n\n const queryString = params.toString();\n const endpoint = `/api/v1/tools/search${queryString ? `?${queryString}` : \"\"}`;\n\n const response = await this.client.fetch<SearchResponse>(endpoint);\n\n return response.tools;\n }\n\n /**\n * Get featured/popular tools (empty query search)\n *\n * @param limit - Maximum number of results (1-50, default 10)\n * @returns Array of featured tools\n *\n * @example\n * ```typescript\n * const featured = await client.discovery.getFeatured(5);\n * ```\n */\n async getFeatured(limit?: number): Promise<Tool[]> {\n return this.search(\"\", limit);\n }\n}\n","import type {\n ExecuteOptions,\n ExecuteApiResponse,\n ExecutionResult,\n} from \"../types.js\";\nimport { ContextError } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Tools resource for executing tools on the Context Protocol marketplace\n */\nexport class Tools {\n constructor(private client: ContextClient) {}\n\n /**\n * Execute a tool with the provided arguments\n *\n * @param options - Execution options\n * @param options.toolId - The UUID of the tool (from search results)\n * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)\n * @param options.args - Arguments to pass to the tool\n * @returns The execution result with the tool's output data\n *\n * @throws {ContextError} With code `no_wallet` if wallet not set up\n * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled\n * @throws {ContextError} With code `payment_failed` if on-chain payment fails\n * @throws {ContextError} With code `execution_failed` if tool execution fails\n *\n * @example\n * ```typescript\n * // First, search for a tool\n * const tools = await client.discovery.search(\"gas prices\");\n * const tool = tools[0];\n *\n * // Execute a specific method from the tool's mcpTools\n * const result = await client.tools.execute({\n * toolId: tool.id,\n * toolName: tool.mcpTools[0].name, // e.g., \"get_gas_prices\"\n * args: { chainId: 1 }\n * });\n *\n * console.log(result.result); // The tool's output\n * console.log(result.durationMs); // Execution time\n * ```\n */\n async execute<T = unknown>(options: ExecuteOptions): Promise<ExecutionResult<T>> {\n const { toolId, toolName, args } = options;\n\n const response = await this.client.fetch<ExecuteApiResponse>(\n \"/api/v1/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({ toolId, toolName, args }),\n }\n );\n\n // Handle error response\n if (\"error\" in response) {\n throw new ContextError(\n response.error,\n response.code,\n 400,\n response.helpUrl\n );\n }\n\n // Handle success response\n if (response.success) {\n return {\n result: response.result as T,\n tool: response.tool,\n durationMs: response.durationMs,\n };\n }\n\n // Fallback - shouldn't reach here with valid API responses\n throw new ContextError(\"Unexpected response format from API\");\n }\n}\n","import type { ContextClientOptions } from \"./types.js\";\nimport { ContextError } from \"./types.js\";\nimport { Discovery } from \"./resources/discovery.js\";\nimport { Tools } from \"./resources/tools.js\";\n\n/**\n * The official TypeScript client for the Context Protocol.\n *\n * Use this client to discover and execute AI tools programmatically.\n *\n * @example\n * ```typescript\n * import { ContextClient } from \"@contextprotocol/client\";\n *\n * const client = new ContextClient({\n * apiKey: \"sk_live_...\"\n * });\n *\n * // Discover tools\n * const tools = await client.discovery.search(\"gas prices\");\n *\n * // Execute a tool method\n * const result = await client.tools.execute({\n * toolId: tools[0].id,\n * toolName: tools[0].mcpTools[0].name,\n * args: { chainId: 1 }\n * });\n * ```\n */\nexport class ContextClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n /**\n * Discovery resource for searching tools\n */\n public readonly discovery: Discovery;\n\n /**\n * Tools resource for executing tools\n */\n public readonly tools: Tools;\n\n /**\n * Creates a new Context Protocol client\n *\n * @param options - Client configuration options\n * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)\n * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)\n */\n constructor(options: ContextClientOptions) {\n if (!options.apiKey) {\n throw new ContextError(\"API key is required\");\n }\n\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? \"https://ctxprotocol.com\").replace(/\\/$/, \"\");\n\n // Initialize resources\n this.discovery = new Discovery(this);\n this.tools = new Tools(this);\n }\n\n /**\n * Internal method for making authenticated HTTP requests\n * All requests include the Authorization header with the API key\n *\n * @internal\n */\n async fetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}: ${response.statusText}`;\n let errorCode: string | undefined;\n let helpUrl: string | undefined;\n\n try {\n const errorBody = await response.json();\n if (errorBody.error) {\n errorMessage = errorBody.error;\n errorCode = errorBody.code;\n helpUrl = errorBody.helpUrl;\n }\n } catch {\n // Use default error message if JSON parsing fails\n }\n\n throw new ContextError(errorMessage, errorCode, response.status, helpUrl);\n }\n\n return response.json() as Promise<T>;\n }\n}\n"]}
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Configuration options for initializing the ContextClient
3
+ */
4
+ interface ContextClientOptions {
5
+ /**
6
+ * Your Context Protocol API key
7
+ * @example "sk_live_abc123..."
8
+ */
9
+ apiKey: string;
10
+ /**
11
+ * Base URL for the Context Protocol API
12
+ * @default "https://ctxprotocol.com"
13
+ */
14
+ baseUrl?: string;
15
+ }
16
+ /**
17
+ * An individual MCP tool exposed by a tool listing
18
+ */
19
+ interface McpTool {
20
+ /** Name of the MCP tool method */
21
+ name: string;
22
+ /** Description of what this method does */
23
+ description: string;
24
+ }
25
+ /**
26
+ * Represents a tool available on the Context Protocol marketplace
27
+ */
28
+ interface Tool {
29
+ /** Unique identifier for the tool (UUID) */
30
+ id: string;
31
+ /** Human-readable name of the tool */
32
+ name: string;
33
+ /** Description of what the tool does */
34
+ description: string;
35
+ /** Price per execution in USDC */
36
+ price: string;
37
+ /** Tool category (e.g., "defi", "nft") */
38
+ category?: string;
39
+ /** Whether the tool is verified by Context Protocol */
40
+ isVerified?: boolean;
41
+ /** Type of tool (e.g., "mcp") */
42
+ kind?: string;
43
+ /**
44
+ * Available MCP tool methods
45
+ * Use items from this array as `toolName` when executing
46
+ */
47
+ mcpTools?: McpTool[];
48
+ /** Creation timestamp */
49
+ createdAt?: string;
50
+ /** Last update timestamp */
51
+ updatedAt?: string;
52
+ }
53
+ /**
54
+ * Response from the tools search endpoint
55
+ */
56
+ interface SearchResponse {
57
+ /** Array of matching tools */
58
+ tools: Tool[];
59
+ /** The search query that was used */
60
+ query: string;
61
+ /** Total number of results */
62
+ count: number;
63
+ }
64
+ /**
65
+ * Options for searching tools
66
+ */
67
+ interface SearchOptions {
68
+ /** Search query (semantic search) */
69
+ query?: string;
70
+ /** Maximum number of results (1-50, default 10) */
71
+ limit?: number;
72
+ }
73
+ /**
74
+ * Options for executing a tool
75
+ */
76
+ interface ExecuteOptions {
77
+ /** The UUID of the tool to execute (from search results) */
78
+ toolId: string;
79
+ /** The specific MCP tool name to call (from tool's mcpTools array) */
80
+ toolName: string;
81
+ /** Arguments to pass to the tool */
82
+ args?: Record<string, unknown>;
83
+ }
84
+ /**
85
+ * Successful execution response from the API
86
+ */
87
+ interface ExecuteApiSuccessResponse {
88
+ success: true;
89
+ /** The result data from the tool execution */
90
+ result: unknown;
91
+ /** Information about the executed tool */
92
+ tool: {
93
+ id: string;
94
+ name: string;
95
+ };
96
+ /** Execution duration in milliseconds */
97
+ durationMs: number;
98
+ }
99
+ /**
100
+ * Error response from the API
101
+ */
102
+ interface ExecuteApiErrorResponse {
103
+ /** Human-readable error message */
104
+ error: string;
105
+ /** Error code for programmatic handling */
106
+ code?: ContextErrorCode;
107
+ /** URL to help resolve the issue */
108
+ helpUrl?: string;
109
+ }
110
+ /**
111
+ * Raw API response from the execute endpoint
112
+ */
113
+ type ExecuteApiResponse = ExecuteApiSuccessResponse | ExecuteApiErrorResponse;
114
+ /**
115
+ * The resolved result returned to the user after SDK processing
116
+ */
117
+ interface ExecutionResult<T = unknown> {
118
+ /** The data returned by the tool */
119
+ result: T;
120
+ /** Information about the executed tool */
121
+ tool: {
122
+ id: string;
123
+ name: string;
124
+ };
125
+ /** Execution duration in milliseconds */
126
+ durationMs: number;
127
+ }
128
+ /**
129
+ * Specific error codes returned by the Context Protocol API
130
+ */
131
+ type ContextErrorCode = "unauthorized" | "no_wallet" | "insufficient_allowance" | "payment_failed" | "execution_failed";
132
+ /**
133
+ * Error thrown by the Context Protocol client
134
+ */
135
+ declare class ContextError extends Error {
136
+ readonly code?: (ContextErrorCode | string) | undefined;
137
+ readonly statusCode?: number | undefined;
138
+ readonly helpUrl?: string | undefined;
139
+ constructor(message: string, code?: (ContextErrorCode | string) | undefined, statusCode?: number | undefined, helpUrl?: string | undefined);
140
+ }
141
+
142
+ /**
143
+ * Discovery resource for searching and finding tools on the Context Protocol marketplace
144
+ */
145
+ declare class Discovery {
146
+ private client;
147
+ constructor(client: ContextClient);
148
+ /**
149
+ * Search for tools matching a query string
150
+ *
151
+ * @param query - The search query (e.g., "gas prices", "nft metadata")
152
+ * @param limit - Maximum number of results (1-50, default 10)
153
+ * @returns Array of matching tools
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const tools = await client.discovery.search("gas prices");
158
+ * console.log(tools[0].name); // "Gas Price Oracle"
159
+ * console.log(tools[0].mcpTools); // Available methods
160
+ * ```
161
+ */
162
+ search(query: string, limit?: number): Promise<Tool[]>;
163
+ /**
164
+ * Get featured/popular tools (empty query search)
165
+ *
166
+ * @param limit - Maximum number of results (1-50, default 10)
167
+ * @returns Array of featured tools
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const featured = await client.discovery.getFeatured(5);
172
+ * ```
173
+ */
174
+ getFeatured(limit?: number): Promise<Tool[]>;
175
+ }
176
+
177
+ /**
178
+ * Tools resource for executing tools on the Context Protocol marketplace
179
+ */
180
+ declare class Tools {
181
+ private client;
182
+ constructor(client: ContextClient);
183
+ /**
184
+ * Execute a tool with the provided arguments
185
+ *
186
+ * @param options - Execution options
187
+ * @param options.toolId - The UUID of the tool (from search results)
188
+ * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)
189
+ * @param options.args - Arguments to pass to the tool
190
+ * @returns The execution result with the tool's output data
191
+ *
192
+ * @throws {ContextError} With code `no_wallet` if wallet not set up
193
+ * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled
194
+ * @throws {ContextError} With code `payment_failed` if on-chain payment fails
195
+ * @throws {ContextError} With code `execution_failed` if tool execution fails
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // First, search for a tool
200
+ * const tools = await client.discovery.search("gas prices");
201
+ * const tool = tools[0];
202
+ *
203
+ * // Execute a specific method from the tool's mcpTools
204
+ * const result = await client.tools.execute({
205
+ * toolId: tool.id,
206
+ * toolName: tool.mcpTools[0].name, // e.g., "get_gas_prices"
207
+ * args: { chainId: 1 }
208
+ * });
209
+ *
210
+ * console.log(result.result); // The tool's output
211
+ * console.log(result.durationMs); // Execution time
212
+ * ```
213
+ */
214
+ execute<T = unknown>(options: ExecuteOptions): Promise<ExecutionResult<T>>;
215
+ }
216
+
217
+ /**
218
+ * The official TypeScript client for the Context Protocol.
219
+ *
220
+ * Use this client to discover and execute AI tools programmatically.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * import { ContextClient } from "@contextprotocol/client";
225
+ *
226
+ * const client = new ContextClient({
227
+ * apiKey: "sk_live_..."
228
+ * });
229
+ *
230
+ * // Discover tools
231
+ * const tools = await client.discovery.search("gas prices");
232
+ *
233
+ * // Execute a tool method
234
+ * const result = await client.tools.execute({
235
+ * toolId: tools[0].id,
236
+ * toolName: tools[0].mcpTools[0].name,
237
+ * args: { chainId: 1 }
238
+ * });
239
+ * ```
240
+ */
241
+ declare class ContextClient {
242
+ private readonly apiKey;
243
+ private readonly baseUrl;
244
+ /**
245
+ * Discovery resource for searching tools
246
+ */
247
+ readonly discovery: Discovery;
248
+ /**
249
+ * Tools resource for executing tools
250
+ */
251
+ readonly tools: Tools;
252
+ /**
253
+ * Creates a new Context Protocol client
254
+ *
255
+ * @param options - Client configuration options
256
+ * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
257
+ * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
258
+ */
259
+ constructor(options: ContextClientOptions);
260
+ /**
261
+ * Internal method for making authenticated HTTP requests
262
+ * All requests include the Authorization header with the API key
263
+ *
264
+ * @internal
265
+ */
266
+ fetch<T>(endpoint: string, options?: RequestInit): Promise<T>;
267
+ }
268
+
269
+ export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, type SearchOptions, type SearchResponse, type Tool, Tools };
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Configuration options for initializing the ContextClient
3
+ */
4
+ interface ContextClientOptions {
5
+ /**
6
+ * Your Context Protocol API key
7
+ * @example "sk_live_abc123..."
8
+ */
9
+ apiKey: string;
10
+ /**
11
+ * Base URL for the Context Protocol API
12
+ * @default "https://ctxprotocol.com"
13
+ */
14
+ baseUrl?: string;
15
+ }
16
+ /**
17
+ * An individual MCP tool exposed by a tool listing
18
+ */
19
+ interface McpTool {
20
+ /** Name of the MCP tool method */
21
+ name: string;
22
+ /** Description of what this method does */
23
+ description: string;
24
+ }
25
+ /**
26
+ * Represents a tool available on the Context Protocol marketplace
27
+ */
28
+ interface Tool {
29
+ /** Unique identifier for the tool (UUID) */
30
+ id: string;
31
+ /** Human-readable name of the tool */
32
+ name: string;
33
+ /** Description of what the tool does */
34
+ description: string;
35
+ /** Price per execution in USDC */
36
+ price: string;
37
+ /** Tool category (e.g., "defi", "nft") */
38
+ category?: string;
39
+ /** Whether the tool is verified by Context Protocol */
40
+ isVerified?: boolean;
41
+ /** Type of tool (e.g., "mcp") */
42
+ kind?: string;
43
+ /**
44
+ * Available MCP tool methods
45
+ * Use items from this array as `toolName` when executing
46
+ */
47
+ mcpTools?: McpTool[];
48
+ /** Creation timestamp */
49
+ createdAt?: string;
50
+ /** Last update timestamp */
51
+ updatedAt?: string;
52
+ }
53
+ /**
54
+ * Response from the tools search endpoint
55
+ */
56
+ interface SearchResponse {
57
+ /** Array of matching tools */
58
+ tools: Tool[];
59
+ /** The search query that was used */
60
+ query: string;
61
+ /** Total number of results */
62
+ count: number;
63
+ }
64
+ /**
65
+ * Options for searching tools
66
+ */
67
+ interface SearchOptions {
68
+ /** Search query (semantic search) */
69
+ query?: string;
70
+ /** Maximum number of results (1-50, default 10) */
71
+ limit?: number;
72
+ }
73
+ /**
74
+ * Options for executing a tool
75
+ */
76
+ interface ExecuteOptions {
77
+ /** The UUID of the tool to execute (from search results) */
78
+ toolId: string;
79
+ /** The specific MCP tool name to call (from tool's mcpTools array) */
80
+ toolName: string;
81
+ /** Arguments to pass to the tool */
82
+ args?: Record<string, unknown>;
83
+ }
84
+ /**
85
+ * Successful execution response from the API
86
+ */
87
+ interface ExecuteApiSuccessResponse {
88
+ success: true;
89
+ /** The result data from the tool execution */
90
+ result: unknown;
91
+ /** Information about the executed tool */
92
+ tool: {
93
+ id: string;
94
+ name: string;
95
+ };
96
+ /** Execution duration in milliseconds */
97
+ durationMs: number;
98
+ }
99
+ /**
100
+ * Error response from the API
101
+ */
102
+ interface ExecuteApiErrorResponse {
103
+ /** Human-readable error message */
104
+ error: string;
105
+ /** Error code for programmatic handling */
106
+ code?: ContextErrorCode;
107
+ /** URL to help resolve the issue */
108
+ helpUrl?: string;
109
+ }
110
+ /**
111
+ * Raw API response from the execute endpoint
112
+ */
113
+ type ExecuteApiResponse = ExecuteApiSuccessResponse | ExecuteApiErrorResponse;
114
+ /**
115
+ * The resolved result returned to the user after SDK processing
116
+ */
117
+ interface ExecutionResult<T = unknown> {
118
+ /** The data returned by the tool */
119
+ result: T;
120
+ /** Information about the executed tool */
121
+ tool: {
122
+ id: string;
123
+ name: string;
124
+ };
125
+ /** Execution duration in milliseconds */
126
+ durationMs: number;
127
+ }
128
+ /**
129
+ * Specific error codes returned by the Context Protocol API
130
+ */
131
+ type ContextErrorCode = "unauthorized" | "no_wallet" | "insufficient_allowance" | "payment_failed" | "execution_failed";
132
+ /**
133
+ * Error thrown by the Context Protocol client
134
+ */
135
+ declare class ContextError extends Error {
136
+ readonly code?: (ContextErrorCode | string) | undefined;
137
+ readonly statusCode?: number | undefined;
138
+ readonly helpUrl?: string | undefined;
139
+ constructor(message: string, code?: (ContextErrorCode | string) | undefined, statusCode?: number | undefined, helpUrl?: string | undefined);
140
+ }
141
+
142
+ /**
143
+ * Discovery resource for searching and finding tools on the Context Protocol marketplace
144
+ */
145
+ declare class Discovery {
146
+ private client;
147
+ constructor(client: ContextClient);
148
+ /**
149
+ * Search for tools matching a query string
150
+ *
151
+ * @param query - The search query (e.g., "gas prices", "nft metadata")
152
+ * @param limit - Maximum number of results (1-50, default 10)
153
+ * @returns Array of matching tools
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const tools = await client.discovery.search("gas prices");
158
+ * console.log(tools[0].name); // "Gas Price Oracle"
159
+ * console.log(tools[0].mcpTools); // Available methods
160
+ * ```
161
+ */
162
+ search(query: string, limit?: number): Promise<Tool[]>;
163
+ /**
164
+ * Get featured/popular tools (empty query search)
165
+ *
166
+ * @param limit - Maximum number of results (1-50, default 10)
167
+ * @returns Array of featured tools
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const featured = await client.discovery.getFeatured(5);
172
+ * ```
173
+ */
174
+ getFeatured(limit?: number): Promise<Tool[]>;
175
+ }
176
+
177
+ /**
178
+ * Tools resource for executing tools on the Context Protocol marketplace
179
+ */
180
+ declare class Tools {
181
+ private client;
182
+ constructor(client: ContextClient);
183
+ /**
184
+ * Execute a tool with the provided arguments
185
+ *
186
+ * @param options - Execution options
187
+ * @param options.toolId - The UUID of the tool (from search results)
188
+ * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)
189
+ * @param options.args - Arguments to pass to the tool
190
+ * @returns The execution result with the tool's output data
191
+ *
192
+ * @throws {ContextError} With code `no_wallet` if wallet not set up
193
+ * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled
194
+ * @throws {ContextError} With code `payment_failed` if on-chain payment fails
195
+ * @throws {ContextError} With code `execution_failed` if tool execution fails
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // First, search for a tool
200
+ * const tools = await client.discovery.search("gas prices");
201
+ * const tool = tools[0];
202
+ *
203
+ * // Execute a specific method from the tool's mcpTools
204
+ * const result = await client.tools.execute({
205
+ * toolId: tool.id,
206
+ * toolName: tool.mcpTools[0].name, // e.g., "get_gas_prices"
207
+ * args: { chainId: 1 }
208
+ * });
209
+ *
210
+ * console.log(result.result); // The tool's output
211
+ * console.log(result.durationMs); // Execution time
212
+ * ```
213
+ */
214
+ execute<T = unknown>(options: ExecuteOptions): Promise<ExecutionResult<T>>;
215
+ }
216
+
217
+ /**
218
+ * The official TypeScript client for the Context Protocol.
219
+ *
220
+ * Use this client to discover and execute AI tools programmatically.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * import { ContextClient } from "@contextprotocol/client";
225
+ *
226
+ * const client = new ContextClient({
227
+ * apiKey: "sk_live_..."
228
+ * });
229
+ *
230
+ * // Discover tools
231
+ * const tools = await client.discovery.search("gas prices");
232
+ *
233
+ * // Execute a tool method
234
+ * const result = await client.tools.execute({
235
+ * toolId: tools[0].id,
236
+ * toolName: tools[0].mcpTools[0].name,
237
+ * args: { chainId: 1 }
238
+ * });
239
+ * ```
240
+ */
241
+ declare class ContextClient {
242
+ private readonly apiKey;
243
+ private readonly baseUrl;
244
+ /**
245
+ * Discovery resource for searching tools
246
+ */
247
+ readonly discovery: Discovery;
248
+ /**
249
+ * Tools resource for executing tools
250
+ */
251
+ readonly tools: Tools;
252
+ /**
253
+ * Creates a new Context Protocol client
254
+ *
255
+ * @param options - Client configuration options
256
+ * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
257
+ * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
258
+ */
259
+ constructor(options: ContextClientOptions);
260
+ /**
261
+ * Internal method for making authenticated HTTP requests
262
+ * All requests include the Authorization header with the API key
263
+ *
264
+ * @internal
265
+ */
266
+ fetch<T>(endpoint: string, options?: RequestInit): Promise<T>;
267
+ }
268
+
269
+ export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, type SearchOptions, type SearchResponse, type Tool, Tools };
package/dist/index.js ADDED
@@ -0,0 +1,189 @@
1
+ // src/types.ts
2
+ var ContextError = class extends Error {
3
+ constructor(message, code, statusCode, helpUrl) {
4
+ super(message);
5
+ this.code = code;
6
+ this.statusCode = statusCode;
7
+ this.helpUrl = helpUrl;
8
+ this.name = "ContextError";
9
+ }
10
+ };
11
+
12
+ // src/resources/discovery.ts
13
+ var Discovery = class {
14
+ constructor(client) {
15
+ this.client = client;
16
+ }
17
+ /**
18
+ * Search for tools matching a query string
19
+ *
20
+ * @param query - The search query (e.g., "gas prices", "nft metadata")
21
+ * @param limit - Maximum number of results (1-50, default 10)
22
+ * @returns Array of matching tools
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const tools = await client.discovery.search("gas prices");
27
+ * console.log(tools[0].name); // "Gas Price Oracle"
28
+ * console.log(tools[0].mcpTools); // Available methods
29
+ * ```
30
+ */
31
+ async search(query, limit) {
32
+ const params = new URLSearchParams();
33
+ if (query) {
34
+ params.set("q", query);
35
+ }
36
+ if (limit !== void 0) {
37
+ params.set("limit", String(limit));
38
+ }
39
+ const queryString = params.toString();
40
+ const endpoint = `/api/v1/tools/search${queryString ? `?${queryString}` : ""}`;
41
+ const response = await this.client.fetch(endpoint);
42
+ return response.tools;
43
+ }
44
+ /**
45
+ * Get featured/popular tools (empty query search)
46
+ *
47
+ * @param limit - Maximum number of results (1-50, default 10)
48
+ * @returns Array of featured tools
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const featured = await client.discovery.getFeatured(5);
53
+ * ```
54
+ */
55
+ async getFeatured(limit) {
56
+ return this.search("", limit);
57
+ }
58
+ };
59
+
60
+ // src/resources/tools.ts
61
+ var Tools = class {
62
+ constructor(client) {
63
+ this.client = client;
64
+ }
65
+ /**
66
+ * Execute a tool with the provided arguments
67
+ *
68
+ * @param options - Execution options
69
+ * @param options.toolId - The UUID of the tool (from search results)
70
+ * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)
71
+ * @param options.args - Arguments to pass to the tool
72
+ * @returns The execution result with the tool's output data
73
+ *
74
+ * @throws {ContextError} With code `no_wallet` if wallet not set up
75
+ * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled
76
+ * @throws {ContextError} With code `payment_failed` if on-chain payment fails
77
+ * @throws {ContextError} With code `execution_failed` if tool execution fails
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // First, search for a tool
82
+ * const tools = await client.discovery.search("gas prices");
83
+ * const tool = tools[0];
84
+ *
85
+ * // Execute a specific method from the tool's mcpTools
86
+ * const result = await client.tools.execute({
87
+ * toolId: tool.id,
88
+ * toolName: tool.mcpTools[0].name, // e.g., "get_gas_prices"
89
+ * args: { chainId: 1 }
90
+ * });
91
+ *
92
+ * console.log(result.result); // The tool's output
93
+ * console.log(result.durationMs); // Execution time
94
+ * ```
95
+ */
96
+ async execute(options) {
97
+ const { toolId, toolName, args } = options;
98
+ const response = await this.client.fetch(
99
+ "/api/v1/tools/execute",
100
+ {
101
+ method: "POST",
102
+ body: JSON.stringify({ toolId, toolName, args })
103
+ }
104
+ );
105
+ if ("error" in response) {
106
+ throw new ContextError(
107
+ response.error,
108
+ response.code,
109
+ 400,
110
+ response.helpUrl
111
+ );
112
+ }
113
+ if (response.success) {
114
+ return {
115
+ result: response.result,
116
+ tool: response.tool,
117
+ durationMs: response.durationMs
118
+ };
119
+ }
120
+ throw new ContextError("Unexpected response format from API");
121
+ }
122
+ };
123
+
124
+ // src/client.ts
125
+ var ContextClient = class {
126
+ apiKey;
127
+ baseUrl;
128
+ /**
129
+ * Discovery resource for searching tools
130
+ */
131
+ discovery;
132
+ /**
133
+ * Tools resource for executing tools
134
+ */
135
+ tools;
136
+ /**
137
+ * Creates a new Context Protocol client
138
+ *
139
+ * @param options - Client configuration options
140
+ * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)
141
+ * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)
142
+ */
143
+ constructor(options) {
144
+ if (!options.apiKey) {
145
+ throw new ContextError("API key is required");
146
+ }
147
+ this.apiKey = options.apiKey;
148
+ this.baseUrl = (options.baseUrl ?? "https://ctxprotocol.com").replace(/\/$/, "");
149
+ this.discovery = new Discovery(this);
150
+ this.tools = new Tools(this);
151
+ }
152
+ /**
153
+ * Internal method for making authenticated HTTP requests
154
+ * All requests include the Authorization header with the API key
155
+ *
156
+ * @internal
157
+ */
158
+ async fetch(endpoint, options = {}) {
159
+ const url = `${this.baseUrl}${endpoint}`;
160
+ const response = await fetch(url, {
161
+ ...options,
162
+ headers: {
163
+ "Content-Type": "application/json",
164
+ Authorization: `Bearer ${this.apiKey}`,
165
+ ...options.headers
166
+ }
167
+ });
168
+ if (!response.ok) {
169
+ let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
170
+ let errorCode;
171
+ let helpUrl;
172
+ try {
173
+ const errorBody = await response.json();
174
+ if (errorBody.error) {
175
+ errorMessage = errorBody.error;
176
+ errorCode = errorBody.code;
177
+ helpUrl = errorBody.helpUrl;
178
+ }
179
+ } catch {
180
+ }
181
+ throw new ContextError(errorMessage, errorCode, response.status, helpUrl);
182
+ }
183
+ return response.json();
184
+ }
185
+ };
186
+
187
+ export { ContextClient, ContextError, Discovery, Tools };
188
+ //# sourceMappingURL=index.js.map
189
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/resources/discovery.ts","../src/resources/tools.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Configuration options for initializing the ContextClient\n */\nexport interface ContextClientOptions {\n /**\n * Your Context Protocol API key\n * @example \"sk_live_abc123...\"\n */\n apiKey: string;\n\n /**\n * Base URL for the Context Protocol API\n * @default \"https://ctxprotocol.com\"\n */\n baseUrl?: string;\n}\n\n/**\n * An individual MCP tool exposed by a tool listing\n */\nexport interface McpTool {\n /** Name of the MCP tool method */\n name: string;\n\n /** Description of what this method does */\n description: string;\n}\n\n/**\n * Represents a tool available on the Context Protocol marketplace\n */\nexport interface Tool {\n /** Unique identifier for the tool (UUID) */\n id: string;\n\n /** Human-readable name of the tool */\n name: string;\n\n /** Description of what the tool does */\n description: string;\n\n /** Price per execution in USDC */\n price: string;\n\n /** Tool category (e.g., \"defi\", \"nft\") */\n category?: string;\n\n /** Whether the tool is verified by Context Protocol */\n isVerified?: boolean;\n\n /** Type of tool (e.g., \"mcp\") */\n kind?: string;\n\n /**\n * Available MCP tool methods\n * Use items from this array as `toolName` when executing\n */\n mcpTools?: McpTool[];\n\n /** Creation timestamp */\n createdAt?: string;\n\n /** Last update timestamp */\n updatedAt?: string;\n}\n\n/**\n * Response from the tools search endpoint\n */\nexport interface SearchResponse {\n /** Array of matching tools */\n tools: Tool[];\n\n /** The search query that was used */\n query: string;\n\n /** Total number of results */\n count: number;\n}\n\n/**\n * Options for searching tools\n */\nexport interface SearchOptions {\n /** Search query (semantic search) */\n query?: string;\n\n /** Maximum number of results (1-50, default 10) */\n limit?: number;\n}\n\n/**\n * Options for executing a tool\n */\nexport interface ExecuteOptions {\n /** The UUID of the tool to execute (from search results) */\n toolId: string;\n\n /** The specific MCP tool name to call (from tool's mcpTools array) */\n toolName: string;\n\n /** Arguments to pass to the tool */\n args?: Record<string, unknown>;\n}\n\n/**\n * Successful execution response from the API\n */\nexport interface ExecuteApiSuccessResponse {\n success: true;\n\n /** The result data from the tool execution */\n result: unknown;\n\n /** Information about the executed tool */\n tool: {\n id: string;\n name: string;\n };\n\n /** Execution duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Error response from the API\n */\nexport interface ExecuteApiErrorResponse {\n /** Human-readable error message */\n error: string;\n\n /** Error code for programmatic handling */\n code?: ContextErrorCode;\n\n /** URL to help resolve the issue */\n helpUrl?: string;\n}\n\n/**\n * Raw API response from the execute endpoint\n */\nexport type ExecuteApiResponse = ExecuteApiSuccessResponse | ExecuteApiErrorResponse;\n\n/**\n * The resolved result returned to the user after SDK processing\n */\nexport interface ExecutionResult<T = unknown> {\n /** The data returned by the tool */\n result: T;\n\n /** Information about the executed tool */\n tool: {\n id: string;\n name: string;\n };\n\n /** Execution duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Specific error codes returned by the Context Protocol API\n */\nexport type ContextErrorCode =\n | \"unauthorized\"\n | \"no_wallet\"\n | \"insufficient_allowance\"\n | \"payment_failed\"\n | \"execution_failed\";\n\n/**\n * Error thrown by the Context Protocol client\n */\nexport class ContextError extends Error {\n constructor(\n message: string,\n public readonly code?: ContextErrorCode | string,\n public readonly statusCode?: number,\n public readonly helpUrl?: string\n ) {\n super(message);\n this.name = \"ContextError\";\n }\n}\n","import type { Tool, SearchResponse } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Discovery resource for searching and finding tools on the Context Protocol marketplace\n */\nexport class Discovery {\n constructor(private client: ContextClient) {}\n\n /**\n * Search for tools matching a query string\n *\n * @param query - The search query (e.g., \"gas prices\", \"nft metadata\")\n * @param limit - Maximum number of results (1-50, default 10)\n * @returns Array of matching tools\n *\n * @example\n * ```typescript\n * const tools = await client.discovery.search(\"gas prices\");\n * console.log(tools[0].name); // \"Gas Price Oracle\"\n * console.log(tools[0].mcpTools); // Available methods\n * ```\n */\n async search(query: string, limit?: number): Promise<Tool[]> {\n const params = new URLSearchParams();\n\n if (query) {\n params.set(\"q\", query);\n }\n\n if (limit !== undefined) {\n params.set(\"limit\", String(limit));\n }\n\n const queryString = params.toString();\n const endpoint = `/api/v1/tools/search${queryString ? `?${queryString}` : \"\"}`;\n\n const response = await this.client.fetch<SearchResponse>(endpoint);\n\n return response.tools;\n }\n\n /**\n * Get featured/popular tools (empty query search)\n *\n * @param limit - Maximum number of results (1-50, default 10)\n * @returns Array of featured tools\n *\n * @example\n * ```typescript\n * const featured = await client.discovery.getFeatured(5);\n * ```\n */\n async getFeatured(limit?: number): Promise<Tool[]> {\n return this.search(\"\", limit);\n }\n}\n","import type {\n ExecuteOptions,\n ExecuteApiResponse,\n ExecutionResult,\n} from \"../types.js\";\nimport { ContextError } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Tools resource for executing tools on the Context Protocol marketplace\n */\nexport class Tools {\n constructor(private client: ContextClient) {}\n\n /**\n * Execute a tool with the provided arguments\n *\n * @param options - Execution options\n * @param options.toolId - The UUID of the tool (from search results)\n * @param options.toolName - The specific MCP tool method to call (from tool's mcpTools array)\n * @param options.args - Arguments to pass to the tool\n * @returns The execution result with the tool's output data\n *\n * @throws {ContextError} With code `no_wallet` if wallet not set up\n * @throws {ContextError} With code `insufficient_allowance` if Auto Pay not enabled\n * @throws {ContextError} With code `payment_failed` if on-chain payment fails\n * @throws {ContextError} With code `execution_failed` if tool execution fails\n *\n * @example\n * ```typescript\n * // First, search for a tool\n * const tools = await client.discovery.search(\"gas prices\");\n * const tool = tools[0];\n *\n * // Execute a specific method from the tool's mcpTools\n * const result = await client.tools.execute({\n * toolId: tool.id,\n * toolName: tool.mcpTools[0].name, // e.g., \"get_gas_prices\"\n * args: { chainId: 1 }\n * });\n *\n * console.log(result.result); // The tool's output\n * console.log(result.durationMs); // Execution time\n * ```\n */\n async execute<T = unknown>(options: ExecuteOptions): Promise<ExecutionResult<T>> {\n const { toolId, toolName, args } = options;\n\n const response = await this.client.fetch<ExecuteApiResponse>(\n \"/api/v1/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({ toolId, toolName, args }),\n }\n );\n\n // Handle error response\n if (\"error\" in response) {\n throw new ContextError(\n response.error,\n response.code,\n 400,\n response.helpUrl\n );\n }\n\n // Handle success response\n if (response.success) {\n return {\n result: response.result as T,\n tool: response.tool,\n durationMs: response.durationMs,\n };\n }\n\n // Fallback - shouldn't reach here with valid API responses\n throw new ContextError(\"Unexpected response format from API\");\n }\n}\n","import type { ContextClientOptions } from \"./types.js\";\nimport { ContextError } from \"./types.js\";\nimport { Discovery } from \"./resources/discovery.js\";\nimport { Tools } from \"./resources/tools.js\";\n\n/**\n * The official TypeScript client for the Context Protocol.\n *\n * Use this client to discover and execute AI tools programmatically.\n *\n * @example\n * ```typescript\n * import { ContextClient } from \"@contextprotocol/client\";\n *\n * const client = new ContextClient({\n * apiKey: \"sk_live_...\"\n * });\n *\n * // Discover tools\n * const tools = await client.discovery.search(\"gas prices\");\n *\n * // Execute a tool method\n * const result = await client.tools.execute({\n * toolId: tools[0].id,\n * toolName: tools[0].mcpTools[0].name,\n * args: { chainId: 1 }\n * });\n * ```\n */\nexport class ContextClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n /**\n * Discovery resource for searching tools\n */\n public readonly discovery: Discovery;\n\n /**\n * Tools resource for executing tools\n */\n public readonly tools: Tools;\n\n /**\n * Creates a new Context Protocol client\n *\n * @param options - Client configuration options\n * @param options.apiKey - Your Context Protocol API key (format: sk_live_...)\n * @param options.baseUrl - Optional base URL override (defaults to https://ctxprotocol.com)\n */\n constructor(options: ContextClientOptions) {\n if (!options.apiKey) {\n throw new ContextError(\"API key is required\");\n }\n\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? \"https://ctxprotocol.com\").replace(/\\/$/, \"\");\n\n // Initialize resources\n this.discovery = new Discovery(this);\n this.tools = new Tools(this);\n }\n\n /**\n * Internal method for making authenticated HTTP requests\n * All requests include the Authorization header with the API key\n *\n * @internal\n */\n async fetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n let errorMessage = `HTTP ${response.status}: ${response.statusText}`;\n let errorCode: string | undefined;\n let helpUrl: string | undefined;\n\n try {\n const errorBody = await response.json();\n if (errorBody.error) {\n errorMessage = errorBody.error;\n errorCode = errorBody.code;\n helpUrl = errorBody.helpUrl;\n }\n } catch {\n // Use default error message if JSON parsing fails\n }\n\n throw new ContextError(errorMessage, errorCode, response.status, helpUrl);\n }\n\n return response.json() as Promise<T>;\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@ctxprotocol/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Official TypeScript SDK for the Context Protocol - Discover and execute AI tools programmatically",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "typecheck": "tsc --noEmit",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "keywords": [
31
+ "context-protocol",
32
+ "ctxprotocol",
33
+ "mcp",
34
+ "ai",
35
+ "tools",
36
+ "sdk",
37
+ "api-client",
38
+ "typescript"
39
+ ],
40
+ "author": "Context Protocol",
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/ctxprotocol/sdk"
45
+ },
46
+ "homepage": "https://ctxprotocol.com",
47
+ "bugs": {
48
+ "url": "https://github.com/ctxprotocol/sdk/issues"
49
+ },
50
+ "devDependencies": {
51
+ "tsup": "^8.3.5",
52
+ "typescript": "^5.7.2"
53
+ },
54
+ "engines": {
55
+ "node": ">=18.0.0"
56
+ }
57
+ }