@juspay/neurolink 8.23.0 → 8.23.2

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 CHANGED
@@ -1,3 +1,15 @@
1
+ ## [8.23.2](https://github.com/juspay/neurolink/compare/v8.23.1...v8.23.2) (2025-12-27)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(format):** Add format validation to PDF image conversion ([bdd3285](https://github.com/juspay/neurolink/commit/bdd32855daa25d1e0fd1e94db6d97055fd5bd478))
6
+
7
+ ## [8.23.1](https://github.com/juspay/neurolink/compare/v8.23.0...v8.23.1) (2025-12-24)
8
+
9
+ ### Bug Fixes
10
+
11
+ - **(mcp):** Added Blocked Tool Support ([852d079](https://github.com/juspay/neurolink/commit/852d079371878d2a808ef6c0dc76103eb1d13a83))
12
+
1
13
  ## [8.23.0](https://github.com/juspay/neurolink/compare/v8.22.0...v8.23.0) (2025-12-23)
2
14
 
3
15
  ### Features
@@ -57,6 +57,15 @@ function isValidExternalMCPServerConfig(config) {
57
57
  return false;
58
58
  }
59
59
  const record = config;
60
+ // Validate blockedTools array contains only strings
61
+ if (record.blockedTools !== undefined) {
62
+ if (!Array.isArray(record.blockedTools)) {
63
+ return false;
64
+ }
65
+ if (!record.blockedTools.every((item) => typeof item === "string")) {
66
+ return false;
67
+ }
68
+ }
60
69
  return (typeof record.command === "string" &&
61
70
  (record.args === undefined || Array.isArray(record.args)) &&
62
71
  (record.env === undefined || isNonNullObject(record.env)) &&
@@ -202,6 +211,9 @@ export class ExternalServerManager extends EventEmitter {
202
211
  url: typeof serverConfig.url === "string"
203
212
  ? serverConfig.url
204
213
  : undefined,
214
+ blockedTools: Array.isArray(serverConfig.blockedTools)
215
+ ? serverConfig.blockedTools
216
+ : undefined,
205
217
  metadata: safeMetadataConversion(serverConfig.metadata),
206
218
  };
207
219
  const result = await this.addServer(serverId, externalConfig);
@@ -313,6 +325,9 @@ export class ExternalServerManager extends EventEmitter {
313
325
  url: typeof serverConfig.url === "string"
314
326
  ? serverConfig.url
315
327
  : undefined,
328
+ blockedTools: Array.isArray(serverConfig.blockedTools)
329
+ ? serverConfig.blockedTools
330
+ : undefined,
316
331
  metadata: safeMetadataConversion(serverConfig.metadata),
317
332
  };
318
333
  const result = await this.addServer(serverId, externalConfig);
@@ -403,6 +418,7 @@ export class ExternalServerManager extends EventEmitter {
403
418
  args: config.args,
404
419
  env: config.env,
405
420
  tools: [], // Will be populated after server connection
421
+ blockedTools: config.blockedTools,
406
422
  metadata: {
407
423
  category: "external",
408
424
  // Store additional ExternalMCPServerConfig fields in metadata
@@ -451,6 +467,7 @@ export class ExternalServerManager extends EventEmitter {
451
467
  autoRestart: serverInfo.metadata?.autoRestart,
452
468
  cwd: serverInfo.metadata?.cwd,
453
469
  url: serverInfo.metadata?.url,
470
+ blockedTools: serverInfo.blockedTools,
454
471
  metadata: safeMetadataConversion(serverInfo.metadata),
455
472
  };
456
473
  const validation = this.validateConfig(tempConfig);
@@ -1034,7 +1051,15 @@ export class ExternalServerManager extends EventEmitter {
1034
1051
  instance.toolsMap.clear();
1035
1052
  instance.toolsArray = undefined;
1036
1053
  instance.tools = [];
1054
+ const blockedTools = instance.blockedTools || [];
1055
+ let blockedCount = 0;
1037
1056
  for (const tool of discoveryResult.tools) {
1057
+ // Check if tool is blocked
1058
+ if (blockedTools.includes(tool.name)) {
1059
+ mcpLogger.info(`[ExternalServerManager] Blocking tool '${tool.name}' from server '${serverId}' (configured in blockedTools)`);
1060
+ blockedCount++;
1061
+ continue; // Skip blocked tools
1062
+ }
1038
1063
  instance.toolsMap.set(tool.name, tool);
1039
1064
  instance.tools.push({
1040
1065
  name: tool.name,
@@ -1042,7 +1067,7 @@ export class ExternalServerManager extends EventEmitter {
1042
1067
  inputSchema: tool.inputSchema,
1043
1068
  });
1044
1069
  }
1045
- mcpLogger.info(`[ExternalServerManager] Discovered ${discoveryResult.toolCount} tools for ${serverId}`);
1070
+ mcpLogger.info(`[ExternalServerManager] Discovered ${discoveryResult.toolCount} tools for ${serverId} (${blockedCount} blocked, ${instance.toolsMap.size} available)`);
1046
1071
  }
1047
1072
  else {
1048
1073
  mcpLogger.warn(`[ExternalServerManager] Tool discovery failed for ${serverId}: ${discoveryResult.error}`);
@@ -1135,6 +1160,11 @@ export class ExternalServerManager extends EventEmitter {
1135
1160
  if (instance.status !== "connected") {
1136
1161
  throw new Error(`Server '${serverId}' is not in connected state: ${instance.status}`);
1137
1162
  }
1163
+ // Check if tool is blocked
1164
+ const blockedTools = instance.blockedTools || [];
1165
+ if (blockedTools.includes(toolName)) {
1166
+ throw new Error(`Tool '${toolName}' is blocked on server '${serverId}' by configuration`);
1167
+ }
1138
1168
  const startTime = Date.now();
1139
1169
  try {
1140
1170
  // HITL Safety Check: Request confirmation if required
@@ -37,6 +37,8 @@ export type ExternalMCPServerConfig = {
37
37
  cwd?: string;
38
38
  /** URL for SSE/WebSocket transports */
39
39
  url?: string;
40
+ /** List of tool names to block/blacklist from this server */
41
+ blockedTools?: string[];
40
42
  /** Additional metadata */
41
43
  metadata?: Record<string, JsonValue>;
42
44
  };
@@ -51,6 +51,7 @@ export type MCPServerInfo = {
51
51
  cwd?: string;
52
52
  autoRestart?: boolean;
53
53
  healthCheckInterval?: number;
54
+ blockedTools?: string[];
54
55
  metadata?: {
55
56
  uptime?: number;
56
57
  toolCount?: number;
@@ -222,6 +222,10 @@ export class PDFProcessor {
222
222
  const scale = options?.scale || 2.0;
223
223
  const format = options?.format || "png";
224
224
  const quality = options?.quality || 0.9;
225
+ // Validate format
226
+ if (format !== "png" && format !== "jpeg") {
227
+ throw new Error(`Invalid format: "${format}". Supported formats: "png", "jpeg".`);
228
+ }
225
229
  let pdfDocument = null;
226
230
  try {
227
231
  const loadingTask = pdfjs.getDocument({
@@ -57,6 +57,15 @@ function isValidExternalMCPServerConfig(config) {
57
57
  return false;
58
58
  }
59
59
  const record = config;
60
+ // Validate blockedTools array contains only strings
61
+ if (record.blockedTools !== undefined) {
62
+ if (!Array.isArray(record.blockedTools)) {
63
+ return false;
64
+ }
65
+ if (!record.blockedTools.every((item) => typeof item === "string")) {
66
+ return false;
67
+ }
68
+ }
60
69
  return (typeof record.command === "string" &&
61
70
  (record.args === undefined || Array.isArray(record.args)) &&
62
71
  (record.env === undefined || isNonNullObject(record.env)) &&
@@ -202,6 +211,9 @@ export class ExternalServerManager extends EventEmitter {
202
211
  url: typeof serverConfig.url === "string"
203
212
  ? serverConfig.url
204
213
  : undefined,
214
+ blockedTools: Array.isArray(serverConfig.blockedTools)
215
+ ? serverConfig.blockedTools
216
+ : undefined,
205
217
  metadata: safeMetadataConversion(serverConfig.metadata),
206
218
  };
207
219
  const result = await this.addServer(serverId, externalConfig);
@@ -313,6 +325,9 @@ export class ExternalServerManager extends EventEmitter {
313
325
  url: typeof serverConfig.url === "string"
314
326
  ? serverConfig.url
315
327
  : undefined,
328
+ blockedTools: Array.isArray(serverConfig.blockedTools)
329
+ ? serverConfig.blockedTools
330
+ : undefined,
316
331
  metadata: safeMetadataConversion(serverConfig.metadata),
317
332
  };
318
333
  const result = await this.addServer(serverId, externalConfig);
@@ -403,6 +418,7 @@ export class ExternalServerManager extends EventEmitter {
403
418
  args: config.args,
404
419
  env: config.env,
405
420
  tools: [], // Will be populated after server connection
421
+ blockedTools: config.blockedTools,
406
422
  metadata: {
407
423
  category: "external",
408
424
  // Store additional ExternalMCPServerConfig fields in metadata
@@ -451,6 +467,7 @@ export class ExternalServerManager extends EventEmitter {
451
467
  autoRestart: serverInfo.metadata?.autoRestart,
452
468
  cwd: serverInfo.metadata?.cwd,
453
469
  url: serverInfo.metadata?.url,
470
+ blockedTools: serverInfo.blockedTools,
454
471
  metadata: safeMetadataConversion(serverInfo.metadata),
455
472
  };
456
473
  const validation = this.validateConfig(tempConfig);
@@ -1034,7 +1051,15 @@ export class ExternalServerManager extends EventEmitter {
1034
1051
  instance.toolsMap.clear();
1035
1052
  instance.toolsArray = undefined;
1036
1053
  instance.tools = [];
1054
+ const blockedTools = instance.blockedTools || [];
1055
+ let blockedCount = 0;
1037
1056
  for (const tool of discoveryResult.tools) {
1057
+ // Check if tool is blocked
1058
+ if (blockedTools.includes(tool.name)) {
1059
+ mcpLogger.info(`[ExternalServerManager] Blocking tool '${tool.name}' from server '${serverId}' (configured in blockedTools)`);
1060
+ blockedCount++;
1061
+ continue; // Skip blocked tools
1062
+ }
1038
1063
  instance.toolsMap.set(tool.name, tool);
1039
1064
  instance.tools.push({
1040
1065
  name: tool.name,
@@ -1042,7 +1067,7 @@ export class ExternalServerManager extends EventEmitter {
1042
1067
  inputSchema: tool.inputSchema,
1043
1068
  });
1044
1069
  }
1045
- mcpLogger.info(`[ExternalServerManager] Discovered ${discoveryResult.toolCount} tools for ${serverId}`);
1070
+ mcpLogger.info(`[ExternalServerManager] Discovered ${discoveryResult.toolCount} tools for ${serverId} (${blockedCount} blocked, ${instance.toolsMap.size} available)`);
1046
1071
  }
1047
1072
  else {
1048
1073
  mcpLogger.warn(`[ExternalServerManager] Tool discovery failed for ${serverId}: ${discoveryResult.error}`);
@@ -1135,6 +1160,11 @@ export class ExternalServerManager extends EventEmitter {
1135
1160
  if (instance.status !== "connected") {
1136
1161
  throw new Error(`Server '${serverId}' is not in connected state: ${instance.status}`);
1137
1162
  }
1163
+ // Check if tool is blocked
1164
+ const blockedTools = instance.blockedTools || [];
1165
+ if (blockedTools.includes(toolName)) {
1166
+ throw new Error(`Tool '${toolName}' is blocked on server '${serverId}' by configuration`);
1167
+ }
1138
1168
  const startTime = Date.now();
1139
1169
  try {
1140
1170
  // HITL Safety Check: Request confirmation if required
@@ -37,6 +37,8 @@ export type ExternalMCPServerConfig = {
37
37
  cwd?: string;
38
38
  /** URL for SSE/WebSocket transports */
39
39
  url?: string;
40
+ /** List of tool names to block/blacklist from this server */
41
+ blockedTools?: string[];
40
42
  /** Additional metadata */
41
43
  metadata?: Record<string, JsonValue>;
42
44
  };
@@ -51,6 +51,7 @@ export type MCPServerInfo = {
51
51
  cwd?: string;
52
52
  autoRestart?: boolean;
53
53
  healthCheckInterval?: number;
54
+ blockedTools?: string[];
54
55
  metadata?: {
55
56
  uptime?: number;
56
57
  toolCount?: number;
@@ -222,6 +222,10 @@ export class PDFProcessor {
222
222
  const scale = options?.scale || 2.0;
223
223
  const format = options?.format || "png";
224
224
  const quality = options?.quality || 0.9;
225
+ // Validate format
226
+ if (format !== "png" && format !== "jpeg") {
227
+ throw new Error(`Invalid format: "${format}". Supported formats: "png", "jpeg".`);
228
+ }
225
229
  let pdfDocument = null;
226
230
  try {
227
231
  const loadingTask = pdfjs.getDocument({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "8.23.0",
3
+ "version": "8.23.2",
4
4
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
5
5
  "author": {
6
6
  "name": "Juspay Technologies",