@h1deya/langchain-mcp-tools 0.2.6 → 0.2.7

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 CHANGED
@@ -158,6 +158,7 @@ TypeScript SDK's [`StdioServerParameters`](https://github.com/modelcontextprotoc
158
158
  "streamable-http-server": {
159
159
  url: `http://${server_host}:${server_port}/...`,
160
160
  transport: "streamable_http"
161
+ // type: "http" // VSCode-style config works too
161
162
  },
162
163
 
163
164
  // Explicit SSE
@@ -172,6 +173,22 @@ TypeScript SDK's [`StdioServerParameters`](https://github.com/modelcontextprotoc
172
173
  },
173
174
  ```
174
175
 
176
+ For the convenience of adding authorization headers, the following shorthand expression is supported.
177
+ This header configuration will be overridden if either `streamableHTTPOptions` or `sseOptions` is specified.
178
+
179
+ ```ts
180
+ github: {
181
+ type: "http", // recommended to specify the protocol explicitly when authentication is used
182
+ url: "https://api.githubcopilot.com/mcp/",
183
+ headers: {
184
+ "Authorization": `Bearer ${process.env.GITHUB_PERSONAL_ACCESS_TOKEN}`
185
+ }
186
+ },
187
+ ```
188
+
189
+ NOTE: When accessing the GitHub MCP server, [GitHub PAT (Personal Access Token)](https://github.com/settings/personal-access-tokens)
190
+ alone is not enough; your GitHub account must have an active Copilot subscription or be assigned a Copilot license through your organization.
191
+
175
192
  **Auto-detection behavior (default):**
176
193
  - For HTTP/HTTPS URLs without explicit `transport`, the library follows [MCP specification recommendations](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility)
177
194
  - First attempts Streamable HTTP transport
@@ -11,7 +11,8 @@ import { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
11
11
  */
12
12
  export interface CommandBasedConfig {
13
13
  url?: never;
14
- transport?: never;
14
+ transport?: string;
15
+ type?: string;
15
16
  command: string;
16
17
  args?: string[];
17
18
  env?: Record<string, string>;
@@ -27,6 +28,8 @@ export interface CommandBasedConfig {
27
28
  export interface UrlBasedConfig {
28
29
  url: string;
29
30
  transport?: string;
31
+ type?: string;
32
+ headers?: Record<string, string>;
30
33
  command?: never;
31
34
  args?: never;
32
35
  env?: never;
@@ -93,7 +93,7 @@ export async function convertMcpToLangchainTools(configs, options) {
93
93
  * performing schema conversions to help track which servers need upstream fixes.
94
94
  *
95
95
  * Gemini supports only a limited subset of OpenAPI 3.0 Schema properties:
96
- * - string: enum, format (only 'date-time' documented)
96
+ * - string: enum, format (only "date-time" documented)
97
97
  * - integer/number: format only
98
98
  * - array: minItems, maxItems, items
99
99
  * - object: properties, required, propertyOrdering, nullable
@@ -112,7 +112,7 @@ export async function convertMcpToLangchainTools(configs, options) {
112
112
  * @internal This function is meant to be used internally by convertSingleMcpToLangchainTools
113
113
  */
114
114
  function sanitizeSchemaForGemini(schema, logger, toolName) {
115
- if (typeof schema !== 'object' || schema === null) {
115
+ if (typeof schema !== "object" || schema === null) {
116
116
  return schema;
117
117
  }
118
118
  const sanitized = { ...schema };
@@ -120,25 +120,25 @@ function sanitizeSchemaForGemini(schema, logger, toolName) {
120
120
  const convertedProperties = [];
121
121
  // Remove unsupported properties
122
122
  if (sanitized.exclusiveMinimum !== undefined) {
123
- removedProperties.push('exclusiveMinimum');
123
+ removedProperties.push("exclusiveMinimum");
124
124
  delete sanitized.exclusiveMinimum;
125
125
  }
126
126
  if (sanitized.exclusiveMaximum !== undefined) {
127
- removedProperties.push('exclusiveMaximum');
127
+ removedProperties.push("exclusiveMaximum");
128
128
  delete sanitized.exclusiveMaximum;
129
129
  }
130
130
  // Convert exclusiveMinimum/Maximum to minimum/maximum if needed
131
131
  if (schema.exclusiveMinimum !== undefined) {
132
132
  sanitized.minimum = schema.exclusiveMinimum;
133
- convertedProperties.push('exclusiveMinimum → minimum');
133
+ convertedProperties.push("exclusiveMinimum → minimum");
134
134
  }
135
135
  if (schema.exclusiveMaximum !== undefined) {
136
136
  sanitized.maximum = schema.exclusiveMaximum;
137
- convertedProperties.push('exclusiveMaximum → maximum');
137
+ convertedProperties.push("exclusiveMaximum → maximum");
138
138
  }
139
- // Remove unsupported string formats (Gemini only supports 'enum' and 'date-time')
140
- if (sanitized.type === 'string' && sanitized.format) {
141
- const supportedFormats = ['enum', 'date-time'];
139
+ // Remove unsupported string formats (Gemini only supports "enum" and "date-time")
140
+ if (sanitized.type === "string" && sanitized.format) {
141
+ const supportedFormats = ["enum", "date-time"];
142
142
  if (!supportedFormats.includes(sanitized.format)) {
143
143
  removedProperties.push(`format: ${sanitized.format}`);
144
144
  delete sanitized.format;
@@ -148,12 +148,12 @@ function sanitizeSchemaForGemini(schema, logger, toolName) {
148
148
  if (logger && toolName && (removedProperties.length > 0 || convertedProperties.length > 0)) {
149
149
  const changes = [];
150
150
  if (removedProperties.length > 0) {
151
- changes.push(`removed: ${removedProperties.join(', ')}`);
151
+ changes.push(`removed: ${removedProperties.join(", ")}`);
152
152
  }
153
153
  if (convertedProperties.length > 0) {
154
- changes.push(`converted: ${convertedProperties.join(', ')}`);
154
+ changes.push(`converted: ${convertedProperties.join(", ")}`);
155
155
  }
156
- logger.warn(`MCP tool "${toolName}": schema sanitized for Gemini compatibility (${changes.join('; ')})`);
156
+ logger.warn(`MCP tool "${toolName}": schema sanitized for Gemini compatibility (${changes.join("; ")})`);
157
157
  }
158
158
  // Recursively process nested objects and arrays
159
159
  if (sanitized.properties) {
@@ -174,7 +174,7 @@ function sanitizeSchemaForGemini(schema, logger, toolName) {
174
174
  if (sanitized.items) {
175
175
  sanitized.items = sanitizeSchemaForGemini(sanitized.items, logger, toolName);
176
176
  }
177
- if (sanitized.additionalProperties && typeof sanitized.additionalProperties === 'object') {
177
+ if (sanitized.additionalProperties && typeof sanitized.additionalProperties === "object") {
178
178
  sanitized.additionalProperties = sanitizeSchemaForGemini(sanitized.additionalProperties, logger, toolName);
179
179
  }
180
180
  return sanitized;
@@ -207,6 +207,9 @@ function createStreamableHttpOptions(config, logger, serverName) {
207
207
  options.sessionId = config.streamableHTTPOptions.sessionId;
208
208
  }
209
209
  }
210
+ else if (config.headers) {
211
+ options.requestInit = { headers: config.headers };
212
+ }
210
213
  return Object.keys(options).length > 0 ? options : undefined;
211
214
  }
212
215
  /**
@@ -233,6 +236,9 @@ function createSseOptions(config, logger, serverName) {
233
236
  if (config.sseOptions.requestInit) {
234
237
  options.requestInit = config.sseOptions.requestInit;
235
238
  }
239
+ else if (config.headers) {
240
+ options.requestInit = { headers: config.headers };
241
+ }
236
242
  }
237
243
  return Object.keys(options).length > 0 ? options : undefined;
238
244
  }
@@ -246,34 +252,126 @@ function createSseOptions(config, logger, serverName) {
246
252
  * @internal This function is meant to be used internally by createHttpTransportWithFallback
247
253
  */
248
254
  function is4xxError(error) {
249
- if (!error || typeof error !== 'object') {
255
+ if (!error || typeof error !== "object") {
250
256
  return false;
251
257
  }
252
258
  // Check for common error patterns that indicate 4xx responses
253
259
  const errorObj = error;
254
- // Check if it's a fetch Response error with status
255
- if (errorObj.status && typeof errorObj.status === 'number') {
260
+ // Check if it"s a fetch Response error with status
261
+ if (errorObj.status && typeof errorObj.status === "number") {
256
262
  return errorObj.status >= 400 && errorObj.status < 500;
257
263
  }
258
264
  // Check if it's wrapped in a Response object
259
- if (errorObj.response && errorObj.response.status && typeof errorObj.response.status === 'number') {
265
+ if (errorObj.response && errorObj.response.status && typeof errorObj.response.status === "number") {
260
266
  return errorObj.response.status >= 400 && errorObj.response.status < 500;
261
267
  }
262
268
  // Check for error messages that typically indicate 4xx errors
263
269
  const message = errorObj.message || errorObj.toString();
264
- if (typeof message === 'string') {
270
+ if (typeof message === "string") {
265
271
  return /4[0-9]{2}/.test(message) ||
266
- message.includes('Bad Request') ||
267
- message.includes('Unauthorized') ||
268
- message.includes('Forbidden') ||
269
- message.includes('Not Found') ||
270
- message.includes('Method Not Allowed');
272
+ message.includes("Bad Request") ||
273
+ message.includes("Unauthorized") ||
274
+ message.includes("Forbidden") ||
275
+ message.includes("Not Found") ||
276
+ message.includes("Method Not Allowed");
271
277
  }
272
278
  return false;
273
279
  }
280
+ /**
281
+ * Tests MCP server transport support using direct POST InitializeRequest.
282
+ * Follows the official MCP specification's recommended approach for backwards compatibility.
283
+ *
284
+ * See: https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility
285
+ *
286
+ * @param url - The URL to test
287
+ * @param config - URL-based server configuration
288
+ * @param logger - Logger instance for recording test attempts
289
+ * @param serverName - Server name for logging context
290
+ * @returns A promise that resolves to the detected transport type
291
+ *
292
+ * @internal This function is meant to be used internally by createHttpTransportWithFallback
293
+ */
294
+ async function testTransportSupport(url, config, logger, serverName) {
295
+ logger.debug(`MCP server "${serverName}": testing transport support using InitializeRequest`);
296
+ // Create InitializeRequest as per MCP specification
297
+ const initRequest = {
298
+ jsonrpc: "2.0",
299
+ id: `transport-test-${Date.now()}`,
300
+ method: "initialize",
301
+ params: {
302
+ protocolVersion: "2024-11-05", // Latest supported version
303
+ capabilities: {},
304
+ clientInfo: {
305
+ name: "mcp-transport-test",
306
+ version: "1.0.0"
307
+ }
308
+ }
309
+ };
310
+ // Prepare headers as required by MCP spec
311
+ const headers = {
312
+ "Content-Type": "application/json",
313
+ "Accept": "application/json, text/event-stream" // Required by spec
314
+ };
315
+ // Add authentication headers if available
316
+ if (config.streamableHTTPOptions?.authProvider) {
317
+ try {
318
+ const tokens = await config.streamableHTTPOptions.authProvider.tokens();
319
+ if (tokens?.access_token) {
320
+ headers["Authorization"] = `${tokens.token_type || "Bearer"} ${tokens.access_token}`;
321
+ logger.debug(`MCP server "${serverName}": added authentication to transport test`);
322
+ }
323
+ }
324
+ catch (authError) {
325
+ logger.debug(`MCP server "${serverName}": authentication setup failed for transport test:`, authError);
326
+ }
327
+ }
328
+ // Merge custom headers from config
329
+ if (config.streamableHTTPOptions?.requestInit?.headers) {
330
+ Object.assign(headers, config.streamableHTTPOptions.requestInit.headers);
331
+ }
332
+ if (config.sseOptions?.requestInit?.headers) {
333
+ Object.assign(headers, config.sseOptions.requestInit.headers);
334
+ }
335
+ try {
336
+ logger.debug(`MCP server "${serverName}": POST InitializeRequest to test Streamable HTTP support`);
337
+ // POST InitializeRequest directly to test Streamable HTTP support
338
+ const response = await fetch(url.toString(), {
339
+ method: "POST",
340
+ headers,
341
+ body: JSON.stringify(initRequest),
342
+ ...config.streamableHTTPOptions?.requestInit
343
+ });
344
+ logger.debug(`MCP server "${serverName}": transport test response: ${response.status} ${response.statusText}`);
345
+ if (response.ok) {
346
+ // Success indicates Streamable HTTP support
347
+ logger.info(`MCP server "${serverName}": detected Streamable HTTP transport support`);
348
+ return "streamable_http";
349
+ }
350
+ else if (response.status >= 400 && response.status < 500) {
351
+ // 4xx error indicates fallback to SSE per MCP spec
352
+ logger.info(`MCP server "${serverName}": received ${response.status}, falling back to SSE transport`);
353
+ return "sse";
354
+ }
355
+ else {
356
+ // Other errors should be re-thrown
357
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
358
+ }
359
+ }
360
+ catch (error) {
361
+ // Network errors or other issues
362
+ logger.debug(`MCP server "${serverName}": transport test failed:`, error);
363
+ // Check if it's a 4xx-like error
364
+ if (is4xxError(error)) {
365
+ logger.info(`MCP server "${serverName}": transport test failed with 4xx-like error, falling back to SSE`);
366
+ return "sse";
367
+ }
368
+ // Re-throw other errors (network issues, etc.)
369
+ throw error;
370
+ }
371
+ }
274
372
  /**
275
373
  * Creates an HTTP transport with automatic fallback from Streamable HTTP to SSE.
276
- * Follows the MCP specification recommendation to try Streamable HTTP first,
374
+ * Follows the MCP specification recommendation to test with direct POST InitializeRequest first,
277
375
  * then fall back to SSE if a 4xx error is encountered.
278
376
  *
279
377
  * See: https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility
@@ -288,32 +386,33 @@ function is4xxError(error) {
288
386
  */
289
387
  async function createHttpTransportWithFallback(url, config, logger, serverName) {
290
388
  // If transport is explicitly specified, respect user's choice
291
- if (config.transport === "streamable_http") {
389
+ if (config.transport === "streamable_http" || config.transport === "http" ||
390
+ config.type === "streamable_http" || config.type === "http") {
292
391
  logger.debug(`MCP server "${serverName}": using explicitly configured Streamable HTTP transport`);
293
392
  const options = createStreamableHttpOptions(config, logger, serverName);
294
393
  return new StreamableHTTPClientTransport(url, options);
295
394
  }
296
- if (config.transport === "sse") {
395
+ if (config.transport === "sse" || config.type === "sse") {
297
396
  logger.debug(`MCP server "${serverName}": using explicitly configured SSE transport`);
298
397
  const options = createSseOptions(config, logger, serverName);
299
398
  return new SSEClientTransport(url, options);
300
399
  }
301
- // Auto-detection: try Streamable HTTP first, fall back to SSE on 4xx errors
302
- logger.debug(`MCP server "${serverName}": attempting Streamable HTTP transport with SSE fallback`);
400
+ // Auto-detection: test with POST InitializeRequest per MCP specification
401
+ logger.debug(`MCP server "${serverName}": auto-detecting transport using MCP specification method`);
303
402
  try {
304
- const options = createStreamableHttpOptions(config, logger, serverName);
305
- const transport = new StreamableHTTPClientTransport(url, options);
306
- logger.info(`MCP server "${serverName}": successfully created Streamable HTTP transport`);
307
- return transport;
308
- }
309
- catch (error) {
310
- if (is4xxError(error)) {
311
- logger.info(`MCP server "${serverName}": Streamable HTTP failed with 4xx error, falling back to SSE transport`);
403
+ const detectedTransport = await testTransportSupport(url, config, logger, serverName);
404
+ if (detectedTransport === "streamable_http") {
405
+ const options = createStreamableHttpOptions(config, logger, serverName);
406
+ return new StreamableHTTPClientTransport(url, options);
407
+ }
408
+ else {
312
409
  const options = createSseOptions(config, logger, serverName);
313
410
  return new SSEClientTransport(url, options);
314
411
  }
315
- // Re-throw non-4xx errors (network issues, etc.)
316
- logger.error(`MCP server "${serverName}": Streamable HTTP transport creation failed with non-4xx error:`, error);
412
+ }
413
+ catch (error) {
414
+ // If transport detection fails completely, log error and re-throw
415
+ logger.error(`MCP server "${serverName}": transport detection failed:`, error);
317
416
  throw error;
318
417
  }
319
418
  }
@@ -391,68 +490,14 @@ async function convertSingleMcpToLangchainTools(serverName, config, logger) {
391
490
  const urlConfig = config;
392
491
  // Try to connect with Streamable HTTP first, fallback to SSE on 4xx errors
393
492
  let connectionSucceeded = false;
394
- // If transport is explicitly specified, respect user's choice (no fallback)
395
- if (urlConfig.transport === "streamable_http" || urlConfig.transport === "sse") {
396
- transport = await createHttpTransportWithFallback(url, urlConfig, logger, serverName);
397
- }
398
- else {
399
- // Auto-detection with connection-level fallback
400
- logger.debug(`MCP server "${serverName}": attempting Streamable HTTP transport with SSE fallback`);
401
- try {
402
- // First attempt: Streamable HTTP
403
- const options = createStreamableHttpOptions(urlConfig, logger, serverName);
404
- transport = new StreamableHTTPClientTransport(url, options);
405
- logger.info(`MCP server "${serverName}": created Streamable HTTP transport, attempting connection`);
406
- // Try to connect with Streamable HTTP
407
- client = new Client({
408
- name: "mcp-client",
409
- version: "0.0.1",
410
- }, {
411
- capabilities: {},
412
- });
413
- await client.connect(transport);
414
- connectionSucceeded = true;
415
- logger.info(`MCP server "${serverName}": successfully connected using Streamable HTTP`);
416
- }
417
- catch (error) {
418
- if (is4xxError(error)) {
419
- logger.info(`MCP server "${serverName}": Streamable HTTP failed with 4xx error, falling back to SSE transport`);
420
- // Cleanup failed transport and client
421
- if (transport) {
422
- try {
423
- await transport.close();
424
- }
425
- catch (cleanupError) {
426
- logger.debug(`MCP server "${serverName}": cleanup error during fallback:`, cleanupError);
427
- }
428
- }
429
- // Fallback to SSE
430
- const options = createSseOptions(urlConfig, logger, serverName);
431
- transport = new SSEClientTransport(url, options);
432
- logger.info(`MCP server "${serverName}": created SSE transport, attempting fallback connection`);
433
- // Create new client for SSE connection
434
- client = new Client({
435
- name: "mcp-client",
436
- version: "0.0.1",
437
- }, {
438
- capabilities: {},
439
- });
440
- await client.connect(transport);
441
- connectionSucceeded = true;
442
- logger.info(`MCP server "${serverName}": successfully connected using SSE fallback`);
443
- }
444
- else {
445
- // Re-throw non-4xx errors (network issues, etc.)
446
- logger.error(`MCP server "${serverName}": Streamable HTTP transport failed with non-4xx error:`, error);
447
- throw error;
448
- }
449
- }
450
- }
493
+ // Use the updated transport detection with MCP spec compliance
494
+ transport = await createHttpTransportWithFallback(url, urlConfig, logger, serverName);
495
+ logger.info(`MCP server "${serverName}": created transport, attempting connection`);
451
496
  }
452
497
  else if (url?.protocol === "ws:" || url?.protocol === "wss:") {
453
498
  transport = new WebSocketClientTransport(url);
454
499
  }
455
- else {
500
+ else if (!(config?.transport) || config?.transport === "stdio" || config?.type === "stdio") {
456
501
  // NOTE: Some servers (e.g. Brave) seem to require PATH to be set.
457
502
  // To avoid confusion, it was decided to automatically append it to the env
458
503
  // if not explicitly set by the config.
@@ -469,6 +514,9 @@ async function convertSingleMcpToLangchainTools(serverName, config, logger) {
469
514
  cwd: stdioServerConfig.cwd
470
515
  });
471
516
  }
517
+ else {
518
+ throw new McpInitializationError(serverName, `Failed to initialize MCP server: ${serverName}: unknown transport type: ${config?.transport}`);
519
+ }
472
520
  // Only create client if not already created during auto-detection fallback
473
521
  if (!client) {
474
522
  client = new Client({
package/dist/logger.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- type LogLevelString = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
1
+ type LogLevelString = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
2
2
  declare enum LogLevel {
3
3
  TRACE = 0,
4
4
  DEBUG = 1,
package/dist/logger.js CHANGED
@@ -9,12 +9,12 @@ var LogLevel;
9
9
  LogLevel[LogLevel["FATAL"] = 5] = "FATAL";
10
10
  })(LogLevel || (LogLevel = {}));
11
11
  const LOG_COLORS = {
12
- [LogLevel.TRACE]: '\x1b[90m', // Gray
13
- [LogLevel.DEBUG]: '\x1b[90m', // Gray
14
- [LogLevel.INFO]: '\x1b[90m', // Gray
15
- [LogLevel.WARN]: '\x1b[1;93m', // Bold bright yellow
16
- [LogLevel.ERROR]: '\x1b[1;91m', // Bold bright red
17
- [LogLevel.FATAL]: '\x1b[1;101m', // Red background, Bold text
12
+ [LogLevel.TRACE]: "\x1b[90m", // Gray
13
+ [LogLevel.DEBUG]: "\x1b[90m", // Gray
14
+ [LogLevel.INFO]: "\x1b[90m", // Gray
15
+ [LogLevel.WARN]: "\x1b[1;93m", // Bold bright yellow
16
+ [LogLevel.ERROR]: "\x1b[1;91m", // Bold bright red
17
+ [LogLevel.FATAL]: "\x1b[1;101m", // Red background, Bold text
18
18
  };
19
19
  const LOG_LEVEL_MAP = {
20
20
  trace: LogLevel.TRACE,
@@ -26,12 +26,12 @@ const LOG_LEVEL_MAP = {
26
26
  };
27
27
  class Logger {
28
28
  level;
29
- static RESET = '\x1b[0m';
29
+ static RESET = "\x1b[0m";
30
30
  constructor({ level = LogLevel.INFO } = {}) {
31
31
  this.level = this.parseLogLevel(level);
32
32
  }
33
33
  parseLogLevel(level) {
34
- if (typeof level === 'number')
34
+ if (typeof level === "number")
35
35
  return level;
36
36
  return LOG_LEVEL_MAP[level.toLowerCase()];
37
37
  }
@@ -44,10 +44,10 @@ class Logger {
44
44
  }
45
45
  formatValue(value) {
46
46
  if (value === null)
47
- return 'null';
47
+ return "null";
48
48
  if (value === undefined)
49
- return 'undefined';
50
- return typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value);
49
+ return "undefined";
50
+ return typeof value === "object" ? JSON.stringify(value, null, 2) : String(value);
51
51
  }
52
52
  trace(...args) { this.log(LogLevel.TRACE, ...args); }
53
53
  debug(...args) { this.log(LogLevel.DEBUG, ...args); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h1deya/langchain-mcp-tools",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "MCP To LangChain Tools Conversion Utility",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -36,30 +36,24 @@
36
36
  "watch": "tsc --watch",
37
37
  "lint": "eslint src",
38
38
  "clean": "git clean -fdxn -e .env && read -p 'OK?' && git clean -fdx -e .env",
39
-
40
39
  "_comment_test": "# Testing scripts",
41
40
  "test": "vitest run",
42
41
  "test:watch": "vitest",
43
42
  "test:coverage": "vitest run --coverage",
44
-
45
43
  "_comment_examples": "# Basic usage examples",
46
44
  "example:simple": "tsx testfiles/simple-usage.ts",
47
-
48
45
  "_comment_streamable": "# Streamable HTTP transport tests",
49
46
  "test:streamable:auth:server": "tsx testfiles/streamable-http-auth-test-server.ts",
50
47
  "test:streamable:auth:client": "tsx testfiles/streamable-http-auth-test-client.ts",
51
48
  "test:streamable:stateless:server": "tsx testfiles/streamable-http-stateless-test-server.ts",
52
49
  "test:streamable:stateless:client": "tsx testfiles/streamable-http-stateless-test-client.ts",
53
50
  "test:streamable:auto-detection": "tsx testfiles/streamable-http-auto-detection-test.ts",
54
-
55
51
  "_comment_sse": "# SSE transport tests (with authentication)",
56
52
  "test:sse:server": "tsx testfiles/sse-auth-test-server.ts",
57
53
  "test:sse:client": "tsx testfiles/sse-auth-test-client.ts",
58
-
59
54
  "_comment_docs": "# Documentation scripts",
60
55
  "docs:build": "npx typedoc --options typedoc.json",
61
56
  "docs:deploy": "npm run docs:build && ghp-import -n -p -f docs",
62
-
63
57
  "_comment_publish": "# Publishing scripts",
64
58
  "publish:test": "npm run clean && npm install && npm publish --access=public --dry-run",
65
59
  "publish:do": "npm run clean && npm install && npm publish --access=public"
@@ -77,6 +71,7 @@
77
71
  "@langchain/langgraph": "^0.2.36",
78
72
  "@langchain/openai": "^0.3.16",
79
73
  "@types/node": "^22.10.5",
74
+ "@types/ws": "^8.18.1",
80
75
  "@typescript-eslint/eslint-plugin": "^8.19.0",
81
76
  "@typescript-eslint/parser": "^8.19.0",
82
77
  "@vitest/coverage-v8": "^3.0.9",