UNPKG

@wonderwhy-er/desktop-commander

Version:

MCP server for terminal operations and file editing

218 lines (217 loc) 7.71 kB
import { replManager } from '../repl-manager.js'; import { capture } from '../utils/capture.js'; import { CreateREPLSessionArgsSchema, ExecuteREPLCodeArgsSchema, TerminateREPLSessionArgsSchema, ListREPLSessionsArgsSchema, GetREPLSessionInfoArgsSchema } from './schemas.js'; /** * Create a new REPL session */ export async function createREPLSession(args) { const parsed = CreateREPLSessionArgsSchema.safeParse(args); if (!parsed.success) { capture('server_create_repl_session_failed', { error: 'Invalid arguments' }); return { content: [{ type: "text", text: `Error: Invalid arguments for create_repl_session: ${parsed.error}` }], isError: true, }; } try { const pid = await replManager.createSession(parsed.data.language, parsed.data.timeout); return { content: [{ type: "text", text: `Successfully created ${parsed.data.language} REPL session with PID ${pid}` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); capture('server_create_repl_session_error', { error: errorMessage }); return { content: [{ type: "text", text: `Error creating REPL session: ${errorMessage}` }], isError: true, }; } } /** * Execute code in a REPL session */ export async function executeREPLCode(args) { const parsed = ExecuteREPLCodeArgsSchema.safeParse(args); if (!parsed.success) { capture('server_execute_repl_code_failed', { error: 'Invalid arguments' }); return { content: [{ type: "text", text: `Error: Invalid arguments for execute_repl_code: ${parsed.error}` }], isError: true, }; } try { const result = await replManager.executeCode(parsed.data.pid, parsed.data.code, { timeout: parsed.data.timeout, waitForPrompt: parsed.data.waitForPrompt, ignoreErrors: parsed.data.ignoreErrors, multiline: parsed.data.multiline }); if (!result.success) { return { content: [{ type: "text", text: result.error ? `Error executing code: ${result.error}` : `Failed to execute code in REPL session ${parsed.data.pid}` + (result.timeout ? ` (timed out)` : '') + (result.output ? `\nOutput received: ${result.output}` : '') }], isError: true, }; } return { content: [{ type: "text", text: `Code executed in REPL session ${parsed.data.pid}` + (result.timeout ? ` (timed out, partial output below)` : '') + `\n\nOutput:\n${result.output || '(No output)'}` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); capture('server_execute_repl_code_error', { error: errorMessage }); return { content: [{ type: "text", text: `Error executing REPL code: ${errorMessage}` }], isError: true, }; } } /** * Terminate a REPL session */ export async function terminateREPLSession(args) { const parsed = TerminateREPLSessionArgsSchema.safeParse(args); if (!parsed.success) { capture('server_terminate_repl_session_failed', { error: 'Invalid arguments' }); return { content: [{ type: "text", text: `Error: Invalid arguments for terminate_repl_session: ${parsed.error}` }], isError: true, }; } try { const success = await replManager.terminateSession(parsed.data.pid); if (!success) { return { content: [{ type: "text", text: `Failed to terminate REPL session ${parsed.data.pid}. The session may have already ended.` }], isError: true, }; } return { content: [{ type: "text", text: `Successfully terminated REPL session ${parsed.data.pid}` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); capture('server_terminate_repl_session_error', { error: errorMessage }); return { content: [{ type: "text", text: `Error terminating REPL session: ${errorMessage}` }], isError: true, }; } } /** * List all active REPL sessions */ export async function listREPLSessions(args) { const parsed = ListREPLSessionsArgsSchema.safeParse(args); if (!parsed.success) { capture('server_list_repl_sessions_failed', { error: 'Invalid arguments' }); return { content: [{ type: "text", text: `Error: Invalid arguments for list_repl_sessions: ${parsed.error}` }], isError: true, }; } try { const sessions = replManager.listSessions(); if (sessions.length === 0) { return { content: [{ type: "text", text: `No active REPL sessions found` }], }; } const sessionsText = sessions.map(s => `PID: ${s.pid}, Language: ${s.language}, Runtime: ${Math.round(s.runtime / 1000)}s`).join('\n'); return { content: [{ type: "text", text: `Active REPL sessions:\n${sessionsText}` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); capture('server_list_repl_sessions_error', { error: errorMessage }); return { content: [{ type: "text", text: `Error listing REPL sessions: ${errorMessage}` }], isError: true, }; } } /** * Get information about a specific REPL session */ export async function getREPLSessionInfo(args) { const parsed = GetREPLSessionInfoArgsSchema.safeParse(args); if (!parsed.success) { capture('server_get_repl_session_info_failed', { error: 'Invalid arguments' }); return { content: [{ type: "text", text: `Error: Invalid arguments for get_repl_session_info: ${parsed.error}` }], isError: true, }; } try { const info = replManager.getSessionInfo(parsed.data.pid); if (!info) { return { content: [{ type: "text", text: `No active REPL session found with PID ${parsed.data.pid}` }], isError: true, }; } return { content: [{ type: "text", text: `REPL Session ${parsed.data.pid}:\nLanguage: ${info.language}\nRuntime: ${Math.round(info.runtime / 1000)}s` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); capture('server_get_repl_session_info_error', { error: errorMessage }); return { content: [{ type: "text", text: `Error getting REPL session info: ${errorMessage}` }], isError: true, }; } }