From b56735c5552816645bd8bd7b8ea51324b5a2e868 Mon Sep 17 00:00:00 2001 From: anzax <49080+anzax@users.noreply.github.com> Date: Thu, 5 Jun 2025 13:15:39 +0000 Subject: [PATCH 1/4] Enhance DockaShell configuration documentation with complete examples and improved organization --- docs/dockashell-configuration.md | 56 ++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/dockashell-configuration.md b/docs/dockashell-configuration.md index 52ec29a..d3f66b6 100644 --- a/docs/dockashell-configuration.md +++ b/docs/dockashell-configuration.md @@ -6,21 +6,73 @@ This document covers both global and project-specific configuration for DockaShe DockaShell stores global settings in `~/.dockashell/config.json`. This file controls system-wide behavior and default settings. -### Global Configuration Example +### Complete Global Configuration Example ```json { + "projects": { + "directory": "~/dockashell-projects" + }, + "tui": { + "display": { + "max_entries": 300 + } + }, "logging": { "traces": { "session_timeout": "4h" } + }, + "remote_mcp": { + "enabled": false, + "port": 3333, + "auth": { + "username": "admin", + "password": "changeme123" + }, + "cors": { + "origin": "*", + "credentials": true + }, + "session": { + "timeout": "24h" + } } } ``` ### Global Configuration Fields -- `logging.traces.session_timeout` – Time between trace entries before starting a new session (e.g., `"2h"`, `"4h"`) +#### Projects Configuration + +- `projects.directory` – Default directory where project files are stored (default: `"~/dockashell-projects"`) + +#### TUI Configuration + +- `tui.display.max_entries` – Maximum number of trace entries to display in the TUI log viewer (default: `300`) + +#### Logging Configuration + +- `logging.traces.session_timeout` – Time between trace entries before starting a new session (default: `"4h"`, formats: `"2h"`, `"30m"`) + +#### Remote MCP Server Configuration + +- `remote_mcp.enabled` – Enable remote MCP server for multi-user access (default: `false`) +- `remote_mcp.port` – Port for remote MCP server (default: `3333`) + +##### Authentication Settings + +- `remote_mcp.auth.username` – Username for authentication (default: `"admin"`) +- `remote_mcp.auth.password` – Password for authentication (default: `"changeme123"` - should be changed) + +##### CORS Settings + +- `remote_mcp.cors.origin` – Allowed origins for CORS requests (default: `"*"`) +- `remote_mcp.cors.credentials` – Allow credentials in CORS requests (default: `true`) + +##### Session Settings + +- `remote_mcp.session.timeout` – Session timeout for authenticated users (default: `"24h"`) ## Project Configuration From 5af5c0af8e729ac06a17654438af2897003e6595 Mon Sep 17 00:00:00 2001 From: anzax <49080+anzax@users.noreply.github.com> Date: Thu, 5 Jun 2025 13:30:32 +0000 Subject: [PATCH 2/4] Refactor tool registration to include descriptions for better clarity and usability --- src/mcp/remote/remote-mcp-server.js | 30 +++++++------- src/mcp/tools/execution-tools.js | 6 +++ src/mcp/tools/log-tools.js | 4 ++ src/mcp/tools/project-tools.js | 61 +++++++++++++++++++---------- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/src/mcp/remote/remote-mcp-server.js b/src/mcp/remote/remote-mcp-server.js index 4b4c529..89de4b1 100644 --- a/src/mcp/remote/remote-mcp-server.js +++ b/src/mcp/remote/remote-mcp-server.js @@ -1,16 +1,16 @@ -import express from 'express'; -import cors from 'cors'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import { SimpleAuth } from './auth/simple-auth.js'; -import { TransportManager } from './transport/transport-manager.js'; -import { registerProjectTools } from '../tools/project-tools.js'; -import { registerExecutionTools } from '../tools/execution-tools.js'; -import { registerLogTools } from '../tools/log-tools.js'; -import ProjectManager from '../../core/project-manager.js'; +import cors from 'cors'; +import express from 'express'; +import { v4 as uuidv4 } from 'uuid'; import ContainerManager from '../../core/container-manager.js'; +import ProjectManager from '../../core/project-manager.js'; import SecurityManager from '../../core/security.js'; import Logger from '../../utils/logger.js'; -import { v4 as uuidv4 } from 'uuid'; +import { registerExecutionTools } from '../tools/execution-tools.js'; +import { registerLogTools } from '../tools/log-tools.js'; +import { registerProjectTools } from '../tools/project-tools.js'; +import { SimpleAuth } from './auth/simple-auth.js'; +import { TransportManager } from './transport/transport-manager.js'; /** * Remote MCP Server with simple single-user authentication @@ -80,7 +80,7 @@ export class RemoteMCPServer { if (process.env.NODE_ENV !== 'production') { this.app.use((req, _res, next) => { if (req.method === 'OPTIONS') { - console.log('🔍 CORS Preflight Request:', { + console.log('CORS Preflight Request:', { origin: req.headers.origin, method: req.headers['access-control-request-method'], headers: req.headers['access-control-request-headers'], @@ -167,7 +167,7 @@ export class RemoteMCPServer { -

