@juspay/neurolink 13.8.17 → 13.8.18

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.
Files changed (192) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +1 -1
  3. package/dist/action/actionExecutor.d.ts +33 -3
  4. package/dist/action/actionExecutor.js +71 -15
  5. package/dist/action/actionInputs.js +4 -1
  6. package/dist/action/cliVersion.d.ts +25 -0
  7. package/dist/action/cliVersion.js +26 -0
  8. package/dist/action/index.d.ts +2 -1
  9. package/dist/action/index.js +2 -1
  10. package/dist/adapters/video/directorPipeline.js +46 -36
  11. package/dist/adapters/video/ffmpegAdapter.d.ts +17 -0
  12. package/dist/adapters/video/ffmpegAdapter.js +32 -5
  13. package/dist/adapters/video/frameExtractor.js +1 -1
  14. package/dist/adapters/video/videoMerger.js +5 -2
  15. package/dist/agent/arithmeticEvaluator.d.ts +32 -0
  16. package/dist/agent/arithmeticEvaluator.js +349 -0
  17. package/dist/agent/directTools.d.ts +6 -18
  18. package/dist/agent/directTools.js +17 -56
  19. package/dist/artifacts/artifactStore.d.ts +22 -1
  20. package/dist/artifacts/artifactStore.js +66 -6
  21. package/dist/auth/anthropicOAuth.d.ts +26 -1
  22. package/dist/auth/anthropicOAuth.js +81 -5
  23. package/dist/auth/secureFiles.d.ts +37 -0
  24. package/dist/auth/secureFiles.js +95 -0
  25. package/dist/auth/tokenStore.d.ts +43 -6
  26. package/dist/auth/tokenStore.js +260 -79
  27. package/dist/avatar/providers/DIDAvatar.js +49 -45
  28. package/dist/avatar/providers/ReplicateAvatar.js +33 -40
  29. package/dist/browser/neurolink.min.js +485 -558
  30. package/dist/cli/commands/auth.js +112 -70
  31. package/dist/cli/commands/proxy.d.ts +4 -0
  32. package/dist/cli/commands/proxy.js +128 -13
  33. package/dist/cli/commands/serve.d.ts +10 -1
  34. package/dist/cli/commands/serve.js +98 -17
  35. package/dist/cli/commands/server.js +17 -5
  36. package/dist/cli/index.js +146 -5
  37. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  38. package/dist/cli/utils/envManager.js +17 -3
  39. package/dist/cli/utils/serverUtils.d.ts +39 -3
  40. package/dist/cli/utils/serverUtils.js +63 -6
  41. package/dist/core/baseProvider.js +7 -1
  42. package/dist/core/modules/MessageBuilder.js +5 -0
  43. package/dist/core/modules/ToolsManager.d.ts +46 -1
  44. package/dist/core/modules/ToolsManager.js +190 -43
  45. package/dist/files/fileReferenceRegistry.d.ts +2 -23
  46. package/dist/files/fileReferenceRegistry.js +55 -5
  47. package/dist/hitl/hitlManager.js +1 -0
  48. package/dist/index.d.ts +2 -1
  49. package/dist/index.js +6 -1
  50. package/dist/mcp/auth/tokenStorage.d.ts +7 -0
  51. package/dist/mcp/auth/tokenStorage.js +23 -4
  52. package/dist/mcp/externalServerManager.d.ts +13 -3
  53. package/dist/mcp/externalServerManager.js +154 -136
  54. package/dist/mcp/index.d.ts +2 -0
  55. package/dist/mcp/index.js +3 -0
  56. package/dist/mcp/mcpClientFactory.d.ts +14 -0
  57. package/dist/mcp/mcpClientFactory.js +70 -7
  58. package/dist/mcp/projectConfigTrust.d.ts +72 -0
  59. package/dist/mcp/projectConfigTrust.js +237 -0
  60. package/dist/mcp/transportUrlPolicy.d.ts +39 -0
  61. package/dist/mcp/transportUrlPolicy.js +172 -0
  62. package/dist/music/providers/BeatovenMusic.js +35 -46
  63. package/dist/music/providers/ReplicateMusic.js +33 -40
  64. package/dist/neurolink.d.ts +16 -1
  65. package/dist/neurolink.js +64 -11
  66. package/dist/processors/archive/ArchiveProcessor.js +15 -1
  67. package/dist/processors/archive/zipEntryIndex.d.ts +22 -0
  68. package/dist/processors/archive/zipEntryIndex.js +33 -0
  69. package/dist/processors/base/BaseFileProcessor.d.ts +9 -21
  70. package/dist/processors/base/BaseFileProcessor.js +40 -111
  71. package/dist/processors/data/YamlProcessor.d.ts +13 -1
  72. package/dist/processors/data/YamlProcessor.js +93 -2
  73. package/dist/processors/document/OpenDocumentProcessor.js +7 -2
  74. package/dist/processors/document/PptxProcessor.js +12 -7
  75. package/dist/processors/media/VideoProcessor.js +93 -15
  76. package/dist/proxy/inboundAuth.d.ts +89 -0
  77. package/dist/proxy/inboundAuth.js +219 -0
  78. package/dist/proxy/tokenRefresh.d.ts +6 -0
  79. package/dist/proxy/tokenRefresh.js +13 -1
  80. package/dist/proxy/updateState.js +4 -4
  81. package/dist/rag/document/loaders.d.ts +0 -6
  82. package/dist/rag/document/loaders.js +16 -10
  83. package/dist/rag/ragIntegration.d.ts +2 -2
  84. package/dist/rag/ragIntegration.js +35 -10
  85. package/dist/rag/retrieval/vectorQueryTool.d.ts +7 -0
  86. package/dist/rag/retrieval/vectorQueryTool.js +54 -17
  87. package/dist/server/abstract/baseServerAdapter.d.ts +43 -0
  88. package/dist/server/abstract/baseServerAdapter.js +119 -6
  89. package/dist/server/adapters/expressAdapter.d.ts +3 -0
  90. package/dist/server/adapters/expressAdapter.js +78 -6
  91. package/dist/server/adapters/fastifyAdapter.d.ts +3 -0
  92. package/dist/server/adapters/fastifyAdapter.js +165 -70
  93. package/dist/server/adapters/honoAdapter.d.ts +9 -1
  94. package/dist/server/adapters/honoAdapter.js +99 -21
  95. package/dist/server/adapters/koaAdapter.d.ts +1 -0
  96. package/dist/server/adapters/koaAdapter.js +153 -74
  97. package/dist/server/index.d.ts +2 -0
  98. package/dist/server/index.js +4 -0
  99. package/dist/server/middleware/auth.js +6 -2
  100. package/dist/server/middleware/cache.js +6 -1
  101. package/dist/server/middleware/rateLimit.js +29 -4
  102. package/dist/server/routes/agentRoutes.js +24 -11
  103. package/dist/server/routes/claudeProxyRoutes.d.ts +1 -0
  104. package/dist/server/routes/claudeProxyRoutes.js +273 -84
  105. package/dist/server/routes/codexProxyRoutes.d.ts +2 -2
  106. package/dist/server/routes/codexProxyRoutes.js +125 -40
  107. package/dist/server/routes/index.d.ts +4 -0
  108. package/dist/server/routes/index.js +35 -4
  109. package/dist/server/routes/mcpRoutes.d.ts +6 -2
  110. package/dist/server/routes/mcpRoutes.js +21 -7
  111. package/dist/server/routes/memoryRoutes.js +7 -6
  112. package/dist/server/routes/toolRoutes.d.ts +12 -2
  113. package/dist/server/routes/toolRoutes.js +33 -3
  114. package/dist/server/routes/transcribeRoutes.js +60 -13
  115. package/dist/server/utils/clientAddress.d.ts +23 -0
  116. package/dist/server/utils/clientAddress.js +65 -0
  117. package/dist/server/utils/clientError.d.ts +35 -0
  118. package/dist/server/utils/clientError.js +129 -0
  119. package/dist/server/utils/pathMatch.d.ts +21 -0
  120. package/dist/server/utils/pathMatch.js +41 -0
  121. package/dist/server/utils/validation.d.ts +9 -0
  122. package/dist/server/utils/validation.js +9 -0
  123. package/dist/server/websocket/WebSocketHandler.js +22 -3
  124. package/dist/server/websocket/frameQueue.d.ts +19 -0
  125. package/dist/server/websocket/frameQueue.js +41 -3
  126. package/dist/server/websocket/transcribeWebSocket.d.ts +8 -1
  127. package/dist/server/websocket/transcribeWebSocket.js +223 -34
  128. package/dist/skills/skillStores.js +5 -0
  129. package/dist/tasks/store/fileTaskStore.d.ts +2 -0
  130. package/dist/tasks/store/fileTaskStore.js +11 -4
  131. package/dist/types/attachments.d.ts +117 -0
  132. package/dist/types/attachments.js +15 -0
  133. package/dist/types/auth.d.ts +6 -0
  134. package/dist/types/cli.d.ts +4 -0
  135. package/dist/types/config.d.ts +56 -0
  136. package/dist/types/file.d.ts +8 -0
  137. package/dist/types/hitl.d.ts +8 -0
  138. package/dist/types/index.d.ts +1 -0
  139. package/dist/types/index.js +1 -0
  140. package/dist/types/mcp.d.ts +98 -0
  141. package/dist/types/multimodal.js +0 -41
  142. package/dist/types/processor.d.ts +14 -1
  143. package/dist/types/proxy.d.ts +62 -3
  144. package/dist/types/rag.d.ts +9 -0
  145. package/dist/types/safeFetch.d.ts +40 -0
  146. package/dist/types/server.d.ts +206 -10
  147. package/dist/types/tools.d.ts +57 -0
  148. package/dist/types/transcribe.d.ts +6 -0
  149. package/dist/utils/attachmentPolicy.d.ts +89 -0
  150. package/dist/utils/attachmentPolicy.js +327 -0
  151. package/dist/utils/dotenvBootstrap.d.ts +48 -19
  152. package/dist/utils/dotenvBootstrap.js +172 -31
  153. package/dist/utils/fileDetector.js +115 -65
  154. package/dist/utils/json/coerce.js +11 -1
  155. package/dist/utils/logSanitize.d.ts +5 -0
  156. package/dist/utils/logSanitize.js +8 -0
  157. package/dist/utils/logger.js +73 -1
  158. package/dist/utils/messageBuilder.d.ts +2 -2
  159. package/dist/utils/messageBuilder.js +118 -105
  160. package/dist/utils/multimodalOptionsBuilder.d.ts +1 -0
  161. package/dist/utils/multimodalOptionsBuilder.js +2 -0
  162. package/dist/utils/redis.d.ts +12 -0
  163. package/dist/utils/redis.js +72 -0
  164. package/dist/utils/safeFetch.d.ts +22 -1
  165. package/dist/utils/safeFetch.js +132 -38
  166. package/dist/utils/safeStoreId.d.ts +19 -0
  167. package/dist/utils/safeStoreId.js +29 -0
  168. package/dist/utils/schemaConversion.d.ts +30 -3
  169. package/dist/utils/schemaConversion.js +457 -84
  170. package/dist/utils/sizeGuard.js +2 -2
  171. package/dist/utils/ssrfGuard.d.ts +3 -3
  172. package/dist/utils/ssrfGuard.js +71 -39
  173. package/dist/voice/eval/sttEvalStore.d.ts +26 -3
  174. package/dist/voice/eval/sttEvalStore.js +77 -12
  175. package/dist/voice/livekit/agentDefinition.d.ts +18 -0
  176. package/dist/voice/livekit/agentDefinition.js +22 -0
  177. package/dist/voice/livekit/realtimeMcpTools.d.ts +1 -1
  178. package/dist/voice/livekit/realtimeMcpTools.js +8 -7
  179. package/dist/voice/livekit/realtimeVoiceAgent.d.ts +2 -4
  180. package/dist/voice/livekit/realtimeVoiceAgent.js +18 -7
  181. package/dist/voice/livekit/voiceAgent.d.ts +2 -2
  182. package/dist/voice/livekit/voiceAgent.js +2 -1
  183. package/dist/voice/livekit/xaiSessionWatch.d.ts +0 -5
  184. package/dist/voice/livekit/xaiSessionWatch.js +30 -0
  185. package/dist/voice/providers/GeminiLive.js +21 -6
  186. package/dist/voice/providers/GoogleSTT.js +8 -5
  187. package/dist/voice/transcribe.d.ts +2 -2
  188. package/dist/voice/transcribe.js +34 -18
  189. package/dist/voice/whistle/audio.js +11 -5
  190. package/docs-site/static/search-index.json +71 -49
  191. package/package.json +171 -156
  192. package/scripts/observability/import-openobserve-dashboard.mjs +11 -3
