@silkweave/mcp 4.0.0 → 4.0.1
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/build/cliProxy.mjs +2 -2
- package/build/cliProxy.mjs.map +1 -1
- package/package.json +3 -3
package/build/cliProxy.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as parseResourceMessage } from "./result-uIqPNNxF.mjs";
|
|
2
2
|
import { createConsoleLogger } from "@silkweave/core";
|
|
3
|
-
import { kebabCase } from "change-case";
|
|
3
|
+
import { camelCase, kebabCase } from "change-case";
|
|
4
4
|
import { randomUUID } from "crypto";
|
|
5
5
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
6
6
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
@@ -83,7 +83,7 @@ const cliProxy = ({ url, formatter = defaultFormatter }) => {
|
|
|
83
83
|
}
|
|
84
84
|
const input = {};
|
|
85
85
|
for (const key of Object.keys(properties)) {
|
|
86
|
-
const value = args[key];
|
|
86
|
+
const value = args[camelCase(key)];
|
|
87
87
|
if (value !== void 0) input[key] = coerce(value, properties[key]?.type);
|
|
88
88
|
}
|
|
89
89
|
(await client.callTool({
|
package/build/cliProxy.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliProxy.mjs","names":[],"sources":["../src/adapter/cliProxy.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport { ContentBlock, LoggingMessageNotificationSchema, ProgressNotificationSchema, ToolResultContent } from '@modelcontextprotocol/sdk/types.js'\nimport { AdapterFactory, createConsoleLogger } from '@silkweave/core'\nimport { kebabCase } from 'change-case'\nimport { Command } from 'commander'\nimport { randomUUID } from 'crypto'\nimport { parseResourceMessage } from '../util/result.js'\n\nexport type CLIFormatterFn = (message: ContentBlock, index: number, messages: ContentBlock[]) => string | undefined\n\nexport interface CliProxyOptions {\n url: URL\n formatter?: CLIFormatterFn\n}\n\ninterface JsonSchemaProperty {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | string\n description?: string\n default?: unknown\n enum?: unknown[]\n}\n\ninterface JsonSchemaObject {\n type?: 'object'\n properties?: Record<string, JsonSchemaProperty>\n required?: string[]\n}\n\nfunction coerce(value: unknown, type: JsonSchemaProperty['type']): unknown {\n if (value === undefined) { return undefined }\n if (type === 'number' || type === 'integer') {\n const n = Number(value)\n return Number.isNaN(n) ? value : n\n }\n return value\n}\n\nfunction addCliOption(command: Command, key: string, prop: JsonSchemaProperty) {\n const flag = kebabCase(key)\n const description = prop.description\n const defaultValue = prop.default\n const type = prop.type\n if (type === 'boolean') {\n command.option(`--${flag}`, description, defaultValue as boolean | undefined)\n command.option(`--no-${flag}`)\n return\n }\n if (type === 'number' || type === 'integer') {\n command.option(`--${flag} <number>`, description, defaultValue as string | undefined)\n return\n }\n if (type === 'string' || prop.enum) {\n command.option(`--${flag} <string>`, description, defaultValue as string | undefined)\n return\n }\n if (type === 'object' || type === 'array') {\n command.option(`--${flag} <json>`, description ?? '', JSON.parse, defaultValue as never)\n return\n }\n throw new Error(`Unsupported JSON Schema type for CLI option \"${key}\": ${type ?? 'undefined'}`)\n}\n\nconst defaultFormatter: CLIFormatterFn = (message) => {\n if (message.type === 'text' && !message.text.includes('mcp://toolResult/')) {\n return `${message.text}`\n } else if (message.type === 'resource') {\n return parseResourceMessage(message)\n } else {\n return JSON.stringify(message)\n }\n}\n\nexport const cliProxy: AdapterFactory<CliProxyOptions> = ({ url, formatter = defaultFormatter }) => {\n return (options, baseContext) => {\n const context = baseContext.fork({ adapter: 'cliProxy' })\n const program = new Command()\n .name(options.name)\n .description(options.description)\n .version(options.version)\n .option('-s, --silent', 'Silent mode, prevent log messages', false)\n\n return {\n context,\n start: async () => {\n const client = new Client({\n name: options.name,\n description: options.description,\n version: options.version\n })\n const transport = new StreamableHTTPClientTransport(url)\n await client.connect(transport)\n const { tools } = await client.listTools()\n for (const tool of tools) {\n const name = kebabCase(tool.name)\n const command = program.command(name)\n if (tool.description) { command.description(tool.description) }\n const schema = tool.inputSchema as JsonSchemaObject\n const properties = schema.properties ?? {}\n for (const key of Object.keys(properties)) {\n addCliOption(command, key, properties[key])\n }\n command.action(async (args: Record<string, unknown>) => {\n const { silent } = program.opts<{ silent: boolean }>()\n const logger = createConsoleLogger()\n if (!silent) {\n console.info(`${options.name} - ${tool.name}`)\n client.setNotificationHandler(LoggingMessageNotificationSchema, ({ params: { level, data } }) => {\n logger[level](data)\n })\n client.setNotificationHandler(ProgressNotificationSchema, ({ params: { progress, total, message } }) => {\n logger.info({ progress, total, message })\n })\n }\n const input: Record<string, unknown> = {}\n for (const key of Object.keys(properties)) {\n const value = args[key]\n if (value !== undefined) { input[key] = coerce(value, properties[key]?.type) }\n }\n const response = await client.callTool({\n name: tool.name,\n arguments: input,\n _meta: { progressToken: randomUUID(), disposition: 'json' }\n }) as ToolResultContent\n response.content.forEach((message, index, messages) => {\n const text = formatter(message, index, messages)\n process.stdout.write(`${text}\\n`)\n })\n })\n }\n await program.parseAsync()\n await transport.close()\n },\n stop: async () => { /* noop */ }\n }\n }\n}\n"],"mappings":";;;;;;;;;AA6BA,SAAS,OAAO,OAAgB,MAA2C;AACzE,KAAI,UAAU,KAAA,EAAa;AAC3B,KAAI,SAAS,YAAY,SAAS,WAAW;EAC3C,MAAM,IAAI,OAAO,MAAM;AACvB,SAAO,OAAO,MAAM,EAAE,GAAG,QAAQ;;AAEnC,QAAO;;AAGT,SAAS,aAAa,SAAkB,KAAa,MAA0B;CAC7E,MAAM,OAAO,UAAU,IAAI;CAC3B,MAAM,cAAc,KAAK;CACzB,MAAM,eAAe,KAAK;CAC1B,MAAM,OAAO,KAAK;AAClB,KAAI,SAAS,WAAW;AACtB,UAAQ,OAAO,KAAK,QAAQ,aAAa,aAAoC;AAC7E,UAAQ,OAAO,QAAQ,OAAO;AAC9B;;AAEF,KAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,UAAQ,OAAO,KAAK,KAAK,YAAY,aAAa,aAAmC;AACrF;;AAEF,KAAI,SAAS,YAAY,KAAK,MAAM;AAClC,UAAQ,OAAO,KAAK,KAAK,YAAY,aAAa,aAAmC;AACrF;;AAEF,KAAI,SAAS,YAAY,SAAS,SAAS;AACzC,UAAQ,OAAO,KAAK,KAAK,UAAU,eAAe,IAAI,KAAK,OAAO,aAAsB;AACxF;;AAEF,OAAM,IAAI,MAAM,gDAAgD,IAAI,KAAK,QAAQ,cAAc;;AAGjG,MAAM,oBAAoC,YAAY;AACpD,KAAI,QAAQ,SAAS,UAAU,CAAC,QAAQ,KAAK,SAAS,oBAAoB,CACxE,QAAO,GAAG,QAAQ;UACT,QAAQ,SAAS,WAC1B,QAAO,qBAAqB,QAAQ;KAEpC,QAAO,KAAK,UAAU,QAAQ;;AAIlC,MAAa,YAA6C,EAAE,KAAK,YAAY,uBAAuB;AAClG,SAAQ,SAAS,gBAAgB;EAC/B,MAAM,UAAU,YAAY,KAAK,EAAE,SAAS,YAAY,CAAC;EACzD,MAAM,UAAU,IAAI,SAAS,CAC1B,KAAK,QAAQ,KAAK,CAClB,YAAY,QAAQ,YAAY,CAChC,QAAQ,QAAQ,QAAQ,CACxB,OAAO,gBAAgB,qCAAqC,MAAM;AAErE,SAAO;GACL;GACA,OAAO,YAAY;IACjB,MAAM,SAAS,IAAI,OAAO;KACxB,MAAM,QAAQ;KACd,aAAa,QAAQ;KACrB,SAAS,QAAQ;KAClB,CAAC;IACF,MAAM,YAAY,IAAI,8BAA8B,IAAI;AACxD,UAAM,OAAO,QAAQ,UAAU;IAC/B,MAAM,EAAE,UAAU,MAAM,OAAO,WAAW;AAC1C,SAAK,MAAM,QAAQ,OAAO;KACxB,MAAM,OAAO,UAAU,KAAK,KAAK;KACjC,MAAM,UAAU,QAAQ,QAAQ,KAAK;AACrC,SAAI,KAAK,YAAe,SAAQ,YAAY,KAAK,YAAY;KAE7D,MAAM,aADS,KAAK,YACM,cAAc,EAAE;AAC1C,UAAK,MAAM,OAAO,OAAO,KAAK,WAAW,CACvC,cAAa,SAAS,KAAK,WAAW,KAAK;AAE7C,aAAQ,OAAO,OAAO,SAAkC;MACtD,MAAM,EAAE,WAAW,QAAQ,MAA2B;MACtD,MAAM,SAAS,qBAAqB;AACpC,UAAI,CAAC,QAAQ;AACX,eAAQ,KAAK,GAAG,QAAQ,KAAK,KAAK,KAAK,OAAO;AAC9C,cAAO,uBAAuB,mCAAmC,EAAE,QAAQ,EAAE,OAAO,aAAa;AAC/F,eAAO,OAAO,KAAK;SACnB;AACF,cAAO,uBAAuB,6BAA6B,EAAE,QAAQ,EAAE,UAAU,OAAO,gBAAgB;AACtG,eAAO,KAAK;SAAE;SAAU;SAAO;SAAS,CAAC;SACzC;;MAEJ,MAAM,QAAiC,EAAE;AACzC,WAAK,MAAM,OAAO,OAAO,KAAK,WAAW,EAAE;
|
|
1
|
+
{"version":3,"file":"cliProxy.mjs","names":[],"sources":["../src/adapter/cliProxy.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport { ContentBlock, LoggingMessageNotificationSchema, ProgressNotificationSchema, ToolResultContent } from '@modelcontextprotocol/sdk/types.js'\nimport { AdapterFactory, createConsoleLogger } from '@silkweave/core'\nimport { camelCase, kebabCase } from 'change-case'\nimport { Command } from 'commander'\nimport { randomUUID } from 'crypto'\nimport { parseResourceMessage } from '../util/result.js'\n\nexport type CLIFormatterFn = (message: ContentBlock, index: number, messages: ContentBlock[]) => string | undefined\n\nexport interface CliProxyOptions {\n url: URL\n formatter?: CLIFormatterFn\n}\n\ninterface JsonSchemaProperty {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | string\n description?: string\n default?: unknown\n enum?: unknown[]\n}\n\ninterface JsonSchemaObject {\n type?: 'object'\n properties?: Record<string, JsonSchemaProperty>\n required?: string[]\n}\n\nfunction coerce(value: unknown, type: JsonSchemaProperty['type']): unknown {\n if (value === undefined) { return undefined }\n if (type === 'number' || type === 'integer') {\n const n = Number(value)\n return Number.isNaN(n) ? value : n\n }\n return value\n}\n\nfunction addCliOption(command: Command, key: string, prop: JsonSchemaProperty) {\n const flag = kebabCase(key)\n const description = prop.description\n const defaultValue = prop.default\n const type = prop.type\n if (type === 'boolean') {\n command.option(`--${flag}`, description, defaultValue as boolean | undefined)\n command.option(`--no-${flag}`)\n return\n }\n if (type === 'number' || type === 'integer') {\n command.option(`--${flag} <number>`, description, defaultValue as string | undefined)\n return\n }\n if (type === 'string' || prop.enum) {\n command.option(`--${flag} <string>`, description, defaultValue as string | undefined)\n return\n }\n if (type === 'object' || type === 'array') {\n command.option(`--${flag} <json>`, description ?? '', JSON.parse, defaultValue as never)\n return\n }\n throw new Error(`Unsupported JSON Schema type for CLI option \"${key}\": ${type ?? 'undefined'}`)\n}\n\nconst defaultFormatter: CLIFormatterFn = (message) => {\n if (message.type === 'text' && !message.text.includes('mcp://toolResult/')) {\n return `${message.text}`\n } else if (message.type === 'resource') {\n return parseResourceMessage(message)\n } else {\n return JSON.stringify(message)\n }\n}\n\nexport const cliProxy: AdapterFactory<CliProxyOptions> = ({ url, formatter = defaultFormatter }) => {\n return (options, baseContext) => {\n const context = baseContext.fork({ adapter: 'cliProxy' })\n const program = new Command()\n .name(options.name)\n .description(options.description)\n .version(options.version)\n .option('-s, --silent', 'Silent mode, prevent log messages', false)\n\n return {\n context,\n start: async () => {\n const client = new Client({\n name: options.name,\n description: options.description,\n version: options.version\n })\n const transport = new StreamableHTTPClientTransport(url)\n await client.connect(transport)\n const { tools } = await client.listTools()\n for (const tool of tools) {\n const name = kebabCase(tool.name)\n const command = program.command(name)\n if (tool.description) { command.description(tool.description) }\n const schema = tool.inputSchema as JsonSchemaObject\n const properties = schema.properties ?? {}\n for (const key of Object.keys(properties)) {\n addCliOption(command, key, properties[key])\n }\n command.action(async (args: Record<string, unknown>) => {\n const { silent } = program.opts<{ silent: boolean }>()\n const logger = createConsoleLogger()\n if (!silent) {\n console.info(`${options.name} - ${tool.name}`)\n client.setNotificationHandler(LoggingMessageNotificationSchema, ({ params: { level, data } }) => {\n logger[level](data)\n })\n client.setNotificationHandler(ProgressNotificationSchema, ({ params: { progress, total, message } }) => {\n logger.info({ progress, total, message })\n })\n }\n const input: Record<string, unknown> = {}\n for (const key of Object.keys(properties)) {\n // Options register as kebab-case flags (--action-id) and Commander stores them\n // camelized (actionId) — read back via camelCase(key) so snake_case schema keys\n // (action_id) map too, not just single-word ones.\n const value = args[camelCase(key)]\n if (value !== undefined) { input[key] = coerce(value, properties[key]?.type) }\n }\n const response = await client.callTool({\n name: tool.name,\n arguments: input,\n _meta: { progressToken: randomUUID(), disposition: 'json' }\n }) as ToolResultContent\n response.content.forEach((message, index, messages) => {\n const text = formatter(message, index, messages)\n process.stdout.write(`${text}\\n`)\n })\n })\n }\n await program.parseAsync()\n await transport.close()\n },\n stop: async () => { /* noop */ }\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silkweave/mcp",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Silkweave MCP Package",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://www.silkweave.dev",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
45
45
|
"change-case": "^5.4.4",
|
|
46
46
|
"zod": "^3.25.0",
|
|
47
|
-
"@silkweave/auth": "4.0.
|
|
48
|
-
"@silkweave/core": "4.0.
|
|
47
|
+
"@silkweave/auth": "4.0.1",
|
|
48
|
+
"@silkweave/core": "4.0.1"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"commander": "^13.1.0",
|