@juspay/neurolink 1.9.0 → 1.11.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 (156) hide show
  1. package/CHANGELOG.md +41 -31
  2. package/README.md +17 -1
  3. package/dist/agent/direct-tools.d.ts +9 -9
  4. package/dist/cli/commands/agent-generate.d.ts +1 -2
  5. package/dist/cli/commands/agent-generate.js +5 -8
  6. package/dist/cli/commands/config.d.ts +2 -2
  7. package/dist/cli/commands/config.js +1 -1
  8. package/dist/cli/commands/mcp.js +91 -100
  9. package/dist/cli/commands/ollama.d.ts +2 -7
  10. package/dist/cli/commands/ollama.js +5 -8
  11. package/dist/cli/index.js +263 -258
  12. package/dist/core/factory.js +11 -12
  13. package/dist/index.d.ts +24 -1
  14. package/dist/index.js +36 -1
  15. package/dist/lib/agent/direct-tools.d.ts +9 -9
  16. package/dist/lib/core/factory.js +11 -12
  17. package/dist/lib/index.d.ts +24 -1
  18. package/dist/lib/index.js +36 -1
  19. package/dist/lib/mcp/adapters/plugin-bridge.d.ts +39 -0
  20. package/dist/lib/mcp/adapters/plugin-bridge.js +82 -0
  21. package/dist/lib/mcp/auto-discovery.d.ts +38 -96
  22. package/dist/lib/mcp/auto-discovery.js +100 -744
  23. package/dist/lib/mcp/client.js +4 -4
  24. package/dist/lib/mcp/context-manager.js +72 -1
  25. package/dist/lib/mcp/contracts/mcp-contract.d.ts +162 -0
  26. package/dist/lib/mcp/contracts/mcp-contract.js +58 -0
  27. package/dist/lib/mcp/core/plugin-manager.d.ts +45 -0
  28. package/dist/lib/mcp/core/plugin-manager.js +110 -0
  29. package/dist/lib/mcp/demo/plugin-demo.d.ts +20 -0
  30. package/dist/lib/mcp/demo/plugin-demo.js +116 -0
  31. package/dist/lib/mcp/ecosystem.d.ts +75 -0
  32. package/dist/lib/mcp/ecosystem.js +161 -0
  33. package/dist/lib/mcp/external-client.d.ts +88 -0
  34. package/dist/lib/mcp/external-client.js +323 -0
  35. package/dist/lib/mcp/external-manager.d.ts +112 -0
  36. package/dist/lib/mcp/external-manager.js +302 -0
  37. package/dist/lib/mcp/factory.d.ts +4 -4
  38. package/dist/lib/mcp/function-calling.js +59 -34
  39. package/dist/lib/mcp/index.d.ts +39 -184
  40. package/dist/lib/mcp/index.js +72 -150
  41. package/dist/lib/mcp/initialize.js +5 -5
  42. package/dist/lib/mcp/logging.d.ts +27 -60
  43. package/dist/lib/mcp/logging.js +77 -165
  44. package/dist/lib/mcp/neurolink-mcp-client.js +31 -3
  45. package/dist/lib/mcp/orchestrator.d.ts +1 -1
  46. package/dist/lib/mcp/orchestrator.js +13 -12
  47. package/dist/lib/mcp/plugin-manager.d.ts +98 -0
  48. package/dist/lib/mcp/plugin-manager.js +294 -0
  49. package/dist/lib/mcp/plugins/core/filesystem-mcp.d.ts +35 -0
  50. package/dist/lib/mcp/plugins/core/filesystem-mcp.js +139 -0
  51. package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +36 -0
  52. package/dist/lib/mcp/plugins/filesystem-mcp.js +54 -0
  53. package/dist/lib/mcp/registry.d.ts +26 -167
  54. package/dist/lib/mcp/registry.js +31 -354
  55. package/dist/lib/mcp/security-manager.d.ts +85 -0
  56. package/dist/lib/mcp/security-manager.js +344 -0
  57. package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.js +1 -1
  58. package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +1 -1
  59. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  60. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +1 -1
  61. package/dist/lib/mcp/tool-integration.d.ts +4 -14
  62. package/dist/lib/mcp/tool-integration.js +43 -21
  63. package/dist/lib/mcp/tool-registry.d.ts +66 -0
  64. package/dist/lib/mcp/tool-registry.js +160 -0
  65. package/dist/lib/mcp/unified-mcp.d.ts +123 -0
  66. package/dist/lib/mcp/unified-mcp.js +246 -0
  67. package/dist/lib/mcp/unified-registry.d.ts +42 -229
  68. package/dist/lib/mcp/unified-registry.js +96 -1346
  69. package/dist/lib/neurolink.d.ts +3 -4
  70. package/dist/lib/neurolink.js +18 -19
  71. package/dist/lib/providers/agent-enhanced-provider.js +2 -2
  72. package/dist/lib/providers/amazonBedrock.js +2 -2
  73. package/dist/lib/providers/anthropic.js +3 -3
  74. package/dist/lib/providers/azureOpenAI.js +3 -3
  75. package/dist/lib/providers/function-calling-provider.js +34 -25
  76. package/dist/lib/providers/googleAIStudio.js +3 -3
  77. package/dist/lib/providers/googleVertexAI.js +2 -2
  78. package/dist/lib/providers/huggingFace.js +2 -2
  79. package/dist/lib/providers/mcp-provider.js +33 -5
  80. package/dist/lib/providers/mistralAI.js +2 -2
  81. package/dist/lib/providers/ollama.js +17 -2
  82. package/dist/lib/providers/openAI.js +2 -2
  83. package/dist/lib/utils/providerUtils-fixed.d.ts +8 -0
  84. package/dist/lib/utils/providerUtils-fixed.js +75 -0
  85. package/dist/lib/utils/providerUtils.d.ts +8 -1
  86. package/dist/lib/utils/providerUtils.js +10 -1
  87. package/dist/mcp/adapters/plugin-bridge.d.ts +39 -0
  88. package/dist/mcp/adapters/plugin-bridge.js +82 -0
  89. package/dist/mcp/auto-discovery.d.ts +38 -96
  90. package/dist/mcp/auto-discovery.js +100 -745
  91. package/dist/mcp/client.js +4 -4
  92. package/dist/mcp/context-manager.js +72 -1
  93. package/dist/mcp/contracts/mcp-contract.d.ts +162 -0
  94. package/dist/mcp/contracts/mcp-contract.js +58 -0
  95. package/dist/mcp/core/plugin-manager.d.ts +45 -0
  96. package/dist/mcp/core/plugin-manager.js +110 -0
  97. package/dist/mcp/demo/plugin-demo.d.ts +20 -0
  98. package/dist/mcp/demo/plugin-demo.js +116 -0
  99. package/dist/mcp/ecosystem.d.ts +75 -0
  100. package/dist/mcp/ecosystem.js +162 -0
  101. package/dist/mcp/external-client.d.ts +88 -0
  102. package/dist/mcp/external-client.js +323 -0
  103. package/dist/mcp/external-manager.d.ts +112 -0
  104. package/dist/mcp/external-manager.js +302 -0
  105. package/dist/mcp/factory.d.ts +4 -4
  106. package/dist/mcp/function-calling.js +59 -34
  107. package/dist/mcp/index.d.ts +39 -184
  108. package/dist/mcp/index.js +72 -150
  109. package/dist/mcp/initialize.js +5 -5
  110. package/dist/mcp/logging.d.ts +27 -60
  111. package/dist/mcp/logging.js +77 -165
  112. package/dist/mcp/neurolink-mcp-client.js +31 -3
  113. package/dist/mcp/orchestrator.d.ts +1 -1
  114. package/dist/mcp/orchestrator.js +13 -12
  115. package/dist/mcp/plugin-manager.d.ts +98 -0
  116. package/dist/mcp/plugin-manager.js +295 -0
  117. package/dist/mcp/plugins/core/filesystem-mcp.d.ts +35 -0
  118. package/dist/mcp/plugins/core/filesystem-mcp.js +139 -0
  119. package/dist/mcp/plugins/core/neurolink-mcp.json +17 -0
  120. package/dist/mcp/plugins/filesystem-mcp.d.ts +36 -0
  121. package/dist/mcp/plugins/filesystem-mcp.js +54 -0
  122. package/dist/mcp/registry.d.ts +26 -167
  123. package/dist/mcp/registry.js +31 -354
  124. package/dist/mcp/security-manager.d.ts +85 -0
  125. package/dist/mcp/security-manager.js +344 -0
  126. package/dist/mcp/servers/ai-providers/ai-analysis-tools.js +1 -1
  127. package/dist/mcp/servers/ai-providers/ai-core-server.js +1 -1
  128. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  129. package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +1 -1
  130. package/dist/mcp/tool-integration.d.ts +4 -14
  131. package/dist/mcp/tool-integration.js +43 -21
  132. package/dist/mcp/tool-registry.d.ts +66 -0
  133. package/dist/mcp/tool-registry.js +160 -0
  134. package/dist/mcp/unified-mcp.d.ts +123 -0
  135. package/dist/mcp/unified-mcp.js +246 -0
  136. package/dist/mcp/unified-registry.d.ts +42 -229
  137. package/dist/mcp/unified-registry.js +96 -1345
  138. package/dist/neurolink.d.ts +3 -4
  139. package/dist/neurolink.js +18 -19
  140. package/dist/providers/agent-enhanced-provider.js +2 -2
  141. package/dist/providers/amazonBedrock.js +2 -2
  142. package/dist/providers/anthropic.js +3 -3
  143. package/dist/providers/azureOpenAI.js +3 -3
  144. package/dist/providers/function-calling-provider.js +34 -25
  145. package/dist/providers/googleAIStudio.js +3 -3
  146. package/dist/providers/googleVertexAI.js +2 -2
  147. package/dist/providers/huggingFace.js +2 -2
  148. package/dist/providers/mcp-provider.js +33 -5
  149. package/dist/providers/mistralAI.js +2 -2
  150. package/dist/providers/ollama.js +17 -2
  151. package/dist/providers/openAI.js +2 -2
  152. package/dist/utils/providerUtils-fixed.d.ts +8 -0
  153. package/dist/utils/providerUtils-fixed.js +75 -0
  154. package/dist/utils/providerUtils.d.ts +8 -1
  155. package/dist/utils/providerUtils.js +10 -1
  156. package/package.json +28 -20