🐳 DockaShell Authentication

+

DockaShell Authentication

@@ -472,13 +472,11 @@ export class RemoteMCPServer { const server = this.app.listen(this.config.port, () => { console.log( - `🐳 DockaShell Remote MCP Server started on port ${this.config.port}` - ); - console.log( - `📊 Health check: http://localhost:${this.config.port}/health` + `DockaShell Remote MCP Server started on port ${this.config.port}` ); + console.log(`Health check: http://localhost:${this.config.port}/health`); console.log( - `🔐 OAuth discovery: http://localhost:${this.config.port}/.well-known/oauth-authorization-server` + `OAuth discovery: http://localhost:${this.config.port}/.well-known/oauth-authorization-server` ); }); diff --git a/src/mcp/tools/execution-tools.js b/src/mcp/tools/execution-tools.js index 60488bb..873859f 100644 --- a/src/mcp/tools/execution-tools.js +++ b/src/mcp/tools/execution-tools.js @@ -11,6 +11,8 @@ export function registerExecutionTools( server.tool( 'bash', { + description: + 'Executes shell commands in a project container. Avoid interactive commands (vim, nano, less, top) as they require TTY. Use non-interactive alternatives instead.', project_name: z.string().describe('Name of the project'), command: z.string().describe('Shell command to execute'), }, @@ -56,6 +58,8 @@ export function registerExecutionTools( server.tool( 'apply_patch', { + description: + 'Applies code patches using OpenAI format. Patch must start with "*** Begin Patch\n" and end with "\n*** End Patch". Use "*** Add File: path", "*** Update File: path", or "*** Delete File: path" followed by diff content with +/- lines.', project_name: z.string().describe('Name of the project'), patch: z .string() @@ -91,6 +95,8 @@ export function registerExecutionTools( server.tool( 'write_file', { + description: + 'Creates or overwrites files in a project container with the specified content', project_name: z.string().describe('Name of the project'), path: z.string().describe('File path inside container'), content: z.string().describe('File contents'), diff --git a/src/mcp/tools/log-tools.js b/src/mcp/tools/log-tools.js index 73f6719..f32b451 100644 --- a/src/mcp/tools/log-tools.js +++ b/src/mcp/tools/log-tools.js @@ -6,6 +6,8 @@ export function registerLogTools(server, logger) { server.tool( 'write_trace', { + description: + 'Records trace entries for auditing agent actions and preserving session context', project_name: z.string().describe('Project name'), type: z.enum(['user', 'summary', 'agent']).describe('Note type'), text: z.string().describe('Text to record'), @@ -24,6 +26,8 @@ export function registerLogTools(server, logger) { server.tool( 'read_traces', { + description: + 'Retrieves and filters trace history for a project, showing command executions, file operations, and notes with timestamps', project_name: z.string().describe('Project name'), type: z .string() diff --git a/src/mcp/tools/project-tools.js b/src/mcp/tools/project-tools.js index 51358db..bd07fdd 100644 --- a/src/mcp/tools/project-tools.js +++ b/src/mcp/tools/project-tools.js @@ -3,31 +3,42 @@ import { validateProjectName, textResponse } from './helpers.js'; export function registerProjectTools(server, projectManager, containerManager) { // List projects - server.tool('list_projects', {}, async () => { - try { - const projects = await projectManager.listProjects(); - let response = '# Configured Projects\n\n'; - if (projects.length === 0) { - response += - 'No projects configured. Create project configs in `~/.dockashell/projects/`\n'; - } else { - projects.forEach((project) => { - response += `**${project.name}**\n`; - response += `- Description: ${project.description || 'None'}\n`; - response += `- Image: ${project.image}\n`; - response += `- Status: ${project.status}\n\n`; - }); + server.tool( + 'list_projects', + { + description: + 'Lists all configured DockaShell projects with their status and configuration details', + }, + async () => { + try { + const projects = await projectManager.listProjects(); + let response = '# Configured Projects\n\n'; + if (projects.length === 0) { + response += + 'No projects configured. Create project configs in `~/.dockashell/projects/`\n'; + } else { + projects.forEach((project) => { + response += `**${project.name}**\n`; + response += `- Description: ${project.description || 'None'}\n`; + response += `- Image: ${project.image}\n`; + response += `- Status: ${project.status}\n\n`; + }); + } + return textResponse(response); + } catch (error) { + throw new Error(`Failed to list projects: ${error.message}`); } - return textResponse(response); - } catch (error) { - throw new Error(`Failed to list projects: ${error.message}`); } - }); + ); // Start project server.tool( 'start_project', - { project_name: z.string().describe('Name of the project to start') }, + { + description: + 'Starts a Docker container for the specified project with configured mounts and port forwarding', + project_name: z.string().describe('Name of the project to start'), + }, async ({ project_name }) => { validateProjectName(project_name); try { @@ -66,7 +77,11 @@ export function registerProjectTools(server, projectManager, containerManager) { // Stop project server.tool( 'stop_project', - { project_name: z.string().describe('Name of the project to stop') }, + { + description: + 'Stops the running Docker container for the specified project', + project_name: z.string().describe('Name of the project to stop'), + }, async ({ project_name }) => { validateProjectName(project_name); try { @@ -86,7 +101,11 @@ export function registerProjectTools(server, projectManager, containerManager) { // Project status server.tool( 'project_status', - { project_name: z.string().describe('Name of the project to check') }, + { + description: + 'Shows current status, configuration, and runtime details of a project container', + project_name: z.string().describe('Name of the project to check'), + }, async ({ project_name }) => { try { validateProjectName(project_name); From f66dc9c0b0a01547d235c3d5f78a31943f7bb358 Mon Sep 17 00:00:00 2001 From: anzax <49080+anzax@users.noreply.github.com> Date: Thu, 5 Jun 2025 13:50:48 +0000 Subject: [PATCH 3/4] fixes: tools description --- package.json | 1 + src/mcp/tools/execution-tools.js | 18 ++++++++++++------ src/mcp/tools/log-tools.js | 12 ++++++++---- src/mcp/tools/project-tools.js | 27 +++++++++++++++++---------- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 9431401..2713ac1 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dev:tui": "node src/tui/tui-launcher.js", "start": "node src/mcp/mcp-server.js", "start:remote": "node src/cli/cli.js remote", + "debug": "npx @modelcontextprotocol/inspector node src/mcp/mcp-server.js", "test": "node --test test/**/*.test.js", "test:integration": "node test/integration/test-*.js", "lint": "eslint .", diff --git a/src/mcp/tools/execution-tools.js b/src/mcp/tools/execution-tools.js index 873859f..e5ee1d6 100644 --- a/src/mcp/tools/execution-tools.js +++ b/src/mcp/tools/execution-tools.js @@ -11,8 +11,6 @@ export function registerExecutionTools( server.tool( 'bash', { - description: - 'Executes shell commands in a project container. Avoid interactive commands (vim, nano, less, top) as they require TTY. Use non-interactive alternatives instead.', project_name: z.string().describe('Name of the project'), command: z.string().describe('Shell command to execute'), }, @@ -51,6 +49,10 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } + }, + { + description: + 'Executes shell commands in a project container. Avoid interactive commands (vim, nano, less, top) as they require TTY. Use non-interactive alternatives instead.', } ); @@ -58,8 +60,6 @@ export function registerExecutionTools( server.tool( 'apply_patch', { - description: - 'Applies code patches using OpenAI format. Patch must start with "*** Begin Patch\n" and end with "\n*** End Patch". Use "*** Add File: path", "*** Update File: path", or "*** Delete File: path" followed by diff content with +/- lines.', project_name: z.string().describe('Name of the project'), patch: z .string() @@ -88,6 +88,10 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } + }, + { + description: + 'Applies code patches using OpenAI format. Patch must start with "*** Begin Patch\\n" and end with "\\n*** End Patch". Use "*** Add File: path", "*** Update File: path", or "*** Delete File: path" followed by diff content with +/- lines.', } ); @@ -95,8 +99,6 @@ export function registerExecutionTools( server.tool( 'write_file', { - description: - 'Creates or overwrites files in a project container with the specified content', project_name: z.string().describe('Name of the project'), path: z.string().describe('File path inside container'), content: z.string().describe('File contents'), @@ -128,6 +130,10 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } + }, + { + description: + 'Creates or overwrites files in a project container with the specified content', } ); } diff --git a/src/mcp/tools/log-tools.js b/src/mcp/tools/log-tools.js index f32b451..f7779bb 100644 --- a/src/mcp/tools/log-tools.js +++ b/src/mcp/tools/log-tools.js @@ -6,8 +6,6 @@ export function registerLogTools(server, logger) { server.tool( 'write_trace', { - description: - 'Records trace entries for auditing agent actions and preserving session context', project_name: z.string().describe('Project name'), type: z.enum(['user', 'summary', 'agent']).describe('Note type'), text: z.string().describe('Text to record'), @@ -19,6 +17,10 @@ export function registerLogTools(server, logger) { } catch (error) { throw new Error(`Failed to write trace: ${error.message}`); } + }, + { + description: + 'Records trace entries for auditing agent actions and preserving session context', } ); @@ -26,8 +28,6 @@ export function registerLogTools(server, logger) { server.tool( 'read_traces', { - description: - 'Retrieves and filters trace history for a project, showing command executions, file operations, and notes with timestamps', project_name: z.string().describe('Project name'), type: z .string() @@ -174,6 +174,10 @@ export function registerLogTools(server, logger) { } catch (error) { throw new Error(`Failed to read traces: ${error.message}`); } + }, + { + description: + 'Retrieves and filters trace history for a project, showing command executions, file operations, and notes with timestamps', } ); } diff --git a/src/mcp/tools/project-tools.js b/src/mcp/tools/project-tools.js index bd07fdd..d797197 100644 --- a/src/mcp/tools/project-tools.js +++ b/src/mcp/tools/project-tools.js @@ -5,10 +5,7 @@ export function registerProjectTools(server, projectManager, containerManager) { // List projects server.tool( 'list_projects', - { - description: - 'Lists all configured DockaShell projects with their status and configuration details', - }, + {}, async () => { try { const projects = await projectManager.listProjects(); @@ -28,6 +25,10 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { throw new Error(`Failed to list projects: ${error.message}`); } + }, + { + description: + 'Lists all configured DockaShell projects with their status and configuration details', } ); @@ -35,8 +36,6 @@ export function registerProjectTools(server, projectManager, containerManager) { server.tool( 'start_project', { - description: - 'Starts a Docker container for the specified project with configured mounts and port forwarding', project_name: z.string().describe('Name of the project to start'), }, async ({ project_name }) => { @@ -71,6 +70,10 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } + }, + { + description: + 'Starts a Docker container for the specified project with configured mounts and port forwarding', } ); @@ -78,8 +81,6 @@ export function registerProjectTools(server, projectManager, containerManager) { server.tool( 'stop_project', { - description: - 'Stops the running Docker container for the specified project', project_name: z.string().describe('Name of the project to stop'), }, async ({ project_name }) => { @@ -95,6 +96,10 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } + }, + { + description: + 'Stops the running Docker container for the specified project', } ); @@ -102,8 +107,6 @@ export function registerProjectTools(server, projectManager, containerManager) { server.tool( 'project_status', { - description: - 'Shows current status, configuration, and runtime details of a project container', project_name: z.string().describe('Name of the project to check'), }, async ({ project_name }) => { @@ -137,6 +140,10 @@ export function registerProjectTools(server, projectManager, containerManager) { `Failed to get status for project '${project_name}': ${error.message}` ); } + }, + { + description: + 'Shows current status, configuration, and runtime details of a project container', } ); } From 747132bd55eeea5c43d628d425d2f9985cc3a0b2 Mon Sep 17 00:00:00 2001 From: anzax <49080+anzax@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:32:50 +0000 Subject: [PATCH 4/4] Add descriptions to execution, log, and project tools for improved clarity --- src/mcp/tools/execution-tools.js | 15 +++------------ src/mcp/tools/log-tools.js | 10 ++-------- src/mcp/tools/project-tools.js | 20 ++++---------------- test/mcp/execution-tools.test.js | 14 ++++++++++++-- test/mcp/log-tools.test.js | 14 ++++++++++++-- test/mcp/project-tools.test.js | 14 ++++++++++++-- 6 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/mcp/tools/execution-tools.js b/src/mcp/tools/execution-tools.js index e5ee1d6..57106d2 100644 --- a/src/mcp/tools/execution-tools.js +++ b/src/mcp/tools/execution-tools.js @@ -10,6 +10,7 @@ export function registerExecutionTools( // Run command server.tool( 'bash', + 'Executes shell commands in a project container. Avoid interactive commands (vim, nano, less, top) as they require TTY. Use non-interactive alternatives instead.', { project_name: z.string().describe('Name of the project'), command: z.string().describe('Shell command to execute'), @@ -49,16 +50,13 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } - }, - { - description: - 'Executes shell commands in a project container. Avoid interactive commands (vim, nano, less, top) as they require TTY. Use non-interactive alternatives instead.', } ); // Apply patch server.tool( 'apply_patch', + 'Applies code patches using OpenAI format. Patch must start with "*** Begin Patch\\n" and end with "\\n*** End Patch". Use "*** Add File: path", "*** Update File: path", or "*** Delete File: path" followed by diff content with +/- lines.', { project_name: z.string().describe('Name of the project'), patch: z @@ -88,16 +86,13 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } - }, - { - description: - 'Applies code patches using OpenAI format. Patch must start with "*** Begin Patch\\n" and end with "\\n*** End Patch". Use "*** Add File: path", "*** Update File: path", or "*** Delete File: path" followed by diff content with +/- lines.', } ); // Write file server.tool( 'write_file', + 'Creates or overwrites files in a project container with the specified content', { project_name: z.string().describe('Name of the project'), path: z.string().describe('File path inside container'), @@ -130,10 +125,6 @@ export function registerExecutionTools( } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } - }, - { - description: - 'Creates or overwrites files in a project container with the specified content', } ); } diff --git a/src/mcp/tools/log-tools.js b/src/mcp/tools/log-tools.js index f7779bb..65bd298 100644 --- a/src/mcp/tools/log-tools.js +++ b/src/mcp/tools/log-tools.js @@ -5,6 +5,7 @@ export function registerLogTools(server, logger) { // Write trace note server.tool( 'write_trace', + 'Records trace entries for auditing agent actions and preserving session context', { project_name: z.string().describe('Project name'), type: z.enum(['user', 'summary', 'agent']).describe('Note type'), @@ -17,16 +18,13 @@ export function registerLogTools(server, logger) { } catch (error) { throw new Error(`Failed to write trace: ${error.message}`); } - }, - { - description: - 'Records trace entries for auditing agent actions and preserving session context', } ); // Read traces server.tool( 'read_traces', + 'Retrieves and filters trace history for a project, showing command executions, file operations, and notes with timestamps', { project_name: z.string().describe('Project name'), type: z @@ -174,10 +172,6 @@ export function registerLogTools(server, logger) { } catch (error) { throw new Error(`Failed to read traces: ${error.message}`); } - }, - { - description: - 'Retrieves and filters trace history for a project, showing command executions, file operations, and notes with timestamps', } ); } diff --git a/src/mcp/tools/project-tools.js b/src/mcp/tools/project-tools.js index d797197..58eab66 100644 --- a/src/mcp/tools/project-tools.js +++ b/src/mcp/tools/project-tools.js @@ -5,6 +5,7 @@ export function registerProjectTools(server, projectManager, containerManager) { // List projects server.tool( 'list_projects', + 'Lists all configured DockaShell projects with their status and configuration details', {}, async () => { try { @@ -25,16 +26,13 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { throw new Error(`Failed to list projects: ${error.message}`); } - }, - { - description: - 'Lists all configured DockaShell projects with their status and configuration details', } ); // Start project server.tool( 'start_project', + 'Starts a Docker container for the specified project with configured mounts and port forwarding', { project_name: z.string().describe('Name of the project to start'), }, @@ -70,16 +68,13 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } - }, - { - description: - 'Starts a Docker container for the specified project with configured mounts and port forwarding', } ); // Stop project server.tool( 'stop_project', + 'Stops the running Docker container for the specified project', { project_name: z.string().describe('Name of the project to stop'), }, @@ -96,16 +91,13 @@ export function registerProjectTools(server, projectManager, containerManager) { } catch (error) { return { ...textResponse(`Error: ${error.message}`), isError: true }; } - }, - { - description: - 'Stops the running Docker container for the specified project', } ); // Project status server.tool( 'project_status', + 'Shows current status, configuration, and runtime details of a project container', { project_name: z.string().describe('Name of the project to check'), }, @@ -140,10 +132,6 @@ export function registerProjectTools(server, projectManager, containerManager) { `Failed to get status for project '${project_name}': ${error.message}` ); } - }, - { - description: - 'Shows current status, configuration, and runtime details of a project container', } ); } diff --git a/test/mcp/execution-tools.test.js b/test/mcp/execution-tools.test.js index 3efaab3..118ed6d 100644 --- a/test/mcp/execution-tools.test.js +++ b/test/mcp/execution-tools.test.js @@ -5,8 +5,18 @@ import { registerExecutionTools } from '../../src/mcp/tools/execution-tools.js'; function createServer() { return { tools: {}, - tool(name, _schema, handler) { - this.tools[name] = { handler }; + tool(name, description, schema, handler) { + // Handle both 3-param (old) and 4-param (new) formats + if (typeof description === 'function') { + // 3-param format: tool(name, schema, handler) + this.tools[name] = { handler: description }; + } else if (typeof schema === 'function') { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler: schema }; + } else { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler }; + } }, }; } diff --git a/test/mcp/log-tools.test.js b/test/mcp/log-tools.test.js index cc67d4b..767ef5d 100644 --- a/test/mcp/log-tools.test.js +++ b/test/mcp/log-tools.test.js @@ -5,8 +5,18 @@ import { registerLogTools } from '../../src/mcp/tools/log-tools.js'; function createServer() { return { tools: {}, - tool(name, _schema, handler) { - this.tools[name] = { handler }; + tool(name, description, schema, handler) { + // Handle both 3-param (old) and 4-param (new) formats + if (typeof description === 'function') { + // 3-param format: tool(name, schema, handler) + this.tools[name] = { handler: description }; + } else if (typeof schema === 'function') { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler: schema }; + } else { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler }; + } }, }; } diff --git a/test/mcp/project-tools.test.js b/test/mcp/project-tools.test.js index 0058ad4..3ae0fd6 100644 --- a/test/mcp/project-tools.test.js +++ b/test/mcp/project-tools.test.js @@ -5,8 +5,18 @@ import { registerProjectTools } from '../../src/mcp/tools/project-tools.js'; function createServer() { return { tools: {}, - tool(name, _schema, handler) { - this.tools[name] = { handler }; + tool(name, description, schema, handler) { + // Handle both 3-param (old) and 4-param (new) formats + if (typeof description === 'function') { + // 3-param format: tool(name, schema, handler) + this.tools[name] = { handler: description }; + } else if (typeof schema === 'function') { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler: schema }; + } else { + // 4-param format: tool(name, description, schema, handler) + this.tools[name] = { handler }; + } }, }; }