@juspay/neurolink 1.6.0 → 1.9.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.
Files changed (176) hide show
  1. package/CHANGELOG.md +193 -7
  2. package/README.md +100 -17
  3. package/dist/agent/direct-tools.d.ts +1203 -0
  4. package/dist/agent/direct-tools.js +387 -0
  5. package/dist/cli/commands/agent-generate.d.ts +2 -0
  6. package/dist/cli/commands/agent-generate.js +70 -0
  7. package/dist/cli/commands/config.d.ts +6 -6
  8. package/dist/cli/commands/config.js +326 -273
  9. package/dist/cli/commands/mcp.d.ts +2 -1
  10. package/dist/cli/commands/mcp.js +874 -146
  11. package/dist/cli/commands/ollama.d.ts +1 -1
  12. package/dist/cli/commands/ollama.js +153 -143
  13. package/dist/cli/index.js +589 -323
  14. package/dist/cli/utils/complete-setup.d.ts +19 -0
  15. package/dist/cli/utils/complete-setup.js +81 -0
  16. package/dist/cli/utils/env-manager.d.ts +44 -0
  17. package/dist/cli/utils/env-manager.js +226 -0
  18. package/dist/cli/utils/interactive-setup.d.ts +48 -0
  19. package/dist/cli/utils/interactive-setup.js +302 -0
  20. package/dist/core/dynamic-models.d.ts +208 -0
  21. package/dist/core/dynamic-models.js +250 -0
  22. package/dist/core/factory.d.ts +13 -6
  23. package/dist/core/factory.js +176 -61
  24. package/dist/core/types.d.ts +4 -2
  25. package/dist/core/types.js +4 -4
  26. package/dist/index.d.ts +16 -16
  27. package/dist/index.js +16 -16
  28. package/dist/lib/agent/direct-tools.d.ts +1203 -0
  29. package/dist/lib/agent/direct-tools.js +387 -0
  30. package/dist/lib/core/dynamic-models.d.ts +208 -0
  31. package/dist/lib/core/dynamic-models.js +250 -0
  32. package/dist/lib/core/factory.d.ts +13 -6
  33. package/dist/lib/core/factory.js +176 -61
  34. package/dist/lib/core/types.d.ts +4 -2
  35. package/dist/lib/core/types.js +4 -4
  36. package/dist/lib/index.d.ts +16 -16
  37. package/dist/lib/index.js +16 -16
  38. package/dist/lib/mcp/auto-discovery.d.ts +120 -0
  39. package/dist/lib/mcp/auto-discovery.js +793 -0
  40. package/dist/lib/mcp/client.d.ts +66 -0
  41. package/dist/lib/mcp/client.js +245 -0
  42. package/dist/lib/mcp/config.d.ts +31 -0
  43. package/dist/lib/mcp/config.js +74 -0
  44. package/dist/lib/mcp/context-manager.d.ts +4 -4
  45. package/dist/lib/mcp/context-manager.js +24 -18
  46. package/dist/lib/mcp/factory.d.ts +28 -11
  47. package/dist/lib/mcp/factory.js +36 -29
  48. package/dist/lib/mcp/function-calling.d.ts +51 -0
  49. package/dist/lib/mcp/function-calling.js +510 -0
  50. package/dist/lib/mcp/index.d.ts +190 -0
  51. package/dist/lib/mcp/index.js +156 -0
  52. package/dist/lib/mcp/initialize-tools.d.ts +28 -0
  53. package/dist/lib/mcp/initialize-tools.js +209 -0
  54. package/dist/lib/mcp/initialize.d.ts +17 -0
  55. package/dist/lib/mcp/initialize.js +51 -0
  56. package/dist/lib/mcp/logging.d.ts +71 -0
  57. package/dist/lib/mcp/logging.js +183 -0
  58. package/dist/lib/mcp/manager.d.ts +67 -0
  59. package/dist/lib/mcp/manager.js +176 -0
  60. package/dist/lib/mcp/neurolink-mcp-client.d.ts +96 -0
  61. package/dist/lib/mcp/neurolink-mcp-client.js +417 -0
  62. package/dist/lib/mcp/orchestrator.d.ts +3 -3
  63. package/dist/lib/mcp/orchestrator.js +46 -43
  64. package/dist/lib/mcp/registry.d.ts +2 -2
  65. package/dist/lib/mcp/registry.js +42 -33
  66. package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.d.ts +1 -1
  67. package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.js +204 -65
  68. package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +142 -102
  69. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +6 -6
  70. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +197 -142
  71. package/dist/lib/mcp/servers/utilities/utility-server.d.ts +8 -0
  72. package/dist/lib/mcp/servers/utilities/utility-server.js +326 -0
  73. package/dist/lib/mcp/tool-integration.d.ts +67 -0
  74. package/dist/lib/mcp/tool-integration.js +179 -0
  75. package/dist/lib/mcp/unified-registry.d.ts +269 -0
  76. package/dist/lib/mcp/unified-registry.js +1411 -0
  77. package/dist/lib/neurolink.d.ts +68 -6
  78. package/dist/lib/neurolink.js +304 -42
  79. package/dist/lib/providers/agent-enhanced-provider.d.ts +59 -0
  80. package/dist/lib/providers/agent-enhanced-provider.js +242 -0
  81. package/dist/lib/providers/amazonBedrock.d.ts +3 -3
  82. package/dist/lib/providers/amazonBedrock.js +54 -50
  83. package/dist/lib/providers/anthropic.d.ts +2 -2
  84. package/dist/lib/providers/anthropic.js +92 -84
  85. package/dist/lib/providers/azureOpenAI.d.ts +2 -2
  86. package/dist/lib/providers/azureOpenAI.js +97 -86
  87. package/dist/lib/providers/function-calling-provider.d.ts +70 -0
  88. package/dist/lib/providers/function-calling-provider.js +359 -0
  89. package/dist/lib/providers/googleAIStudio.d.ts +10 -5
  90. package/dist/lib/providers/googleAIStudio.js +60 -38
  91. package/dist/lib/providers/googleVertexAI.d.ts +3 -3
  92. package/dist/lib/providers/googleVertexAI.js +96 -86
  93. package/dist/lib/providers/huggingFace.d.ts +3 -3
  94. package/dist/lib/providers/huggingFace.js +70 -63
  95. package/dist/lib/providers/index.d.ts +11 -11
  96. package/dist/lib/providers/index.js +18 -18
  97. package/dist/lib/providers/mcp-provider.d.ts +62 -0
  98. package/dist/lib/providers/mcp-provider.js +183 -0
  99. package/dist/lib/providers/mistralAI.d.ts +3 -3
  100. package/dist/lib/providers/mistralAI.js +42 -36
  101. package/dist/lib/providers/ollama.d.ts +4 -4
  102. package/dist/lib/providers/ollama.js +113 -98
  103. package/dist/lib/providers/openAI.d.ts +7 -3
  104. package/dist/lib/providers/openAI.js +45 -33
  105. package/dist/lib/utils/logger.js +2 -2
  106. package/dist/lib/utils/providerUtils.js +53 -31
  107. package/dist/mcp/auto-discovery.d.ts +120 -0
  108. package/dist/mcp/auto-discovery.js +794 -0
  109. package/dist/mcp/client.d.ts +66 -0
  110. package/dist/mcp/client.js +245 -0
  111. package/dist/mcp/config.d.ts +31 -0
  112. package/dist/mcp/config.js +74 -0
  113. package/dist/mcp/context-manager.d.ts +4 -4
  114. package/dist/mcp/context-manager.js +24 -18
  115. package/dist/mcp/factory.d.ts +28 -11
  116. package/dist/mcp/factory.js +36 -29
  117. package/dist/mcp/function-calling.d.ts +51 -0
  118. package/dist/mcp/function-calling.js +510 -0
  119. package/dist/mcp/index.d.ts +190 -0
  120. package/dist/mcp/index.js +156 -0
  121. package/dist/mcp/initialize-tools.d.ts +28 -0
  122. package/dist/mcp/initialize-tools.js +210 -0
  123. package/dist/mcp/initialize.d.ts +17 -0
  124. package/dist/mcp/initialize.js +51 -0
  125. package/dist/mcp/logging.d.ts +71 -0
  126. package/dist/mcp/logging.js +183 -0
  127. package/dist/mcp/manager.d.ts +67 -0
  128. package/dist/mcp/manager.js +176 -0
  129. package/dist/mcp/neurolink-mcp-client.d.ts +96 -0
  130. package/dist/mcp/neurolink-mcp-client.js +417 -0
  131. package/dist/mcp/orchestrator.d.ts +3 -3
  132. package/dist/mcp/orchestrator.js +46 -43
  133. package/dist/mcp/registry.d.ts +2 -2
  134. package/dist/mcp/registry.js +42 -33
  135. package/dist/mcp/servers/ai-providers/ai-analysis-tools.d.ts +1 -1
  136. package/dist/mcp/servers/ai-providers/ai-analysis-tools.js +204 -65
  137. package/dist/mcp/servers/ai-providers/ai-core-server.js +142 -102
  138. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +6 -6
  139. package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +197 -142
  140. package/dist/mcp/servers/utilities/utility-server.d.ts +8 -0
  141. package/dist/mcp/servers/utilities/utility-server.js +326 -0
  142. package/dist/mcp/tool-integration.d.ts +67 -0
  143. package/dist/mcp/tool-integration.js +179 -0
  144. package/dist/mcp/unified-registry.d.ts +269 -0
  145. package/dist/mcp/unified-registry.js +1411 -0
  146. package/dist/neurolink.d.ts +68 -6
  147. package/dist/neurolink.js +304 -42
  148. package/dist/providers/agent-enhanced-provider.d.ts +59 -0
  149. package/dist/providers/agent-enhanced-provider.js +242 -0
  150. package/dist/providers/amazonBedrock.d.ts +3 -3
  151. package/dist/providers/amazonBedrock.js +54 -50
  152. package/dist/providers/anthropic.d.ts +2 -2
  153. package/dist/providers/anthropic.js +92 -84
  154. package/dist/providers/azureOpenAI.d.ts +2 -2
  155. package/dist/providers/azureOpenAI.js +97 -86
  156. package/dist/providers/function-calling-provider.d.ts +70 -0
  157. package/dist/providers/function-calling-provider.js +359 -0
  158. package/dist/providers/googleAIStudio.d.ts +10 -5
  159. package/dist/providers/googleAIStudio.js +60 -38
  160. package/dist/providers/googleVertexAI.d.ts +3 -3
  161. package/dist/providers/googleVertexAI.js +96 -86
  162. package/dist/providers/huggingFace.d.ts +3 -3
  163. package/dist/providers/huggingFace.js +70 -63
  164. package/dist/providers/index.d.ts +11 -11
  165. package/dist/providers/index.js +18 -18
  166. package/dist/providers/mcp-provider.d.ts +62 -0
  167. package/dist/providers/mcp-provider.js +183 -0
  168. package/dist/providers/mistralAI.d.ts +3 -3
  169. package/dist/providers/mistralAI.js +42 -36
  170. package/dist/providers/ollama.d.ts +4 -4
  171. package/dist/providers/ollama.js +113 -98
  172. package/dist/providers/openAI.d.ts +7 -3
  173. package/dist/providers/openAI.js +45 -33
  174. package/dist/utils/logger.js +2 -2
  175. package/dist/utils/providerUtils.js +53 -31
  176. package/package.json +175 -161
