mcp-use 1.5.0 → 1.5.1-canary.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/.tsbuildinfo +1 -1
- package/dist/{chunk-WERYJ6PF.js → chunk-2AOGMX4T.js} +1 -1
- package/dist/{chunk-DSBKVAWD.js → chunk-2JBWOW4S.js} +152 -0
- package/dist/{chunk-UT7O4SIJ.js → chunk-BWOTID2D.js} +209 -75
- package/dist/{chunk-GPAOZN2F.js → chunk-QRABML5H.js} +15 -3
- package/dist/index.cjs +395 -84
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -10
- package/dist/src/agents/index.cjs +1 -0
- package/dist/src/agents/index.js +2 -2
- package/dist/src/browser.cjs +351 -72
- package/dist/src/browser.d.ts +2 -0
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +2 -2
- package/dist/src/client/browser.d.ts.map +1 -1
- package/dist/src/client/prompts.cjs +3 -0
- package/dist/src/client/prompts.js +2 -2
- package/dist/src/client.d.ts +8 -0
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/config.d.ts +2 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/connectors/base.d.ts +79 -1
- package/dist/src/connectors/base.d.ts.map +1 -1
- package/dist/src/connectors/http.d.ts +1 -0
- package/dist/src/connectors/http.d.ts.map +1 -1
- package/dist/src/connectors/stdio.d.ts.map +1 -1
- package/dist/src/connectors/websocket.d.ts +6 -0
- package/dist/src/connectors/websocket.d.ts.map +1 -1
- package/dist/src/react/index.cjs +365 -73
- package/dist/src/react/index.d.ts +1 -0
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/react/index.js +3 -3
- package/dist/src/react/types.d.ts +9 -1
- package/dist/src/react/types.d.ts.map +1 -1
- package/dist/src/react/useMcp.d.ts.map +1 -1
- package/dist/src/server/adapters/mcp-ui-adapter.d.ts +1 -0
- package/dist/src/server/adapters/mcp-ui-adapter.d.ts.map +1 -1
- package/dist/src/server/index.cjs +605 -168
- package/dist/src/server/index.js +605 -168
- package/dist/src/server/mcp-server.d.ts +201 -10
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/types/common.d.ts +28 -0
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/dist/src/session.d.ts +40 -1
- package/dist/src/session.d.ts.map +1 -1
- package/package.json +10 -4
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-3GQAWCBQ.js";
|
|
7
7
|
|
|
8
8
|
// src/connectors/base.ts
|
|
9
|
+
import {
|
|
10
|
+
ListRootsRequestSchema,
|
|
11
|
+
CreateMessageRequestSchema
|
|
12
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
13
|
var BaseConnector = class {
|
|
10
14
|
static {
|
|
11
15
|
__name(this, "BaseConnector");
|
|
@@ -17,8 +21,156 @@ var BaseConnector = class {
|
|
|
17
21
|
serverInfoCache = null;
|
|
18
22
|
connected = false;
|
|
19
23
|
opts;
|
|
24
|
+
notificationHandlers = [];
|
|
25
|
+
rootsCache = [];
|
|
20
26
|
constructor(opts = {}) {
|
|
21
27
|
this.opts = opts;
|
|
28
|
+
if (opts.roots) {
|
|
29
|
+
this.rootsCache = [...opts.roots];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Register a handler for server notifications
|
|
34
|
+
*
|
|
35
|
+
* @param handler - Function to call when a notification is received
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* connector.onNotification((notification) => {
|
|
40
|
+
* console.log(`Received: ${notification.method}`, notification.params);
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
onNotification(handler) {
|
|
45
|
+
this.notificationHandlers.push(handler);
|
|
46
|
+
if (this.client) {
|
|
47
|
+
this.setupNotificationHandler();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Internal: wire notification handlers to the SDK client
|
|
52
|
+
* Includes automatic handling for list_changed notifications per MCP spec
|
|
53
|
+
*/
|
|
54
|
+
setupNotificationHandler() {
|
|
55
|
+
if (!this.client) return;
|
|
56
|
+
this.client.fallbackNotificationHandler = async (notification) => {
|
|
57
|
+
switch (notification.method) {
|
|
58
|
+
case "notifications/tools/list_changed":
|
|
59
|
+
await this.refreshToolsCache();
|
|
60
|
+
break;
|
|
61
|
+
case "notifications/resources/list_changed":
|
|
62
|
+
await this.onResourcesListChanged();
|
|
63
|
+
break;
|
|
64
|
+
case "notifications/prompts/list_changed":
|
|
65
|
+
await this.onPromptsListChanged();
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
for (const handler of this.notificationHandlers) {
|
|
71
|
+
try {
|
|
72
|
+
await handler(notification);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
logger.error("Error in notification handler:", err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Auto-refresh tools cache when server sends tools/list_changed notification
|
|
81
|
+
*/
|
|
82
|
+
async refreshToolsCache() {
|
|
83
|
+
if (!this.client) return;
|
|
84
|
+
try {
|
|
85
|
+
logger.debug(
|
|
86
|
+
"[Auto] Refreshing tools cache due to list_changed notification"
|
|
87
|
+
);
|
|
88
|
+
const result = await this.client.listTools();
|
|
89
|
+
this.toolsCache = result.tools ?? [];
|
|
90
|
+
logger.debug(
|
|
91
|
+
`[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
|
|
92
|
+
);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
logger.warn("[Auto] Failed to refresh tools cache:", err);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Called when server sends resources/list_changed notification
|
|
99
|
+
* Resources aren't cached by default, but we log for user awareness
|
|
100
|
+
*/
|
|
101
|
+
async onResourcesListChanged() {
|
|
102
|
+
logger.debug(
|
|
103
|
+
"[Auto] Resources list changed - clients should re-fetch if needed"
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Called when server sends prompts/list_changed notification
|
|
108
|
+
* Prompts aren't cached by default, but we log for user awareness
|
|
109
|
+
*/
|
|
110
|
+
async onPromptsListChanged() {
|
|
111
|
+
logger.debug(
|
|
112
|
+
"[Auto] Prompts list changed - clients should re-fetch if needed"
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Set roots and notify the server.
|
|
117
|
+
* Roots represent directories or files that the client has access to.
|
|
118
|
+
*
|
|
119
|
+
* @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* await connector.setRoots([
|
|
124
|
+
* { uri: "file:///home/user/project", name: "My Project" },
|
|
125
|
+
* { uri: "file:///home/user/data" }
|
|
126
|
+
* ]);
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
async setRoots(roots) {
|
|
130
|
+
this.rootsCache = [...roots];
|
|
131
|
+
if (this.client) {
|
|
132
|
+
logger.debug(
|
|
133
|
+
`Sending roots/list_changed notification with ${roots.length} root(s)`
|
|
134
|
+
);
|
|
135
|
+
await this.client.sendRootsListChanged();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the current roots.
|
|
140
|
+
*/
|
|
141
|
+
getRoots() {
|
|
142
|
+
return [...this.rootsCache];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Internal: set up roots/list request handler.
|
|
146
|
+
* This is called after the client connects to register the handler for server requests.
|
|
147
|
+
*/
|
|
148
|
+
setupRootsHandler() {
|
|
149
|
+
if (!this.client) return;
|
|
150
|
+
this.client.setRequestHandler(
|
|
151
|
+
ListRootsRequestSchema,
|
|
152
|
+
async (_request, _extra) => {
|
|
153
|
+
logger.debug(
|
|
154
|
+
`Server requested roots list, returning ${this.rootsCache.length} root(s)`
|
|
155
|
+
);
|
|
156
|
+
return { roots: this.rootsCache };
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Internal: set up sampling/createMessage request handler.
|
|
162
|
+
* This is called after the client connects to register the handler for sampling requests.
|
|
163
|
+
*/
|
|
164
|
+
setupSamplingHandler() {
|
|
165
|
+
if (!this.client) return;
|
|
166
|
+
if (!this.opts.samplingCallback) return;
|
|
167
|
+
this.client.setRequestHandler(
|
|
168
|
+
CreateMessageRequestSchema,
|
|
169
|
+
async (request, _extra) => {
|
|
170
|
+
logger.debug("Server requested sampling, forwarding to callback");
|
|
171
|
+
return await this.opts.samplingCallback(request.params);
|
|
172
|
+
}
|
|
173
|
+
);
|
|
22
174
|
}
|
|
23
175
|
/** Disconnect and release resources. */
|
|
24
176
|
async disconnect() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BaseConnector
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2JBWOW4S.js";
|
|
4
4
|
import {
|
|
5
5
|
logger
|
|
6
6
|
} from "./chunk-34R6SIER.js";
|
|
@@ -34,11 +34,59 @@ var MCPSession = class {
|
|
|
34
34
|
get isConnected() {
|
|
35
35
|
return this.connector && this.connector.isClientConnected;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Register an event handler for session events
|
|
39
|
+
*
|
|
40
|
+
* @param event - The event type to listen for
|
|
41
|
+
* @param handler - The handler function to call when the event occurs
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* session.on("notification", async (notification) => {
|
|
46
|
+
* console.log(`Received: ${notification.method}`, notification.params);
|
|
47
|
+
*
|
|
48
|
+
* if (notification.method === "notifications/tools/list_changed") {
|
|
49
|
+
* // Refresh tools list
|
|
50
|
+
* }
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
on(event, handler) {
|
|
55
|
+
if (event === "notification") {
|
|
56
|
+
this.connector.onNotification(handler);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Set roots and notify the server.
|
|
61
|
+
* Roots represent directories or files that the client has access to.
|
|
62
|
+
*
|
|
63
|
+
* @param roots - Array of Root objects with `uri` (must start with "file://") and optional `name`
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* await session.setRoots([
|
|
68
|
+
* { uri: "file:///home/user/project", name: "My Project" },
|
|
69
|
+
* { uri: "file:///home/user/data" }
|
|
70
|
+
* ]);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
async setRoots(roots) {
|
|
74
|
+
return this.connector.setRoots(roots);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get the current roots.
|
|
78
|
+
*/
|
|
79
|
+
getRoots() {
|
|
80
|
+
return this.connector.getRoots();
|
|
81
|
+
}
|
|
37
82
|
};
|
|
38
83
|
|
|
39
84
|
// src/connectors/http.ts
|
|
40
85
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
41
|
-
import {
|
|
86
|
+
import {
|
|
87
|
+
StreamableHTTPClientTransport,
|
|
88
|
+
StreamableHTTPError
|
|
89
|
+
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
42
90
|
|
|
43
91
|
// src/task_managers/sse.ts
|
|
44
92
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
@@ -203,57 +251,6 @@ var SseConnectionManager = class extends ConnectionManager {
|
|
|
203
251
|
}
|
|
204
252
|
};
|
|
205
253
|
|
|
206
|
-
// src/task_managers/streamable_http.ts
|
|
207
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
208
|
-
var StreamableHttpConnectionManager = class extends ConnectionManager {
|
|
209
|
-
static {
|
|
210
|
-
__name(this, "StreamableHttpConnectionManager");
|
|
211
|
-
}
|
|
212
|
-
url;
|
|
213
|
-
opts;
|
|
214
|
-
_transport = null;
|
|
215
|
-
/**
|
|
216
|
-
* Create a Streamable HTTP connection manager.
|
|
217
|
-
*
|
|
218
|
-
* @param url The HTTP endpoint URL.
|
|
219
|
-
* @param opts Optional transport options (auth, headers, etc.).
|
|
220
|
-
*/
|
|
221
|
-
constructor(url, opts) {
|
|
222
|
-
super();
|
|
223
|
-
this.url = typeof url === "string" ? new URL(url) : url;
|
|
224
|
-
this.opts = opts;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Spawn a new `StreamableHTTPClientTransport` and return it.
|
|
228
|
-
* The Client.connect() method will handle starting the transport.
|
|
229
|
-
*/
|
|
230
|
-
async establishConnection() {
|
|
231
|
-
this._transport = new StreamableHTTPClientTransport(this.url, this.opts);
|
|
232
|
-
logger.debug(`${this.constructor.name} created successfully`);
|
|
233
|
-
return this._transport;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Close the underlying transport and clean up resources.
|
|
237
|
-
*/
|
|
238
|
-
async closeConnection(_connection) {
|
|
239
|
-
if (this._transport) {
|
|
240
|
-
try {
|
|
241
|
-
await this._transport.close();
|
|
242
|
-
} catch (e) {
|
|
243
|
-
logger.warn(`Error closing Streamable HTTP transport: ${e}`);
|
|
244
|
-
} finally {
|
|
245
|
-
this._transport = null;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Get the session ID from the transport if available.
|
|
251
|
-
*/
|
|
252
|
-
get sessionId() {
|
|
253
|
-
return this._transport?.sessionId;
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
|
|
257
254
|
// src/connectors/http.ts
|
|
258
255
|
var HttpConnector = class extends BaseConnector {
|
|
259
256
|
static {
|
|
@@ -266,6 +263,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
266
263
|
clientInfo;
|
|
267
264
|
preferSse;
|
|
268
265
|
transportType = null;
|
|
266
|
+
streamableTransport = null;
|
|
269
267
|
constructor(baseUrl, opts = {}) {
|
|
270
268
|
super(opts);
|
|
271
269
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -357,34 +355,67 @@ var HttpConnector = class extends BaseConnector {
|
|
|
357
355
|
}
|
|
358
356
|
async connectWithStreamableHttp(baseUrl) {
|
|
359
357
|
try {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
358
|
+
const streamableTransport = new StreamableHTTPClientTransport(
|
|
359
|
+
new URL(baseUrl),
|
|
360
|
+
{
|
|
361
|
+
authProvider: this.opts.authProvider,
|
|
362
|
+
// ← Pass OAuth provider to SDK
|
|
363
|
+
requestInit: {
|
|
364
|
+
headers: this.headers
|
|
365
|
+
},
|
|
366
|
+
// Pass through reconnection options
|
|
367
|
+
reconnectionOptions: {
|
|
368
|
+
maxReconnectionDelay: 3e4,
|
|
369
|
+
initialReconnectionDelay: 1e3,
|
|
370
|
+
reconnectionDelayGrowFactor: 1.5,
|
|
371
|
+
maxRetries: 2
|
|
372
|
+
}
|
|
373
|
+
// Don't pass sessionId - let the SDK generate it automatically during connect()
|
|
372
374
|
}
|
|
373
|
-
|
|
374
|
-
let transport =
|
|
375
|
+
);
|
|
376
|
+
let transport = streamableTransport;
|
|
375
377
|
if (this.opts.wrapTransport) {
|
|
376
378
|
const serverId = this.baseUrl;
|
|
377
|
-
transport = this.opts.wrapTransport(
|
|
379
|
+
transport = this.opts.wrapTransport(
|
|
380
|
+
transport,
|
|
381
|
+
serverId
|
|
382
|
+
);
|
|
378
383
|
}
|
|
379
|
-
|
|
384
|
+
const clientOptions = {
|
|
385
|
+
...this.opts.clientOptions || {},
|
|
386
|
+
capabilities: {
|
|
387
|
+
...this.opts.clientOptions?.capabilities || {},
|
|
388
|
+
roots: { listChanged: true },
|
|
389
|
+
// Always advertise roots capability
|
|
390
|
+
// Add sampling capability if callback is provided
|
|
391
|
+
...this.opts.samplingCallback ? { sampling: {} } : {}
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
logger.debug(
|
|
395
|
+
`Creating Client with capabilities:`,
|
|
396
|
+
JSON.stringify(clientOptions.capabilities, null, 2)
|
|
397
|
+
);
|
|
398
|
+
this.client = new Client(this.clientInfo, clientOptions);
|
|
399
|
+
this.setupRootsHandler();
|
|
400
|
+
logger.debug("Roots handler registered before connect");
|
|
380
401
|
try {
|
|
381
|
-
await this.client.connect(transport
|
|
402
|
+
await this.client.connect(transport, {
|
|
403
|
+
timeout: Math.min(this.timeout, 3e3)
|
|
404
|
+
});
|
|
405
|
+
const sessionId = streamableTransport.sessionId;
|
|
406
|
+
if (sessionId) {
|
|
407
|
+
logger.debug(`Session ID obtained: ${sessionId}`);
|
|
408
|
+
} else {
|
|
409
|
+
logger.warn(
|
|
410
|
+
"Session ID not available after connect - this may cause issues with SSE stream"
|
|
411
|
+
);
|
|
412
|
+
}
|
|
382
413
|
} catch (connectErr) {
|
|
383
414
|
if (connectErr instanceof Error) {
|
|
384
415
|
const errMsg = connectErr.message || connectErr.toString();
|
|
385
|
-
if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID")) {
|
|
416
|
+
if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID") || errMsg.includes("Mcp-Session-Id header is required")) {
|
|
386
417
|
const wrappedError = new Error(
|
|
387
|
-
`
|
|
418
|
+
`Session ID error: ${errMsg}. The SDK should automatically extract session ID from initialize response.`
|
|
388
419
|
);
|
|
389
420
|
wrappedError.cause = connectErr;
|
|
390
421
|
throw wrappedError;
|
|
@@ -392,8 +423,24 @@ var HttpConnector = class extends BaseConnector {
|
|
|
392
423
|
}
|
|
393
424
|
throw connectErr;
|
|
394
425
|
}
|
|
426
|
+
this.streamableTransport = streamableTransport;
|
|
427
|
+
this.connectionManager = {
|
|
428
|
+
stop: /* @__PURE__ */ __name(async () => {
|
|
429
|
+
if (this.streamableTransport) {
|
|
430
|
+
try {
|
|
431
|
+
await this.streamableTransport.close();
|
|
432
|
+
} catch (e) {
|
|
433
|
+
logger.warn(`Error closing Streamable HTTP transport: ${e}`);
|
|
434
|
+
} finally {
|
|
435
|
+
this.streamableTransport = null;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}, "stop")
|
|
439
|
+
};
|
|
395
440
|
this.connected = true;
|
|
396
441
|
this.transportType = "streamable-http";
|
|
442
|
+
this.setupNotificationHandler();
|
|
443
|
+
this.setupSamplingHandler();
|
|
397
444
|
logger.debug(
|
|
398
445
|
`Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
|
|
399
446
|
);
|
|
@@ -414,10 +461,28 @@ var HttpConnector = class extends BaseConnector {
|
|
|
414
461
|
const serverId = this.baseUrl;
|
|
415
462
|
transport = this.opts.wrapTransport(transport, serverId);
|
|
416
463
|
}
|
|
417
|
-
|
|
464
|
+
const clientOptions = {
|
|
465
|
+
...this.opts.clientOptions || {},
|
|
466
|
+
capabilities: {
|
|
467
|
+
...this.opts.clientOptions?.capabilities || {},
|
|
468
|
+
roots: { listChanged: true },
|
|
469
|
+
// Always advertise roots capability
|
|
470
|
+
// Add sampling capability if callback is provided
|
|
471
|
+
...this.opts.samplingCallback ? { sampling: {} } : {}
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
logger.debug(
|
|
475
|
+
`Creating Client with capabilities (SSE):`,
|
|
476
|
+
JSON.stringify(clientOptions.capabilities, null, 2)
|
|
477
|
+
);
|
|
478
|
+
this.client = new Client(this.clientInfo, clientOptions);
|
|
479
|
+
this.setupRootsHandler();
|
|
480
|
+
logger.debug("Roots handler registered before connect (SSE)");
|
|
418
481
|
await this.client.connect(transport);
|
|
419
482
|
this.connected = true;
|
|
420
483
|
this.transportType = "sse";
|
|
484
|
+
this.setupNotificationHandler();
|
|
485
|
+
this.setupSamplingHandler();
|
|
421
486
|
logger.debug(
|
|
422
487
|
`Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
|
|
423
488
|
);
|
|
@@ -591,6 +656,9 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
591
656
|
this.pending.delete(id);
|
|
592
657
|
if ("result" in data) resolve(data.result);
|
|
593
658
|
else if ("error" in data) reject(data.error);
|
|
659
|
+
} else if (data.method && !data.id) {
|
|
660
|
+
logger.debug("Received notification", data.method, data.params);
|
|
661
|
+
this.handleNotification(data);
|
|
594
662
|
} else {
|
|
595
663
|
logger.debug("Received unsolicited message", data);
|
|
596
664
|
}
|
|
@@ -621,6 +689,49 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
621
689
|
for (const { reject } of this.pending.values()) reject(err);
|
|
622
690
|
this.pending.clear();
|
|
623
691
|
}
|
|
692
|
+
async handleNotification(data) {
|
|
693
|
+
switch (data.method) {
|
|
694
|
+
case "notifications/tools/list_changed":
|
|
695
|
+
await this.refreshToolsCache();
|
|
696
|
+
break;
|
|
697
|
+
case "notifications/resources/list_changed":
|
|
698
|
+
await this.onResourcesListChanged();
|
|
699
|
+
break;
|
|
700
|
+
case "notifications/prompts/list_changed":
|
|
701
|
+
await this.onPromptsListChanged();
|
|
702
|
+
break;
|
|
703
|
+
default:
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
for (const handler of this.notificationHandlers) {
|
|
707
|
+
try {
|
|
708
|
+
await handler({
|
|
709
|
+
method: data.method,
|
|
710
|
+
params: data.params
|
|
711
|
+
});
|
|
712
|
+
} catch (err) {
|
|
713
|
+
logger.error("Error in notification handler:", err);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Auto-refresh tools cache when server sends tools/list_changed notification
|
|
719
|
+
* Override to use WebSocket-specific listTools method
|
|
720
|
+
*/
|
|
721
|
+
async refreshToolsCache() {
|
|
722
|
+
try {
|
|
723
|
+
logger.debug(
|
|
724
|
+
"[Auto] Refreshing tools cache due to list_changed notification"
|
|
725
|
+
);
|
|
726
|
+
const tools = await this.listTools();
|
|
727
|
+
this.toolsCache = tools.map((t) => t);
|
|
728
|
+
logger.debug(
|
|
729
|
+
`[Auto] Refreshed tools cache: ${this.toolsCache.length} tools`
|
|
730
|
+
);
|
|
731
|
+
} catch (err) {
|
|
732
|
+
logger.warn("[Auto] Failed to refresh tools cache:", err);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
624
735
|
async initialize() {
|
|
625
736
|
logger.debug("Initializing MCP session over WebSocket");
|
|
626
737
|
const result = await this.sendRequest("initialize");
|
|
@@ -1148,7 +1259,16 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
|
|
|
1148
1259
|
* Supports HTTP and WebSocket connectors only
|
|
1149
1260
|
*/
|
|
1150
1261
|
createConnectorFromConfig(serverConfig) {
|
|
1151
|
-
const {
|
|
1262
|
+
const {
|
|
1263
|
+
url,
|
|
1264
|
+
transport,
|
|
1265
|
+
headers,
|
|
1266
|
+
authToken,
|
|
1267
|
+
authProvider,
|
|
1268
|
+
wrapTransport,
|
|
1269
|
+
clientOptions,
|
|
1270
|
+
samplingCallback
|
|
1271
|
+
} = serverConfig;
|
|
1152
1272
|
if (!url) {
|
|
1153
1273
|
throw new Error("Server URL is required");
|
|
1154
1274
|
}
|
|
@@ -1157,9 +1277,23 @@ var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
|
|
|
1157
1277
|
authToken,
|
|
1158
1278
|
authProvider,
|
|
1159
1279
|
// ← Pass OAuth provider to connector
|
|
1160
|
-
wrapTransport
|
|
1280
|
+
wrapTransport,
|
|
1161
1281
|
// ← Pass transport wrapper if provided
|
|
1282
|
+
clientOptions,
|
|
1283
|
+
// ← Pass client options (capabilities, etc.) to connector
|
|
1284
|
+
samplingCallback
|
|
1285
|
+
// ← Pass sampling callback to connector
|
|
1162
1286
|
};
|
|
1287
|
+
if (clientOptions) {
|
|
1288
|
+
console.log(
|
|
1289
|
+
"[BrowserMCPClient] Passing clientOptions to connector:",
|
|
1290
|
+
JSON.stringify(clientOptions, null, 2)
|
|
1291
|
+
);
|
|
1292
|
+
} else {
|
|
1293
|
+
console.warn(
|
|
1294
|
+
"[BrowserMCPClient] No clientOptions provided to connector!"
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1163
1297
|
if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
|
|
1164
1298
|
return new WebSocketConnector(url, connectorOptions);
|
|
1165
1299
|
} else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BrowserMCPClient,
|
|
3
3
|
BrowserOAuthClientProvider
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BWOTID2D.js";
|
|
5
5
|
import {
|
|
6
6
|
__name
|
|
7
7
|
} from "./chunk-3GQAWCBQ.js";
|
|
@@ -44,7 +44,9 @@ function useMcp(options) {
|
|
|
44
44
|
// 30 seconds default for connection timeout
|
|
45
45
|
sseReadTimeout = 3e5,
|
|
46
46
|
// 5 minutes default for SSE read timeout
|
|
47
|
-
wrapTransport
|
|
47
|
+
wrapTransport,
|
|
48
|
+
onNotification,
|
|
49
|
+
samplingCallback
|
|
48
50
|
} = options;
|
|
49
51
|
const [state, setState] = useState("discovering");
|
|
50
52
|
const [tools, setTools] = useState([]);
|
|
@@ -197,6 +199,10 @@ function useMcp(options) {
|
|
|
197
199
|
...serverConfig,
|
|
198
200
|
authProvider: authProviderRef.current,
|
|
199
201
|
// ← SDK handles OAuth automatically!
|
|
202
|
+
clientOptions: clientConfig,
|
|
203
|
+
// ← Pass client config to connector
|
|
204
|
+
samplingCallback,
|
|
205
|
+
// ← Pass sampling callback to connector
|
|
200
206
|
wrapTransport: wrapTransport ? (transport) => {
|
|
201
207
|
console.log(
|
|
202
208
|
"[useMcp] Applying transport wrapper for server:",
|
|
@@ -207,7 +213,13 @@ function useMcp(options) {
|
|
|
207
213
|
return wrapTransport(transport, url);
|
|
208
214
|
} : void 0
|
|
209
215
|
});
|
|
210
|
-
const session = await clientRef.current.createSession(
|
|
216
|
+
const session = await clientRef.current.createSession(
|
|
217
|
+
serverName,
|
|
218
|
+
false
|
|
219
|
+
);
|
|
220
|
+
if (onNotification) {
|
|
221
|
+
session.on("notification", onNotification);
|
|
222
|
+
}
|
|
211
223
|
await session.initialize();
|
|
212
224
|
addLog("info", "\u2705 Successfully connected to MCP server");
|
|
213
225
|
addLog("info", "Server info:", session.connector.serverInfo);
|