@@ -0,0 +1,294 @@
1
+ /**
2
+ * PluginManager - Central Orchestrator for MCP Lifecycle
3
+ * Implements generic factory pattern with manifest-based discovery
4
+ * Based on research blueprint for extensible plugin architecture
5
+ */
6
+ import * as fs from "fs/promises";
7
+ import * as path from "path";
8
+ import { fileURLToPath } from "url";
9
+ import { dirname } from "path";
10
+ // ES Module compatibility
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ import { SecurityManager } from "./security-manager.js";
14
+ import { mcpLogger } from "./logging.js";
15
+ /**
16
+ * Central Plugin Manager implementing the research blueprint
17
+ */
18
+ export class PluginManager {
19
+ static instance;
20
+ mcpConstructors = new Map();
21
+ mcpInstances = new Map();
22
+ discoveredMCPs = new Map();
23
+ securityManager;
24
+ initialized = false;
25
+ config;
26
+ constructor(config = {}) {
27
+ this.config = {
28
+ enableDiscovery: true,
29
+ pluginDirectories: [],
30
+ securityLevel: "moderate",
31
+ maxPlugins: 50,
32
+ ...config,
33
+ };
34
+ this.securityManager = new SecurityManager(this.config.securityLevel);
35
+ }
36
+ /**
37
+ * Get the singleton instance
38
+ */
39
+ static getInstance(config) {
40
+ if (!PluginManager.instance) {
41
+ PluginManager.instance = new PluginManager(config);
42
+ }
43
+ return PluginManager.instance;
44
+ }
45
+ /**
46
+ * Initialize the plugin manager with discovery
47
+ */
48
+ async initialize() {
49
+ if (this.initialized) {
50
+ return;
51
+ }
52
+ mcpLogger.info("[PluginManager] Initializing plugin discovery...");
53
+ if (this.config.enableDiscovery) {
54
+ await this.discoverPlugins();
55
+ }
56
+ this.initialized = true;
57
+ mcpLogger.info(`[PluginManager] Initialized with ${this.discoveredMCPs.size} discovered plugins`);
58
+ }
59
+ /**
60
+ * Discover plugins following research blueprint priority:
61
+ * 1. Core plugins (bundled)
62
+ * 2. Project plugins (./neurolink-mcp/)
63
+ * 3. Installed plugins (node_modules)
64
+ */
65
+ async discoverPlugins() {
66
+ const functionTag = "PluginManager.discoverPlugins";
67
+ try {
68
+ // 1. Discover core plugins
69
+ await this.discoverCorePlugins();
70
+ // 2. Discover project plugins
71
+ await this.discoverProjectPlugins();
72
+ // 3. Discover installed plugins
73
+ await this.discoverInstalledPlugins();
74
+ mcpLogger.debug(`[${functionTag}] Discovery completed`, {
75
+ total: this.discoveredMCPs.size,
76
+ bySource: this.getDiscoveryStats(),
77
+ });
78
+ }
79
+ catch (error) {
80
+ mcpLogger.error(`[${functionTag}] Discovery failed:`, error);
81
+ }
82
+ }
83
+ /**
84
+ * Discover core plugins bundled with NeuroLink
85
+ */
86
+ async discoverCorePlugins() {
87
+ // Correctly resolve path from 'dist' to 'src'
88
+ const corePluginsPath = path.resolve(__dirname, "../../src/lib/mcp/plugins/core");
89
+ await this.discoverPluginsInDirectory(corePluginsPath, "core");
90
+ }
91
+ /**
92
+ * Discover project-local plugins
93
+ */
94
+ async discoverProjectPlugins() {
95
+ const projectPluginsPath = path.join(process.cwd(), "neurolink-mcp");
96
+ await this.discoverPluginsInDirectory(projectPluginsPath, "project");
97
+ }
98
+ /**
99
+ * Discover installed plugins from node_modules
100
+ */
101
+ async discoverInstalledPlugins() {
102
+ const nodeModulesPath = path.join(process.cwd(), "node_modules");
103
+ try {
104
+ const packages = await fs.readdir(nodeModulesPath);
105
+ for (const pkg of packages) {
106
+ if (pkg.startsWith(".")) {
107
+ continue;
108
+ }
109
+ const packagePath = path.join(nodeModulesPath, pkg);
110
+ const packageJsonPath = path.join(packagePath, "package.json");
111
+ try {
112
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
113
+ // Check for neurolink-mcp keyword
114
+ if (packageJson.keywords?.includes("neurolink-mcp")) {
115
+ await this.discoverPluginsInDirectory(packagePath, "installed");
116
+ }
117
+ }
118
+ catch {
119
+ // Skip invalid packages
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ // node_modules doesn't exist or not accessible
125
+ }
126
+ }
127
+ /**
128
+ * Discover plugins in a specific directory
129
+ */
130
+ async discoverPluginsInDirectory(dirPath, source) {
131
+ try {
132
+ const manifestPath = path.join(dirPath, "neurolink-mcp.json");
133
+ const manifestExists = await fs
134
+ .access(manifestPath)
135
+ .then(() => true)
136
+ .catch(() => false);
137
+ if (!manifestExists) {
138
+ return;
139
+ }
140
+ const manifest = JSON.parse(await fs.readFile(manifestPath, "utf-8"));
141
+ // Validate manifest
142
+ if (!this.validateManifest(manifest)) {
143
+ mcpLogger.warn(`[PluginManager] Invalid manifest in ${dirPath}`);
144
+ return;
145
+ }
146
+ // Now we know manifest is MCPMetadata due to type guard
147
+ const validatedManifest = manifest;
148
+ const entryPath = path
149
+ .resolve(dirPath, validatedManifest.main)
150
+ .replace(`${process.cwd()}/src/lib`, `${process.cwd()}/dist`);
151
+ this.discoveredMCPs.set(validatedManifest.name, {
152
+ metadata: validatedManifest,
153
+ entryPath,
154
+ source,
155
+ constructor: undefined, // Will be loaded on demand
156
+ });
157
+ mcpLogger.debug(`[PluginManager] Discovered ${validatedManifest.name} from ${source}`);
158
+ }
159
+ catch (error) {
160
+ mcpLogger.debug(`[PluginManager] Failed to discover plugin in ${dirPath}:`, error);
161
+ }
162
+ }
163
+ /**
164
+ * Validate manifest structure
165
+ */
166
+ validateManifest(manifest) {
167
+ if (!manifest || typeof manifest !== "object") {
168
+ return false;
169
+ }
170
+ const obj = manifest;
171
+ return (typeof obj.name === "string" &&
172
+ typeof obj.version === "string" &&
173
+ typeof obj.main === "string" &&
174
+ obj.engine?.neurolink &&
175
+ typeof obj.description === "string" &&
176
+ Array.isArray(obj.permissions));
177
+ }
178
+ /**
179
+ * Generic Factory Method - Creates type-safe MCP instances
180
+ * Core implementation of the research blueprint
181
+ */
182
+ async createInstance(name, config) {
183
+ const functionTag = "PluginManager.createInstance";
184
+ if (!this.initialized) {
185
+ await this.initialize();
186
+ }
187
+ // Check if already instantiated
188
+ const existingInstance = this.mcpInstances.get(name);
189
+ if (existingInstance) {
190
+ mcpLogger.debug(`[${functionTag}] Returning existing instance of ${name}`);
191
+ return existingInstance;
192
+ }
193
+ // Get constructor (load if necessary)
194
+ const Constructor = await this.getConstructor(name);
195
+ if (!Constructor) {
196
+ throw new Error(`MCP with name "${name}" is not registered or failed validation.`);
197
+ }
198
+ // Security check
199
+ const discovered = this.discoveredMCPs.get(name);
200
+ if (discovered &&
201
+ !this.securityManager.validatePermissions(discovered.metadata.permissions)) {
202
+ throw new Error(`Security validation failed for MCP "${name}"`);
203
+ }
204
+ try {
205
+ // Instantiate the class
206
+ const instance = new Constructor();
207
+ // Initialize with config
208
+ await instance.initialize(config);
209
+ // Store instance
210
+ this.mcpInstances.set(name, instance);
211
+ mcpLogger.info(`[${functionTag}] Created and initialized ${name}`);
212
+ return instance;
213
+ }
214
+ catch (error) {
215
+ mcpLogger.error(`[${functionTag}] Failed to create instance of ${name}:`, error);
216
+ throw error;
217
+ }
218
+ }
219
+ /**
220
+ * Get or load constructor for an MCP
221
+ */
222
+ async getConstructor(name) {
223
+ // Check if already loaded
224
+ const existingConstructor = this.mcpConstructors.get(name);
225
+ if (existingConstructor) {
226
+ return existingConstructor;
227
+ }
228
+ // Load from discovered plugins
229
+ const discovered = this.discoveredMCPs.get(name);
230
+ if (!discovered) {
231
+ return null;
232
+ }
233
+ try {
234
+ // Dynamic import of the plugin
235
+ const module = await import(discovered.entryPath);
236
+ const Constructor = module.default || module[discovered.metadata.name];
237
+ if (typeof Constructor !== "function") {
238
+ throw new Error(`Invalid export from ${discovered.entryPath}`);
239
+ }
240
+ // Store constructor
241
+ this.mcpConstructors.set(name, Constructor);
242
+ return Constructor;
243
+ }
244
+ catch (error) {
245
+ mcpLogger.error(`[PluginManager] Failed to load ${name} from ${discovered.entryPath}:`, error);
246
+ return null;
247
+ }
248
+ }
249
+ /**
250
+ * List all discovered MCPs
251
+ */
252
+ listDiscovered() {
253
+ return Array.from(this.discoveredMCPs.values()).map((d) => d.metadata);
254
+ }
255
+ /**
256
+ * Get metadata for a specific MCP
257
+ */
258
+ getMetadata(name) {
259
+ const discovered = this.discoveredMCPs.get(name);
260
+ return discovered ? discovered.metadata : null;
261
+ }
262
+ /**
263
+ * Get discovery statistics
264
+ */
265
+ getDiscoveryStats() {
266
+ const stats = { core: 0, project: 0, installed: 0 };
267
+ for (const discovered of this.discoveredMCPs.values()) {
268
+ stats[discovered.source]++;
269
+ }
270
+ return stats;
271
+ }
272
+ /**
273
+ * Dispose of all instances and cleanup
274
+ */
275
+ async dispose() {
276
+ mcpLogger.info("[PluginManager] Disposing all MCP instances...");
277
+ for (const [name, instance] of this.mcpInstances) {
278
+ try {
279
+ await instance.dispose();
280
+ mcpLogger.debug(`[PluginManager] Disposed ${name}`);
281
+ }
282
+ catch (error) {
283
+ mcpLogger.error(`[PluginManager] Failed to dispose ${name}:`, error);
284
+ }
285
+ }
286
+ this.mcpInstances.clear();
287
+ this.mcpConstructors.clear();
288
+ this.initialized = false;
289
+ }
290
+ }
291
+ /**
292
+ * Export singleton instance getter
293
+ */
294
+ export const pluginManager = PluginManager.getInstance();
@@ -0,0 +1,35 @@
1
+ /**
2
+ * FileSystemMCP - Proof of Concept Plugin
3
+ * Demonstrates the research blueprint implementation
4
+ */
5
+ import { MCP } from "../../contracts/mcp-contract.js";
6
+ import type { MCPMetadata, ExecutionContext } from "../../contracts/mcp-contract.js";
7
+ interface FileSystemConfig {
8
+ basePath: string;
9
+ allowedExtensions?: string[];
10
+ }
11
+ interface FileSystemArgs {
12
+ operation: "readFile" | "writeFile" | "listFiles" | "createDir";
13
+ path: string;
14
+ content?: string;
15
+ options?: any;
16
+ }
17
+ interface FileSystemResult {
18
+ success: boolean;
19
+ data?: any;
20
+ error?: string;
21
+ }
22
+ /**
23
+ * FileSystem MCP implementing the abstract contract
24
+ */
25
+ export declare class FileSystemMCP extends MCP<FileSystemConfig, FileSystemArgs, FileSystemResult> {
26
+ readonly metadata: MCPMetadata;
27
+ initialize(config: FileSystemConfig): Promise<void>;
28
+ execute(context: ExecutionContext, args: FileSystemArgs): Promise<FileSystemResult>;
29
+ private readFile;
30
+ private writeFile;
31
+ private listFiles;
32
+ private createDirectory;
33
+ dispose(): Promise<void>;
34
+ }
35
+ export default FileSystemMCP;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * FileSystemMCP - Proof of Concept Plugin
3
+ * Demonstrates the research blueprint implementation
4
+ */
5
+ import { MCP } from "../../contracts/mcp-contract.js";
6
+ import * as path from "path";
7
+ /**
8
+ * FileSystem MCP implementing the abstract contract
9
+ */
10
+ export class FileSystemMCP extends MCP {
11
+ metadata = {
12
+ name: "@neurolink-mcp/filesystem",
13
+ version: "1.0.0",
14
+ main: "./filesystem-mcp.js",
15
+ engine: {
16
+ neurolink: ">=1.9.0 <2.0.0",
17
+ },
18
+ description: "Provides secure file system operations for NeuroLink agents",
19
+ permissions: [
20
+ "fs:read:./**/*",
21
+ "fs:write:./output/**/*",
22
+ "fs:write:./temp/**/*",
23
+ ],
24
+ };
25
+ async initialize(config) {
26
+ if (!config.basePath) {
27
+ throw new Error("basePath is required in FileSystemMCP configuration");
28
+ }
29
+ this.config = {
30
+ allowedExtensions: [".txt", ".json", ".md", ".js", ".ts"],
31
+ ...config,
32
+ };
33
+ this.initialized = true;
34
+ }
35
+ async execute(context, args) {
36
+ this.log(context, "info", "Executing FileSystemMCP", { args });
37
+ this.log(context, "info", "Executing FileSystemMCP", { args });
38
+ this.log(context, "info", "Executing FileSystemMCP", { args });
39
+ this.ensureInitialized();
40
+ try {
41
+ if (!args.path) {
42
+ // This is a configuration call, not an operation
43
+ return { success: true, data: { configured: true } };
44
+ }
45
+ const fullPath = path.isAbsolute(args.path)
46
+ ? args.path
47
+ : context.path.join(this.config.basePath, args.path);
48
+ switch (args.operation) {
49
+ case "readFile":
50
+ return await this.readFile(context, fullPath);
51
+ case "writeFile":
52
+ return await this.writeFile(context, fullPath, args.content);
53
+ case "listFiles":
54
+ return await this.listFiles(context, fullPath);
55
+ case "createDir":
56
+ return await this.createDirectory(context, fullPath);
57
+ default:
58
+ throw new Error(`Unsupported operation: ${args.operation}`);
59
+ }
60
+ }
61
+ catch (error) {
62
+ this.log(context, "error", "Operation failed", {
63
+ operation: args.operation,
64
+ error,
65
+ });
66
+ return {
67
+ success: false,
68
+ error: error instanceof Error ? error.message : String(error),
69
+ };
70
+ }
71
+ }
72
+ async readFile(context, filePath) {
73
+ const content = await context.secureFS.readFile(filePath, "utf-8");
74
+ const stats = await context.secureFS.stat(filePath);
75
+ return {
76
+ success: true,
77
+ data: {
78
+ content,
79
+ size: stats.size,
80
+ lastModified: stats.mtime,
81
+ path: filePath,
82
+ },
83
+ };
84
+ }
85
+ async writeFile(context, filePath, content) {
86
+ await context.secureFS.writeFile(filePath, content);
87
+ return {
88
+ success: true,
89
+ data: {
90
+ path: filePath,
91
+ size: content.length,
92
+ written: true,
93
+ },
94
+ };
95
+ }
96
+ async listFiles(context, dirPath) {
97
+ const items = await context.secureFS.readdir(dirPath);
98
+ const itemDetails = [];
99
+ for (const item of items) {
100
+ const itemPath = context.path.join(dirPath, item);
101
+ try {
102
+ const stats = await context.secureFS.stat(itemPath);
103
+ itemDetails.push({
104
+ name: item,
105
+ type: stats.isDirectory() ? "directory" : "file",
106
+ size: stats.isFile() ? stats.size : undefined,
107
+ lastModified: stats.mtime,
108
+ });
109
+ }
110
+ catch {
111
+ // Skip inaccessible items
112
+ }
113
+ }
114
+ return {
115
+ success: true,
116
+ data: {
117
+ path: dirPath,
118
+ items: itemDetails,
119
+ count: itemDetails.length,
120
+ },
121
+ };
122
+ }
123
+ async createDirectory(context, dirPath) {
124
+ await context.secureFS.mkdir(dirPath, { recursive: true });
125
+ return {
126
+ success: true,
127
+ data: {
128
+ path: dirPath,
129
+ created: true,
130
+ },
131
+ };
132
+ }
133
+ async dispose() {
134
+ this.initialized = false;
135
+ this.config = undefined;
136
+ }
137
+ }
138
+ // Export as default for dynamic import
139
+ export default FileSystemMCP;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Enhanced FileSystem MCP Plugin
3
+ * Implements the new MCP contract with security sandbox
4
+ * Based on research document recommendations
5
+ */
6
+ import { MCP, MCPMetadata, ExecutionContext } from "../contracts/mcp-contract.js";
7
+ /**
8
+ * FileSystem MCP Configuration
9
+ */
10
+ export interface FileSystemConfig {
11
+ basePath: string;
12
+ allowedExtensions?: string[];
13
+ maxFileSize?: number;
14
+ readOnly?: boolean;
15
+ }
16
+ /**
17
+ * FileSystem Operation Arguments
18
+ */
19
+ export interface FileSystemArgs {
20
+ operation: "readFile" | "writeFile" | "listFiles" | "getFileInfo";
21
+ path: string;
22
+ content?: string;
23
+ encoding?: string;
24
+ }
25
+ /**
26
+ * Enhanced FileSystem MCP Plugin
27
+ */
28
+ export declare class FileSystemMCP extends MCP<FileSystemConfig> {
29
+ config: FileSystemConfig;
30
+ readonly metadata: MCPMetadata;
31
+ initialize(config: FileSystemConfig): Promise<void>;
32
+ execute(context: ExecutionContext, args: FileSystemArgs): Promise<any>;
33
+ private resolvePath;
34
+ dispose(): Promise<void>;
35
+ }
36
+ export declare function createFileSystemMCP(): FileSystemMCP;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Enhanced FileSystem MCP Plugin
3
+ * Implements the new MCP contract with security sandbox
4
+ * Based on research document recommendations
5
+ */
6
+ import path from "path";
7
+ import { MCP, } from "../contracts/mcp-contract.js";
8
+ /**
9
+ * Enhanced FileSystem MCP Plugin
10
+ */
11
+ export class FileSystemMCP extends MCP {
12
+ metadata = {
13
+ name: "@neurolink-mcp/filesystem",
14
+ version: "1.0.0",
15
+ main: "./dist/filesystem-mcp.js",
16
+ engine: { neurolink: ">=1.9.0 <2.0.0" },
17
+ description: "Secure file system operations with permission-based access control",
18
+ permissions: ["fs:read:./**/*", "fs:write:./output/**/*"],
19
+ };
20
+ async initialize(config) {
21
+ this.config = {
22
+ allowedExtensions: [".txt", ".md", ".json", ".js", ".ts"],
23
+ maxFileSize: 10 * 1024 * 1024,
24
+ readOnly: false,
25
+ ...config,
26
+ };
27
+ }
28
+ async execute(context, args) {
29
+ const resolvedPath = this.resolvePath(args.path);
30
+ switch (args.operation) {
31
+ case "readFile":
32
+ return await context.secureFS.readFile(resolvedPath, args.encoding || "utf-8");
33
+ case "listFiles":
34
+ return await context.secureFS.readdir(resolvedPath);
35
+ case "getFileInfo":
36
+ return await context.secureFS.stat(resolvedPath);
37
+ default:
38
+ throw new Error(`Unsupported operation: ${args.operation}`);
39
+ }
40
+ }
41
+ resolvePath(inputPath) {
42
+ const resolved = path.resolve(this.config.basePath, inputPath);
43
+ if (!resolved.startsWith(this.config.basePath)) {
44
+ throw new Error(`Path outside allowed directory: ${inputPath}`);
45
+ }
46
+ return resolved;
47
+ }
48
+ async dispose() {
49
+ // Cleanup resources
50
+ }
51
+ }
52
+ export function createFileSystemMCP() {
53
+ return new FileSystemMCP();
54
+ }