mcp-use 0.1.20 → 0.3.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/dist/chunk-2HFIPY7C.js +429 -0
- package/dist/chunk-4DEFXVWT.js +680 -0
- package/dist/chunk-JXLQRAW2.js +532 -0
- package/dist/chunk-SHUYVCID.js +6 -0
- package/dist/chunk-YUSC6R6V.js +299 -0
- package/dist/index.cjs +5762 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3767 -22
- package/dist/langfuse-YA2S23SM.js +13 -0
- package/dist/src/agents/remote.d.ts.map +1 -1
- package/dist/src/agents/utils/ai_sdk.d.ts.map +1 -1
- package/dist/src/auth/browser-provider.d.ts +52 -0
- package/dist/src/auth/browser-provider.d.ts.map +1 -0
- package/dist/src/auth/callback.d.ts +6 -0
- package/dist/src/auth/callback.d.ts.map +1 -0
- package/dist/src/auth/index.d.ts +7 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/types.d.ts +18 -0
- package/dist/src/auth/types.d.ts.map +1 -0
- package/dist/src/browser.cjs +323 -0
- package/dist/src/browser.d.ts +8 -0
- package/dist/src/browser.d.ts.map +1 -0
- package/dist/src/browser.js +9 -0
- package/dist/src/client/base.d.ts +32 -0
- package/dist/src/client/base.d.ts.map +1 -0
- package/dist/src/client.d.ts +19 -16
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/logging.d.ts +1 -1
- package/dist/src/logging.d.ts.map +1 -1
- package/dist/src/oauth-helper.d.ts +125 -0
- package/dist/src/oauth-helper.d.ts.map +1 -0
- package/dist/src/react/index.cjs +986 -0
- package/dist/src/react/index.d.ts +9 -0
- package/dist/src/react/index.d.ts.map +1 -0
- package/dist/src/react/index.js +11 -0
- package/dist/src/react/types.d.ts +139 -0
- package/dist/src/react/types.d.ts.map +1 -0
- package/dist/src/react/useMcp.d.ts +3 -0
- package/dist/src/react/useMcp.d.ts.map +1 -0
- package/dist/src/server/index.cjs +566 -0
- package/dist/src/server/index.d.ts +3 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +9 -0
- package/dist/src/server/logging.d.ts +16 -0
- package/dist/src/server/logging.d.ts.map +1 -0
- package/dist/src/server/mcp-server.d.ts +282 -0
- package/dist/src/server/mcp-server.d.ts.map +1 -0
- package/dist/src/server/types.d.ts +47 -0
- package/dist/src/server/types.d.ts.map +1 -0
- package/dist/src/utils/assert.d.ts +8 -0
- package/dist/src/utils/assert.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +72 -40
- package/dist/examples/add_server_tool.d.ts +0 -8
- package/dist/examples/add_server_tool.d.ts.map +0 -1
- package/dist/examples/add_server_tool.js +0 -79
- package/dist/examples/ai_sdk_example.d.ts +0 -23
- package/dist/examples/ai_sdk_example.d.ts.map +0 -1
- package/dist/examples/ai_sdk_example.js +0 -213
- package/dist/examples/airbnb_use.d.ts +0 -10
- package/dist/examples/airbnb_use.d.ts.map +0 -1
- package/dist/examples/airbnb_use.js +0 -43
- package/dist/examples/blender_use.d.ts +0 -15
- package/dist/examples/blender_use.d.ts.map +0 -1
- package/dist/examples/blender_use.js +0 -39
- package/dist/examples/browser_use.d.ts +0 -10
- package/dist/examples/browser_use.d.ts.map +0 -1
- package/dist/examples/browser_use.js +0 -46
- package/dist/examples/chat_example.d.ts +0 -10
- package/dist/examples/chat_example.d.ts.map +0 -1
- package/dist/examples/chat_example.js +0 -86
- package/dist/examples/filesystem_use.d.ts +0 -11
- package/dist/examples/filesystem_use.d.ts.map +0 -1
- package/dist/examples/filesystem_use.js +0 -43
- package/dist/examples/http_example.d.ts +0 -18
- package/dist/examples/http_example.d.ts.map +0 -1
- package/dist/examples/http_example.js +0 -37
- package/dist/examples/mcp_everything.d.ts +0 -6
- package/dist/examples/mcp_everything.d.ts.map +0 -1
- package/dist/examples/mcp_everything.js +0 -25
- package/dist/examples/multi_server_example.d.ts +0 -10
- package/dist/examples/multi_server_example.d.ts.map +0 -1
- package/dist/examples/multi_server_example.js +0 -51
- package/dist/examples/observability.d.ts +0 -6
- package/dist/examples/observability.d.ts.map +0 -1
- package/dist/examples/observability.js +0 -50
- package/dist/examples/stream_example.d.ts +0 -12
- package/dist/examples/stream_example.d.ts.map +0 -1
- package/dist/examples/stream_example.js +0 -198
- package/dist/examples/structured_output.d.ts +0 -9
- package/dist/examples/structured_output.d.ts.map +0 -1
- package/dist/examples/structured_output.js +0 -95
- package/dist/src/adapters/base.js +0 -124
- package/dist/src/adapters/index.js +0 -2
- package/dist/src/adapters/langchain_adapter.js +0 -49
- package/dist/src/agents/base.js +0 -9
- package/dist/src/agents/index.js +0 -3
- package/dist/src/agents/mcp_agent.js +0 -1002
- package/dist/src/agents/prompts/system_prompt_builder.js +0 -40
- package/dist/src/agents/prompts/templates.js +0 -39
- package/dist/src/agents/remote.js +0 -264
- package/dist/src/agents/utils/ai_sdk.js +0 -62
- package/dist/src/agents/utils/index.js +0 -1
- package/dist/src/client.js +0 -133
- package/dist/src/config.js +0 -34
- package/dist/src/connectors/base.js +0 -143
- package/dist/src/connectors/http.js +0 -150
- package/dist/src/connectors/index.js +0 -4
- package/dist/src/connectors/stdio.js +0 -68
- package/dist/src/connectors/websocket.js +0 -157
- package/dist/src/logging.js +0 -217
- package/dist/src/managers/index.js +0 -2
- package/dist/src/managers/server_manager.js +0 -106
- package/dist/src/managers/tools/acquire_active_mcp_server.js +0 -17
- package/dist/src/managers/tools/add_server_from_config.js +0 -40
- package/dist/src/managers/tools/base.js +0 -17
- package/dist/src/managers/tools/connect_mcp_server.js +0 -46
- package/dist/src/managers/tools/index.js +0 -5
- package/dist/src/managers/tools/list_mcp_servers.js +0 -33
- package/dist/src/managers/tools/release_mcp_server_connection.js +0 -19
- package/dist/src/observability/index.js +0 -12
- package/dist/src/observability/langfuse.js +0 -211
- package/dist/src/observability/manager.js +0 -199
- package/dist/src/observability/types.js +0 -4
- package/dist/src/session.js +0 -23
- package/dist/src/task_managers/base.js +0 -127
- package/dist/src/task_managers/index.js +0 -5
- package/dist/src/task_managers/sse.js +0 -43
- package/dist/src/task_managers/stdio.js +0 -51
- package/dist/src/task_managers/streamable_http.js +0 -50
- package/dist/src/task_managers/websocket.js +0 -67
- package/dist/src/telemetry/events.js +0 -44
- package/dist/src/telemetry/index.js +0 -8
- package/dist/src/telemetry/telemetry.js +0 -324
- package/dist/src/telemetry/utils.js +0 -39
- package/dist/tests/ai_sdk_compatibility.test.js +0 -214
- package/dist/tests/stream_events.test.js +0 -307
- package/dist/tests/stream_events_simple.test.js +0 -179
- package/dist/vitest.config.js +0 -21
@@ -1,143 +0,0 @@
|
|
1
|
-
import { logger } from '../logging.js';
|
2
|
-
/**
|
3
|
-
* Base class for MCP connectors.
|
4
|
-
*/
|
5
|
-
export class BaseConnector {
|
6
|
-
client = null;
|
7
|
-
connectionManager = null;
|
8
|
-
toolsCache = null;
|
9
|
-
connected = false;
|
10
|
-
opts;
|
11
|
-
constructor(opts = {}) {
|
12
|
-
this.opts = opts;
|
13
|
-
}
|
14
|
-
/** Disconnect and release resources. */
|
15
|
-
async disconnect() {
|
16
|
-
if (!this.connected) {
|
17
|
-
logger.debug('Not connected to MCP implementation');
|
18
|
-
return;
|
19
|
-
}
|
20
|
-
logger.debug('Disconnecting from MCP implementation');
|
21
|
-
await this.cleanupResources();
|
22
|
-
this.connected = false;
|
23
|
-
logger.debug('Disconnected from MCP implementation');
|
24
|
-
}
|
25
|
-
/** Check if the client is connected */
|
26
|
-
get isClientConnected() {
|
27
|
-
return this.client != null;
|
28
|
-
}
|
29
|
-
/**
|
30
|
-
* Initialise the MCP session **after** `connect()` has succeeded.
|
31
|
-
*
|
32
|
-
* In the SDK, `Client.connect(transport)` automatically performs the
|
33
|
-
* protocol‑level `initialize` handshake, so we only need to cache the list of
|
34
|
-
* tools and expose some server info.
|
35
|
-
*/
|
36
|
-
async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
|
37
|
-
if (!this.client) {
|
38
|
-
throw new Error('MCP client is not connected');
|
39
|
-
}
|
40
|
-
logger.debug('Caching server capabilities & tools');
|
41
|
-
// Cache server capabilities for callers who need them.
|
42
|
-
const capabilities = this.client.getServerCapabilities();
|
43
|
-
// Fetch and cache tools
|
44
|
-
const listToolsRes = await this.client.listTools(undefined, defaultRequestOptions);
|
45
|
-
this.toolsCache = (listToolsRes.tools ?? []);
|
46
|
-
logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
|
47
|
-
return capabilities;
|
48
|
-
}
|
49
|
-
/** Lazily expose the cached tools list. */
|
50
|
-
get tools() {
|
51
|
-
if (!this.toolsCache) {
|
52
|
-
throw new Error('MCP client is not initialized; call initialize() first');
|
53
|
-
}
|
54
|
-
return this.toolsCache;
|
55
|
-
}
|
56
|
-
/** Call a tool on the server. */
|
57
|
-
async callTool(name, args, options) {
|
58
|
-
if (!this.client) {
|
59
|
-
throw new Error('MCP client is not connected');
|
60
|
-
}
|
61
|
-
logger.debug(`Calling tool '${name}' with args`, args);
|
62
|
-
const res = await this.client.callTool({ name, arguments: args }, undefined, options);
|
63
|
-
logger.debug(`Tool '${name}' returned`, res);
|
64
|
-
return res;
|
65
|
-
}
|
66
|
-
/** List resources from the server. */
|
67
|
-
async listResources(options) {
|
68
|
-
if (!this.client) {
|
69
|
-
throw new Error('MCP client is not connected');
|
70
|
-
}
|
71
|
-
logger.debug('Listing resources');
|
72
|
-
return await this.client.listResources(undefined, options);
|
73
|
-
}
|
74
|
-
/** Read a resource by URI. */
|
75
|
-
async readResource(uri, options) {
|
76
|
-
if (!this.client) {
|
77
|
-
throw new Error('MCP client is not connected');
|
78
|
-
}
|
79
|
-
logger.debug(`Reading resource ${uri}`);
|
80
|
-
const res = await this.client.readResource({ uri }, options);
|
81
|
-
return { content: res.content, mimeType: res.mimeType };
|
82
|
-
}
|
83
|
-
async listPrompts() {
|
84
|
-
if (!this.client) {
|
85
|
-
throw new Error('MCP client is not connected');
|
86
|
-
}
|
87
|
-
logger.debug('Listing prompt');
|
88
|
-
return await this.client.listPrompts();
|
89
|
-
}
|
90
|
-
async getPrompt(name, args) {
|
91
|
-
if (!this.client) {
|
92
|
-
throw new Error('MCP client is not connected');
|
93
|
-
}
|
94
|
-
logger.debug(`Getting prompt ${name}`);
|
95
|
-
return await this.client.getPrompt({ name, arguments: args });
|
96
|
-
}
|
97
|
-
/** Send a raw request through the client. */
|
98
|
-
async request(method, params = null, options) {
|
99
|
-
if (!this.client) {
|
100
|
-
throw new Error('MCP client is not connected');
|
101
|
-
}
|
102
|
-
logger.debug(`Sending raw request '${method}' with params`, params);
|
103
|
-
return await this.client.request({ method, params: params ?? {} }, undefined, options);
|
104
|
-
}
|
105
|
-
/**
|
106
|
-
* Helper to tear down the client & connection manager safely.
|
107
|
-
*/
|
108
|
-
async cleanupResources() {
|
109
|
-
const issues = [];
|
110
|
-
if (this.client) {
|
111
|
-
try {
|
112
|
-
if (typeof this.client.close === 'function') {
|
113
|
-
await this.client.close();
|
114
|
-
}
|
115
|
-
}
|
116
|
-
catch (e) {
|
117
|
-
const msg = `Error closing client: ${e}`;
|
118
|
-
logger.warn(msg);
|
119
|
-
issues.push(msg);
|
120
|
-
}
|
121
|
-
finally {
|
122
|
-
this.client = null;
|
123
|
-
}
|
124
|
-
}
|
125
|
-
if (this.connectionManager) {
|
126
|
-
try {
|
127
|
-
await this.connectionManager.stop();
|
128
|
-
}
|
129
|
-
catch (e) {
|
130
|
-
const msg = `Error stopping connection manager: ${e}`;
|
131
|
-
logger.warn(msg);
|
132
|
-
issues.push(msg);
|
133
|
-
}
|
134
|
-
finally {
|
135
|
-
this.connectionManager = null;
|
136
|
-
}
|
137
|
-
}
|
138
|
-
this.toolsCache = null;
|
139
|
-
if (issues.length) {
|
140
|
-
logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
|
141
|
-
}
|
142
|
-
}
|
143
|
-
}
|
@@ -1,150 +0,0 @@
|
|
1
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
2
|
-
import { StreamableHTTPError } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
3
|
-
import { logger } from '../logging.js';
|
4
|
-
import { SseConnectionManager } from '../task_managers/sse.js';
|
5
|
-
import { StreamableHttpConnectionManager } from '../task_managers/streamable_http.js';
|
6
|
-
import { BaseConnector } from './base.js';
|
7
|
-
export class HttpConnector extends BaseConnector {
|
8
|
-
baseUrl;
|
9
|
-
headers;
|
10
|
-
timeout;
|
11
|
-
sseReadTimeout;
|
12
|
-
clientInfo;
|
13
|
-
preferSse;
|
14
|
-
transportType = null;
|
15
|
-
constructor(baseUrl, opts = {}) {
|
16
|
-
super(opts);
|
17
|
-
this.baseUrl = baseUrl.replace(/\/$/, '');
|
18
|
-
this.headers = { ...(opts.headers ?? {}) };
|
19
|
-
if (opts.authToken) {
|
20
|
-
this.headers.Authorization = `Bearer ${opts.authToken}`;
|
21
|
-
}
|
22
|
-
this.timeout = opts.timeout ?? 5;
|
23
|
-
this.sseReadTimeout = opts.sseReadTimeout ?? 60 * 5;
|
24
|
-
this.clientInfo = opts.clientInfo ?? { name: 'http-connector', version: '1.0.0' };
|
25
|
-
this.preferSse = opts.preferSse ?? false;
|
26
|
-
}
|
27
|
-
/** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
|
28
|
-
async connect() {
|
29
|
-
if (this.connected) {
|
30
|
-
logger.debug('Already connected to MCP implementation');
|
31
|
-
return;
|
32
|
-
}
|
33
|
-
const baseUrl = this.baseUrl;
|
34
|
-
// If preferSse is set, skip directly to SSE
|
35
|
-
if (this.preferSse) {
|
36
|
-
logger.debug(`Connecting to MCP implementation via HTTP/SSE: ${baseUrl}`);
|
37
|
-
await this.connectWithSse(baseUrl);
|
38
|
-
return;
|
39
|
-
}
|
40
|
-
// Try streamable HTTP first, then fall back to SSE
|
41
|
-
logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
|
42
|
-
try {
|
43
|
-
// Try streamable HTTP transport first
|
44
|
-
logger.debug('Attempting streamable HTTP transport...');
|
45
|
-
await this.connectWithStreamableHttp(baseUrl);
|
46
|
-
}
|
47
|
-
catch (err) {
|
48
|
-
// Check if this is a 4xx error that indicates we should try SSE fallback
|
49
|
-
let fallbackReason = 'Unknown error';
|
50
|
-
if (err instanceof StreamableHTTPError) {
|
51
|
-
if (err.code === 404 || err.code === 405) {
|
52
|
-
fallbackReason = `Server returned ${err.code} - server likely doesn't support streamable HTTP`;
|
53
|
-
logger.debug(fallbackReason);
|
54
|
-
}
|
55
|
-
else {
|
56
|
-
fallbackReason = `Server returned ${err.code}: ${err.message}`;
|
57
|
-
logger.debug(fallbackReason);
|
58
|
-
}
|
59
|
-
}
|
60
|
-
else if (err instanceof Error) {
|
61
|
-
// Check for 404/405 in error message as fallback detection
|
62
|
-
const errorStr = err.toString();
|
63
|
-
if (errorStr.includes('405 Method Not Allowed') || errorStr.includes('404 Not Found')) {
|
64
|
-
fallbackReason = 'Server doesn\'t support streamable HTTP (405/404)';
|
65
|
-
logger.debug(fallbackReason);
|
66
|
-
}
|
67
|
-
else {
|
68
|
-
fallbackReason = `Streamable HTTP failed: ${err.message}`;
|
69
|
-
logger.debug(fallbackReason);
|
70
|
-
}
|
71
|
-
}
|
72
|
-
// Always try SSE fallback for maximum compatibility
|
73
|
-
logger.debug('Falling back to SSE transport...');
|
74
|
-
try {
|
75
|
-
await this.connectWithSse(baseUrl);
|
76
|
-
}
|
77
|
-
catch (sseErr) {
|
78
|
-
logger.error(`Failed to connect with both transports:`);
|
79
|
-
logger.error(` Streamable HTTP: ${fallbackReason}`);
|
80
|
-
logger.error(` SSE: ${sseErr}`);
|
81
|
-
await this.cleanupResources();
|
82
|
-
throw new Error('Could not connect to server with any available transport');
|
83
|
-
}
|
84
|
-
}
|
85
|
-
}
|
86
|
-
async connectWithStreamableHttp(baseUrl) {
|
87
|
-
try {
|
88
|
-
// Create and start the streamable HTTP connection manager
|
89
|
-
this.connectionManager = new StreamableHttpConnectionManager(baseUrl, {
|
90
|
-
requestInit: {
|
91
|
-
headers: this.headers,
|
92
|
-
},
|
93
|
-
// Pass through timeout and other options
|
94
|
-
reconnectionOptions: {
|
95
|
-
maxReconnectionDelay: 30000,
|
96
|
-
initialReconnectionDelay: 1000,
|
97
|
-
reconnectionDelayGrowFactor: 1.5,
|
98
|
-
maxRetries: 2,
|
99
|
-
},
|
100
|
-
});
|
101
|
-
const transport = await this.connectionManager.start();
|
102
|
-
// Create and connect the client
|
103
|
-
this.client = new Client(this.clientInfo, this.opts.clientOptions);
|
104
|
-
await this.client.connect(transport);
|
105
|
-
this.connected = true;
|
106
|
-
this.transportType = 'streamable-http';
|
107
|
-
logger.debug(`Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`);
|
108
|
-
}
|
109
|
-
catch (err) {
|
110
|
-
// Clean up partial resources before throwing
|
111
|
-
await this.cleanupResources();
|
112
|
-
throw err;
|
113
|
-
}
|
114
|
-
}
|
115
|
-
async connectWithSse(baseUrl) {
|
116
|
-
try {
|
117
|
-
// Create and start the SSE connection manager
|
118
|
-
this.connectionManager = new SseConnectionManager(baseUrl, {
|
119
|
-
requestInit: {
|
120
|
-
headers: this.headers,
|
121
|
-
},
|
122
|
-
});
|
123
|
-
const transport = await this.connectionManager.start();
|
124
|
-
// Create and connect the client
|
125
|
-
this.client = new Client(this.clientInfo, this.opts.clientOptions);
|
126
|
-
await this.client.connect(transport);
|
127
|
-
this.connected = true;
|
128
|
-
this.transportType = 'sse';
|
129
|
-
logger.debug(`Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`);
|
130
|
-
}
|
131
|
-
catch (err) {
|
132
|
-
// Clean up partial resources before throwing
|
133
|
-
await this.cleanupResources();
|
134
|
-
throw err;
|
135
|
-
}
|
136
|
-
}
|
137
|
-
get publicIdentifier() {
|
138
|
-
return {
|
139
|
-
type: 'http',
|
140
|
-
url: this.baseUrl,
|
141
|
-
transport: this.transportType || 'unknown',
|
142
|
-
};
|
143
|
-
}
|
144
|
-
/**
|
145
|
-
* Get the transport type being used (streamable-http or sse)
|
146
|
-
*/
|
147
|
-
getTransportType() {
|
148
|
-
return this.transportType;
|
149
|
-
}
|
150
|
-
}
|
@@ -1,68 +0,0 @@
|
|
1
|
-
import process from 'node:process';
|
2
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
3
|
-
import { logger } from '../logging.js';
|
4
|
-
import { StdioConnectionManager } from '../task_managers/stdio.js';
|
5
|
-
import { BaseConnector } from './base.js';
|
6
|
-
export class StdioConnector extends BaseConnector {
|
7
|
-
command;
|
8
|
-
args;
|
9
|
-
env;
|
10
|
-
errlog;
|
11
|
-
clientInfo;
|
12
|
-
constructor({ command = 'npx', args = [], env, errlog = process.stderr, ...rest } = {}) {
|
13
|
-
super(rest);
|
14
|
-
this.command = command;
|
15
|
-
this.args = args;
|
16
|
-
this.env = env;
|
17
|
-
this.errlog = errlog;
|
18
|
-
this.clientInfo = rest.clientInfo ?? { name: 'stdio-connector', version: '1.0.0' };
|
19
|
-
}
|
20
|
-
/** Establish connection to the MCP implementation. */
|
21
|
-
async connect() {
|
22
|
-
if (this.connected) {
|
23
|
-
logger.debug('Already connected to MCP implementation');
|
24
|
-
return;
|
25
|
-
}
|
26
|
-
logger.debug(`Connecting to MCP implementation via stdio: ${this.command}`);
|
27
|
-
try {
|
28
|
-
// 1. Build server parameters for the transport
|
29
|
-
// Merge env with process.env, filtering out undefined values
|
30
|
-
let mergedEnv;
|
31
|
-
if (this.env) {
|
32
|
-
mergedEnv = {};
|
33
|
-
// First add process.env values (excluding undefined)
|
34
|
-
for (const [key, value] of Object.entries(process.env)) {
|
35
|
-
if (value !== undefined) {
|
36
|
-
mergedEnv[key] = value;
|
37
|
-
}
|
38
|
-
}
|
39
|
-
// Then override with provided env
|
40
|
-
Object.assign(mergedEnv, this.env);
|
41
|
-
}
|
42
|
-
const serverParams = {
|
43
|
-
command: this.command,
|
44
|
-
args: this.args,
|
45
|
-
env: mergedEnv,
|
46
|
-
};
|
47
|
-
// 2. Start the connection manager -> returns a live transport
|
48
|
-
this.connectionManager = new StdioConnectionManager(serverParams, this.errlog);
|
49
|
-
const transport = await this.connectionManager.start();
|
50
|
-
// 3. Create & connect the MCP client
|
51
|
-
this.client = new Client(this.clientInfo, this.opts.clientOptions);
|
52
|
-
await this.client.connect(transport);
|
53
|
-
this.connected = true;
|
54
|
-
logger.debug(`Successfully connected to MCP implementation: ${this.command}`);
|
55
|
-
}
|
56
|
-
catch (err) {
|
57
|
-
logger.error(`Failed to connect to MCP implementation: ${err}`);
|
58
|
-
await this.cleanupResources();
|
59
|
-
throw err;
|
60
|
-
}
|
61
|
-
}
|
62
|
-
get publicIdentifier() {
|
63
|
-
return {
|
64
|
-
'type': 'stdio',
|
65
|
-
'command&args': `${this.command} ${this.args.join(' ')}`,
|
66
|
-
};
|
67
|
-
}
|
68
|
-
}
|
@@ -1,157 +0,0 @@
|
|
1
|
-
import { v4 as uuidv4 } from 'uuid';
|
2
|
-
import { logger } from '../logging.js';
|
3
|
-
import { WebSocketConnectionManager } from '../task_managers/websocket.js';
|
4
|
-
import { BaseConnector } from './base.js';
|
5
|
-
export class WebSocketConnector extends BaseConnector {
|
6
|
-
url;
|
7
|
-
headers;
|
8
|
-
connectionManager = null;
|
9
|
-
ws = null;
|
10
|
-
receiverTask = null;
|
11
|
-
pending = new Map();
|
12
|
-
toolsCache = null;
|
13
|
-
constructor(url, opts = {}) {
|
14
|
-
super();
|
15
|
-
this.url = url;
|
16
|
-
this.headers = { ...(opts.headers ?? {}) };
|
17
|
-
if (opts.authToken)
|
18
|
-
this.headers.Authorization = `Bearer ${opts.authToken}`;
|
19
|
-
}
|
20
|
-
async connect() {
|
21
|
-
if (this.connected) {
|
22
|
-
logger.debug('Already connected to MCP implementation');
|
23
|
-
return;
|
24
|
-
}
|
25
|
-
logger.debug(`Connecting via WebSocket: ${this.url}`);
|
26
|
-
try {
|
27
|
-
this.connectionManager = new WebSocketConnectionManager(this.url, this.headers);
|
28
|
-
this.ws = await this.connectionManager.start();
|
29
|
-
this.receiverTask = this.receiveLoop();
|
30
|
-
this.connected = true;
|
31
|
-
logger.debug('WebSocket connected successfully');
|
32
|
-
}
|
33
|
-
catch (e) {
|
34
|
-
logger.error(`Failed to connect: ${e}`);
|
35
|
-
await this.cleanupResources();
|
36
|
-
throw e;
|
37
|
-
}
|
38
|
-
}
|
39
|
-
async disconnect() {
|
40
|
-
if (!this.connected) {
|
41
|
-
logger.debug('Not connected to MCP implementation');
|
42
|
-
return;
|
43
|
-
}
|
44
|
-
logger.debug('Disconnecting …');
|
45
|
-
await this.cleanupResources();
|
46
|
-
this.connected = false;
|
47
|
-
}
|
48
|
-
sendRequest(method, params = null) {
|
49
|
-
if (!this.ws)
|
50
|
-
throw new Error('WebSocket is not connected');
|
51
|
-
const id = uuidv4();
|
52
|
-
const payload = JSON.stringify({ id, method, params: params ?? {} });
|
53
|
-
return new Promise((resolve, reject) => {
|
54
|
-
this.pending.set(id, { resolve, reject });
|
55
|
-
this.ws.send(payload, (err) => {
|
56
|
-
if (err) {
|
57
|
-
this.pending.delete(id);
|
58
|
-
reject(err);
|
59
|
-
}
|
60
|
-
});
|
61
|
-
});
|
62
|
-
}
|
63
|
-
async receiveLoop() {
|
64
|
-
if (!this.ws)
|
65
|
-
return;
|
66
|
-
const socket = this.ws; // Node.ws or browser WS
|
67
|
-
const onMessage = (msg) => {
|
68
|
-
let data;
|
69
|
-
try {
|
70
|
-
data = JSON.parse(msg.data ?? msg);
|
71
|
-
}
|
72
|
-
catch (e) {
|
73
|
-
logger.warn('Received non‑JSON frame', e);
|
74
|
-
return;
|
75
|
-
}
|
76
|
-
const id = data.id;
|
77
|
-
if (id && this.pending.has(id)) {
|
78
|
-
const { resolve, reject } = this.pending.get(id);
|
79
|
-
this.pending.delete(id);
|
80
|
-
if ('result' in data)
|
81
|
-
resolve(data.result);
|
82
|
-
else if ('error' in data)
|
83
|
-
reject(data.error);
|
84
|
-
}
|
85
|
-
else {
|
86
|
-
logger.debug('Received unsolicited message', data);
|
87
|
-
}
|
88
|
-
};
|
89
|
-
socket.addEventListener ? socket.addEventListener('message', onMessage) : socket.on('message', onMessage);
|
90
|
-
// keep promise pending until close
|
91
|
-
return new Promise((resolve) => {
|
92
|
-
const onClose = () => {
|
93
|
-
socket.removeEventListener ? socket.removeEventListener('message', onMessage) : socket.off('message', onMessage);
|
94
|
-
this.rejectAll(new Error('WebSocket closed'));
|
95
|
-
resolve();
|
96
|
-
};
|
97
|
-
socket.addEventListener ? socket.addEventListener('close', onClose) : socket.on('close', onClose);
|
98
|
-
});
|
99
|
-
}
|
100
|
-
rejectAll(err) {
|
101
|
-
for (const { reject } of this.pending.values())
|
102
|
-
reject(err);
|
103
|
-
this.pending.clear();
|
104
|
-
}
|
105
|
-
async initialize() {
|
106
|
-
logger.debug('Initializing MCP session over WebSocket');
|
107
|
-
const result = await this.sendRequest('initialize');
|
108
|
-
const toolsList = await this.listTools();
|
109
|
-
this.toolsCache = toolsList.map(t => t);
|
110
|
-
logger.debug(`Initialized with ${this.toolsCache.length} tools`);
|
111
|
-
return result;
|
112
|
-
}
|
113
|
-
async listTools() {
|
114
|
-
const res = await this.sendRequest('tools/list');
|
115
|
-
return res.tools ?? [];
|
116
|
-
}
|
117
|
-
async callTool(name, args) {
|
118
|
-
return await this.sendRequest('tools/call', { name, arguments: args });
|
119
|
-
}
|
120
|
-
async listResources() {
|
121
|
-
const resources = await this.sendRequest('resources/list');
|
122
|
-
return { resources: Array.isArray(resources) ? resources : [] };
|
123
|
-
}
|
124
|
-
async readResource(uri) {
|
125
|
-
const res = await this.sendRequest('resources/read', { uri });
|
126
|
-
return { content: res.content, mimeType: res.mimeType };
|
127
|
-
}
|
128
|
-
async request(method, params = null) {
|
129
|
-
return await this.sendRequest(method, params);
|
130
|
-
}
|
131
|
-
get tools() {
|
132
|
-
if (!this.toolsCache)
|
133
|
-
throw new Error('MCP client is not initialized');
|
134
|
-
return this.toolsCache;
|
135
|
-
}
|
136
|
-
async cleanupResources() {
|
137
|
-
// Stop receiver
|
138
|
-
if (this.receiverTask)
|
139
|
-
await this.receiverTask.catch(() => { });
|
140
|
-
this.receiverTask = null;
|
141
|
-
// Reject pending
|
142
|
-
this.rejectAll(new Error('WebSocket disconnected'));
|
143
|
-
// Stop connection manager → closes socket
|
144
|
-
if (this.connectionManager) {
|
145
|
-
await this.connectionManager.stop();
|
146
|
-
this.connectionManager = null;
|
147
|
-
this.ws = null;
|
148
|
-
}
|
149
|
-
this.toolsCache = null;
|
150
|
-
}
|
151
|
-
get publicIdentifier() {
|
152
|
-
return {
|
153
|
-
type: 'websocket',
|
154
|
-
url: this.url,
|
155
|
-
};
|
156
|
-
}
|
157
|
-
}
|