conductor-node-mcp 12.25.0 → 12.27.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 (76) hide show
  1. package/README.md +13 -0
  2. package/code-tool-paths.cjs +6 -0
  3. package/code-tool-paths.cjs.map +1 -0
  4. package/code-tool-paths.d.cts +2 -0
  5. package/code-tool-paths.d.cts.map +1 -0
  6. package/code-tool-types.d.mts +14 -0
  7. package/code-tool-types.d.mts.map +1 -0
  8. package/code-tool-types.d.ts +14 -0
  9. package/code-tool-types.d.ts.map +1 -0
  10. package/code-tool-types.js +4 -0
  11. package/code-tool-types.js.map +1 -0
  12. package/code-tool-types.mjs +3 -0
  13. package/code-tool-types.mjs.map +1 -0
  14. package/code-tool-worker.d.mts +5 -0
  15. package/code-tool-worker.d.mts.map +1 -0
  16. package/code-tool-worker.d.ts +5 -0
  17. package/code-tool-worker.d.ts.map +1 -0
  18. package/code-tool-worker.js +45 -0
  19. package/code-tool-worker.js.map +1 -0
  20. package/code-tool-worker.mjs +40 -0
  21. package/code-tool-worker.mjs.map +1 -0
  22. package/code-tool.d.mts +12 -0
  23. package/code-tool.d.mts.map +1 -0
  24. package/code-tool.d.ts +12 -0
  25. package/code-tool.d.ts.map +1 -0
  26. package/code-tool.js +123 -0
  27. package/code-tool.js.map +1 -0
  28. package/code-tool.mjs +120 -0
  29. package/code-tool.mjs.map +1 -0
  30. package/compat.d.mts +3 -1
  31. package/compat.d.mts.map +1 -1
  32. package/compat.d.ts +3 -1
  33. package/compat.d.ts.map +1 -1
  34. package/compat.js +3 -1
  35. package/compat.js.map +1 -1
  36. package/compat.mjs +2 -0
  37. package/compat.mjs.map +1 -1
  38. package/headers.js +1 -1
  39. package/headers.js.map +1 -1
  40. package/headers.mjs +1 -1
  41. package/headers.mjs.map +1 -1
  42. package/http.d.mts.map +1 -1
  43. package/http.d.ts.map +1 -1
  44. package/http.js +18 -1
  45. package/http.js.map +1 -1
  46. package/http.mjs +18 -1
  47. package/http.mjs.map +1 -1
  48. package/index.js +1 -1
  49. package/index.js.map +1 -1
  50. package/index.mjs +2 -2
  51. package/index.mjs.map +1 -1
  52. package/options.d.mts +3 -1
  53. package/options.d.mts.map +1 -1
  54. package/options.d.ts +3 -1
  55. package/options.d.ts.map +1 -1
  56. package/options.js +121 -6
  57. package/options.js.map +1 -1
  58. package/options.mjs +120 -6
  59. package/options.mjs.map +1 -1
  60. package/package.json +8 -4
  61. package/server.d.mts.map +1 -1
  62. package/server.d.ts.map +1 -1
  63. package/server.js +8 -2
  64. package/server.js.map +1 -1
  65. package/server.mjs +6 -1
  66. package/server.mjs.map +1 -1
  67. package/src/code-tool-paths.cts +3 -0
  68. package/src/code-tool-types.ts +14 -0
  69. package/src/code-tool-worker.ts +46 -0
  70. package/src/code-tool.ts +146 -0
  71. package/src/compat.ts +3 -1
  72. package/src/headers.ts +1 -1
  73. package/src/http.ts +23 -2
  74. package/src/index.ts +2 -2
  75. package/src/options.ts +132 -7
  76. package/src/server.ts +4 -1
package/src/http.ts CHANGED
@@ -4,13 +4,33 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
4
4
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
5
5
 
6
6
  import express from 'express';
7
- import { McpOptions } from './options';
7
+ import { fromError } from 'zod-validation-error/v3';
8
+ import { McpOptions, parseQueryOptions } from './options';
8
9
  import { initMcpServer, newMcpServer } from './server';