package/dist/index.d.ts CHANGED
@@ -237,7 +237,8 @@ export declare function createBestAIProvider(requestedProvider?: string, modelNa
237
237
  * await writeFile('output.txt', 'Hello from MCP!');
238
238
  * ```
239
239
  */
240
- export { CircuitBreakerManager, calculateExpiresAt, createMCPServer, createOAuthProviderFromConfig, DEFAULT_HTTP_RETRY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, executeMCP, FileTokenStorage, getMCPStats, getServerInfo, globalCircuitBreakerManager, globalRateLimiterManager, HTTPRateLimiter, InMemoryTokenStorage, initializeMCPEcosystem, isRetryableHTTPError, isRetryableStatusCode, isTokenExpired, listMCPs, CircuitBreakerOpenError, MCPCircuitBreaker, mcpLogger, NeuroLinkOAuthProvider, RateLimiterManager, validateServerTools, validateTool as validateMCPTool, withHTTPRetry, MCPToolRegistry, ExternalServerManager, MCPClientFactory, ToolRouter, createToolRouter, DEFAULT_ROUTER_CONFIG, ToolCache, createToolCache, DEFAULT_CACHE_CONFIG, ToolResultCache, createToolResultCache, RequestBatcher, ToolCallBatcher, createRequestBatcher, createToolCallBatcher, DEFAULT_BATCH_CONFIG, inferAnnotations, createAnnotatedTool, validateAnnotations, filterToolsByAnnotations, mergeAnnotations, getAnnotationSummary, requiresConfirmation, isSafeToRetry, getToolSafetyLevel, ElicitationManager, globalElicitationManager, EnhancedToolDiscovery, MCPRegistryClient, globalMCPRegistryClient, getWellKnownServer, getAllWellKnownServers, MCPServerBase, MultiServerManager, globalMultiServerManager, AgentExposureManager, exposeAgentAsTool, exposeAgentsAsTools, exposeWorkflowAsTool, exposeWorkflowsAsTools, globalAgentExposureManager, ServerCapabilitiesManager, createTextResource, createJsonResource, createPrompt, neuroLinkToolToMCP, mcpToolToNeuroLink, batchConvertToMCP, batchConvertToNeuroLink, sanitizeToolName, validateToolName, createToolFromFunction, mcpProtocolToolToServerTool, serverToolToMCPProtocol, TOOL_COMPATIBILITY, ToolIntegrationManager, globalToolIntegrationManager, wrapToolWithElicitation, wrapToolsWithElicitation, createElicitationContext, confirmationMiddleware, validationMiddleware, loggingMiddleware, createRetryMiddleware, createTimeoutMiddleware, createToolMiddlewareChain, ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest, } from "./mcp/index.js";
240
+ export { CircuitBreakerManager, calculateExpiresAt, createMCPServer, createOAuthProviderFromConfig, DEFAULT_HTTP_RETRY_CONFIG, DEFAULT_RATE_LIMIT_CONFIG, executeMCP, FileTokenStorage, getMCPStats, getServerInfo, globalCircuitBreakerManager, globalRateLimiterManager, HTTPRateLimiter, InMemoryTokenStorage, initializeMCPEcosystem, isRetryableHTTPError, isRetryableStatusCode, isTokenExpired, listMCPs, CircuitBreakerOpenError, MCPCircuitBreaker, mcpLogger, NeuroLinkOAuthProvider, RateLimiterManager, validateServerTools, validateTool as validateMCPTool, withHTTPRetry, MCPToolRegistry, ExternalServerManager, MCPClientFactory, ToolRouter, createToolRouter, DEFAULT_ROUTER_CONFIG, ToolCache, createToolCache, DEFAULT_CACHE_CONFIG, ToolResultCache, createToolResultCache, RequestBatcher, ToolCallBatcher, createRequestBatcher, createToolCallBatcher, DEFAULT_BATCH_CONFIG, inferAnnotations, createAnnotatedTool, validateAnnotations, filterToolsByAnnotations, mergeAnnotations, getAnnotationSummary, requiresConfirmation, isSafeToRetry, getToolSafetyLevel, ElicitationManager, globalElicitationManager, EnhancedToolDiscovery, MCPRegistryClient, globalMCPRegistryClient, getWellKnownServer, getAllWellKnownServers, MCPServerBase, MultiServerManager, globalMultiServerManager, AgentExposureManager, exposeAgentAsTool, exposeAgentsAsTools, exposeWorkflowAsTool, exposeWorkflowsAsTools, globalAgentExposureManager, ServerCapabilitiesManager, createTextResource, createJsonResource, createPrompt, neuroLinkToolToMCP, mcpToolToNeuroLink, batchConvertToMCP, batchConvertToNeuroLink, sanitizeToolName, validateToolName, createToolFromFunction, mcpProtocolToolToServerTool, serverToolToMCPProtocol, TOOL_COMPATIBILITY, ToolIntegrationManager, globalToolIntegrationManager, wrapToolWithElicitation, wrapToolsWithElicitation, createElicitationContext, confirmationMiddleware, validationMiddleware, loggingMiddleware, createRetryMiddleware, createTimeoutMiddleware, createToolMiddlewareChain, ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest, assertMcpTransportUrlAllowed, classifyMcpTransportAddress, resolveProjectMcpConfigPath, setProjectMcpConfigTrustHook, getProjectMcpConfigTrustHook, summarizeProjectMcpConfig, formatProjectMcpConfigSummary, getProjectMcpConfigTrustStatus, recordTrustedProjectMcpConfig, readProjectMcpConfigTrustStore, hashProjectMcpConfig, getTrustedMcpConfigStorePath, PROJECT_MCP_CONFIG_FILENAME, TRUST_MCP_CONFIG_ENV, TRUST_MCP_CONFIG_FLAG, TRUSTED_MCP_CONFIGS_FILENAME, } from "./mcp/index.js";
241
+ export { loadDotenv, loadProcessDotenv } from "./utils/dotenvBootstrap.js";
241
242
  export { computeToolSignature, dedupeTools } from "./core/toolDedup.js";
242
243
  export { logger } from "./utils/logger.js";
243
244
  export { getPoolStats } from "./utils/redis.js";
package/dist/index.js CHANGED
@@ -396,7 +396,12 @@ neuroLinkToolToMCP, mcpToolToNeuroLink, batchConvertToMCP, batchConvertToNeuroLi
396
396
  // MCP Enhancements - Tool Integration
397
397
  ToolIntegrationManager, globalToolIntegrationManager, wrapToolWithElicitation, wrapToolsWithElicitation, createElicitationContext, confirmationMiddleware, validationMiddleware, loggingMiddleware, createRetryMiddleware, createTimeoutMiddleware, createToolMiddlewareChain,
398
398
  // MCP Enhancements - Elicitation Protocol
399
- ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest, } from "./mcp/index.js";
399
+ ElicitationProtocolAdapter, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, elicitationResponseToProtocol, createElicitationRequest, createElicitationResponse, createElicitationCancel, createTextInputRequest, createSelectRequest, createConfirmationRequest, createFormRequest,
400
+ // Project MCP config trust + transport URL policy (2026-10 security audit)
401
+ assertMcpTransportUrlAllowed, classifyMcpTransportAddress, resolveProjectMcpConfigPath, setProjectMcpConfigTrustHook, getProjectMcpConfigTrustHook, summarizeProjectMcpConfig, formatProjectMcpConfigSummary, getProjectMcpConfigTrustStatus, recordTrustedProjectMcpConfig, readProjectMcpConfigTrustStore, hashProjectMcpConfig, getTrustedMcpConfigStorePath, PROJECT_MCP_CONFIG_FILENAME, TRUST_MCP_CONFIG_ENV, TRUST_MCP_CONFIG_FLAG, TRUSTED_MCP_CONFIGS_FILENAME, } from "./mcp/index.js";
402
+ // Explicit `.env` loading for SDK hosts. Importing the SDK no longer reads
403
+ // `<cwd>/.env` (2026-10 security hardening); call `loadDotenv()` to opt in.
404
+ export { loadDotenv, loadProcessDotenv } from "./utils/dotenvBootstrap.js";
400
405
  // Tool signature deduplication utilities (opt-in, fail-open)
401
406
  export { computeToolSignature, dedupeTools } from "./core/toolDedup.js";
402
407
  export { logger } from "./utils/logger.js";
@@ -34,6 +34,13 @@ export declare class FileTokenStorage implements TokenStorage {
34
34
  private loaded;
35
35
  constructor(filePath: string);
36
36
  private loadTokens;
37
+ /**
38
+ * Persist the token map. These are bearer credentials, so the directory is
39
+ * created `0700` and the file lands `0600`: written to a uniquely named
40
+ * temporary file opened with `wx` (a pre-planted file or symlink at that
41
+ * name fails instead of being followed), then renamed into place so a
42
+ * reader never sees a torn file.
43
+ */
37
44
  private saveToFile;
38
45
  getTokens(serverId: string): Promise<OAuthTokens | null>;
39
46
  saveTokens(serverId: string, tokens: OAuthTokens): Promise<void>;
@@ -71,16 +71,35 @@ export class FileTokenStorage {
71
71
  this.loaded = true;
72
72
  }
73
73
  }
74
+ /**
75
+ * Persist the token map. These are bearer credentials, so the directory is
76
+ * created `0700` and the file lands `0600`: written to a uniquely named
77
+ * temporary file opened with `wx` (a pre-planted file or symlink at that
78
+ * name fails instead of being followed), then renamed into place so a
79
+ * reader never sees a torn file.
80
+ */
74
81
  async saveToFile() {
75
82
  try {
76
83
  const fs = await import("fs/promises");
77
84
  const path = await import("path");
78
- // Ensure directory exists
85
+ const { randomBytes } = await import("crypto");
79
86
  const dir = path.dirname(this.filePath);
80
- await fs.mkdir(dir, { recursive: true });
81
- // Write tokens to file
87
+ await fs.mkdir(dir, { recursive: true, mode: 0o700 });
82
88
  const data = Object.fromEntries(this.tokens.entries());
83
- await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), "utf-8");
89
+ const tmp = `${this.filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
90
+ try {
91
+ await fs.writeFile(tmp, JSON.stringify(data, null, 2), {
92
+ encoding: "utf-8",
93
+ mode: 0o600,
94
+ flag: "wx",
95
+ });
96
+ await fs.rename(tmp, this.filePath);
97
+ await fs.chmod(this.filePath, 0o600);
98
+ }
99
+ catch (writeError) {
100
+ await fs.rm(tmp, { force: true });
101
+ throw writeError;
102
+ }
84
103
  }
85
104
  catch (error) {
86
105
  logger.error(`[FileTokenStorage] Error saving tokens: ${error instanceof Error ? error.message : String(error)}`);
@@ -52,9 +52,19 @@ export declare class ExternalServerManager extends EventEmitter {
52
52
  */
53
53
  getServerName(serverId: string): string;
54
54
  /**
55
- * Load MCP server configurations from .mcp-config.json file with parallel loading support
56
- * Automatically registers servers found in the configuration
57
- * @param configPath Optional path to config file (defaults to .mcp-config.json in cwd)
55
+ * Load MCP server configurations from a `.mcp-config.json`-shaped file and
56
+ * register every server it names.
57
+ *
58
+ * Calling this is an explicit decision to run that file's servers. With no
59
+ * `configPath` it reads `.mcp-config.json` from the working directory, so
60
+ * a host must only omit the path when it controls that directory; the SDK
61
+ * itself never calls this without a path it resolved through
62
+ * `resolveProjectMcpConfigPath` (see `projectConfigTrust.ts`).
63
+ *
64
+ * `${NAME}` references in each server's `env` and `args` are expanded from
65
+ * `process.env`; `headers` and `url` are used as written.
66
+ *
67
+ * @param configPath Path to the config file (defaults to .mcp-config.json in cwd)
58
68
  * @param options Loading options including parallel support
59
69
  * @returns Promise resolving to { serversLoaded, errors }
60
70
  */
@@ -66,36 +66,76 @@ const readMCPTransportFetch = (value) => {
66
66
  }
67
67
  return value;
68
68
  };
69
+ const ENV_REFERENCE_PATTERN = /\$\{([^}]*)\}/g;
70
+ const ENV_REFERENCE_PRESENT = /\$\{[^}]*\}/;
69
71
  /**
70
- * Recursively substitute environment variables in strings
71
- * Replaces ${VAR_NAME} with the value from process.env.VAR_NAME
72
- * @param value - Value to process (string, object, array, or primitive)
73
- * @returns Processed value with environment variables substituted
72
+ * The only shape a `${…}` reference may take. Anything else — lower case,
73
+ * a leading digit, `${}`, `${a.b}`, `${PATH:-x}` — is left as written, so a
74
+ * config cannot probe the environment through odd names.
74
75
  */
