@ctxprotocol/sdk 0.7.0 → 0.8.1
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 +52 -12
- package/dist/client/index.cjs +16 -2
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +66 -1
- package/dist/client/index.d.ts +66 -1
- package/dist/client/index.js +16 -2
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +16 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,12 +86,17 @@ const result = await client.tools.execute({
|
|
|
86
86
|
});
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
**Query mode** gives you curated answers — the server handles tool discovery, multi-tool orchestration (up to 100 MCP calls per tool), self-healing retries, and AI synthesis for one flat fee:
|
|
89
|
+
**Query mode** gives you curated answers — the server handles tool discovery, multi-tool orchestration (up to 100 MCP calls per tool), self-healing retries, completeness checks, model-aware context budgeting, and AI synthesis for one flat fee:
|
|
90
90
|
```typescript
|
|
91
|
-
const answer = await client.query.run(
|
|
91
|
+
const answer = await client.query.run({
|
|
92
|
+
query: "What are the top whale movements on Base?",
|
|
93
|
+
modelId: "glm-model", // optional: choose a supported model
|
|
94
|
+
includeDataUrl: true, // optional: persist full execution data to blob
|
|
95
|
+
});
|
|
92
96
|
console.log(answer.response); // AI-synthesized answer
|
|
93
97
|
console.log(answer.toolsUsed); // Which tools were used
|
|
94
98
|
console.log(answer.cost); // Cost breakdown
|
|
99
|
+
console.log(answer.dataUrl); // Optional blob URL with full data
|
|
95
100
|
```
|
|
96
101
|
|
|
97
102
|
## Quick Start
|
|
@@ -170,9 +175,18 @@ const result = await client.tools.execute({
|
|
|
170
175
|
args: llmDecision.args,
|
|
171
176
|
});
|
|
172
177
|
|
|
173
|
-
// Feed
|
|
178
|
+
// Feed a bounded, structured summary back to your LLM for synthesis.
|
|
179
|
+
// Prefer client.query.run() when you want server-managed synthesis.
|
|
180
|
+
const resultPreview = JSON.stringify(result.result, null, 2).slice(0, 50_000);
|
|
181
|
+
const resultKeys =
|
|
182
|
+
result.result && typeof result.result === "object"
|
|
183
|
+
? Object.keys(result.result as Record<string, unknown>)
|
|
184
|
+
: [];
|
|
185
|
+
|
|
174
186
|
const finalAnswer = await myLLM.generate(
|
|
175
|
-
`
|
|
187
|
+
`Tool output keys: ${resultKeys.join(", ") || "(non-object result)"}\n\n` +
|
|
188
|
+
`Tool output preview (truncated):\n${resultPreview}\n\n` +
|
|
189
|
+
"Summarize this for the user and mention if more data may exist beyond the preview."
|
|
176
190
|
);
|
|
177
191
|
```
|
|
178
192
|
|
|
@@ -234,11 +248,17 @@ If you can answer without a tool, just respond normally.`;
|
|
|
234
248
|
args: toolCall.args || {},
|
|
235
249
|
});
|
|
236
250
|
|
|
237
|
-
// 6. Let LLM synthesize
|
|
251
|
+
// 6. Let LLM synthesize a bounded preview (avoid injecting giant JSON blobs)
|
|
252
|
+
const resultPreview = JSON.stringify(result.result, null, 2).slice(0, 50_000);
|
|
253
|
+
const resultKeys =
|
|
254
|
+
result.result && typeof result.result === "object"
|
|
255
|
+
? Object.keys(result.result as Record<string, unknown>)
|
|
256
|
+
: [];
|
|
257
|
+
|
|
238
258
|
return await myLLM.chat(
|
|
239
|
-
`Tool "${toolCall.toolName}" returned: ${
|
|
240
|
-
|
|
241
|
-
Please provide a helpful response to the user's original question: "${userQuery}"`
|
|
259
|
+
`Tool "${toolCall.toolName}" returned keys: ${resultKeys.join(", ") || "(non-object result)"}\n\n` +
|
|
260
|
+
`Preview (truncated):\n${resultPreview}\n\n` +
|
|
261
|
+
`Please provide a helpful response to the user's original question: "${userQuery}"`
|
|
242
262
|
);
|
|
243
263
|
}
|
|
244
264
|
} catch {
|
|
@@ -310,7 +330,7 @@ const result = await client.tools.execute({
|
|
|
310
330
|
|
|
311
331
|
#### `client.query.run(options)`
|
|
312
332
|
|
|
313
|
-
Run an agentic query. The server discovers tools, executes the full pipeline (up to 100 MCP calls per tool), and returns an AI-synthesized answer.
|
|
333
|
+
Run an agentic query. The server discovers tools, executes the full pipeline (up to 100 MCP calls per tool), applies model-aware mediator/data budgeting, and returns an AI-synthesized answer.
|
|
314
334
|
|
|
315
335
|
```typescript
|
|
316
336
|
// Simple string
|
|
@@ -320,12 +340,17 @@ const answer = await client.query.run("What are the top whale movements on Base?
|
|
|
320
340
|
const answer = await client.query.run({
|
|
321
341
|
query: "Analyze whale activity on Base",
|
|
322
342
|
tools: ["tool-uuid-1", "tool-uuid-2"], // optional — auto-discover if omitted
|
|
343
|
+
modelId: "kimi-model-thinking", // optional
|
|
344
|
+
includeData: true, // optional: include execution data inline
|
|
345
|
+
includeDataUrl: true, // optional: include blob URL for full data
|
|
323
346
|
});
|
|
324
347
|
|
|
325
348
|
console.log(answer.response); // AI-synthesized text
|
|
326
349
|
console.log(answer.toolsUsed); // [{ id, name, skillCalls }]
|
|
327
350
|
console.log(answer.cost); // { modelCostUsd, toolCostUsd, totalCostUsd }
|
|
328
351
|
console.log(answer.durationMs); // Total time
|
|
352
|
+
console.log(answer.data); // Optional execution data (when includeData=true)
|
|
353
|
+
console.log(answer.dataUrl); // Optional blob URL (when includeDataUrl=true)
|
|
329
354
|
```
|
|
330
355
|
|
|
331
356
|
#### `client.query.stream(options)`
|
|
@@ -425,6 +450,8 @@ interface QueryResult {
|
|
|
425
450
|
toolsUsed: QueryToolUsage[]; // Tools used: { id, name, skillCalls }
|
|
426
451
|
cost: QueryCost; // { modelCostUsd, toolCostUsd, totalCostUsd }
|
|
427
452
|
durationMs: number;
|
|
453
|
+
data?: unknown; // Optional execution data (includeData=true)
|
|
454
|
+
dataUrl?: string; // Optional blob URL (includeDataUrl=true)
|
|
428
455
|
}
|
|
429
456
|
```
|
|
430
457
|
|
|
@@ -674,10 +701,19 @@ const TOOLS = [{
|
|
|
674
701
|
name: "analyze_my_positions",
|
|
675
702
|
description: "Analyze your positions with personalized insights",
|
|
676
703
|
|
|
677
|
-
// ⭐
|
|
678
|
-
//
|
|
704
|
+
// ⭐ `_meta` is standard MCP metadata:
|
|
705
|
+
// - contextRequirements => context injection contract
|
|
706
|
+
// - rateLimit => planner/runtime pacing hints for agentic loops
|
|
679
707
|
_meta: {
|
|
680
708
|
contextRequirements: ["wallet"] as ContextRequirementType[],
|
|
709
|
+
rateLimit: {
|
|
710
|
+
maxRequestsPerMinute: 30,
|
|
711
|
+
cooldownMs: 2000,
|
|
712
|
+
maxConcurrency: 1,
|
|
713
|
+
supportsBulk: true,
|
|
714
|
+
recommendedBatchTools: ["get_wallet_snapshot"],
|
|
715
|
+
notes: "Hobby tier: prefer snapshot endpoints over fan-out loops.",
|
|
716
|
+
},
|
|
681
717
|
},
|
|
682
718
|
|
|
683
719
|
inputSchema: {
|
|
@@ -696,7 +732,11 @@ const TOOLS = [{
|
|
|
696
732
|
|
|
697
733
|
**Why `_meta` at the tool level?**
|
|
698
734
|
|
|
699
|
-
The `_meta` field is part of the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-definition) for arbitrary tool metadata. The Context platform reads
|
|
735
|
+
The `_meta` field is part of the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-definition) for arbitrary tool metadata. The Context platform reads:
|
|
736
|
+
- `_meta.contextRequirements` for user-context injection
|
|
737
|
+
- `_meta.rateLimit` / `_meta.rateLimitHints` for planner + runtime pacing guidance
|
|
738
|
+
|
|
739
|
+
Because `_meta` is an MCP-standard field, these hints survive normal MCP transport and discovery.
|
|
700
740
|
|
|
701
741
|
**Available context types:**
|
|
702
742
|
|
package/dist/client/index.cjs
CHANGED
|
@@ -97,11 +97,13 @@ var Tools = class {
|
|
|
97
97
|
* ```
|
|
98
98
|
*/
|
|
99
99
|
async execute(options) {
|
|
100
|
-
const { toolId, toolName, args } = options;
|
|
100
|
+
const { toolId, toolName, args, idempotencyKey } = options;
|
|
101
|
+
const headers = idempotencyKey ? { "Idempotency-Key": idempotencyKey } : void 0;
|
|
101
102
|
const response = await this.client._fetch(
|
|
102
103
|
"/api/v1/tools/execute",
|
|
103
104
|
{
|
|
104
105
|
method: "POST",
|
|
106
|
+
headers,
|
|
105
107
|
body: JSON.stringify({ toolId, toolName, args })
|
|
106
108
|
}
|
|
107
109
|
);
|
|
@@ -163,13 +165,18 @@ var Query = class {
|
|
|
163
165
|
*/
|
|
164
166
|
async run(options) {
|
|
165
167
|
const opts = typeof options === "string" ? { query: options } : options;
|
|
168
|
+
const headers = opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0;
|
|
166
169
|
const response = await this.client._fetch(
|
|
167
170
|
"/api/v1/query",
|
|
168
171
|
{
|
|
169
172
|
method: "POST",
|
|
173
|
+
headers,
|
|
170
174
|
body: JSON.stringify({
|
|
171
175
|
query: opts.query,
|
|
172
176
|
tools: opts.tools,
|
|
177
|
+
modelId: opts.modelId,
|
|
178
|
+
includeData: opts.includeData,
|
|
179
|
+
includeDataUrl: opts.includeDataUrl,
|
|
173
180
|
stream: false
|
|
174
181
|
})
|
|
175
182
|
}
|
|
@@ -187,7 +194,9 @@ var Query = class {
|
|
|
187
194
|
response: response.response,
|
|
188
195
|
toolsUsed: response.toolsUsed,
|
|
189
196
|
cost: response.cost,
|
|
190
|
-
durationMs: response.durationMs
|
|
197
|
+
durationMs: response.durationMs,
|
|
198
|
+
data: response.data,
|
|
199
|
+
dataUrl: response.dataUrl
|
|
191
200
|
};
|
|
192
201
|
}
|
|
193
202
|
throw new ContextError("Unexpected response format from query API");
|
|
@@ -223,11 +232,16 @@ var Query = class {
|
|
|
223
232
|
*/
|
|
224
233
|
async *stream(options) {
|
|
225
234
|
const opts = typeof options === "string" ? { query: options } : options;
|
|
235
|
+
const headers = opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0;
|
|
226
236
|
const response = await this.client._fetchRaw("/api/v1/query", {
|
|
227
237
|
method: "POST",
|
|
238
|
+
headers,
|
|
228
239
|
body: JSON.stringify({
|
|
229
240
|
query: opts.query,
|
|
230
241
|
tools: opts.tools,
|
|
242
|
+
modelId: opts.modelId,
|
|
243
|
+
includeData: opts.includeData,
|
|
244
|
+
includeDataUrl: opts.includeDataUrl,
|
|
231
245
|
stream: true
|
|
232
246
|
})
|
|
233
247
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/types.ts","../../src/client/resources/discovery.ts","../../src/client/resources/tools.ts","../../src/client/resources/query.ts","../../src/client/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 * JSON Schema for the input arguments this tool accepts.\n * Used by LLMs to generate correct arguments.\n */\n inputSchema?: Record<string, unknown>;\n\n /**\n * JSON Schema for the output this tool returns.\n * Used by LLMs to understand the response structure.\n */\n outputSchema?: Record<string, unknown>;\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 /** Tool type - currently always \"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 // Trust metrics (Level 2 - Reputation Ledger)\n /** Total number of queries processed */\n totalQueries?: number;\n\n /** Success rate percentage (0-100) */\n successRate?: string;\n\n /** Uptime percentage (0-100) */\n uptimePercent?: string;\n\n /** Total USDC staked by the developer */\n totalStaked?: string;\n\n /** Whether the tool has \"Proven\" status (100+ queries, >95% success, >98% uptime) */\n isProven?: boolean;\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// Query types (pay-per-response / agentic mode)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for the agentic query endpoint (pay-per-response).\n *\n * Unlike `execute()` which calls a single tool once, `query()` sends a\n * natural-language question and lets the server handle tool discovery,\n * multi-tool orchestration, self-healing retries, and AI synthesis.\n * One flat fee covers up to 100 MCP skill calls per tool.\n */\nexport interface QueryOptions {\n /** The natural-language question to answer */\n query: string;\n\n /**\n * Optional tool IDs to use. When omitted the server discovers tools\n * automatically (Auto Mode). When provided, only these tools are used\n * (Manual Mode).\n */\n tools?: string[];\n}\n\n/**\n * Information about a tool that was used during a query response\n */\nexport interface QueryToolUsage {\n /** Tool ID */\n id: string;\n\n /** Tool name */\n name: string;\n\n /** Number of MCP skill calls made for this tool */\n skillCalls: number;\n}\n\n/**\n * Cost breakdown for a query response.\n * All values are strings representing USD amounts.\n */\nexport interface QueryCost {\n /** AI model inference cost */\n modelCostUsd: string;\n\n /** Sum of all tool fees */\n toolCostUsd: string;\n\n /** Total cost (model + tools) */\n totalCostUsd: string;\n}\n\n/**\n * The resolved result of a pay-per-response query\n */\nexport interface QueryResult {\n /** The AI-synthesized response text */\n response: string;\n\n /** Tools that were used to answer the query */\n toolsUsed: QueryToolUsage[];\n\n /** Cost breakdown */\n cost: QueryCost;\n\n /** Total duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Successful response from the /api/v1/query endpoint\n */\nexport interface QueryApiSuccessResponse {\n success: true;\n response: string;\n toolsUsed: QueryToolUsage[];\n cost: QueryCost;\n durationMs: number;\n}\n\n/**\n * Raw API response from the query endpoint\n */\nexport type QueryApiResponse = QueryApiSuccessResponse | ExecuteApiErrorResponse;\n\n// ---------------------------------------------------------------------------\n// Query stream event types\n// ---------------------------------------------------------------------------\n\n/** Emitted when a tool starts or changes execution status */\nexport interface QueryStreamToolStatusEvent {\n type: \"tool-status\";\n tool: { id: string; name: string };\n status: string;\n}\n\n/** Emitted for each chunk of the AI response text */\nexport interface QueryStreamTextDeltaEvent {\n type: \"text-delta\";\n delta: string;\n}\n\n/** Emitted when the full response is complete */\nexport interface QueryStreamDoneEvent {\n type: \"done\";\n result: QueryResult;\n}\n\n/**\n * Union of all events emitted during a streaming query\n */\nexport type QueryStreamEvent =\n | QueryStreamToolStatusEvent\n | QueryStreamTextDeltaEvent\n | QueryStreamDoneEvent;\n\n// ---------------------------------------------------------------------------\n// Error types\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 | \"query_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 Object.setPrototypeOf(this, ContextError.prototype);\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 spending cap not set\n * @throws {ContextError} With code `payment_failed` if payment settlement 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 undefined, // Don't hardcode - this was a 200 OK with error body\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 {\n QueryOptions,\n QueryApiResponse,\n QueryResult,\n QueryStreamEvent,\n} from \"../types.js\";\nimport { ContextError } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Query resource for pay-per-response agentic queries.\n *\n * Unlike `tools.execute()` which calls a single tool once (pay-per-request),\n * the Query resource sends a natural-language question and lets the server\n * handle tool discovery, multi-tool orchestration, self-healing retries,\n * completeness checks, and AI synthesis — all for one flat fee.\n *\n * This is the \"prepared meal\" vs \"raw ingredients\" distinction:\n * - `tools.execute()` = raw data, full control, predictable cost\n * - `query.run()` / `query.stream()` = curated intelligence, one payment\n */\nexport class Query {\n constructor(private client: ContextClient) {}\n\n /**\n * Run an agentic query and wait for the full response.\n *\n * The server discovers relevant tools (or uses the ones you specify),\n * executes the full agentic pipeline (up to 100 MCP calls per tool),\n * and returns an AI-synthesized answer. Payment is settled after\n * successful execution via deferred settlement.\n *\n * @param options - Query options or a plain string question\n * @returns The complete query result with response text, tools used, and cost\n *\n * @throws {ContextError} With code `no_wallet` if wallet not set up\n * @throws {ContextError} With code `insufficient_allowance` if spending cap not set\n * @throws {ContextError} With code `payment_failed` if payment settlement fails\n * @throws {ContextError} With code `execution_failed` if the agentic pipeline fails\n *\n * @example\n * ```typescript\n * // Simple question — server discovers tools automatically\n * const answer = await client.query.run(\"What are the top whale movements on Base?\");\n * console.log(answer.response); // AI-synthesized answer\n * console.log(answer.toolsUsed); // Which tools were used\n * console.log(answer.cost); // Cost breakdown\n *\n * // With specific tools (Manual Mode)\n * const answer = await client.query.run({\n * query: \"Analyze whale activity\",\n * tools: [\"tool-uuid-1\", \"tool-uuid-2\"],\n * });\n * ```\n */\n async run(options: QueryOptions | string): Promise<QueryResult> {\n const opts = typeof options === \"string\" ? { query: options } : options;\n\n const response = await this.client._fetch<QueryApiResponse>(\n \"/api/v1/query\",\n {\n method: \"POST\",\n body: JSON.stringify({\n query: opts.query,\n tools: opts.tools,\n stream: false,\n }),\n }\n );\n\n // Handle error response\n if (\"error\" in response) {\n throw new ContextError(\n response.error,\n response.code,\n undefined,\n response.helpUrl\n );\n }\n\n // Handle success response\n if (response.success) {\n return {\n response: response.response,\n toolsUsed: response.toolsUsed,\n cost: response.cost,\n durationMs: response.durationMs,\n };\n }\n\n throw new ContextError(\"Unexpected response format from query API\");\n }\n\n /**\n * Run an agentic query with streaming. Returns an async iterable that\n * yields events as the server processes the query in real-time.\n *\n * Event types:\n * - `tool-status` — A tool started executing or changed status\n * - `text-delta` — A chunk of the AI response text\n * - `done` — The full response is complete (includes final `QueryResult`)\n *\n * @param options - Query options or a plain string question\n * @returns An async iterable of stream events\n *\n * @example\n * ```typescript\n * for await (const event of client.query.stream(\"What are the top whale movements?\")) {\n * switch (event.type) {\n * case \"tool-status\":\n * console.log(`Tool ${event.tool.name}: ${event.status}`);\n * break;\n * case \"text-delta\":\n * process.stdout.write(event.delta);\n * break;\n * case \"done\":\n * console.log(\"\\nCost:\", event.result.cost.totalCostUsd);\n * break;\n * }\n * }\n * ```\n */\n async *stream(\n options: QueryOptions | string\n ): AsyncGenerator<QueryStreamEvent> {\n const opts = typeof options === \"string\" ? { query: options } : options;\n\n const response = await this.client._fetchRaw(\"/api/v1/query\", {\n method: \"POST\",\n body: JSON.stringify({\n query: opts.query,\n tools: opts.tools,\n stream: true,\n }),\n });\n\n const body = response.body;\n if (!body) {\n throw new ContextError(\"No response body for streaming query\");\n }\n\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"data: \")) {\n const data = trimmed.slice(6);\n if (data === \"[DONE]\") return;\n try {\n yield JSON.parse(data) as QueryStreamEvent;\n } catch {\n // Skip malformed SSE events\n }\n }\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim().startsWith(\"data: \")) {\n const data = buffer.trim().slice(6);\n if (data !== \"[DONE]\") {\n try {\n yield JSON.parse(data) as QueryStreamEvent;\n } catch {\n // Skip malformed SSE events\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\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\";\nimport { Query } from \"./resources/query.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 * // Pay-per-request: Execute a specific tool\n * const result = await client.tools.execute({\n * toolId: \"tool-uuid\",\n * toolName: \"get_gas_prices\",\n * args: { chainId: 1 }\n * });\n *\n * // Pay-per-response: Ask a question, get a curated answer\n * const answer = await client.query.run(\"What are the top whale movements on Base?\");\n * console.log(answer.response);\n * ```\n */\nexport class ContextClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private _closed = false;\n\n /**\n * Discovery resource for searching tools\n */\n public readonly discovery: Discovery;\n\n /**\n * Tools resource for executing tools (pay-per-request)\n */\n public readonly tools: Tools;\n\n /**\n * Query resource for agentic queries (pay-per-response).\n *\n * Unlike `tools.execute()` which calls a single tool once, `query` sends\n * a natural-language question and lets the server handle tool discovery,\n * multi-tool orchestration, self-healing, and AI synthesis — one flat fee.\n */\n public readonly query: Query;\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 this.query = new Query(this);\n }\n\n /**\n * Close the client and clean up resources.\n * After calling close(), any in-flight requests may be aborted.\n */\n close(): void {\n this._closed = true;\n }\n\n /**\n * Internal method for making authenticated HTTP requests\n * Includes timeout (30s) and retry with exponential backoff for transient errors\n *\n * @internal\n */\n async _fetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n if (this._closed) {\n throw new ContextError(\"Client has been closed\");\n }\n\n const url = `${this.baseUrl}${endpoint}`;\n const maxRetries = 3;\n const timeoutMs = 30_000;\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n // Retry on 5xx server errors\n if (response.status >= 500 && attempt < maxRetries) {\n const delay = Math.min(1000 * 2 ** attempt, 10_000);\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\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 } catch (error) {\n clearTimeout(timeout);\n\n if (error instanceof ContextError) {\n throw error;\n }\n\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Retry on network errors and timeouts\n const isRetryable =\n lastError.name === \"AbortError\" ||\n lastError.message.includes(\"fetch failed\") ||\n lastError.message.includes(\"ECONNRESET\") ||\n lastError.message.includes(\"ETIMEDOUT\");\n\n if (isRetryable && attempt < maxRetries) {\n const delay = Math.min(1000 * 2 ** attempt, 10_000);\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\n if (lastError.name === \"AbortError\") {\n throw new ContextError(\n `Request timed out after ${timeoutMs / 1000}s`,\n undefined,\n 408\n );\n }\n\n throw new ContextError(\n lastError.message,\n undefined,\n undefined\n );\n }\n }\n\n throw lastError ?? new ContextError(\"Request failed after retries\");\n }\n\n /**\n * Internal method for making authenticated HTTP requests that returns\n * the raw Response object. Used for streaming endpoints (SSE).\n *\n * @internal\n */\n async _fetchRaw(endpoint: string, options: RequestInit = {}): Promise<Response> {\n if (this._closed) {\n throw new ContextError(\"Client has been closed\");\n }\n\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;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/types.ts","../../src/client/resources/discovery.ts","../../src/client/resources/tools.ts","../../src/client/resources/query.ts","../../src/client/client.ts"],"names":[],"mappings":";;;AAgZO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,KAAA,CAAM;AAAA,EACtC,WAAA,CACE,OAAA,EACgB,IAAA,EACA,UAAA,EACA,OAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,aAAA,CAAa,SAAS,CAAA;AAAA,EACpD;AACF;;;ACrZO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAAoB,MAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB5C,MAAM,MAAA,CAAO,KAAA,EAAe,KAAA,EAAiC;AAC3D,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAA,CAAO,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACnC;AAEA,IAAA,MAAM,WAAA,GAAc,OAAO,QAAA,EAAS;AACpC,IAAA,MAAM,WAAW,CAAA,oBAAA,EAAuB,WAAA,GAAc,CAAA,CAAA,EAAI,WAAW,KAAK,EAAE,CAAA,CAAA;AAE5E,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,OAAuB,QAAQ,CAAA;AAElE,IAAA,OAAO,QAAA,CAAS,KAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,YAAY,KAAA,EAAiC;AACjD,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,EAAA,EAAI,KAAK,CAAA;AAAA,EAC9B;AACF;;;AC7CO,IAAM,QAAN,MAAY;AAAA,EACjB,YAAoB,MAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiC5C,MAAM,QAAqB,OAAA,EAAsD;AAC/E,IAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,IAAA,EAAM,gBAAe,GAAI,OAAA;AACnD,IAAA,MAAM,OAAA,GAAU,cAAA,GACZ,EAAE,iBAAA,EAAmB,gBAAe,GACpC,MAAA;AAEJ,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA;AAAA,MACjC,uBAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA;AAAA,QACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,MAAA,EAAQ,QAAA,EAAU,MAAM;AAAA;AACjD,KACF;AAGA,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,MAAM,IAAI,YAAA;AAAA,QACR,QAAA,CAAS,KAAA;AAAA,QACT,QAAA,CAAS,IAAA;AAAA,QACT,MAAA;AAAA;AAAA,QACA,QAAA,CAAS;AAAA,OACX;AAAA,IACF;AAGA,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,OAAO;AAAA,QACL,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,MAAM,QAAA,CAAS,IAAA;AAAA,QACf,YAAY,QAAA,CAAS;AAAA,OACvB;AAAA,IACF;AAGA,IAAA,MAAM,IAAI,aAAa,qCAAqC,CAAA;AAAA,EAC9D;AACF;;;AC7DO,IAAM,QAAN,MAAY;AAAA,EACjB,YAAoB,MAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiC5C,MAAM,IAAI,OAAA,EAAsD;AAC9D,IAAA,MAAM,OAAO,OAAO,OAAA,KAAY,WAAW,EAAE,KAAA,EAAO,SAAQ,GAAI,OAAA;AAChE,IAAA,MAAM,UAAU,IAAA,CAAK,cAAA,GACjB,EAAE,iBAAA,EAAmB,IAAA,CAAK,gBAAe,GACzC,MAAA;AAEJ,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA;AAAA,MACjC,eAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA;AAAA,QACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,UACnB,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,SAAS,IAAA,CAAK,OAAA;AAAA,UACd,aAAa,IAAA,CAAK,WAAA;AAAA,UAClB,gBAAgB,IAAA,CAAK,cAAA;AAAA,UACrB,MAAA,EAAQ;AAAA,SACT;AAAA;AACH,KACF;AAGA,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,MAAM,IAAI,YAAA;AAAA,QACR,QAAA,CAAS,KAAA;AAAA,QACT,QAAA,CAAS,IAAA;AAAA,QACT,MAAA;AAAA,QACA,QAAA,CAAS;AAAA,OACX;AAAA,IACF;AAGA,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,OAAO;AAAA,QACL,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,WAAW,QAAA,CAAS,SAAA;AAAA,QACpB,MAAM,QAAA,CAAS,IAAA;AAAA,QACf,YAAY,QAAA,CAAS,UAAA;AAAA,QACrB,MAAM,QAAA,CAAS,IAAA;AAAA,QACf,SAAS,QAAA,CAAS;AAAA,OACpB;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,aAAa,2CAA2C,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,OAAO,OACL,OAAA,EACkC;AAClC,IAAA,MAAM,OAAO,OAAO,OAAA,KAAY,WAAW,EAAE,KAAA,EAAO,SAAQ,GAAI,OAAA;AAChE,IAAA,MAAM,UAAU,IAAA,CAAK,cAAA,GACjB,EAAE,iBAAA,EAAmB,IAAA,CAAK,gBAAe,GACzC,MAAA;AAEJ,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,UAAU,eAAA,EAAiB;AAAA,MAC5D,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,gBAAgB,IAAA,CAAK,cAAA;AAAA,QACrB,MAAA,EAAQ;AAAA,OACT;AAAA,KACF,CAAA;AAED,IAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AACtB,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,aAAa,sCAAsC,CAAA;AAAA,IAC/D;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,QAAA,IAAI,IAAA,EAAM;AAEV,QAAA,MAAA,IAAU,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAChD,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,QAAA,MAAA,GAAS,KAAA,CAAM,KAAI,IAAK,EAAA;AAExB,QAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,UAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,UAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,QAAQ,CAAA,EAAG;AAChC,YAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC5B,YAAA,IAAI,SAAS,QAAA,EAAU;AACvB,YAAA,IAAI;AACF,cAAA,MAAM,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,YACvB,CAAA,CAAA,MAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,MAAA,IAAI,MAAA,CAAO,IAAA,EAAK,CAAE,UAAA,CAAW,QAAQ,CAAA,EAAG;AACtC,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,EAAK,CAAE,MAAM,CAAC,CAAA;AAClC,QAAA,IAAI,SAAS,QAAA,EAAU;AACrB,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UACvB,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAA,CAAO,WAAA,EAAY;AAAA,IACrB;AAAA,EACF;AACF;;;ACxKO,IAAM,gBAAN,MAAoB;AAAA,EACR,MAAA;AAAA,EACA,OAAA;AAAA,EACT,OAAA,GAAU,KAAA;AAAA;AAAA;AAAA;AAAA,EAKF,SAAA;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAShB,YAAY,OAAA,EAA+B;AACzC,IAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACnB,MAAA,MAAM,IAAI,aAAa,qBAAqB,CAAA;AAAA,IAC9C;AAEA,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,OAAA,IAAW,yBAAA,EAA2B,OAAA,CAAQ,OAAO,EAAE,CAAA;AAG/E,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,CAAU,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,KAAA,CAAM,IAAI,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CAAU,QAAA,EAAkB,OAAA,GAAuB,EAAC,EAAe;AACvE,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAI,aAAa,wBAAwB,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,GAAG,QAAQ,CAAA,CAAA;AACtC,IAAA,MAAM,UAAA,GAAa,CAAA;AACnB,IAAA,MAAM,SAAA,GAAY,GAAA;AAElB,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,OAAA,EAAA,EAAW;AACtD,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAE9D,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,UAChC,GAAG,OAAA;AAAA,UACH,QAAQ,UAAA,CAAW,MAAA;AAAA,UACnB,OAAA,EAAS;AAAA,YACP,cAAA,EAAgB,kBAAA;AAAA,YAChB,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,YACpC,GAAG,OAAA,CAAQ;AAAA;AACb,SACD,CAAA;AAED,QAAA,YAAA,CAAa,OAAO,CAAA;AAEpB,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAEhB,UAAA,IAAI,QAAA,CAAS,MAAA,IAAU,GAAA,IAAO,OAAA,GAAU,UAAA,EAAY;AAClD,YAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,GAAO,CAAA,IAAK,SAAS,GAAM,CAAA;AAClD,YAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,KAAK,CAAC,CAAA;AACzD,YAAA;AAAA,UACF;AAEA,UAAA,IAAI,eAAe,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAClE,UAAA,IAAI,SAAA;AACJ,UAAA,IAAI,OAAA;AAEJ,UAAA,IAAI;AACF,YAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,YAAA,IAAI,UAAU,KAAA,EAAO;AACnB,cAAA,YAAA,GAAe,SAAA,CAAU,KAAA;AACzB,cAAA,SAAA,GAAY,SAAA,CAAU,IAAA;AACtB,cAAA,OAAA,GAAU,SAAA,CAAU,OAAA;AAAA,YACtB;AAAA,UACF,CAAA,CAAA,MAAQ;AAAA,UAER;AAEA,UAAA,MAAM,IAAI,YAAA,CAAa,YAAA,EAAc,SAAA,EAAW,QAAA,CAAS,QAAQ,OAAO,CAAA;AAAA,QAC1E;AAEA,QAAA,OAAO,SAAS,IAAA,EAAK;AAAA,MACvB,SAAS,KAAA,EAAO;AACd,QAAA,YAAA,CAAa,OAAO,CAAA;AAEpB,QAAA,IAAI,iBAAiB,YAAA,EAAc;AACjC,UAAA,MAAM,KAAA;AAAA,QACR;AAEA,QAAA,SAAA,GAAY,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAGpE,QAAA,MAAM,cACJ,SAAA,CAAU,IAAA,KAAS,YAAA,IACnB,SAAA,CAAU,QAAQ,QAAA,CAAS,cAAc,CAAA,IACzC,SAAA,CAAU,QAAQ,QAAA,CAAS,YAAY,KACvC,SAAA,CAAU,OAAA,CAAQ,SAAS,WAAW,CAAA;AAExC,QAAA,IAAI,WAAA,IAAe,UAAU,UAAA,EAAY;AACvC,UAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,GAAO,CAAA,IAAK,SAAS,GAAM,CAAA;AAClD,UAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,KAAK,CAAC,CAAA;AACzD,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,SAAA,CAAU,SAAS,YAAA,EAAc;AACnC,UAAA,MAAM,IAAI,YAAA;AAAA,YACR,CAAA,wBAAA,EAA2B,YAAY,GAAI,CAAA,CAAA,CAAA;AAAA,YAC3C,MAAA;AAAA,YACA;AAAA,WACF;AAAA,QACF;AAEA,QAAA,MAAM,IAAI,YAAA;AAAA,UACR,SAAA,CAAU,OAAA;AAAA,UACV,MAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,IAAa,IAAI,YAAA,CAAa,8BAA8B,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAA,CAAU,QAAA,EAAkB,OAAA,GAAuB,EAAC,EAAsB;AAC9E,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAI,aAAa,wBAAwB,CAAA;AAAA,IACjD;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,GAAG,QAAQ,CAAA,CAAA;AAEtC,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAChC,GAAG,OAAA;AAAA,MACH,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,QACpC,GAAG,OAAA,CAAQ;AAAA;AACb,KACD,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,IAAI,eAAe,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAClE,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI,OAAA;AAEJ,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,QAAA,IAAI,UAAU,KAAA,EAAO;AACnB,UAAA,YAAA,GAAe,SAAA,CAAU,KAAA;AACzB,UAAA,SAAA,GAAY,SAAA,CAAU,IAAA;AACtB,UAAA,OAAA,GAAU,SAAA,CAAU,OAAA;AAAA,QACtB;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,MAAM,IAAI,YAAA,CAAa,YAAA,EAAc,SAAA,EAAW,QAAA,CAAS,QAAQ,OAAO,CAAA;AAAA,IAC1E;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AACF","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 McpToolRateLimitHints {\n /** Suggested request budget for this method */\n maxRequestsPerMinute?: number;\n\n /** Suggested parallel call ceiling for this method */\n maxConcurrency?: number;\n\n /** Suggested minimum delay between sequential calls */\n cooldownMs?: number;\n\n /** Whether this method already supports bulk/batch retrieval */\n supportsBulk?: boolean;\n\n /** Preferred batch-oriented methods to call instead of fan-out loops */\n recommendedBatchTools?: string[];\n\n /** Optional human-readable notes for planning */\n notes?: string;\n}\n\nexport interface McpToolMeta {\n /** Context injection requirements handled by the Context runtime */\n contextRequirements?: string[];\n\n /**\n * Optional planner/runtime pacing hints.\n * Tool contributors can publish these to reduce rate-limit failures.\n */\n rateLimit?: McpToolRateLimitHints;\n rateLimitHints?: McpToolRateLimitHints;\n\n /** Flat aliases accepted for convenience */\n maxRequestsPerMinute?: number;\n maxConcurrency?: number;\n cooldownMs?: number;\n supportsBulk?: boolean;\n recommendedBatchTools?: string[];\n notes?: string;\n\n [key: string]: unknown;\n}\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 * JSON Schema for the input arguments this tool accepts.\n * Used by LLMs to generate correct arguments.\n */\n inputSchema?: Record<string, unknown>;\n\n /**\n * JSON Schema for the output this tool returns.\n * Used by LLMs to understand the response structure.\n */\n outputSchema?: Record<string, unknown>;\n\n /** MCP metadata extensions (context injection, rate-limit hints) */\n _meta?: McpToolMeta;\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 /** Tool type - currently always \"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 // Trust metrics (Level 2 - Reputation Ledger)\n /** Total number of queries processed */\n totalQueries?: number;\n\n /** Success rate percentage (0-100) */\n successRate?: string;\n\n /** Uptime percentage (0-100) */\n uptimePercent?: string;\n\n /** Total USDC staked by the developer */\n totalStaked?: string;\n\n /** Whether the tool has \"Proven\" status (100+ queries, >95% success, >98% uptime) */\n isProven?: boolean;\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 * Optional idempotency key (UUID recommended).\n * Reuse the same key when retrying the same logical request.\n */\n idempotencyKey?: string;\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// Query types (pay-per-response / agentic mode)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for the agentic query endpoint (pay-per-response).\n *\n * Unlike `execute()` which calls a single tool once, `query()` sends a\n * natural-language question and lets the server handle tool discovery,\n * multi-tool orchestration, self-healing retries, and AI synthesis.\n * One flat fee covers up to 100 MCP skill calls per tool.\n */\nexport interface QueryOptions {\n /** The natural-language question to answer */\n query: string;\n\n /**\n * Optional tool IDs to use. When omitted the server discovers tools\n * automatically (Auto Mode). When provided, only these tools are used\n * (Manual Mode).\n */\n tools?: string[];\n\n /**\n * Optional model ID for query orchestration/synthesis.\n * Supported IDs are published by the Context API.\n */\n modelId?: string;\n\n /**\n * Include execution data inline in the query response.\n * Useful for headless agents that need raw structured outputs.\n */\n includeData?: boolean;\n\n /**\n * Persist execution data to Vercel Blob and return a download URL.\n * Useful for large payload workflows where inline JSON is not ideal.\n */\n includeDataUrl?: boolean;\n\n /**\n * Optional idempotency key (UUID recommended).\n * Reuse the same key when retrying the same logical request.\n */\n idempotencyKey?: string;\n}\n\n/**\n * Information about a tool that was used during a query response\n */\nexport interface QueryToolUsage {\n /** Tool ID */\n id: string;\n\n /** Tool name */\n name: string;\n\n /** Number of MCP skill calls made for this tool */\n skillCalls: number;\n}\n\n/**\n * Cost breakdown for a query response.\n * All values are strings representing USD amounts.\n */\nexport interface QueryCost {\n /** AI model inference cost */\n modelCostUsd: string;\n\n /** Sum of all tool fees */\n toolCostUsd: string;\n\n /** Total cost (model + tools) */\n totalCostUsd: string;\n}\n\n/**\n * The resolved result of a pay-per-response query\n */\nexport interface QueryResult {\n /** The AI-synthesized response text */\n response: string;\n\n /** Tools that were used to answer the query */\n toolsUsed: QueryToolUsage[];\n\n /** Cost breakdown */\n cost: QueryCost;\n\n /** Total duration in milliseconds */\n durationMs: number;\n\n /** Optional execution data from tools (when includeData=true) */\n data?: unknown;\n\n /** Optional blob URL for persisted execution data (when includeDataUrl=true) */\n dataUrl?: string;\n}\n\n/**\n * Successful response from the /api/v1/query endpoint\n */\nexport interface QueryApiSuccessResponse {\n success: true;\n response: string;\n toolsUsed: QueryToolUsage[];\n cost: QueryCost;\n durationMs: number;\n data?: unknown;\n dataUrl?: string;\n}\n\n/**\n * Raw API response from the query endpoint\n */\nexport type QueryApiResponse = QueryApiSuccessResponse | ExecuteApiErrorResponse;\n\n// ---------------------------------------------------------------------------\n// Query stream event types\n// ---------------------------------------------------------------------------\n\n/** Emitted when a tool starts or changes execution status */\nexport interface QueryStreamToolStatusEvent {\n type: \"tool-status\";\n tool: { id: string; name: string };\n status: string;\n}\n\n/** Emitted for each chunk of the AI response text */\nexport interface QueryStreamTextDeltaEvent {\n type: \"text-delta\";\n delta: string;\n}\n\n/** Emitted when the full response is complete */\nexport interface QueryStreamDoneEvent {\n type: \"done\";\n result: QueryResult;\n}\n\n/**\n * Union of all events emitted during a streaming query\n */\nexport type QueryStreamEvent =\n | QueryStreamToolStatusEvent\n | QueryStreamTextDeltaEvent\n | QueryStreamDoneEvent;\n\n// ---------------------------------------------------------------------------\n// Error types\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 | \"query_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 Object.setPrototypeOf(this, ContextError.prototype);\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 spending cap not set\n * @throws {ContextError} With code `payment_failed` if payment settlement 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, idempotencyKey } = options;\n const headers = idempotencyKey\n ? { \"Idempotency-Key\": idempotencyKey }\n : undefined;\n\n const response = await this.client._fetch<ExecuteApiResponse>(\n \"/api/v1/tools/execute\",\n {\n method: \"POST\",\n headers,\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 undefined, // Don't hardcode - this was a 200 OK with error body\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 {\n QueryOptions,\n QueryApiResponse,\n QueryResult,\n QueryStreamEvent,\n} from \"../types.js\";\nimport { ContextError } from \"../types.js\";\nimport type { ContextClient } from \"../client.js\";\n\n/**\n * Query resource for pay-per-response agentic queries.\n *\n * Unlike `tools.execute()` which calls a single tool once (pay-per-request),\n * the Query resource sends a natural-language question and lets the server\n * handle tool discovery, multi-tool orchestration, self-healing retries,\n * completeness checks, and AI synthesis — all for one flat fee.\n *\n * This is the \"prepared meal\" vs \"raw ingredients\" distinction:\n * - `tools.execute()` = raw data, full control, predictable cost\n * - `query.run()` / `query.stream()` = curated intelligence, one payment\n */\nexport class Query {\n constructor(private client: ContextClient) {}\n\n /**\n * Run an agentic query and wait for the full response.\n *\n * The server discovers relevant tools (or uses the ones you specify),\n * executes the full agentic pipeline (up to 100 MCP calls per tool),\n * and returns an AI-synthesized answer. Payment is settled after\n * successful execution via deferred settlement.\n *\n * @param options - Query options or a plain string question\n * @returns The complete query result with response text, tools used, and cost\n *\n * @throws {ContextError} With code `no_wallet` if wallet not set up\n * @throws {ContextError} With code `insufficient_allowance` if spending cap not set\n * @throws {ContextError} With code `payment_failed` if payment settlement fails\n * @throws {ContextError} With code `execution_failed` if the agentic pipeline fails\n *\n * @example\n * ```typescript\n * // Simple question — server discovers tools automatically\n * const answer = await client.query.run(\"What are the top whale movements on Base?\");\n * console.log(answer.response); // AI-synthesized answer\n * console.log(answer.toolsUsed); // Which tools were used\n * console.log(answer.cost); // Cost breakdown\n *\n * // With specific tools (Manual Mode)\n * const answer = await client.query.run({\n * query: \"Analyze whale activity\",\n * tools: [\"tool-uuid-1\", \"tool-uuid-2\"],\n * });\n * ```\n */\n async run(options: QueryOptions | string): Promise<QueryResult> {\n const opts = typeof options === \"string\" ? { query: options } : options;\n const headers = opts.idempotencyKey\n ? { \"Idempotency-Key\": opts.idempotencyKey }\n : undefined;\n\n const response = await this.client._fetch<QueryApiResponse>(\n \"/api/v1/query\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query: opts.query,\n tools: opts.tools,\n modelId: opts.modelId,\n includeData: opts.includeData,\n includeDataUrl: opts.includeDataUrl,\n stream: false,\n }),\n }\n );\n\n // Handle error response\n if (\"error\" in response) {\n throw new ContextError(\n response.error,\n response.code,\n undefined,\n response.helpUrl\n );\n }\n\n // Handle success response\n if (response.success) {\n return {\n response: response.response,\n toolsUsed: response.toolsUsed,\n cost: response.cost,\n durationMs: response.durationMs,\n data: response.data,\n dataUrl: response.dataUrl,\n };\n }\n\n throw new ContextError(\"Unexpected response format from query API\");\n }\n\n /**\n * Run an agentic query with streaming. Returns an async iterable that\n * yields events as the server processes the query in real-time.\n *\n * Event types:\n * - `tool-status` — A tool started executing or changed status\n * - `text-delta` — A chunk of the AI response text\n * - `done` — The full response is complete (includes final `QueryResult`)\n *\n * @param options - Query options or a plain string question\n * @returns An async iterable of stream events\n *\n * @example\n * ```typescript\n * for await (const event of client.query.stream(\"What are the top whale movements?\")) {\n * switch (event.type) {\n * case \"tool-status\":\n * console.log(`Tool ${event.tool.name}: ${event.status}`);\n * break;\n * case \"text-delta\":\n * process.stdout.write(event.delta);\n * break;\n * case \"done\":\n * console.log(\"\\nCost:\", event.result.cost.totalCostUsd);\n * break;\n * }\n * }\n * ```\n */\n async *stream(\n options: QueryOptions | string\n ): AsyncGenerator<QueryStreamEvent> {\n const opts = typeof options === \"string\" ? { query: options } : options;\n const headers = opts.idempotencyKey\n ? { \"Idempotency-Key\": opts.idempotencyKey }\n : undefined;\n\n const response = await this.client._fetchRaw(\"/api/v1/query\", {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query: opts.query,\n tools: opts.tools,\n modelId: opts.modelId,\n includeData: opts.includeData,\n includeDataUrl: opts.includeDataUrl,\n stream: true,\n }),\n });\n\n const body = response.body;\n if (!body) {\n throw new ContextError(\"No response body for streaming query\");\n }\n\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"data: \")) {\n const data = trimmed.slice(6);\n if (data === \"[DONE]\") return;\n try {\n yield JSON.parse(data) as QueryStreamEvent;\n } catch {\n // Skip malformed SSE events\n }\n }\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim().startsWith(\"data: \")) {\n const data = buffer.trim().slice(6);\n if (data !== \"[DONE]\") {\n try {\n yield JSON.parse(data) as QueryStreamEvent;\n } catch {\n // Skip malformed SSE events\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\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\";\nimport { Query } from \"./resources/query.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 * // Pay-per-request: Execute a specific tool\n * const result = await client.tools.execute({\n * toolId: \"tool-uuid\",\n * toolName: \"get_gas_prices\",\n * args: { chainId: 1 }\n * });\n *\n * // Pay-per-response: Ask a question, get a curated answer\n * const answer = await client.query.run(\"What are the top whale movements on Base?\");\n * console.log(answer.response);\n * ```\n */\nexport class ContextClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private _closed = false;\n\n /**\n * Discovery resource for searching tools\n */\n public readonly discovery: Discovery;\n\n /**\n * Tools resource for executing tools (pay-per-request)\n */\n public readonly tools: Tools;\n\n /**\n * Query resource for agentic queries (pay-per-response).\n *\n * Unlike `tools.execute()` which calls a single tool once, `query` sends\n * a natural-language question and lets the server handle tool discovery,\n * multi-tool orchestration, self-healing, and AI synthesis — one flat fee.\n */\n public readonly query: Query;\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 this.query = new Query(this);\n }\n\n /**\n * Close the client and clean up resources.\n * After calling close(), any in-flight requests may be aborted.\n */\n close(): void {\n this._closed = true;\n }\n\n /**\n * Internal method for making authenticated HTTP requests\n * Includes timeout (30s) and retry with exponential backoff for transient errors\n *\n * @internal\n */\n async _fetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n if (this._closed) {\n throw new ContextError(\"Client has been closed\");\n }\n\n const url = `${this.baseUrl}${endpoint}`;\n const maxRetries = 3;\n const timeoutMs = 30_000;\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n ...options.headers,\n },\n });\n\n clearTimeout(timeout);\n\n if (!response.ok) {\n // Retry on 5xx server errors\n if (response.status >= 500 && attempt < maxRetries) {\n const delay = Math.min(1000 * 2 ** attempt, 10_000);\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\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 } catch (error) {\n clearTimeout(timeout);\n\n if (error instanceof ContextError) {\n throw error;\n }\n\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Retry on network errors and timeouts\n const isRetryable =\n lastError.name === \"AbortError\" ||\n lastError.message.includes(\"fetch failed\") ||\n lastError.message.includes(\"ECONNRESET\") ||\n lastError.message.includes(\"ETIMEDOUT\");\n\n if (isRetryable && attempt < maxRetries) {\n const delay = Math.min(1000 * 2 ** attempt, 10_000);\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\n if (lastError.name === \"AbortError\") {\n throw new ContextError(\n `Request timed out after ${timeoutMs / 1000}s`,\n undefined,\n 408\n );\n }\n\n throw new ContextError(\n lastError.message,\n undefined,\n undefined\n );\n }\n }\n\n throw lastError ?? new ContextError(\"Request failed after retries\");\n }\n\n /**\n * Internal method for making authenticated HTTP requests that returns\n * the raw Response object. Used for streaming endpoints (SSE).\n *\n * @internal\n */\n async _fetchRaw(endpoint: string, options: RequestInit = {}): Promise<Response> {\n if (this._closed) {\n throw new ContextError(\"Client has been closed\");\n }\n\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;\n }\n}\n"]}
|
package/dist/client/index.d.cts
CHANGED
|
@@ -16,6 +16,38 @@ interface ContextClientOptions {
|
|
|
16
16
|
/**
|
|
17
17
|
* An individual MCP tool exposed by a tool listing
|
|
18
18
|
*/
|
|
19
|
+
interface McpToolRateLimitHints {
|
|
20
|
+
/** Suggested request budget for this method */
|
|
21
|
+
maxRequestsPerMinute?: number;
|
|
22
|
+
/** Suggested parallel call ceiling for this method */
|
|
23
|
+
maxConcurrency?: number;
|
|
24
|
+
/** Suggested minimum delay between sequential calls */
|
|
25
|
+
cooldownMs?: number;
|
|
26
|
+
/** Whether this method already supports bulk/batch retrieval */
|
|
27
|
+
supportsBulk?: boolean;
|
|
28
|
+
/** Preferred batch-oriented methods to call instead of fan-out loops */
|
|
29
|
+
recommendedBatchTools?: string[];
|
|
30
|
+
/** Optional human-readable notes for planning */
|
|
31
|
+
notes?: string;
|
|
32
|
+
}
|
|
33
|
+
interface McpToolMeta {
|
|
34
|
+
/** Context injection requirements handled by the Context runtime */
|
|
35
|
+
contextRequirements?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Optional planner/runtime pacing hints.
|
|
38
|
+
* Tool contributors can publish these to reduce rate-limit failures.
|
|
39
|
+
*/
|
|
40
|
+
rateLimit?: McpToolRateLimitHints;
|
|
41
|
+
rateLimitHints?: McpToolRateLimitHints;
|
|
42
|
+
/** Flat aliases accepted for convenience */
|
|
43
|
+
maxRequestsPerMinute?: number;
|
|
44
|
+
maxConcurrency?: number;
|
|
45
|
+
cooldownMs?: number;
|
|
46
|
+
supportsBulk?: boolean;
|
|
47
|
+
recommendedBatchTools?: string[];
|
|
48
|
+
notes?: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
19
51
|
interface McpTool {
|
|
20
52
|
/** Name of the MCP tool method */
|
|
21
53
|
name: string;
|
|
@@ -31,6 +63,8 @@ interface McpTool {
|
|
|
31
63
|
* Used by LLMs to understand the response structure.
|
|
32
64
|
*/
|
|
33
65
|
outputSchema?: Record<string, unknown>;
|
|
66
|
+
/** MCP metadata extensions (context injection, rate-limit hints) */
|
|
67
|
+
_meta?: McpToolMeta;
|
|
34
68
|
}
|
|
35
69
|
/**
|
|
36
70
|
* Represents a tool available on the Context Protocol marketplace
|
|
@@ -96,6 +130,11 @@ interface ExecuteOptions {
|
|
|
96
130
|
toolName: string;
|
|
97
131
|
/** Arguments to pass to the tool */
|
|
98
132
|
args?: Record<string, unknown>;
|
|
133
|
+
/**
|
|
134
|
+
* Optional idempotency key (UUID recommended).
|
|
135
|
+
* Reuse the same key when retrying the same logical request.
|
|
136
|
+
*/
|
|
137
|
+
idempotencyKey?: string;
|
|
99
138
|
}
|
|
100
139
|
/**
|
|
101
140
|
* Successful execution response from the API
|
|
@@ -158,6 +197,26 @@ interface QueryOptions {
|
|
|
158
197
|
* (Manual Mode).
|
|
159
198
|
*/
|
|
160
199
|
tools?: string[];
|
|
200
|
+
/**
|
|
201
|
+
* Optional model ID for query orchestration/synthesis.
|
|
202
|
+
* Supported IDs are published by the Context API.
|
|
203
|
+
*/
|
|
204
|
+
modelId?: string;
|
|
205
|
+
/**
|
|
206
|
+
* Include execution data inline in the query response.
|
|
207
|
+
* Useful for headless agents that need raw structured outputs.
|
|
208
|
+
*/
|
|
209
|
+
includeData?: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Persist execution data to Vercel Blob and return a download URL.
|
|
212
|
+
* Useful for large payload workflows where inline JSON is not ideal.
|
|
213
|
+
*/
|
|
214
|
+
includeDataUrl?: boolean;
|
|
215
|
+
/**
|
|
216
|
+
* Optional idempotency key (UUID recommended).
|
|
217
|
+
* Reuse the same key when retrying the same logical request.
|
|
218
|
+
*/
|
|
219
|
+
idempotencyKey?: string;
|
|
161
220
|
}
|
|
162
221
|
/**
|
|
163
222
|
* Information about a tool that was used during a query response
|
|
@@ -194,6 +253,10 @@ interface QueryResult {
|
|
|
194
253
|
cost: QueryCost;
|
|
195
254
|
/** Total duration in milliseconds */
|
|
196
255
|
durationMs: number;
|
|
256
|
+
/** Optional execution data from tools (when includeData=true) */
|
|
257
|
+
data?: unknown;
|
|
258
|
+
/** Optional blob URL for persisted execution data (when includeDataUrl=true) */
|
|
259
|
+
dataUrl?: string;
|
|
197
260
|
}
|
|
198
261
|
/**
|
|
199
262
|
* Successful response from the /api/v1/query endpoint
|
|
@@ -204,6 +267,8 @@ interface QueryApiSuccessResponse {
|
|
|
204
267
|
toolsUsed: QueryToolUsage[];
|
|
205
268
|
cost: QueryCost;
|
|
206
269
|
durationMs: number;
|
|
270
|
+
data?: unknown;
|
|
271
|
+
dataUrl?: string;
|
|
207
272
|
}
|
|
208
273
|
/**
|
|
209
274
|
* Raw API response from the query endpoint
|
|
@@ -474,4 +539,4 @@ declare class ContextClient {
|
|
|
474
539
|
_fetchRaw(endpoint: string, options?: RequestInit): Promise<Response>;
|
|
475
540
|
}
|
|
476
541
|
|
|
477
|
-
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
|
542
|
+
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, type McpToolMeta, type McpToolRateLimitHints, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -16,6 +16,38 @@ interface ContextClientOptions {
|
|
|
16
16
|
/**
|
|
17
17
|
* An individual MCP tool exposed by a tool listing
|
|
18
18
|
*/
|
|
19
|
+
interface McpToolRateLimitHints {
|
|
20
|
+
/** Suggested request budget for this method */
|
|
21
|
+
maxRequestsPerMinute?: number;
|
|
22
|
+
/** Suggested parallel call ceiling for this method */
|
|
23
|
+
maxConcurrency?: number;
|
|
24
|
+
/** Suggested minimum delay between sequential calls */
|
|
25
|
+
cooldownMs?: number;
|
|
26
|
+
/** Whether this method already supports bulk/batch retrieval */
|
|
27
|
+
supportsBulk?: boolean;
|
|
28
|
+
/** Preferred batch-oriented methods to call instead of fan-out loops */
|
|
29
|
+
recommendedBatchTools?: string[];
|
|
30
|
+
/** Optional human-readable notes for planning */
|
|
31
|
+
notes?: string;
|
|
32
|
+
}
|
|
33
|
+
interface McpToolMeta {
|
|
34
|
+
/** Context injection requirements handled by the Context runtime */
|
|
35
|
+
contextRequirements?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Optional planner/runtime pacing hints.
|
|
38
|
+
* Tool contributors can publish these to reduce rate-limit failures.
|
|
39
|
+
*/
|
|
40
|
+
rateLimit?: McpToolRateLimitHints;
|
|
41
|
+
rateLimitHints?: McpToolRateLimitHints;
|
|
42
|
+
/** Flat aliases accepted for convenience */
|
|
43
|
+
maxRequestsPerMinute?: number;
|
|
44
|
+
maxConcurrency?: number;
|
|
45
|
+
cooldownMs?: number;
|
|
46
|
+
supportsBulk?: boolean;
|
|
47
|
+
recommendedBatchTools?: string[];
|
|
48
|
+
notes?: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
19
51
|
interface McpTool {
|
|
20
52
|
/** Name of the MCP tool method */
|
|
21
53
|
name: string;
|
|
@@ -31,6 +63,8 @@ interface McpTool {
|
|
|
31
63
|
* Used by LLMs to understand the response structure.
|
|
32
64
|
*/
|
|
33
65
|
outputSchema?: Record<string, unknown>;
|
|
66
|
+
/** MCP metadata extensions (context injection, rate-limit hints) */
|
|
67
|
+
_meta?: McpToolMeta;
|
|
34
68
|
}
|
|
35
69
|
/**
|
|
36
70
|
* Represents a tool available on the Context Protocol marketplace
|
|
@@ -96,6 +130,11 @@ interface ExecuteOptions {
|
|
|
96
130
|
toolName: string;
|
|
97
131
|
/** Arguments to pass to the tool */
|
|
98
132
|
args?: Record<string, unknown>;
|
|
133
|
+
/**
|
|
134
|
+
* Optional idempotency key (UUID recommended).
|
|
135
|
+
* Reuse the same key when retrying the same logical request.
|
|
136
|
+
*/
|
|
137
|
+
idempotencyKey?: string;
|
|
99
138
|
}
|
|
100
139
|
/**
|
|
101
140
|
* Successful execution response from the API
|
|
@@ -158,6 +197,26 @@ interface QueryOptions {
|
|
|
158
197
|
* (Manual Mode).
|
|
159
198
|
*/
|
|
160
199
|
tools?: string[];
|
|
200
|
+
/**
|
|
201
|
+
* Optional model ID for query orchestration/synthesis.
|
|
202
|
+
* Supported IDs are published by the Context API.
|
|
203
|
+
*/
|
|
204
|
+
modelId?: string;
|
|
205
|
+
/**
|
|
206
|
+
* Include execution data inline in the query response.
|
|
207
|
+
* Useful for headless agents that need raw structured outputs.
|
|
208
|
+
*/
|
|
209
|
+
includeData?: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Persist execution data to Vercel Blob and return a download URL.
|
|
212
|
+
* Useful for large payload workflows where inline JSON is not ideal.
|
|
213
|
+
*/
|
|
214
|
+
includeDataUrl?: boolean;
|
|
215
|
+
/**
|
|
216
|
+
* Optional idempotency key (UUID recommended).
|
|
217
|
+
* Reuse the same key when retrying the same logical request.
|
|
218
|
+
*/
|
|
219
|
+
idempotencyKey?: string;
|
|
161
220
|
}
|
|
162
221
|
/**
|
|
163
222
|
* Information about a tool that was used during a query response
|
|
@@ -194,6 +253,10 @@ interface QueryResult {
|
|
|
194
253
|
cost: QueryCost;
|
|
195
254
|
/** Total duration in milliseconds */
|
|
196
255
|
durationMs: number;
|
|
256
|
+
/** Optional execution data from tools (when includeData=true) */
|
|
257
|
+
data?: unknown;
|
|
258
|
+
/** Optional blob URL for persisted execution data (when includeDataUrl=true) */
|
|
259
|
+
dataUrl?: string;
|
|
197
260
|
}
|
|
198
261
|
/**
|
|
199
262
|
* Successful response from the /api/v1/query endpoint
|
|
@@ -204,6 +267,8 @@ interface QueryApiSuccessResponse {
|
|
|
204
267
|
toolsUsed: QueryToolUsage[];
|
|
205
268
|
cost: QueryCost;
|
|
206
269
|
durationMs: number;
|
|
270
|
+
data?: unknown;
|
|
271
|
+
dataUrl?: string;
|
|
207
272
|
}
|
|
208
273
|
/**
|
|
209
274
|
* Raw API response from the query endpoint
|
|
@@ -474,4 +539,4 @@ declare class ContextClient {
|
|
|
474
539
|
_fetchRaw(endpoint: string, options?: RequestInit): Promise<Response>;
|
|
475
540
|
}
|
|
476
541
|
|
|
477
|
-
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|
|
542
|
+
export { ContextClient, type ContextClientOptions, ContextError, type ContextErrorCode, Discovery, type ExecuteApiErrorResponse, type ExecuteApiResponse, type ExecuteApiSuccessResponse, type ExecuteOptions, type ExecutionResult, type McpTool, type McpToolMeta, type McpToolRateLimitHints, Query, type QueryApiResponse, type QueryApiSuccessResponse, type QueryCost, type QueryOptions, type QueryResult, type QueryStreamDoneEvent, type QueryStreamEvent, type QueryStreamTextDeltaEvent, type QueryStreamToolStatusEvent, type QueryToolUsage, type SearchOptions, type SearchResponse, type Tool, Tools };
|