@wonderwhy-er/desktop-commander
Version:
MCP server for terminal operations and file editing
218 lines (217 loc) • 7.71 kB
JavaScript
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,
};
}
}