75
- function substituteEnvVariables(value) {
76
+ const ENV_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
77
+ /**
78
+ * Recursively substitute `${NAME}` references in `value` from `process.env`.
79
+ *
80
+ * Applies to a server's `env` and `args` only. `headers` and `url` are sent
81
+ * to a remote host, so a reference there would ship the variable's value off
82
+ * the machine; they are passed through unchanged by `warnOnEnvReferences`.
83
+ *
84
+ * @param value - string, array, object or primitive
85
+ * @param field - the config field being processed, for log messages
86
+ */
87
+ function substituteEnvVariables(value, field) {
76
88
  if (typeof value === "string") {
77
- // Replace ${VAR_NAME} with process.env.VAR_NAME
78
- return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
79
- const envValue = process.env[varName.trim()];
89
+ return value.replace(ENV_REFERENCE_PATTERN, (match, rawName) => {
90
+ const varName = rawName.trim();
91
+ if (!ENV_NAME_PATTERN.test(varName)) {
92
+ mcpLogger.warn(`[ExternalServerManager] ${field}: "${match}" is not a valid environment variable reference (names must match ^[A-Z][A-Z0-9_]*$); left as written`);
93
+ return match;
94
+ }
95
+ const envValue = process.env[varName];
80
96
  if (envValue === undefined) {
81
- mcpLogger.warn(`[ExternalServerManager] Environment variable ${varName} is not defined, using empty string`);
97
+ mcpLogger.warn(`[ExternalServerManager] ${field}: environment variable ${varName} is not defined, using empty string`);
82
98
  return "";
83
99
  }
84
100
  return envValue;
85
101
  });
86
102
  }
87
103
  if (Array.isArray(value)) {
88
- return value.map((item) => substituteEnvVariables(item));
104
+ return value.map((item) => substituteEnvVariables(item, field));
89
105
  }
90
106
  if (isNonNullObject(value)) {
91
107
  const result = {};
92
108
  for (const [key, val] of Object.entries(value)) {
93
- result[key] = substituteEnvVariables(val);
109
+ result[key] = substituteEnvVariables(val, field);
94
110
  }
95
111
  return result;
96
112
  }
97
113
  return value;
98
114
  }
115
+ /**
116
+ * Warn about `${NAME}` references in a field that is never expanded. The
117
+ * value is used exactly as written: a header reading `Bearer ${TOKEN}` is
118
+ * sent literally, which fails authentication loudly instead of leaking.
119
+ */
120
+ function warnOnEnvReferences(value, field) {
121
+ if (typeof value === "string") {
122
+ if (ENV_REFERENCE_PRESENT.test(value)) {
123
+ mcpLogger.warn(`[ExternalServerManager] ${field} contains a \${VAR} reference; environment variables are never expanded in ${field} (only in env and args). The value is used as written.`);
124
+ }
125
+ return;
126
+ }
127
+ if (Array.isArray(value)) {
128
+ for (const item of value) {
129
+ warnOnEnvReferences(item, field);
130
+ }
131
+ return;
132
+ }
133
+ if (isNonNullObject(value)) {
134
+ for (const [key, val] of Object.entries(value)) {
135
+ warnOnEnvReferences(val, `${field}.${key}`);
136
+ }
137
+ }
138
+ }
99
139
  /**
100
140
  * The two messages the MCP SDK produces when the transport underneath a
101
141
  * request is gone: `Protocol._onclose` rejects every pending request with
@@ -249,8 +289,91 @@ function isValidExternalMCPServerConfig(config) {
249
289
  (record.retryConfig === undefined || isNonNullObject(record.retryConfig)) &&
250
290
  (record.rateLimiting === undefined ||
251
291
  isNonNullObject(record.rateLimiting)) &&
292
+ (record.inheritParentEnv === undefined ||
293
+ typeof record.inheritParentEnv === "boolean") &&
294
+ (record.allowPrivateNetwork === undefined ||
295
+ typeof record.allowPrivateNetwork === "boolean") &&
252
296
  (record.metadata === undefined || isNonNullObject(record.metadata)));
253
297
  }
298
+ /**
299
+ * Convert one `mcpServers` entry of a project config into an `MCPServerInfo`.
300
+ *
301
+ * Shared by the parallel and sequential loaders so the two cannot drift.
302
+ * `${NAME}` references are expanded in `env` and `args` only; `headers` and
303
+ * `url` are passed through as written (see `warnOnEnvReferences`).
304
+ *
305
+ * @throws when the entry fails `isValidExternalMCPServerConfig`
306
+ */
307
+ function toExternalServerInfo(serverId, serverConfig) {
308
+ if (!isValidExternalMCPServerConfig(serverConfig)) {
309
+ throw new Error(`Invalid server config for ${serverId}: missing required properties or wrong types`);
310
+ }
311
+ if (serverConfig.headers !== undefined) {
312
+ warnOnEnvReferences(serverConfig.headers, `${serverId}.headers`);
313
+ }
314
+ if (serverConfig.url !== undefined) {
315
+ warnOnEnvReferences(serverConfig.url, `${serverId}.url`);
316
+ }
317
+ return {
318
+ id: serverId,
319
+ name: serverId,
320
+ description: typeof serverConfig.description === "string"
321
+ ? serverConfig.description
322
+ : `External MCP server: ${serverId}`,
323
+ transport: typeof serverConfig.transport === "string"
324
+ ? serverConfig.transport
325
+ : "stdio",
326
+ status: "initializing",
327
+ tools: [],
328
+ command: typeof serverConfig.command === "string"
329
+ ? serverConfig.command
330
+ : undefined,
331
+ args: Array.isArray(serverConfig.args)
332
+ ? substituteEnvVariables(serverConfig.args.map((arg) => String(arg)), `${serverId}.args`)
333
+ : [],
334
+ env: isNonNullObject(serverConfig.env)
335
+ ? substituteEnvVariables(serverConfig.env, `${serverId}.env`)
336
+ : {},
337
+ inheritParentEnv: typeof serverConfig.inheritParentEnv === "boolean"
338
+ ? serverConfig.inheritParentEnv
339
+ : undefined,
340
+ allowPrivateNetwork: typeof serverConfig.allowPrivateNetwork === "boolean"
341
+ ? serverConfig.allowPrivateNetwork
342
+ : undefined,
343
+ timeout: typeof serverConfig.timeout === "number"
344
+ ? serverConfig.timeout
345
+ : undefined,
346
+ retries: typeof serverConfig.retries === "number"
347
+ ? serverConfig.retries
348
+ : undefined,
349
+ healthCheckInterval: typeof serverConfig.healthCheckInterval === "number"
350
+ ? serverConfig.healthCheckInterval
351
+ : undefined,
352
+ autoRestart: typeof serverConfig.autoRestart === "boolean"
353
+ ? serverConfig.autoRestart
354
+ : undefined,
355
+ cwd: typeof serverConfig.cwd === "string" ? serverConfig.cwd : undefined,
356
+ url: typeof serverConfig.url === "string" ? serverConfig.url : undefined,
357
+ // HTTP transport-specific fields — never expanded, see above.
358
+ headers: isNonNullObject(serverConfig.headers)
359
+ ? serverConfig.headers
360
+ : undefined,
361
+ fetch: readMCPTransportFetch(serverConfig.fetch),
362
+ httpOptions: isNonNullObject(serverConfig.httpOptions)
363
+ ? serverConfig.httpOptions
364
+ : undefined,
365
+ retryConfig: isNonNullObject(serverConfig.retryConfig)
366
+ ? serverConfig.retryConfig
367
+ : undefined,
368
+ rateLimiting: isNonNullObject(serverConfig.rateLimiting)
369
+ ? serverConfig.rateLimiting
370
+ : undefined,
371
+ blockedTools: Array.isArray(serverConfig.blockedTools)
372
+ ? serverConfig.blockedTools
373
+ : undefined,
374
+ metadata: safeMetadataConversion(serverConfig.metadata),
375
+ };
376
+ }
254
377
  /**
255
378
  * ExternalServerManager
256
379
  * Core class for managing external MCP servers
@@ -489,9 +612,19 @@ export class ExternalServerManager extends EventEmitter {
489
612
  return instance?.config?.name || serverId;
490
613
  }
491
614
  /**
492
- * Load MCP server configurations from .mcp-config.json file with parallel loading support
493
- * Automatically registers servers found in the configuration
494
- * @param configPath Optional path to config file (defaults to .mcp-config.json in cwd)
615
+ * Load MCP server configurations from a `.mcp-config.json`-shaped file and
616
+ * register every server it names.
617
+ *
618
+ * Calling this is an explicit decision to run that file's servers. With no
619
+ * `configPath` it reads `.mcp-config.json` from the working directory, so
620
+ * a host must only omit the path when it controls that directory; the SDK
621
+ * itself never calls this without a path it resolved through
622
+ * `resolveProjectMcpConfigPath` (see `projectConfigTrust.ts`).
623
+ *
624
+ * `${NAME}` references in each server's `env` and `args` are expanded from
625
+ * `process.env`; `headers` and `url` are used as written.
626
+ *
627
+ * @param configPath Path to the config file (defaults to .mcp-config.json in cwd)
495
628
  * @param options Loading options including parallel support
496
629
  * @returns Promise resolving to { serversLoaded, errors }
497
630
  */
@@ -525,67 +658,7 @@ export class ExternalServerManager extends EventEmitter {
525
658
  // Create promises for all servers to start them concurrently
526
659
  const serverPromises = Object.entries(config.mcpServers).map(async ([serverId, serverConfig]) => {
527
660
  try {
528
- // Validate and convert config format to MCPServerInfo
529
- if (!isValidExternalMCPServerConfig(serverConfig)) {
530
- throw new Error(`Invalid server config for ${serverId}: missing required properties or wrong types`);
531
- }
532
- const externalConfig = {
533
- id: serverId,
534
- name: serverId,
535
- description: typeof serverConfig.description === "string"
536
- ? serverConfig.description
537
- : `External MCP server: ${serverId}`,
538
- transport: typeof serverConfig.transport === "string"
539
- ? serverConfig.transport
540
- : "stdio",
541
- status: "initializing",
542
- tools: [],
543
- command: typeof serverConfig.command === "string"
544
- ? serverConfig.command
545
- : undefined,
546
- args: Array.isArray(serverConfig.args)
547
- ? serverConfig.args
548
- : [],
549
- env: isNonNullObject(serverConfig.env)
550
- ? substituteEnvVariables(serverConfig.env)
551
- : {},
552
- timeout: typeof serverConfig.timeout === "number"
553
- ? serverConfig.timeout
554
- : undefined,
555
- retries: typeof serverConfig.retries === "number"
556
- ? serverConfig.retries
557
- : undefined,
558
- healthCheckInterval: typeof serverConfig.healthCheckInterval === "number"
559
- ? serverConfig.healthCheckInterval
560
- : undefined,
561
- autoRestart: typeof serverConfig.autoRestart === "boolean"
562
- ? serverConfig.autoRestart
563
- : undefined,
564
- cwd: typeof serverConfig.cwd === "string"
565
- ? serverConfig.cwd
566
- : undefined,
567
- url: typeof serverConfig.url === "string"
568
- ? serverConfig.url
569
- : undefined,
570
- // HTTP transport-specific fields
571
- headers: isNonNullObject(serverConfig.headers)
572
- ? substituteEnvVariables(serverConfig.headers)
573
- : undefined,
574
- fetch: readMCPTransportFetch(serverConfig.fetch),
575
- httpOptions: isNonNullObject(serverConfig.httpOptions)
576
- ? serverConfig.httpOptions
577
- : undefined,
578
- retryConfig: isNonNullObject(serverConfig.retryConfig)
579
- ? serverConfig.retryConfig
580
- : undefined,
581
- rateLimiting: isNonNullObject(serverConfig.rateLimiting)
582
- ? serverConfig.rateLimiting
583
- : undefined,
584
- blockedTools: Array.isArray(serverConfig.blockedTools)
585
- ? serverConfig.blockedTools
586
- : undefined,
587
- metadata: safeMetadataConversion(serverConfig.metadata),
588
- };
661
+ const externalConfig = toExternalServerInfo(serverId, serverConfig);
589
662
  const result = await this.addServer(serverId, externalConfig);
590
663
  return { serverId, result };
591
664
  }
@@ -664,67 +737,7 @@ export class ExternalServerManager extends EventEmitter {
664
737
  const errors = [];
665
738
  for (const [serverId, serverConfig] of Object.entries(config.mcpServers)) {
666
739
  try {
667
- // Validate and convert config format to MCPServerInfo
668
- if (!isValidExternalMCPServerConfig(serverConfig)) {
669
- throw new Error(`Invalid server config for ${serverId}: missing required properties or wrong types`);
670
- }
671
- const externalConfig = {
672
- id: serverId,
673
- name: serverId,
674
- description: typeof serverConfig.description === "string"
675
- ? serverConfig.description
676
- : `External MCP server: ${serverId}`,
677
- transport: typeof serverConfig.transport === "string"
678
- ? serverConfig.transport
679
- : "stdio",
680
- status: "initializing",
681
- tools: [],
682
- command: typeof serverConfig.command === "string"
683
- ? serverConfig.command
684
- : undefined,
685
- args: Array.isArray(serverConfig.args)
686
- ? serverConfig.args
687
- : [],
688
- env: isNonNullObject(serverConfig.env)
689
- ? substituteEnvVariables(serverConfig.env)
690
- : {},
691
- timeout: typeof serverConfig.timeout === "number"
692
- ? serverConfig.timeout
693
- : undefined,
694
- retries: typeof serverConfig.retries === "number"
695
- ? serverConfig.retries
696
- : undefined,
697
- healthCheckInterval: typeof serverConfig.healthCheckInterval === "number"
698
- ? serverConfig.healthCheckInterval
699
- : undefined,
700
- autoRestart: typeof serverConfig.autoRestart === "boolean"
701
- ? serverConfig.autoRestart
702
- : undefined,
703
- cwd: typeof serverConfig.cwd === "string"
704
- ? serverConfig.cwd
705
- : undefined,
706
- url: typeof serverConfig.url === "string"
707
- ? serverConfig.url
708
- : undefined,
709
- // HTTP transport-specific fields
710
- headers: isNonNullObject(serverConfig.headers)
711
- ? substituteEnvVariables(serverConfig.headers)
712
- : undefined,
713
- fetch: readMCPTransportFetch(serverConfig.fetch),
714
- httpOptions: isNonNullObject(serverConfig.httpOptions)
715
- ? serverConfig.httpOptions
716
- : undefined,
717
- retryConfig: isNonNullObject(serverConfig.retryConfig)
718
- ? serverConfig.retryConfig
719
- : undefined,
720
- rateLimiting: isNonNullObject(serverConfig.rateLimiting)
721
- ? serverConfig.rateLimiting
722
- : undefined,
723
- blockedTools: Array.isArray(serverConfig.blockedTools)
724
- ? serverConfig.blockedTools
725
- : undefined,
726
- metadata: safeMetadataConversion(serverConfig.metadata),
727
- };
740
+ const externalConfig = toExternalServerInfo(serverId, serverConfig);
728
741
  const result = await this.addServer(serverId, externalConfig);
729
742
  if (result.success) {
730
743
  serversLoaded++;
@@ -843,6 +856,8 @@ export class ExternalServerManager extends EventEmitter {
843
856
  autoRestart: config.autoRestart,
844
857
  minTools: config.minTools,
845
858
  cwd: config.cwd,
859
+ inheritParentEnv: config.inheritParentEnv,
860
+ allowPrivateNetwork: config.allowPrivateNetwork,
846
861
  url: config.url,
847
862
  headers: config.headers,
848
863
  fetch: config.fetch,
@@ -892,11 +907,14 @@ export class ExternalServerManager extends EventEmitter {
892
907
  autoRestart: serverInfo.autoRestart,
893
908
  minTools: serverInfo.minTools,
894
909
  cwd: serverInfo.cwd,
910
+ inheritParentEnv: serverInfo.inheritParentEnv,
911
+ allowPrivateNetwork: serverInfo.allowPrivateNetwork,
895
912
  url: serverInfo.url,
896
913
  blockedTools: serverInfo.blockedTools,
897
914
  metadata: safeMetadataConversion(serverInfo.metadata),
898
915
  // HTTP transport-specific fields
899
916
  headers: serverInfo.headers,
917
+ auth: serverInfo.auth,
900
918
  fetch: serverInfo.fetch,
901
919
  httpOptions: serverInfo.httpOptions,
902
920
  retryConfig: serverInfo.retryConfig,
@@ -20,6 +20,8 @@ export { CircuitBreakerManager, globalCircuitBreakerManager, MCPCircuitBreaker,
20
20
  export { MCPToolRegistry } from "./toolRegistry.js";
21
21
  export { ExternalServerManager } from "./externalServerManager.js";
22
22
  export { MCPClientFactory } from "./mcpClientFactory.js";
23
+ export { PROJECT_MCP_CONFIG_FILENAME, TRUST_MCP_CONFIG_ENV, TRUST_MCP_CONFIG_FLAG, TRUSTED_MCP_CONFIGS_FILENAME, formatProjectMcpConfigSummary, getProjectMcpConfigTrustHook, getProjectMcpConfigTrustStatus, getTrustedMcpConfigStorePath, hashProjectMcpConfig, readProjectMcpConfigTrustStore, recordTrustedProjectMcpConfig, resolveProjectMcpConfigPath, setProjectMcpConfigTrustHook, summarizeProjectMcpConfig, } from "./projectConfigTrust.js";
24
+ export { assertMcpTransportUrlAllowed, classifyMcpTransportAddress, } from "./transportUrlPolicy.js";
23
25
  export { AgentExposureManager, exposeAgentAsTool, exposeAgentsAsTools, exposeWorkflowAsTool, exposeWorkflowsAsTools, globalAgentExposureManager, } from "./agentExposure.js";
24
26
  export { ElicitationManager, globalElicitationManager, } from "./elicitation/index.js";
25
27
  export { createConfirmationRequest, createElicitationCancel, createElicitationRequest, createElicitationResponse, createFormRequest, createSelectRequest, createTextInputRequest, ElicitationProtocolAdapter, elicitationResponseToProtocol, globalElicitationProtocol, isElicitationProtocolMessage, protocolMessageToElicitation, } from "./elicitationProtocol.js";
package/dist/mcp/index.js CHANGED
@@ -15,6 +15,9 @@ export { CircuitBreakerManager, globalCircuitBreakerManager, MCPCircuitBreaker,
15
15
  export { MCPToolRegistry } from "./toolRegistry.js";
16
16
  export { ExternalServerManager } from "./externalServerManager.js";
17
17
  export { MCPClientFactory } from "./mcpClientFactory.js";
18
+ // Project `.mcp-config.json` trust and transport URL policy
19
+ export { PROJECT_MCP_CONFIG_FILENAME, TRUST_MCP_CONFIG_ENV, TRUST_MCP_CONFIG_FLAG, TRUSTED_MCP_CONFIGS_FILENAME, formatProjectMcpConfigSummary, getProjectMcpConfigTrustHook, getProjectMcpConfigTrustStatus, getTrustedMcpConfigStorePath, hashProjectMcpConfig, readProjectMcpConfigTrustStore, recordTrustedProjectMcpConfig, resolveProjectMcpConfigPath, setProjectMcpConfigTrustHook, summarizeProjectMcpConfig, } from "./projectConfigTrust.js";
20
+ export { assertMcpTransportUrlAllowed, classifyMcpTransportAddress, } from "./transportUrlPolicy.js";
18
21
  // ========================================
19
22
  // MCP ENHANCEMENTS (Phase 8.39.0)
20
23
  // ========================================
@@ -32,6 +32,12 @@ export declare const terminateLiveStdioServers: () => void;
32
32
  */
33
33
  export declare class MCPClientFactory {
34
34
  private static readonly NEUROLINK_IMPLEMENTATION;
35
+ /**
36
+ * No `sampling` here: advertising it tells a server it may send
37
+ * `sampling/createMessage` and have this client run an LLM call on its
38
+ * behalf, and the client has no handler for it. Only what is implemented
39
+ * is announced.
40
+ */
35
41
  private static readonly DEFAULT_CAPABILITIES;
36
42
  /**
37
43
  * Create an MCP client for the given server configuration
@@ -53,6 +59,14 @@ export declare class MCPClientFactory {
53
59
  * Create transport based on configuration
54
60
  */
55
61
  private static createTransport;
62
+ /**
63
+ * Apply the transport URL policy (`transportUrlPolicy.ts`) before any
64
+ * network transport is built: TLS unless loopback, and no private,
65
+ * link-local or metadata destinations unless the server config says
66
+ * `allowPrivateNetwork: true`. Runs for every network server, whether it
67
+ * came from a project config or from `addExternalMCPServer`.
68
+ */
69
+ private static assertNetworkUrlAllowed;
56
70
  /**
57
71
  * Create a stdio transport.
58
72
  *