@@ -3,31 +3,33 @@
3
3
  * Factory-First Architecture: MCP servers create tools for internal orchestration
4
4
  * Compatible with Lighthouse MCP patterns for seamless migration
5
5
  */
6
- import { z } from 'zod';
6
+ import { z } from "zod";
7
7
  /**
8
8
  * Input validation schemas
9
9
  */
10
10
  const ServerConfigSchema = z.object({
11
- id: z.string().min(1, 'Server ID is required'),
12
- title: z.string().min(1, 'Server title is required'),
11
+ id: z.string().min(1, "Server ID is required"),
12
+ title: z.string().min(1, "Server title is required"),
13
13
  description: z.string().optional(),
14
14
  version: z.string().optional(),
15
- category: z.enum([
16
- 'ai-providers',
17
- 'frameworks',
18
- 'development',
19
- 'business',
20
- 'content',
21
- 'data',
22
- 'integrations',
23
- 'automation',
24
- 'analysis',
25
- 'custom'
26
- ]).optional(),
27
- visibility: z.enum(['public', 'private', 'organization']).optional(),
15
+ category: z
16
+ .enum([
17
+ "ai-providers",
18
+ "frameworks",
19
+ "development",
20
+ "business",
21
+ "content",
22
+ "data",
23
+ "integrations",
24
+ "automation",
25
+ "analysis",
26
+ "custom",
27
+ ])
28
+ .optional(),
29
+ visibility: z.enum(["public", "private", "organization"]).optional(),
28
30
  metadata: z.record(z.any()).optional(),
29
31
  dependencies: z.array(z.string()).optional(),
30
- capabilities: z.array(z.string()).optional()
32
+ capabilities: z.array(z.string()).optional(),
31
33
  });