9
10
  import { parseAuthHeaders } from './headers';
10
11
  import { Endpoint } from './tools';
11
12
 
12
- const newServer = (mcpOptions: McpOptions, req: express.Request, res: express.Response): McpServer | null => {
13
+ const newServer = (
14
+ defaultMcpOptions: McpOptions,
15
+ req: express.Request,
16
+ res: express.Response,
17
+ ): McpServer | null => {
13
18
  const server = newMcpServer();
19
+
20
+ let mcpOptions: McpOptions;
21
+ try {
22
+ mcpOptions = parseQueryOptions(defaultMcpOptions, req.query);
23
+ } catch (error) {
24
+ res.status(400).json({
25
+ jsonrpc: '2.0',
26
+ error: {
27
+ code: -32000,
28
+ message: `Invalid request: ${fromError(error)}`,
29
+ },
30
+ });
31
+ return null;
32
+ }
33
+
14
34
  try {
15
35
  const authOptions = parseAuthHeaders(req);
16
36
  initMcpServer({
@@ -71,6 +91,7 @@ const del = async (req: express.Request, res: express.Response) => {
71
91
 
72
92
  export const streamableHTTPApp = (options: McpOptions): express.Express => {
73
93
  const app = express();
94
+ app.set('query parser', 'extended');
74
95
  app.use(express.json());
75
96
 
76
97
  app.get('/', get);
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { selectTools } from './server';
4
4
  import { Endpoint, endpoints } from './tools';
5
- import { McpOptions, parseOptions } from './options';
5
+ import { McpOptions, parseCLIOptions } from './options';
6
6
  import { launchStdioServer } from './stdio';
7
7
  import { launchStreamableHTTPServer } from './http';
8
8
 
@@ -40,7 +40,7 @@ if (require.main === module) {
40
40
 
41
41
  function parseOptionsOrError() {
42
42
  try {
43
- return parseOptions();
43
+ return parseCLIOptions();
44
44
  } catch (error) {
45
45
  console.error('Error parsing options:', error);
46
46
  process.exit(1);
package/src/options.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import qs from 'qs';
1
2
  import yargs from 'yargs';
2
3
  import { hideBin } from 'yargs/helpers';
4
+ import z from 'zod';
3
5
  import { endpoints, Filter } from './tools';
4
6
  import { ClientCapabilities, knownClients, ClientType } from './compat';
5
7
 
@@ -14,6 +16,7 @@ export type McpOptions = {
14
16
  client: ClientType | undefined;
15
17
  includeDynamicTools: boolean | undefined;
16
18
  includeAllTools: boolean | undefined;
19
+ includeCodeTools: boolean | undefined;
17
20
  filters: Filter[];
18
21
  capabilities?: Partial<ClientCapabilities>;
19
22
  };
@@ -47,18 +50,18 @@ function parseCapabilityValue(cap: string): { name: Capability; value?: number }
47
50
  return { name: cap as Capability };
48
51
  }
49
52
 
50
- export function parseOptions(): CLIOptions {
53
+ export function parseCLIOptions(): CLIOptions {
51
54
  const opts = yargs(hideBin(process.argv))
52
55
  .option('tools', {
53
56
  type: 'string',
54
57
  array: true,
55
- choices: ['dynamic', 'all'],
58
+ choices: ['dynamic', 'all', 'code'],
56
59
  description: 'Use dynamic tools or all tools',
57
60
  })
58
61
  .option('no-tools', {
59
62
  type: 'string',
60
63
  array: true,
61
- choices: ['dynamic', 'all'],
64
+ choices: ['dynamic', 'all', 'code'],
62
65
  description: 'Do not use any dynamic or all tools',
63
66
  })
64
67
  .option('tool', {
@@ -249,11 +252,13 @@ export function parseOptions(): CLIOptions {
249
252
  }
250
253
  }
251
254
 
255
+ const shouldIncludeToolType = (toolType: 'dynamic' | 'all' | 'code') =>
256
+ explicitTools ? argv.tools?.includes(toolType) && !argv.noTools?.includes(toolType) : undefined;
257
+
252
258
  const explicitTools = Boolean(argv.tools || argv.noTools);
253
- const includeDynamicTools =
254
- explicitTools ? argv.tools?.includes('dynamic') && !argv.noTools?.includes('dynamic') : undefined;
255
- const includeAllTools =
256
- explicitTools ? argv.tools?.includes('all') && !argv.noTools?.includes('all') : undefined;
259
+ const includeDynamicTools = shouldIncludeToolType('dynamic');
260
+ const includeAllTools = shouldIncludeToolType('all');
261
+ const includeCodeTools = shouldIncludeToolType('code');
257
262
 
258
263
  const transport = argv.transport as 'stdio' | 'http';
259
264
 
@@ -262,6 +267,7 @@ export function parseOptions(): CLIOptions {
262
267
  client: client && knownClients[client] ? client : undefined,
263
268
  includeDynamicTools,
264
269
  includeAllTools,
270
+ includeCodeTools,
265
271
  filters,
266
272
  capabilities: clientCapabilities,
267
273
  list: argv.list || false,
@@ -271,6 +277,125 @@ export function parseOptions(): CLIOptions {
271
277
  };
272
278
  }
273
279
 
280
+ const coerceArray = <T extends z.ZodTypeAny>(zodType: T) =>
281
+ z.preprocess(
282
+ (val) =>
283
+ Array.isArray(val) ? val
284
+ : val ? [val]
285
+ : val,
286
+ z.array(zodType).optional(),
287
+ );
288
+
289
+ const QueryOptions = z.object({
290
+ tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Use dynamic tools or all tools'),
291
+ no_tools: coerceArray(z.enum(['dynamic', 'all'])).describe('Do not use dynamic tools or all tools'),
292
+ tool: coerceArray(z.string()).describe('Include tools matching the specified names'),
293
+ resource: coerceArray(z.string()).describe('Include tools matching the specified resources'),
294
+ operation: coerceArray(z.enum(['read', 'write'])).describe(
295
+ 'Include tools matching the specified operations',
296
+ ),
297
+ tag: coerceArray(z.string()).describe('Include tools with the specified tags'),
298
+ no_tool: coerceArray(z.string()).describe('Exclude tools matching the specified names'),
299
+ no_resource: coerceArray(z.string()).describe('Exclude tools matching the specified resources'),
300
+ no_operation: coerceArray(z.enum(['read', 'write'])).describe(
301
+ 'Exclude tools matching the specified operations',
302
+ ),
303
+ no_tag: coerceArray(z.string()).describe('Exclude tools with the specified tags'),
304
+ client: ClientType.optional().describe('Specify the MCP client being used'),
305
+ capability: coerceArray(z.string()).describe('Specify client capabilities'),
306
+ no_capability: coerceArray(z.enum(CAPABILITY_CHOICES)).describe('Unset client capabilities'),
307
+ });
308
+
309
+ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): McpOptions {
310
+ const queryObject = typeof query === 'string' ? qs.parse(query) : query;
311
+ const queryOptions = QueryOptions.parse(queryObject);
312
+
313
+ const filters: Filter[] = [...defaultOptions.filters];
314
+
315
+ for (const resource of queryOptions.resource || []) {
316
+ filters.push({ type: 'resource', op: 'include', value: resource });
317
+ }
318
+ for (const operation of queryOptions.operation || []) {
319
+ filters.push({ type: 'operation', op: 'include', value: operation });
320
+ }
321
+ for (const tag of queryOptions.tag || []) {
322
+ filters.push({ type: 'tag', op: 'include', value: tag });
323
+ }
324
+ for (const tool of queryOptions.tool || []) {
325
+ filters.push({ type: 'tool', op: 'include', value: tool });
326
+ }
327
+ for (const resource of queryOptions.no_resource || []) {
328
+ filters.push({ type: 'resource', op: 'exclude', value: resource });
329
+ }
330
+ for (const operation of queryOptions.no_operation || []) {
331
+ filters.push({ type: 'operation', op: 'exclude', value: operation });
332
+ }
333
+ for (const tag of queryOptions.no_tag || []) {
334
+ filters.push({ type: 'tag', op: 'exclude', value: tag });
335
+ }
336
+ for (const tool of queryOptions.no_tool || []) {
337
+ filters.push({ type: 'tool', op: 'exclude', value: tool });
338
+ }
339
+
340
+ // Parse client capabilities
341
+ const clientCapabilities: ClientCapabilities = {
342
+ topLevelUnions: true,
343
+ validJson: true,
344
+ refs: true,
345
+ unions: true,
346
+ formats: true,
347
+ toolNameLength: undefined,
348
+ ...defaultOptions.capabilities,
349
+ };
350
+
351
+ for (const cap of queryOptions.capability || []) {
352
+ const parsed = parseCapabilityValue(cap);
353
+ if (parsed.name === 'top-level-unions') {
354
+ clientCapabilities.topLevelUnions = true;
355
+ } else if (parsed.name === 'valid-json') {
356
+ clientCapabilities.validJson = true;
357
+ } else if (parsed.name === 'refs') {
358
+ clientCapabilities.refs = true;
359
+ } else if (parsed.name === 'unions') {
360
+ clientCapabilities.unions = true;
361
+ } else if (parsed.name === 'formats') {
362
+ clientCapabilities.formats = true;
363
+ } else if (parsed.name === 'tool-name-length') {
364
+ clientCapabilities.toolNameLength = parsed.value;
365
+ }
366
+ }
367
+
368
+ for (const cap of queryOptions.no_capability || []) {
369
+ if (cap === 'top-level-unions') {
370
+ clientCapabilities.topLevelUnions = false;
371
+ } else if (cap === 'valid-json') {
372
+ clientCapabilities.validJson = false;
373
+ } else if (cap === 'refs') {
374
+ clientCapabilities.refs = false;
375
+ } else if (cap === 'unions') {
376
+ clientCapabilities.unions = false;
377
+ } else if (cap === 'formats') {
378
+ clientCapabilities.formats = false;
379
+ } else if (cap === 'tool-name-length') {
380
+ clientCapabilities.toolNameLength = undefined;
381
+ }
382
+ }
383
+
384
+ return {
385
+ client: queryOptions.client ?? defaultOptions.client,
386
+ includeDynamicTools:
387
+ defaultOptions.includeDynamicTools ??
388
+ (queryOptions.tools?.includes('dynamic') && !queryOptions.no_tools?.includes('dynamic')),
389
+ includeAllTools:
390
+ defaultOptions.includeAllTools ??
391
+ (queryOptions.tools?.includes('all') && !queryOptions.no_tools?.includes('all')),
392
+ // Never include code tools on remote server.
393
+ includeCodeTools: undefined,
394
+ filters,
395
+ capabilities: clientCapabilities,
396
+ };
397
+ }
398
+
274
399
  function getCapabilitiesExplanation(): string {
275
400
  return `
276
401
  Client Capabilities Explanation:
package/src/server.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  parseEmbeddedJSON,
15
15
  } from './compat';
16
16
  import { dynamicTools } from './dynamic-tools';
17
+ import { codeTool } from './code-tool';
17
18
  import { McpOptions } from './options';
18
19
 
19
20
  export { McpOptions } from './options';
@@ -26,7 +27,7 @@ export const newMcpServer = () =>
26
27
  new McpServer(
27
28
  {
28
29
  name: 'conductor_node_api',
29
- version: '12.25.0',
30
+ version: '12.27.0',
30
31
  },
31
32
  { capabilities: { tools: {}, logging: {} } },
32
33
  );
@@ -100,6 +101,8 @@ export function selectTools(endpoints: Endpoint[], options: McpOptions): Endpoin
100
101
  includedTools = endpoints;
101
102
  } else if (options.includeDynamicTools) {
102
103
  includedTools = dynamicTools(endpoints);
104
+ } else if (options.includeCodeTools) {
105
+ includedTools = [codeTool()];
103
106
  } else {
104
107
  includedTools = endpoints;
105
108
  }