@juspay/neurolink 12.49.16 → 12.49.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +385 -385
- package/dist/mcp/externalServerManager.d.ts +6 -0
- package/dist/mcp/externalServerManager.js +212 -35
- package/dist/mcp/mcpClientFactory.js +37 -5
- package/dist/mcp/toolDiscoveryService.d.ts +3 -1
- package/dist/mcp/toolDiscoveryService.js +42 -19
- package/dist/neurolink.d.ts +2 -1
- package/dist/neurolink.js +6 -0
- package/dist/types/externalMcp.d.ts +11 -1
- package/dist/types/mcp.d.ts +9 -3
- package/package.json +6 -2
|
@@ -106,15 +106,21 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Discover tools from an external MCP server
|
|
109
|
+
* Startup probes use the fresh connection directly under the same operation
|
|
110
|
+
* deadline, so an ordinary discovery cooldown cannot exhaust reconnects.
|
|
109
111
|
*/
|
|
110
|
-
async discoverTools(serverId, client, timeout = DEFAULT_TOOL_TIMEOUT) {
|
|
112
|
+
async discoverTools(serverId, client, timeout = DEFAULT_TOOL_TIMEOUT, isCurrentDiscovery = () => true, startupDiscovery = false) {
|
|
111
113
|
return withSpan({
|
|
112
114
|
name: "neurolink.mcp.discoverTools",
|
|
113
115
|
tracer: tracers.mcp,
|
|
114
116
|
attributes: { "mcp.server_id": serverId },
|
|
115
117
|
}, async (span) => {
|
|
116
118
|
const startTime = Date.now();
|
|
119
|
+
let ownsDiscovery = false;
|
|
117
120
|
try {
|
|
121
|
+
if (!isCurrentDiscovery()) {
|
|
122
|
+
throw new Error(`Discovery owner for '${serverId}' is no longer current`);
|
|
123
|
+
}
|
|
118
124
|
// Prevent concurrent discovery for same server
|
|
119
125
|
if (this.discoveryInProgress.has(serverId)) {
|
|
120
126
|
return {
|
|
@@ -127,19 +133,23 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
127
133
|
};
|
|
128
134
|
}
|
|
129
135
|
this.discoveryInProgress.add(serverId);
|
|
136
|
+
ownsDiscovery = true;
|
|
130
137
|
mcpLogger.info(`[ToolDiscoveryService] Starting tool discovery for server: ${serverId}`);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
const discover = () => this.performToolDiscovery(serverId, client, timeout);
|
|
139
|
+
// A new connection must get its bounded readiness probe even while
|
|
140
|
+
// the ordinary discovery breaker is cooling down. Its transport and
|
|
141
|
+
// operation deadlines still apply; real failures still reject startup.
|
|
142
|
+
const tools = startupDiscovery
|
|
143
|
+
? await discover()
|
|
144
|
+
: await globalCircuitBreakerManager
|
|
145
|
+
.getBreaker(`tool-discovery-${serverId}`, {
|
|
146
|
+
failureThreshold: 2,
|
|
147
|
+
resetTimeout: 60000,
|
|
148
|
+
operationTimeout: timeout,
|
|
149
|
+
})
|
|
150
|
+
.execute(discover);
|
|
141
151
|
// Register discovered tools
|
|
142
|
-
const registeredTools = await this.registerDiscoveredTools(serverId, tools);
|
|
152
|
+
const registeredTools = await this.registerDiscoveredTools(serverId, tools, isCurrentDiscovery);
|
|
143
153
|
span.setAttribute("mcp.tools_discovered", registeredTools.length);
|
|
144
154
|
const result = {
|
|
145
155
|
success: true,
|
|
@@ -182,7 +192,9 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
182
192
|
};
|
|
183
193
|
}
|
|
184
194
|
finally {
|
|
185
|
-
|
|
195
|
+
if (ownsDiscovery) {
|
|
196
|
+
this.discoveryInProgress.delete(serverId);
|
|
197
|
+
}
|
|
186
198
|
}
|
|
187
199
|
});
|
|
188
200
|
}
|
|
@@ -201,13 +213,19 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
201
213
|
/**
|
|
202
214
|
* Register discovered tools
|
|
203
215
|
*/
|
|
204
|
-
async registerDiscoveredTools(serverId, tools) {
|
|
216
|
+
async registerDiscoveredTools(serverId, tools, isCurrentDiscovery) {
|
|
205
217
|
const registeredTools = [];
|
|
218
|
+
if (!isCurrentDiscovery()) {
|
|
219
|
+
throw new Error(`Discovery owner for '${serverId}' is no longer current`);
|
|
220
|
+
}
|
|
206
221
|
// Clear existing tools for this server
|
|
207
222
|
this.clearServerTools(serverId);
|
|
208
223
|
for (const tool of tools) {
|
|
209
224
|
try {
|
|
210
225
|
const toolInfo = await this.createToolInfo(serverId, tool);
|
|
226
|
+
if (!isCurrentDiscovery()) {
|
|
227
|
+
throw new Error(`Discovery owner for '${serverId}' is no longer current`);
|
|
228
|
+
}
|
|
211
229
|
const validation = this.validateTool(toolInfo);
|
|
212
230
|
if (!validation.isValid) {
|
|
213
231
|
mcpLogger.warn(`[ToolDiscoveryService] Skipping invalid tool ${tool.name} from ${serverId}:`, validation.errors);
|
|
@@ -232,11 +250,7 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
232
250
|
}
|
|
233
251
|
// Add tool if not already present
|
|
234
252
|
if (!serverTools.find((t) => t.name === tool.name)) {
|
|
235
|
-
serverTools.push(
|
|
236
|
-
name: tool.name,
|
|
237
|
-
description: tool.description || "",
|
|
238
|
-
inputSchema: tool.inputSchema,
|
|
239
|
-
});
|
|
253
|
+
serverTools.push(toolInfo);
|
|
240
254
|
}
|
|
241
255
|
// Track server tools (legacy)
|
|
242
256
|
if (!this.serverTools.has(serverId)) {
|
|
@@ -257,9 +271,15 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
257
271
|
mcpLogger.debug(`[ToolDiscoveryService] Registered tool: ${tool.name} from ${serverId}`);
|
|
258
272
|
}
|
|
259
273
|
catch (error) {
|
|
274
|
+
if (!isCurrentDiscovery()) {
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
260
277
|
mcpLogger.error(`[ToolDiscoveryService] Failed to register tool ${tool.name} from ${serverId}:`, error);
|
|
261
278
|
}
|
|
262
279
|
}
|
|
280
|
+
if (!isCurrentDiscovery()) {
|
|
281
|
+
throw new Error(`Discovery owner for '${serverId}' is no longer current`);
|
|
282
|
+
}
|
|
263
283
|
return registeredTools;
|
|
264
284
|
}
|
|
265
285
|
/**
|
|
@@ -271,6 +291,7 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
271
291
|
description: tool.description || "No description provided",
|
|
272
292
|
serverId,
|
|
273
293
|
inputSchema: tool.inputSchema,
|
|
294
|
+
...(tool.annotations ? { annotations: { ...tool.annotations } } : {}),
|
|
274
295
|
isAvailable: true,
|
|
275
296
|
stats: {
|
|
276
297
|
totalCalls: 0,
|
|
@@ -782,6 +803,7 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
782
803
|
description: tool.description,
|
|
783
804
|
serverId,
|
|
784
805
|
inputSchema: tool.inputSchema,
|
|
806
|
+
...(tool.annotations ? { annotations: { ...tool.annotations } } : {}),
|
|
785
807
|
isAvailable: true,
|
|
786
808
|
stats: {
|
|
787
809
|
totalCalls: 0,
|
|
@@ -819,6 +841,7 @@ export class ToolDiscoveryService extends EventEmitter {
|
|
|
819
841
|
description: tool.description,
|
|
820
842
|
serverId,
|
|
821
843
|
inputSchema: tool.inputSchema,
|
|
844
|
+
...(tool.annotations ? { annotations: { ...tool.annotations } } : {}),
|
|
822
845
|
isAvailable: true,
|
|
823
846
|
stats: {
|
|
824
847
|
totalCalls: 0,
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Uses real MCP infrastructure for tool discovery and execution.
|
|
7
7
|
*/
|
|
8
8
|
import type { DecisionCallerOptions, DecisionLimitsQuery, DecisionLimitsReading, DecisionOptions, DecisionResult, AgentDefinition, AgentNetworkConfig, AgentRunOptions, AgentRunOutcome, AgentToolRegistrationOptions, IsolatedAgentDefinition, NetworkExecutionInput, NetworkExecutionOptions, NetworkExecutionResult, NetworkStreamChunk, WorkerInstanceOptions } from "./types/index.js";
|
|
9
|
-
import type { CompactionConfig, CompactionResult, ArtifactStore, SpanData, ObservabilityConfig, MetricsSummary, MCPToolAnnotations, TraceView, AuthenticatedContext, AuthProvider, JsonObject, NeuroLinkEvents, TypedEventEmitter, MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig, ChatMessage, ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPToolInfo, GenerateOptions, GenerateResult, ProviderStatus, TextGenerationOptions, TextGenerationResult, MCPExecutableTool, MCPServerInfo, MCPStatus, StreamOptions, StreamResult, ToolExecutionContext, ToolExecutionSummary, ToolInfo, ToolRegistrationOptions, BatchOperationResult, StreamGenerationEndContext, ToolRoutingServerDescriptor, ToolDedupConfig, ToolConfig, KnowledgeEngineStatus, ChecklistState, ArtifactPageRequest, BankArtifactOptions, BankedArtifactRef, DelegateCollectRequest, DelegateCollectResult, DelegateHandle, DelegateRegistrationOptions, DelegateSpawnOptions, BackgroundCommandHandle, BackgroundCommandOptions, BackgroundCommandOutputPage, BackgroundCommandPageRequest, BackgroundCommandPolicy, BackgroundCommandStatus, GitToolResult, GitToolsetOptions } from "./types/index.js";
|
|
9
|
+
import type { CompactionConfig, CompactionResult, ArtifactStore, SpanData, ObservabilityConfig, MetricsSummary, MCPToolAnnotations, TraceView, AuthenticatedContext, AuthProvider, JsonObject, NeuroLinkEvents, TypedEventEmitter, MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig, ChatMessage, ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPServerHealth, ExternalMCPToolInfo, GenerateOptions, GenerateResult, ProviderStatus, TextGenerationOptions, TextGenerationResult, MCPExecutableTool, MCPServerInfo, MCPStatus, StreamOptions, StreamResult, ToolExecutionContext, ToolExecutionSummary, ToolInfo, ToolRegistrationOptions, BatchOperationResult, StreamGenerationEndContext, ToolRoutingServerDescriptor, ToolDedupConfig, ToolConfig, KnowledgeEngineStatus, ChecklistState, ArtifactPageRequest, BankArtifactOptions, BankedArtifactRef, DelegateCollectRequest, DelegateCollectResult, DelegateHandle, DelegateRegistrationOptions, DelegateSpawnOptions, BackgroundCommandHandle, BackgroundCommandOptions, BackgroundCommandOutputPage, BackgroundCommandPageRequest, BackgroundCommandPolicy, BackgroundCommandStatus, GitToolResult, GitToolsetOptions } from "./types/index.js";
|
|
10
10
|
import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
|
|
11
11
|
import type { RedisConversationMemoryManager } from "./core/redisConversationMemoryManager.js";
|
|
12
12
|
import { ExternalServerManager } from "./mcp/externalServerManager.js";
|
|
@@ -2150,6 +2150,7 @@ export declare class NeuroLink {
|
|
|
2150
2150
|
* List all external MCP servers
|
|
2151
2151
|
* @returns Array of server health information
|
|
2152
2152
|
*/
|
|
2153
|
+
getExternalMCPServerHealth(): ExternalMCPServerHealth[];
|
|
2153
2154
|
listExternalMCPServers(): Array<{
|
|
2154
2155
|
serverId: string;
|
|
2155
2156
|
status: string;
|
package/dist/neurolink.js
CHANGED
|
@@ -2306,6 +2306,9 @@ Current user's request: ${currentInput}`;
|
|
|
2306
2306
|
* Setup event handlers for external server manager
|
|
2307
2307
|
*/
|
|
2308
2308
|
setupExternalServerEventHandlers(constructorId) {
|
|
2309
|
+
this.externalServerManager.on("healthCheck", (event) => {
|
|
2310
|
+
this.emitter.emit("externalMCP:serverHealth", event);
|
|
2311
|
+
});
|
|
2309
2312
|
this.externalServerManager.on("connected", (event) => {
|
|
2310
2313
|
logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
|
|
2311
2314
|
constructorId,
|
|
@@ -12812,6 +12815,9 @@ Current user's request: ${currentInput}`;
|
|
|
12812
12815
|
* List all external MCP servers
|
|
12813
12816
|
* @returns Array of server health information
|
|
12814
12817
|
*/
|
|
12818
|
+
getExternalMCPServerHealth() {
|
|
12819
|
+
return this.externalServerManager.getServerStatuses();
|
|
12820
|
+
}
|
|
12815
12821
|
listExternalMCPServers() {
|
|
12816
12822
|
const serverStatuses = this.externalServerManager.getServerStatuses();
|
|
12817
12823
|
const allServers = this.externalServerManager.listServers();
|
|
@@ -10,7 +10,7 @@ import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
|
10
10
|
/**
|
|
11
11
|
* Supported MCP transport protocols - imported from mcpTypes.js (canonical definition)
|
|
12
12
|
*/
|
|
13
|
-
import type { MCPTransportType, MCPServerInfo, MCPServerReadiness } from "./mcp.js";
|
|
13
|
+
import type { MCPTransportType, MCPServerInfo, MCPServerReadiness, MCPToolAnnotations } from "./mcp.js";
|
|
14
14
|
export type { MCPTransportType } from "./mcp.js";
|
|
15
15
|
/**
|
|
16
16
|
* External MCP server configuration for process spawning
|
|
@@ -40,6 +40,8 @@ export type ExternalMCPServerConfig = {
|
|
|
40
40
|
url?: string;
|
|
41
41
|
/** HTTP headers for authentication and configuration (HTTP/SSE/WebSocket) */
|
|
42
42
|
headers?: Record<string, string>;
|
|
43
|
+
/** Trusted HTTP/SSE egress hook, retained for every connection and request. */
|
|
44
|
+
fetch?: typeof globalThis.fetch;
|
|
43
45
|
/** List of tool names to block/blacklist from this server */
|
|
44
46
|
blockedTools?: string[];
|
|
45
47
|
/** Additional metadata */
|
|
@@ -114,6 +116,8 @@ export type ExternalMCPToolInfo = {
|
|
|
114
116
|
serverId: string;
|
|
115
117
|
/** Input schema (JSON Schema) */
|
|
116
118
|
inputSchema?: JsonObject;
|
|
119
|
+
/** Server-supplied behavior hints; absent annotations remain absent. */
|
|
120
|
+
annotations?: MCPToolAnnotations;
|
|
117
121
|
/** Whether the tool is currently available */
|
|
118
122
|
isAvailable: boolean;
|
|
119
123
|
/** Tool metadata */
|
|
@@ -147,6 +151,12 @@ export type ExternalMCPServerHealth = {
|
|
|
147
151
|
toolCount: number;
|
|
148
152
|
/** Any health issues detected */
|
|
149
153
|
issues: string[];
|
|
154
|
+
/** Consecutive failed connections or live health checks, reset on recovery. */
|
|
155
|
+
consecutiveFailures?: number;
|
|
156
|
+
/** Most recent connection/health error, absent after successful recovery. */
|
|
157
|
+
lastError?: string;
|
|
158
|
+
/** Next automatic retry deadline, absent when no retry is scheduled. */
|
|
159
|
+
nextRetryAt?: Date;
|
|
150
160
|
/** Performance metrics */
|
|
151
161
|
performance: {
|
|
152
162
|
uptime: number;
|
package/dist/types/mcp.d.ts
CHANGED
|
@@ -54,6 +54,12 @@ export type MCPServerInfo = {
|
|
|
54
54
|
env?: Record<string, string>;
|
|
55
55
|
url?: string;
|
|
56
56
|
headers?: Record<string, string>;
|
|
57
|
+
/**
|
|
58
|
+
* Trusted host-provided fetch for HTTP and SSE, including reconnects and tool
|
|
59
|
+
* calls. Use a guarded, DNS-pinned dispatcher for untrusted server URLs.
|
|
60
|
+
* Programmatic only: functions cannot be persisted in JSON configuration.
|
|
61
|
+
*/
|
|
62
|
+
fetch?: typeof globalThis.fetch;
|
|
57
63
|
/** HTTP transport-specific options */
|
|
58
64
|
httpOptions?: MCPHTTPTransportOptions;
|
|
59
65
|
timeout?: number;
|
|
@@ -132,12 +138,12 @@ export type MCPServerInfo = {
|
|
|
132
138
|
};
|
|
133
139
|
};
|
|
134
140
|
/**
|
|
135
|
-
*
|
|
141
|
+
* Transport deadlines (all transports), plus HTTP connection-pool options
|
|
136
142
|
*/
|
|
137
143
|
export type MCPHTTPTransportOptions = {
|
|
138
|
-
/**
|
|
144
|
+
/** Explicit connection cap in milliseconds for every transport; absent retains the server/client startup budget. */
|
|
139
145
|
connectionTimeout?: number;
|
|
140
|
-
/**
|
|
146
|
+
/** Explicit whole-request cap in milliseconds for every transport; absent retains caller/server RPC limits (HTTP fetch defaults are separate). */
|
|
141
147
|
requestTimeout?: number;
|
|
142
148
|
/** Idle timeout for connection pool (default: 120000) */
|
|
143
149
|
idleTimeout?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.49.
|
|
3
|
+
"version": "12.49.17",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
@@ -83,6 +83,9 @@
|
|
|
83
83
|
"test:harness-offline-timeout": "pnpm exec tsx test/continuous-test-suite-harness-offline-timeout.ts",
|
|
84
84
|
"test:resolve-request-kind": "pnpm exec tsx test/continuous-test-suite-resolve-request-kind.ts",
|
|
85
85
|
"test:mcp": "pnpm exec tsx test/continuous-test-suite-mcp-infra.ts",
|
|
86
|
+
"test:mcp:egress": "pnpm exec tsx test/continuous-test-suite-mcp-egress.ts",
|
|
87
|
+
"test:mcp:deadline-health": "pnpm exec tsx test/continuous-test-suite-mcp-deadline-health.ts",
|
|
88
|
+
"test:mcp:timeout-compat": "pnpm exec tsx test/continuous-test-suite-mcp-timeout-compat.ts",
|
|
86
89
|
"test:tool-resolution": "pnpm exec tsx test/continuous-test-suite-tool-resolution.ts",
|
|
87
90
|
"test:mcp:http": "pnpm exec tsx test/continuous-test-suite-mcp-http.ts",
|
|
88
91
|
"test:mcp:sdk": "pnpm exec tsx test/continuous-test-suite-mcp-sdk.ts",
|
|
@@ -302,7 +305,8 @@
|
|
|
302
305
|
"test:native-audio-model-aware": "pnpm exec tsx test/continuous-test-suite-native-audio-model-aware.ts",
|
|
303
306
|
"test:cli-json-output": "pnpm exec tsx test/continuous-test-suite-cli-json-output.ts",
|
|
304
307
|
"test:logging-guidelines": "pnpm exec tsx test/continuous-test-suite-logging-guidelines.ts",
|
|
305
|
-
"test:proxy-polyfills": "pnpm exec tsx test/continuous-test-suite-proxy-polyfills.ts"
|
|
308
|
+
"test:proxy-polyfills": "pnpm exec tsx test/continuous-test-suite-proxy-polyfills.ts",
|
|
309
|
+
"test:mcp:startup-readiness": "pnpm exec tsx test/continuous-test-suite-mcp-startup-readiness.ts"
|
|
306
310
|
},
|
|
307
311
|
"files": [
|
|
308
312
|
"dist",
|