32
34
  /**
33
35
  * Create MCP Server Factory Function
@@ -67,9 +69,9 @@ export function createMCPServer(config) {
67
69
  title: validatedConfig.title,
68
70
  // Optional fields with defaults
69
71
  description: validatedConfig.description,
70
- version: validatedConfig.version || '1.0.0',
71
- category: validatedConfig.category || 'custom',
72
- visibility: validatedConfig.visibility || 'private',
72
+ version: validatedConfig.version || "1.0.0",
73
+ category: validatedConfig.category || "custom",
74
+ visibility: validatedConfig.visibility || "private",
73
75
  // Tool management
74
76
  tools: {},
75
77
  // Tool registration method
@@ -90,15 +92,15 @@ export function createMCPServer(config) {
90
92
  ...tool.metadata,
91
93
  serverId: this.id,
92
94
  serverCategory: this.category,
93
- registeredAt: Date.now()
94
- }
95
+ registeredAt: Date.now(),
96
+ },
95
97
  };
96
98
  return this;
97
99
  },
98
100
  // Extension points
99
101
  metadata: validatedConfig.metadata || {},
100
102
  dependencies: validatedConfig.dependencies || [],
101
- capabilities: validatedConfig.capabilities || []
103
+ capabilities: validatedConfig.capabilities || [],
102
104
  };
103
105
  return server;
104
106
  }
@@ -108,17 +110,22 @@ export function createMCPServer(config) {
108
110
  export function validateTool(tool) {
109
111
  try {
110
112
  // Check required fields
111
- if (!tool.name || typeof tool.name !== 'string')
113
+ if (!tool.name || typeof tool.name !== "string") {
112
114
  return false;
113
- if (!tool.description || typeof tool.description !== 'string')
115
+ }
116
+ if (!tool.description || typeof tool.description !== "string") {
114
117
  return false;
115
- if (!tool.execute || typeof tool.execute !== 'function')
118
+ }
119
+ if (!tool.execute || typeof tool.execute !== "function") {
116
120
  return false;
121
+ }
117
122
  // Validate optional schemas if present
118
- if (tool.inputSchema && !(tool.inputSchema instanceof z.ZodSchema))
123
+ if (tool.inputSchema && !(tool.inputSchema instanceof z.ZodSchema)) {
119
124
  return false;
120
- if (tool.outputSchema && !(tool.outputSchema instanceof z.ZodSchema))
125
+ }
126
+ if (tool.outputSchema && !(tool.outputSchema instanceof z.ZodSchema)) {
121
127
  return false;
128
+ }
122
129
  return true;
123
130
  }
124
131
  catch (error) {
@@ -135,7 +142,7 @@ export function getServerInfo(server) {
135
142
  description: server.description,
136
143
  category: server.category,
137
144
  toolCount: Object.keys(server.tools).length,
138
- capabilities: server.capabilities || []
145
+ capabilities: server.capabilities || [],
139
146
  };
140
147
  }
141
148
  // Types are already exported above via export interface declarations
@@ -0,0 +1,51 @@
1
+ /**
2
+ * MCP Function-Calling Integration
3
+ * Converts MCP tools to AI SDK function definitions and handles function calls
4
+ * Enables true AI function calling with discovered MCP tools
5
+ */
6
+ import type { Tool } from "ai";
7
+ import type { NeuroLinkMCPTool, ToolResult, NeuroLinkExecutionContext } from "./factory.js";
8
+ /**
9
+ * Convert MCP tool to AI SDK function definition
10
+ */
11
+ export declare function mcpToolToAISDKTool(tool: NeuroLinkMCPTool, serverId: string): Tool;
12
+ /**
13
+ * Get all available MCP tools as AI SDK function definitions
14
+ */
15
+ export declare function getAvailableFunctionTools(): Promise<{
16
+ tools: Tool[];
17
+ toolMap: Map<string, {
18
+ serverId: string;
19
+ toolName: string;
20
+ }>;
21
+ }>;
22
+ /**
23
+ * Execute MCP tool from AI function call
24
+ */
25
+ export declare function executeFunctionCall(functionName: string, parameters: Record<string, unknown>, context?: NeuroLinkExecutionContext): Promise<ToolResult>;
26
+ /**
27
+ * Handle multiple function calls and format results for AI
28
+ */
29
+ export declare function handleFunctionCalls(functionCalls: Array<{
30
+ name: string;
31
+ parameters: Record<string, unknown>;
32
+ id?: string;
33
+ }>, context?: NeuroLinkExecutionContext): Promise<Array<{
34
+ id?: string;
35
+ result: ToolResult;
36
+ formattedForAI: string;
37
+ }>>;
38
+ /**
39
+ * Create a subset of tools for specific categories or capabilities
40
+ */
41
+ export declare function getFunctionToolsForCategory(category?: string, maxTools?: number): Promise<{
42
+ tools: Tool[];
43
+ toolMap: Map<string, {
44
+ serverId: string;
45
+ toolName: string;
46
+ }>;
47
+ }>;
48
+ /**
49
+ * Check if function calling is available
50
+ */
51
+ export declare function isFunctionCallingAvailable(): Promise<boolean>;
@@ -0,0 +1,510 @@
1
+ /**
2
+ * MCP Function-Calling Integration
3
+ * Converts MCP tools to AI SDK function definitions and handles function calls
4
+ * Enables true AI function calling with discovered MCP tools
5
+ */
6
+ import { tool } from "ai";
7
+ import { z } from "zod";
8
+ import { defaultUnifiedRegistry } from "./unified-registry.js";
9
+ import { createExecutionContext } from "./context-manager.js";
10
+ import { mcpLogger } from "./logging.js";
11
+ /**
12
+ * Convert MCP tool to AI SDK function definition
13
+ */
14
+ export function mcpToolToAISDKTool(tool, serverId) {
15
+ // Create basic JSON Schema for AI SDK
16
+ const parameters = {
17
+ type: "object",
18
+ properties: {},
19
+ required: [],
20
+ };
21
+ // If we have an input schema, try to extract basic information
22
+ if (tool.inputSchema) {
23
+ try {
24
+ // For now, create a simple schema that accepts any object
25
+ // This could be enhanced with proper Zod-to-JSON-Schema conversion
26
+ parameters.properties = {
27
+ // Generic parameter support
28
+ data: {
29
+ type: "object",
30
+ description: "Tool parameters",
31
+ },
32
+ };
33
+ }
34
+ catch (error) {
35
+ mcpLogger.warn(`[Function-Calling] Failed to convert schema for tool ${tool.name}:`, error);
36
+ }
37
+ }
38
+ return {
39
+ description: tool.description,
40
+ parameters,
41
+ execute: async (args) => {
42
+ // This will be handled by the AI SDK's function calling mechanism
43
+ // We'll implement the actual execution in the provider level
44
+ mcpLogger.debug(`[Function-Calling] AI SDK tool executed: ${serverId}.${tool.name}`, args);
45
+ return {
46
+ success: true,
47
+ message: "Tool execution handled by MCP integration",
48
+ };
49
+ },
50
+ };
51
+ }
52
+ /**
53
+ * Get all available MCP tools as AI SDK function definitions
54
+ */
55
+ export async function getAvailableFunctionTools() {
56
+ const functionTag = "getAvailableFunctionTools";
57
+ const tools = [];
58
+ const toolMap = new Map();
59
+ try {
60
+ // Add overall timeout for the entire function
61
+ const overallTimeoutMs = 5000; // 5 seconds max for everything
62
+ let overallTimeoutId;
63
+ const overallTimeoutPromise = new Promise((_, reject) => {
64
+ overallTimeoutId = setTimeout(() => {
65
+ mcpLogger.warn(`[${functionTag}] Overall timeout reached, returning empty tools`);
66
+ reject(new Error("getAvailableFunctionTools overall timeout"));
67
+ }, overallTimeoutMs);
68
+ // CRITICAL FIX: Unref timeout to prevent event loop hanging
69
+ overallTimeoutId.unref();
70
+ });
71
+ const toolsLoadingPromise = (async () => {
72
+ try {
73
+ // Ensure NeuroLink MCP is initialized first
74
+ const { initializeNeuroLinkMCP } = await import("./initialize.js");
75
+ await initializeNeuroLinkMCP();
76
+ // Ensure unified registry is initialized
77
+ await defaultUnifiedRegistry.initialize();
78
+ // Try to activate important servers like filesystem
79
+ mcpLogger.debug(`[${functionTag}] Attempting to activate important servers...`);
80
+ try {
81
+ // Get auto-discovered servers
82
+ const autoServers = defaultUnifiedRegistry.getAutoDiscoveredServers();
83
+ // Try to activate filesystem server specifically
84
+ for (const [serverId, entry] of autoServers) {
85
+ if (serverId.includes("filesystem") &&
86
+ entry.status !== "activated") {
87
+ mcpLogger.debug(`[${functionTag}] Activating filesystem server: ${serverId}`);
88
+ await defaultUnifiedRegistry.lazyActivateServer(serverId, entry);
89
+ }
90
+ }
91
+ }
92
+ catch (error) {
93
+ mcpLogger.debug(`[${functionTag}] Error activating servers: ${error}`);
94
+ }
95
+ // Get all tools from unified registry directly
96
+ const allTools = await defaultUnifiedRegistry.listAllTools();
97
+ mcpLogger.debug(`[${functionTag}] Found ${allTools.length} total tools`);
98
+ // Try to activate servers that have "-tools" entries to get real tools
99
+ const serversToActivate = allTools
100
+ .filter((tool) => tool.name.endsWith("-tools") || tool.name.includes("placeholder"))
101
+ .map((tool) => tool.server);
102
+ mcpLogger.debug(`[${functionTag}] Attempting to activate ${serversToActivate.length} servers for real tool discovery`);
103
+ // Activate servers to convert placeholders to real tools
104
+ for (const serverId of [...new Set(serversToActivate)]) {
105
+ try {
106
+ mcpLogger.debug(`[${functionTag}] Activating server: ${serverId}`);
107
+ // Get the server entry from auto-discovered or manual servers
108
+ const autoServers = defaultUnifiedRegistry.getAutoDiscoveredServers();
109
+ const manualServers = defaultUnifiedRegistry.getManualServers();
110
+ const serverEntry = autoServers.get(serverId) || manualServers.get(serverId);
111
+ if (serverEntry) {
112
+ await defaultUnifiedRegistry.lazyActivateServer(serverId, serverEntry);
113
+ }
114
+ else {
115
+ mcpLogger.debug(`[${functionTag}] Server entry not found for: ${serverId}`);
116
+ }
117
+ }
118
+ catch (error) {
119
+ mcpLogger.debug(`[${functionTag}] Failed to activate server ${serverId}:`, error);
120
+ }
121
+ }
122
+ // Get tools again after activation
123
+ const activatedTools = await defaultUnifiedRegistry.listAllTools();
124
+ mcpLogger.debug(`[${functionTag}] Found ${activatedTools.length} total tools after activation`);
125
+ // Filter to get real, individual tools (not placeholder or grouped tools)
126
+ const realTools = activatedTools.filter((toolInfo) => {
127
+ // Skip placeholder tools that weren't activated
128
+ if (toolInfo.name.includes("placeholder") &&
129
+ toolInfo.isImplemented === false) {
130
+ return false;
131
+ }
132
+ // Skip grouped "-tools" entries unless they're the only ones available
133
+ if (toolInfo.name.endsWith("-tools")) {
134
+ // Check if we have individual tools from the same server
135
+ const serverTools = activatedTools.filter((t) => t.server === toolInfo.server &&
136
+ !t.name.endsWith("-tools") &&
137
+ !t.name.includes("placeholder"));
138
+ // If we have individual tools, skip the grouped entry
139
+ if (serverTools.length > 0) {
140
+ return false;
141
+ }
142
+ // Otherwise, include the grouped tool (better than nothing)
143
+ }
144
+ // Include all other real tools
145
+ return true;
146
+ });
147
+ mcpLogger.debug(`[${functionTag}] Filtered to ${realTools.length} real tools from ${activatedTools.length} total`);
148
+ // Process tools and create function definitions
149
+ for (const toolInfo of realTools) {
150
+ try {
151
+ // Check if tool name already includes server info (e.g., from unified registry)
152
+ let functionName;
153
+ let originalFunctionName;
154
+ // Convert server name to underscore format to check if it's embedded in tool name
155
+ const sanitizedServerCheck = toolInfo.server.replace(/[^a-zA-Z0-9_]/g, "_");
156
+ if (toolInfo.name.includes(sanitizedServerCheck) ||
157
+ toolInfo.name.endsWith("-tools") ||
158
+ toolInfo.name.startsWith("github_com_") ||
159
+ toolInfo.name.length > 50) {
160
+ // Tool name already includes server info, sanitize and shorten it
161
+ let sanitized = toolInfo.name.replace(/[^a-zA-Z0-9_]/g, "_");
162
+ // Shorten long MCP server names
163
+ if (sanitized.startsWith("github_com_modelcontextprotocol_servers_tree_main_src_")) {
164
+ // Replace the long prefix with just 'mcp_'
165
+ sanitized =
166
+ "mcp_" +
167
+ sanitized.substring("github_com_modelcontextprotocol_servers_tree_main_src_"
168
+ .length);
169
+ mcpLogger.debug(`[${functionTag}] Shortened MCP name: ${toolInfo.name} -> ${sanitized}`);
170
+ }
171
+ else if (sanitized.startsWith("github_com_") &&
172
+ sanitized.length > 64) {
173
+ // Shorten other github paths
174
+ const parts = sanitized.split("_");
175
+ // Keep only the meaningful parts (skip github_com)
176
+ sanitized = parts.slice(2).join("_");
177
+ mcpLogger.debug(`[${functionTag}] Shortened github name: ${toolInfo.name} -> ${sanitized}`);
178
+ }
179
+ // If still too long, truncate intelligently
180
+ if (sanitized.length > 64) {
181
+ // Keep the ending part which usually has the actual tool name
182
+ sanitized = sanitized.substring(sanitized.length - 63);
183
+ }
184
+ // Ensure it starts with a letter or underscore (Google AI requirement)
185
+ if (!/^[a-zA-Z_]/.test(sanitized)) {
186
+ sanitized = "_" + sanitized;
187
+ }
188
+ // Final length check after adding prefix
189
+ if (sanitized.length > 64) {
190
+ // For filesystem tools, create a shorter name
191
+ if (sanitized.includes("filesystem")) {
192
+ const toolPart = sanitized.split("_").pop() || "tool";
193
+ sanitized = "fs_" + toolPart;
194
+ }
195
+ else {
196
+ // Generic truncation from the beginning, keeping the end
197
+ sanitized = "_" + sanitized.substring(sanitized.length - 63);
198
+ }
199
+ }
200
+ functionName = sanitized;
201
+ originalFunctionName = toolInfo.name;
202
+ }
203
+ else {
204
+ // Tool name doesn't include server info, create compound name
205
+ const sanitizedServerName = toolInfo.server.replace(/[^a-zA-Z0-9_]/g, "_");
206
+ const sanitizedToolName = toolInfo.name.replace(/[^a-zA-Z0-9_]/g, "_");
207
+ // Check if it's a filesystem tool from MCP
208
+ if (sanitizedServerName.includes("modelcontextprotocol") &&
209
+ sanitizedServerName.includes("filesystem")) {
210
+ functionName = `mcp_${sanitizedToolName}`;
211
+ }
212
+ else if (sanitizedServerName.length > 40) {
213
+ // For other long server names, use a shortened version
214
+ const serverParts = sanitizedServerName.split("_");
215
+ const shortServer = serverParts.length > 2
216
+ ? serverParts.slice(-2).join("_")
217
+ : sanitizedServerName.substring(0, 20);
218
+ functionName = `${shortServer}_${sanitizedToolName}`;
219
+ }
220
+ else {
221
+ functionName = `${sanitizedServerName}_${sanitizedToolName}`;
222
+ }
223
+ // Ensure it starts with a letter or underscore
224
+ if (!/^[a-zA-Z_]/.test(functionName)) {
225
+ functionName = "_" + functionName;
226
+ }
227
+ // Final length check
228
+ if (functionName.length > 64) {
229
+ // Create a very short version
230
+ functionName = `tool_${sanitizedToolName}`;
231
+ if (functionName.length > 64) {
232
+ functionName = sanitizedToolName.substring(0, 63);
233
+ if (!/^[a-zA-Z_]/.test(functionName)) {
234
+ functionName = "_" + functionName.substring(1);
235
+ }
236
+ }
237
+ }
238
+ originalFunctionName = `${toolInfo.server}.${toolInfo.name}`;
239
+ }
240
+ // Create AI SDK tool using the proper tool() helper
241
+ const aiTool = tool({
242
+ description: toolInfo.description || `Tool from ${toolInfo.server}`,
243
+ parameters: z.object({
244
+ // Create a generic parameter schema for all MCP tools
245
+ input: z
246
+ .unknown()
247
+ .optional()
248
+ .describe("Input parameters for the tool"),
249
+ }),
250
+ execute: async ({ input }) => {
251
+ mcpLogger.debug(`[Function-Calling] AI SDK tool executed: ${functionName}`, { input });
252
+ try {
253
+ // Execute the actual MCP tool
254
+ const result = await executeFunctionCall(functionName, input || {});
255
+ if (result.success) {
256
+ return (result.data || {
257
+ success: true,
258
+ message: "Tool executed successfully",
259
+ });
260
+ }
261
+ else {
262
+ return { error: result.error || "Tool execution failed" };
263
+ }
264
+ }
265
+ catch (error) {
266
+ mcpLogger.error(`[Function-Calling] Tool execution error: ${functionName}`, error);
267
+ return {
268
+ error: error instanceof Error ? error.message : String(error),
269
+ };
270
+ }
271
+ },
272
+ });
273
+ tools.push(aiTool);
274
+ // Store mapping for execution - CRITICAL: Use sanitized functionName as key
275
+ toolMap.set(functionName, {
276
+ serverId: toolInfo.server,
277
+ toolName: toolInfo.name,
278
+ });
279
+ mcpLogger.debug(`[${functionTag}] Converted tool: ${functionName} (original: ${originalFunctionName})`);
280
+ }
281
+ catch (error) {
282
+ mcpLogger.warn(`[${functionTag}] Failed to convert tool ${toolInfo.name}:`, error);
283
+ }
284
+ }
285
+ mcpLogger.debug(`[${functionTag}] Converted ${tools.length} tools for function calling`);
286
+ // Log the tool names for debugging
287
+ const toolNames = Array.from(toolMap.keys());
288
+ mcpLogger.debug(`[${functionTag}] Tool names:`, toolNames);
289
+ mcpLogger.debug(`[${functionTag}] First 5 tool names:`, toolNames.slice(0, 5));
290
+ if (overallTimeoutId) {
291
+ clearTimeout(overallTimeoutId);
292
+ }
293
+ return { tools, toolMap };
294
+ }
295
+ catch (error) {
296
+ if (overallTimeoutId) {
297
+ clearTimeout(overallTimeoutId);
298
+ }
299
+ throw error;
300
+ }
301
+ })();
302
+ return await Promise.race([toolsLoadingPromise, overallTimeoutPromise]);
303
+ }
304
+ catch (error) {
305
+ mcpLogger.error(`[${functionTag}] Error getting function tools:`, error);
306
+ return { tools: [], toolMap: new Map() };
307
+ }
308
+ }
309
+ /**
310
+ * Execute MCP tool from AI function call
311
+ */
312
+ export async function executeFunctionCall(functionName, parameters, context) {
313
+ const functionTag = "executeFunctionCall";
314
+ try {
315
+ mcpLogger.debug(`[${functionTag}] Executing function call: ${functionName}`, { parameters });
316
+ // Create context if not provided
317
+ let finalContext = context;
318
+ if (!finalContext) {
319
+ finalContext = createExecutionContext({
320
+ sessionId: `function-call-${Date.now()}`,
321
+ userId: "ai-function-caller",
322
+ aiProvider: "function-calling",
323
+ });
324
+ }
325
+ // Parse server and tool name from function name
326
+ // First try underscore format (sanitized), then fallback to dot format
327
+ let parts = functionName.split("_");
328
+ let serverId;
329
+ let toolName;
330
+ if (parts.length >= 2) {
331
+ // Handle underscore format (sanitized names)
332
+ serverId = parts[0];
333
+ toolName = parts.slice(1).join("_"); // Rejoin in case tool name had underscores
334
+ }
335
+ else {
336
+ // Fallback to dot format for backward compatibility
337
+ parts = functionName.split(".");
338
+ if (parts.length === 2) {
339
+ [serverId, toolName] = parts;
340
+ }
341
+ else {
342
+ // Can't parse - try executing as-is through unified registry
343
+ mcpLogger.debug(`[${functionTag}] Cannot parse function name format: ${functionName}, trying unified registry`);
344
+ const result = await defaultUnifiedRegistry.executeTool(functionName, parameters, finalContext);
345
+ return result;
346
+ }
347
+ }
348
+ // Handle built-in NeuroLink servers directly
349
+ if (serverId === "neurolink-utility" ||
350
+ serverId === "neurolink-ai-core" ||
351
+ serverId === "neurolink_utility" ||
352
+ serverId === "neurolink_ai_core") {
353
+ mcpLogger.debug(`[${functionTag}] Executing built-in tool: ${toolName} from ${serverId}`);
354
+ // Import and execute from default registry
355
+ const { defaultToolRegistry } = await import("./registry.js");
356
+ return await defaultToolRegistry.executeTool(toolName, parameters, finalContext);
357
+ }
358
+ // Handle filesystem server with special activation logic
359
+ if (serverId === "filesystem") {
360
+ mcpLogger.debug(`[${functionTag}] Executing filesystem tool: ${toolName}`);
361
+ try {
362
+ // First, try to execute through unified registry
363
+ const result = await defaultUnifiedRegistry.executeTool(functionName, parameters, finalContext);
364
+ if (result.success) {
365
+ return result;
366
+ }
367
+ }
368
+ catch {
369
+ mcpLogger.debug(`[${functionTag}] Unified registry execution failed for ${functionName}, trying fallback`);
370
+ }
371
+ // Fallback: Try to trigger activation and retry
372
+ try {
373
+ // Force activation by attempting to activate the filesystem server directly
374
+ // This should convert placeholders to real tools
375
+ await defaultUnifiedRegistry.initialize();
376
+ // Try a few common activation patterns
377
+ const activationAttempts = [
378
+ `${serverId}.list_directory`,
379
+ `${serverId}.${toolName}`,
380
+ toolName,
381
+ ];
382
+ for (const attempt of activationAttempts) {
383
+ try {
384
+ const result = await defaultUnifiedRegistry.executeTool(attempt, parameters, finalContext);
385
+ if (result.success) {
386
+ mcpLogger.debug(`[${functionTag}] Filesystem tool executed successfully with: ${attempt}`);
387
+ return result;
388
+ }
389
+ }
390
+ catch {
391
+ // Continue to next attempt
392
+ }
393
+ }
394
+ // If all attempts fail, return a helpful error
395
+ return {
396
+ success: false,
397
+ error: `Filesystem tool '${toolName}' could not be activated. Available parameters: ${JSON.stringify(parameters)}`,
398
+ metadata: {
399
+ functionName,
400
+ timestamp: Date.now(),
401
+ source: "function-calling-filesystem-fallback",
402
+ },
403
+ };
404
+ }
405
+ catch (fallbackError) {
406
+ mcpLogger.error(`[${functionTag}] Filesystem fallback failed:`, fallbackError);
407
+ return {
408
+ success: false,
409
+ error: `Filesystem tool execution failed: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`,
410
+ metadata: {
411
+ functionName,
412
+ timestamp: Date.now(),
413
+ source: "function-calling-filesystem-fallback",
414
+ },
415
+ };
416
+ }
417
+ }
418
+ // For other tools, use unified registry
419
+ mcpLogger.debug(`[${functionTag}] Executing through unified registry: ${functionName}`);
420
+ const result = await defaultUnifiedRegistry.executeTool(functionName, parameters, finalContext);
421
+ mcpLogger.debug(`[${functionTag}] Function call completed: ${functionName}`, {
422
+ success: result.success,
423
+ hasData: !!result.data,
424
+ });
425
+ return result;
426
+ }
427
+ catch (error) {
428
+ const errorMessage = error instanceof Error ? error.message : String(error);
429
+ mcpLogger.error(`[${functionTag}] Function call failed: ${functionName}`, {
430
+ error: errorMessage,
431
+ });
432
+ return {
433
+ success: false,
434
+ error: errorMessage,
435
+ metadata: {
436
+ functionName,
437
+ timestamp: Date.now(),
438
+ source: "function-calling-integration",
439
+ },
440
+ };
441
+ }
442
+ }
443
+ /**
444
+ * Handle multiple function calls and format results for AI
445
+ */
446
+ export async function handleFunctionCalls(functionCalls, context) {
447
+ const functionTag = "handleFunctionCalls";
448
+ const results = [];
449
+ mcpLogger.debug(`[${functionTag}] Handling ${functionCalls.length} function calls`);
450
+ for (const call of functionCalls) {
451
+ const result = await executeFunctionCall(call.name, call.parameters, context);
452
+ // Format result for AI consumption
453
+ let formattedForAI = "";
454
+ if (result.success) {
455
+ if (typeof result.data === "string") {
456
+ formattedForAI = result.data;
457
+ }
458
+ else if (result.data) {
459
+ formattedForAI = JSON.stringify(result.data, null, 2);
460
+ }
461
+ else {
462
+ formattedForAI = "Function executed successfully (no data returned)";
463
+ }
464
+ }
465
+ else {
466
+ formattedForAI = `Error: ${result.error || "Function execution failed"}`;
467
+ }
468
+ results.push({
469
+ id: call.id,
470
+ result,
471
+ formattedForAI,
472
+ });
473
+ }
474
+ return results;
475
+ }
476
+ /**
477
+ * Create a subset of tools for specific categories or capabilities
478
+ */
479
+ export async function getFunctionToolsForCategory(category, maxTools) {
480
+ const { tools, toolMap } = await getAvailableFunctionTools();
481
+ if (!category) {
482
+ return maxTools
483
+ ? {
484
+ tools: tools.slice(0, maxTools),
485
+ toolMap,
486
+ }
487
+ : { tools, toolMap };
488
+ }
489
+ // Filter by category (simplified - just include all for now)
490
+ const filteredTools = tools;
491
+ return maxTools
492
+ ? {
493
+ tools: filteredTools.slice(0, maxTools),
494
+ toolMap,
495
+ }
496
+ : { tools: filteredTools, toolMap };
497
+ }
498
+ /**
499
+ * Check if function calling is available
500
+ */
501
+ export async function isFunctionCallingAvailable() {
502
+ try {
503
+ const { tools } = await getAvailableFunctionTools();
504
+ return tools.length > 0;
505
+ }
506
+ catch (error) {
507
+ mcpLogger.warn("[isFunctionCallingAvailable] Failed to check availability:", error);
508
+ return false;
509
+ }
510
+ }