bigtool-ts 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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +641 -0
- package/dist/adapters/agent-protocol.d.ts +149 -0
- package/dist/adapters/agent-protocol.d.ts.map +1 -0
- package/dist/adapters/agent-protocol.js +133 -0
- package/dist/adapters/agent-protocol.js.map +1 -0
- package/dist/adapters/index.d.ts +39 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +42 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/inngest.d.ts +234 -0
- package/dist/adapters/inngest.d.ts.map +1 -0
- package/dist/adapters/inngest.js +276 -0
- package/dist/adapters/inngest.js.map +1 -0
- package/dist/adapters/mastra.d.ts +201 -0
- package/dist/adapters/mastra.d.ts.map +1 -0
- package/dist/adapters/mastra.js +250 -0
- package/dist/adapters/mastra.js.map +1 -0
- package/dist/adapters/types.d.ts +42 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +6 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/vercel-ai.d.ts +176 -0
- package/dist/adapters/vercel-ai.d.ts.map +1 -0
- package/dist/adapters/vercel-ai.js +244 -0
- package/dist/adapters/vercel-ai.js.map +1 -0
- package/dist/catalog/index.d.ts +177 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +244 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/graph/agent.d.ts +214 -0
- package/dist/graph/agent.d.ts.map +1 -0
- package/dist/graph/agent.js +196 -0
- package/dist/graph/agent.js.map +1 -0
- package/dist/graph/index.d.ts +5 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/nodes.d.ts +100 -0
- package/dist/graph/nodes.d.ts.map +1 -0
- package/dist/graph/nodes.js +190 -0
- package/dist/graph/nodes.js.map +1 -0
- package/dist/graph/search-tool.d.ts +34 -0
- package/dist/graph/search-tool.d.ts.map +1 -0
- package/dist/graph/search-tool.js +54 -0
- package/dist/graph/search-tool.js.map +1 -0
- package/dist/graph/state.d.ts +26 -0
- package/dist/graph/state.d.ts.map +1 -0
- package/dist/graph/state.js +29 -0
- package/dist/graph/state.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/loader/index.d.ts +172 -0
- package/dist/loader/index.d.ts.map +1 -0
- package/dist/loader/index.js +179 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/loader.d.ts +114 -0
- package/dist/loader/loader.d.ts.map +1 -0
- package/dist/loader/loader.js +185 -0
- package/dist/loader/loader.js.map +1 -0
- package/dist/search/cache.d.ts +76 -0
- package/dist/search/cache.d.ts.map +1 -0
- package/dist/search/cache.js +135 -0
- package/dist/search/cache.js.map +1 -0
- package/dist/search/index.d.ts +63 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +122 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/normalize.d.ts +104 -0
- package/dist/search/normalize.d.ts.map +1 -0
- package/dist/search/normalize.js +211 -0
- package/dist/search/normalize.js.map +1 -0
- package/dist/search/orama.d.ts +256 -0
- package/dist/search/orama.d.ts.map +1 -0
- package/dist/search/orama.js +511 -0
- package/dist/search/orama.js.map +1 -0
- package/dist/search/types.d.ts +96 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +8 -0
- package/dist/search/types.js.map +1 -0
- package/dist/sources/dynamic.d.ts +200 -0
- package/dist/sources/dynamic.d.ts.map +1 -0
- package/dist/sources/dynamic.js +194 -0
- package/dist/sources/dynamic.js.map +1 -0
- package/dist/sources/index.d.ts +11 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +14 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/local.d.ts +128 -0
- package/dist/sources/local.d.ts.map +1 -0
- package/dist/sources/local.js +155 -0
- package/dist/sources/local.js.map +1 -0
- package/dist/sources/mcp.d.ts +438 -0
- package/dist/sources/mcp.d.ts.map +1 -0
- package/dist/sources/mcp.js +438 -0
- package/dist/sources/mcp.js.map +1 -0
- package/dist/sources/types.d.ts +16 -0
- package/dist/sources/types.d.ts.map +1 -0
- package/dist/sources/types.js +7 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/sources/with-metadata.d.ts +7 -0
- package/dist/sources/with-metadata.d.ts.map +1 -0
- package/dist/sources/with-metadata.js +7 -0
- package/dist/sources/with-metadata.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types.d.ts +700 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +97 -0
- package/dist/types.js.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPSource module.
|
|
3
|
+
*
|
|
4
|
+
* Provides a ToolSource implementation that connects to an MCP
|
|
5
|
+
* (Model Context Protocol) server and exposes its tools.
|
|
6
|
+
*
|
|
7
|
+
* Supports two patterns:
|
|
8
|
+
* 1. Pre-connected client: Pass an already-connected MCPClient
|
|
9
|
+
* 2. Config-based: Pass server config and MCPSource manages the connection
|
|
10
|
+
*
|
|
11
|
+
* @module sources/mcp
|
|
12
|
+
*/
|
|
13
|
+
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
14
|
+
import { createEventEmitter } from "../types.js";
|
|
15
|
+
/**
|
|
16
|
+
* MCPSource connects to an MCP server and provides its tools.
|
|
17
|
+
*
|
|
18
|
+
* Tools are fetched from the MCP server on first access and cached.
|
|
19
|
+
* Wrapper tools are created lazily that delegate execution back to
|
|
20
|
+
* the server.
|
|
21
|
+
*
|
|
22
|
+
* The source can optionally refresh its tool list periodically to
|
|
23
|
+
* pick up new tools or changes from the server.
|
|
24
|
+
*
|
|
25
|
+
* @example Basic usage
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import { MCPSource } from '@repo/bigtool-ts';
|
|
28
|
+
* import { Client } from '@modelcontextprotocol/sdk/client';
|
|
29
|
+
*
|
|
30
|
+
* const client = new Client({ name: 'github' });
|
|
31
|
+
* await client.connect(transport);
|
|
32
|
+
*
|
|
33
|
+
* const source = new MCPSource(client);
|
|
34
|
+
* await catalog.register(source);
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example With auto-refresh
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const source = new MCPSource(client, {
|
|
40
|
+
* namespace: 'github',
|
|
41
|
+
* refreshInterval: 60000, // Check for new tools every minute
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Listen for refresh events
|
|
45
|
+
* source.onRefresh.subscribe((metadata) => {
|
|
46
|
+
* console.log(`Refreshed: ${metadata.length} tools`);
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export class MCPSource {
|
|
51
|
+
/**
|
|
52
|
+
* Unique identifier for this source.
|
|
53
|
+
*
|
|
54
|
+
* Format: 'mcp:{namespace}' (e.g., 'mcp:github').
|
|
55
|
+
*/
|
|
56
|
+
id;
|
|
57
|
+
/** @internal The MCP client */
|
|
58
|
+
client;
|
|
59
|
+
/** @internal Cached tool metadata */
|
|
60
|
+
metadata = [];
|
|
61
|
+
/** @internal Cache of wrapped tools */
|
|
62
|
+
toolCache = new Map();
|
|
63
|
+
/** @internal Timer for periodic refresh */
|
|
64
|
+
refreshTimer;
|
|
65
|
+
/** @internal Whether initial fetch has completed */
|
|
66
|
+
initialized = false;
|
|
67
|
+
/**
|
|
68
|
+
* Event emitter for refresh notifications.
|
|
69
|
+
*
|
|
70
|
+
* Subscribe to be notified when the tool list is refreshed
|
|
71
|
+
* from the MCP server.
|
|
72
|
+
*/
|
|
73
|
+
onRefresh = createEventEmitter();
|
|
74
|
+
/**
|
|
75
|
+
* Creates a new MCPSource.
|
|
76
|
+
*
|
|
77
|
+
* @param client - MCP client instance (must be connected)
|
|
78
|
+
* @param options - Configuration options
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const source = new MCPSource(client, {
|
|
83
|
+
* namespace: 'github',
|
|
84
|
+
* refreshInterval: 60000,
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
constructor(client, options = {}) {
|
|
89
|
+
this.client = client;
|
|
90
|
+
this.id = `mcp:${options.namespace ?? client.name ?? "default"}`;
|
|
91
|
+
if (options.refreshInterval && options.refreshInterval > 0) {
|
|
92
|
+
this.refreshTimer = setInterval(() => {
|
|
93
|
+
this.refresh().catch((err) => {
|
|
94
|
+
console.error(`[MCPSource:${this.id}] Refresh failed:`, err);
|
|
95
|
+
});
|
|
96
|
+
}, options.refreshInterval);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get metadata for all tools from this MCP server.
|
|
101
|
+
*
|
|
102
|
+
* Fetches from the server on first call, then returns cached metadata.
|
|
103
|
+
* Call refresh() to update the metadata from the server.
|
|
104
|
+
*
|
|
105
|
+
* @returns Promise resolving to array of tool metadata
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const metadata = await source.getMetadata();
|
|
110
|
+
* console.log(`MCP server has ${metadata.length} tools`);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
async getMetadata() {
|
|
114
|
+
if (!this.initialized) {
|
|
115
|
+
await this.refresh();
|
|
116
|
+
}
|
|
117
|
+
return this.metadata;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get a tool by its ID.
|
|
121
|
+
*
|
|
122
|
+
* Creates a wrapper tool on first request that delegates execution
|
|
123
|
+
* to the MCP server. Wrappers are cached for subsequent calls.
|
|
124
|
+
*
|
|
125
|
+
* @param id - Tool ID (e.g., 'mcp:github:create_pr' or just 'create_pr')
|
|
126
|
+
* @returns Promise resolving to the tool wrapper, or null if not found
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const tool = await source.getTool('mcp:github:create_pr');
|
|
131
|
+
* if (tool) {
|
|
132
|
+
* const result = await tool.invoke({ title: 'My PR' });
|
|
133
|
+
* }
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
async getTool(id) {
|
|
137
|
+
// Ensure we have metadata
|
|
138
|
+
if (!this.initialized) {
|
|
139
|
+
await this.refresh();
|
|
140
|
+
}
|
|
141
|
+
// Extract tool name from ID
|
|
142
|
+
// Format: "mcp:namespace:toolName" or just "toolName"
|
|
143
|
+
const parts = id.split(":");
|
|
144
|
+
const toolName = parts[parts.length - 1];
|
|
145
|
+
// Check if tool exists in metadata
|
|
146
|
+
const meta = this.metadata.find((m) => m.name === toolName);
|
|
147
|
+
if (!meta) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
// Return cached wrapper or create new one
|
|
151
|
+
if (!this.toolCache.has(toolName)) {
|
|
152
|
+
const wrapper = this.createToolWrapper(toolName, meta);
|
|
153
|
+
this.toolCache.set(toolName, wrapper);
|
|
154
|
+
}
|
|
155
|
+
return this.toolCache.get(toolName) ?? null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Refresh the tool list from the MCP server.
|
|
159
|
+
*
|
|
160
|
+
* Fetches the current tool list, updates metadata, clears the
|
|
161
|
+
* tool wrapper cache, and emits an onRefresh event.
|
|
162
|
+
*
|
|
163
|
+
* @throws MCPSourceError if the server request fails
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // Manually refresh tools
|
|
168
|
+
* await source.refresh();
|
|
169
|
+
*
|
|
170
|
+
* // Or listen for auto-refresh events
|
|
171
|
+
* source.onRefresh.subscribe((metadata) => {
|
|
172
|
+
* console.log('Tools refreshed:', metadata.length);
|
|
173
|
+
* });
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
async refresh() {
|
|
177
|
+
try {
|
|
178
|
+
const { tools } = await this.client.listTools();
|
|
179
|
+
this.metadata = tools.map((t) => ({
|
|
180
|
+
id: `${this.id}:${t.name}`,
|
|
181
|
+
name: t.name,
|
|
182
|
+
description: t.description ?? "",
|
|
183
|
+
parameters: t.inputSchema,
|
|
184
|
+
source: "mcp",
|
|
185
|
+
sourceId: this.id,
|
|
186
|
+
}));
|
|
187
|
+
this.initialized = true;
|
|
188
|
+
// Clear tool cache on refresh since schemas may have changed
|
|
189
|
+
this.toolCache.clear();
|
|
190
|
+
this.onRefresh.emit(this.metadata);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
// Wrap error with more context
|
|
194
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
195
|
+
throw new MCPSourceError(`Failed to fetch tools from MCP server: ${message}`, { cause: error });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Create a wrapper tool that delegates execution to the MCP server.
|
|
200
|
+
*/
|
|
201
|
+
createToolWrapper(toolName, meta) {
|
|
202
|
+
const client = this.client;
|
|
203
|
+
const sourceId = this.id;
|
|
204
|
+
return new DynamicStructuredTool({
|
|
205
|
+
name: toolName,
|
|
206
|
+
description: meta.description,
|
|
207
|
+
schema: this.createSchemaFromParameters(meta.parameters),
|
|
208
|
+
func: async (input) => {
|
|
209
|
+
try {
|
|
210
|
+
const result = await client.callTool({
|
|
211
|
+
name: toolName,
|
|
212
|
+
arguments: input,
|
|
213
|
+
});
|
|
214
|
+
if (result.isError) {
|
|
215
|
+
const errorText = result.content
|
|
216
|
+
?.filter((c) => c.type === "text")
|
|
217
|
+
.map((c) => c.text)
|
|
218
|
+
.join("\n");
|
|
219
|
+
throw new MCPToolError(`MCP tool "${toolName}" returned error: ${errorText ?? "Unknown error"}`);
|
|
220
|
+
}
|
|
221
|
+
// Extract text content from result
|
|
222
|
+
const textContent = result.content
|
|
223
|
+
?.filter((c) => c.type === "text")
|
|
224
|
+
.map((c) => c.text)
|
|
225
|
+
.join("\n");
|
|
226
|
+
return textContent ?? JSON.stringify(result);
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
if (error instanceof MCPToolError) {
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
233
|
+
throw new MCPToolError(`Failed to execute MCP tool "${toolName}" on ${sourceId}: ${message}`, { cause: error });
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Create a Zod-like schema from MCP input schema.
|
|
240
|
+
* For simplicity, we create a pass-through schema.
|
|
241
|
+
*/
|
|
242
|
+
createSchemaFromParameters(parameters) {
|
|
243
|
+
// Return the raw JSON schema - LangChain will handle it
|
|
244
|
+
return parameters ?? {};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Clean up resources.
|
|
248
|
+
*
|
|
249
|
+
* Stops the refresh timer and clears all event subscriptions.
|
|
250
|
+
* Call this when you're done with the source to prevent memory leaks.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* // When shutting down
|
|
255
|
+
* source.dispose();
|
|
256
|
+
* catalog.unregister(source.id);
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
dispose() {
|
|
260
|
+
if (this.refreshTimer) {
|
|
261
|
+
clearInterval(this.refreshTimer);
|
|
262
|
+
this.refreshTimer = undefined;
|
|
263
|
+
}
|
|
264
|
+
this.onRefresh.clear();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Error thrown when MCP source operations fail.
|
|
269
|
+
*
|
|
270
|
+
* This error indicates a problem with the MCP server connection
|
|
271
|
+
* or protocol, such as failing to list tools.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* try {
|
|
276
|
+
* await source.refresh();
|
|
277
|
+
* } catch (error) {
|
|
278
|
+
* if (error instanceof MCPSourceError) {
|
|
279
|
+
* console.error('MCP server error:', error.message);
|
|
280
|
+
* }
|
|
281
|
+
* }
|
|
282
|
+
* ```
|
|
283
|
+
*/
|
|
284
|
+
export class MCPSourceError extends Error {
|
|
285
|
+
/**
|
|
286
|
+
* Creates a new MCPSourceError.
|
|
287
|
+
*
|
|
288
|
+
* @param message - Error message
|
|
289
|
+
* @param options - Error options (e.g., cause)
|
|
290
|
+
*/
|
|
291
|
+
constructor(message, options) {
|
|
292
|
+
super(message, options);
|
|
293
|
+
this.name = "MCPSourceError";
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Error thrown when MCP tool execution fails.
|
|
298
|
+
*
|
|
299
|
+
* This error indicates a problem executing a specific tool on
|
|
300
|
+
* the MCP server, such as invalid arguments or server-side errors.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```typescript
|
|
304
|
+
* try {
|
|
305
|
+
* await tool.invoke({ title: '' });
|
|
306
|
+
* } catch (error) {
|
|
307
|
+
* if (error instanceof MCPToolError) {
|
|
308
|
+
* console.error('Tool execution failed:', error.message);
|
|
309
|
+
* }
|
|
310
|
+
* }
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
export class MCPToolError extends Error {
|
|
314
|
+
/**
|
|
315
|
+
* Creates a new MCPToolError.
|
|
316
|
+
*
|
|
317
|
+
* @param message - Error message
|
|
318
|
+
* @param options - Error options (e.g., cause)
|
|
319
|
+
*/
|
|
320
|
+
constructor(message, options) {
|
|
321
|
+
super(message, options);
|
|
322
|
+
this.name = "MCPToolError";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Creates an MCPSource from a server configuration.
|
|
327
|
+
*
|
|
328
|
+
* This is the preferred way to create an MCPSource when you don't have
|
|
329
|
+
* a pre-connected MCP client. The function handles:
|
|
330
|
+
* - Starting the MCP server process (for stdio transport)
|
|
331
|
+
* - Connecting to remote servers (for SSE/WebSocket transport)
|
|
332
|
+
* - Managing the client lifecycle
|
|
333
|
+
*
|
|
334
|
+
* @param config - Server configuration
|
|
335
|
+
* @returns Promise resolving to a configured MCPSource
|
|
336
|
+
*
|
|
337
|
+
* @example stdio transport (local server)
|
|
338
|
+
* ```typescript
|
|
339
|
+
* import { createMCPSource } from '@repo/bigtool-ts';
|
|
340
|
+
*
|
|
341
|
+
* const source = await createMCPSource({
|
|
342
|
+
* name: 'github',
|
|
343
|
+
* transport: 'stdio',
|
|
344
|
+
* command: 'npx',
|
|
345
|
+
* args: ['-y', '@modelcontextprotocol/server-github'],
|
|
346
|
+
* env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
|
|
347
|
+
* });
|
|
348
|
+
*
|
|
349
|
+
* // Use like any ToolSource
|
|
350
|
+
* await catalog.register(source);
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @example SSE transport (remote server)
|
|
354
|
+
* ```typescript
|
|
355
|
+
* const source = await createMCPSource({
|
|
356
|
+
* name: 'remote-tools',
|
|
357
|
+
* transport: 'sse',
|
|
358
|
+
* url: 'https://mcp.example.com/sse',
|
|
359
|
+
* headers: { Authorization: `Bearer ${apiKey}` },
|
|
360
|
+
* });
|
|
361
|
+
* ```
|
|
362
|
+
*
|
|
363
|
+
* @example Multiple servers
|
|
364
|
+
* ```typescript
|
|
365
|
+
* const sources = await Promise.all([
|
|
366
|
+
* createMCPSource({ name: 'github', transport: 'stdio', command: 'npx', args: ['-y', '@mcp/server-github'] }),
|
|
367
|
+
* createMCPSource({ name: 'slack', transport: 'stdio', command: 'npx', args: ['-y', '@mcp/server-slack'] }),
|
|
368
|
+
* createMCPSource({ name: 'notion', transport: 'stdio', command: 'npx', args: ['-y', '@mcp/server-notion'] }),
|
|
369
|
+
* ]);
|
|
370
|
+
*
|
|
371
|
+
* for (const source of sources) {
|
|
372
|
+
* await catalog.register(source);
|
|
373
|
+
* }
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
376
|
+
export async function createMCPSource(config) {
|
|
377
|
+
// Dynamic import of MCP SDK to avoid hard dependency
|
|
378
|
+
let Client;
|
|
379
|
+
let StdioClientTransport;
|
|
380
|
+
let SSEClientTransport;
|
|
381
|
+
try {
|
|
382
|
+
const sdk = await import("@modelcontextprotocol/sdk/client/index.js");
|
|
383
|
+
Client = sdk.Client;
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
throw new MCPSourceError("Failed to import @modelcontextprotocol/sdk. Please install it: pnpm add @modelcontextprotocol/sdk");
|
|
387
|
+
}
|
|
388
|
+
const client = new Client({ name: config.name, version: "1.0.0" }, { capabilities: {} });
|
|
389
|
+
try {
|
|
390
|
+
if (config.transport === "stdio") {
|
|
391
|
+
try {
|
|
392
|
+
const stdioModule = await import("@modelcontextprotocol/sdk/client/stdio.js");
|
|
393
|
+
StdioClientTransport = stdioModule.StdioClientTransport;
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
throw new MCPSourceError("Failed to import stdio transport. Ensure @modelcontextprotocol/sdk is installed.");
|
|
397
|
+
}
|
|
398
|
+
const transport = new StdioClientTransport({
|
|
399
|
+
command: config.command,
|
|
400
|
+
args: config.args,
|
|
401
|
+
env: config.env,
|
|
402
|
+
cwd: config.cwd,
|
|
403
|
+
});
|
|
404
|
+
await client.connect(transport);
|
|
405
|
+
}
|
|
406
|
+
else if (config.transport === "sse") {
|
|
407
|
+
try {
|
|
408
|
+
const sseModule = await import("@modelcontextprotocol/sdk/client/sse.js");
|
|
409
|
+
SSEClientTransport = sseModule.SSEClientTransport;
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
throw new MCPSourceError("Failed to import SSE transport. Ensure @modelcontextprotocol/sdk is installed.");
|
|
413
|
+
}
|
|
414
|
+
const transport = new SSEClientTransport(new URL(config.url));
|
|
415
|
+
await client.connect(transport);
|
|
416
|
+
}
|
|
417
|
+
else if (config.transport === "websocket") {
|
|
418
|
+
// WebSocket transport - not yet available in MCP SDK
|
|
419
|
+
throw new MCPSourceError(`WebSocket transport is not yet supported by the MCP SDK`);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
throw new MCPSourceError(`Unknown transport type: ${config.transport}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
if (error instanceof MCPSourceError) {
|
|
427
|
+
throw error;
|
|
428
|
+
}
|
|
429
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
430
|
+
throw new MCPSourceError(`Failed to connect to MCP server "${config.name}": ${message}`, { cause: error });
|
|
431
|
+
}
|
|
432
|
+
// Create MCPSource with the connected client
|
|
433
|
+
return new MCPSource(client, {
|
|
434
|
+
namespace: config.name,
|
|
435
|
+
refreshInterval: config.refreshInterval,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/sources/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source Types
|
|
3
|
+
*
|
|
4
|
+
* Re-exports types used by source implementations.
|
|
5
|
+
*/
|
|
6
|
+
export type { ToolSource, ToolMetadata, ToolEnhancement, EnhancedTool, } from "../types.js";
|
|
7
|
+
export { withMetadata } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Additional search metadata that can be attached to tools.
|
|
10
|
+
* @deprecated Use ToolEnhancement instead
|
|
11
|
+
*/
|
|
12
|
+
export interface ToolSearchMetadata {
|
|
13
|
+
categories?: string[];
|
|
14
|
+
keywords?: string[];
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sources/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,UAAU,EACV,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sources/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-metadata.d.ts","sourceRoot":"","sources":["../../src/sources/with-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-metadata.js","sourceRoot":"","sources":["../../src/sources/with-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bigtool-ts Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all types from the main types.ts file.
|
|
5
|
+
*/
|
|
6
|
+
export { type EventHandler, type Unsubscribe, type EventEmitter, createEventEmitter, type ToolMetadata, type ToolSource, type ToolsChangedEvent, type ToolCatalog, type ToolLoader, type SearchOptions, type SearchResult, type SearchIndex, type ToolEnhancement, type EnhancedTool, withMetadata, } from "../types.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,kBAAkB,EAGlB,KAAK,YAAY,EAGjB,KAAK,UAAU,EAGf,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAGhB,KAAK,UAAU,EAGf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAGhB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,YAAY,GACb,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kDAAkD;AAClD,OAAO,EAKL,kBAAkB,EAuBlB,YAAY,GACb,MAAM,aAAa,CAAC"}
|