import { z } from 'zod'; import { Autowired } from '@opensumi/di'; import { AppConfig } from '@opensumi/ide-core-browser'; import { Deferred, Domain } from '@opensumi/ide-core-common'; import { ITerminalController, ITerminalGroupViewService } from '@opensumi/ide-terminal-next/lib/common/controller'; import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types'; import { TerminalToolComponent } from './components/Terminal'; import { RunCommandHandler, inputSchema } from './handlers/RunCommand'; @Domain(MCPServerContribution) export class RunTerminalCommandTool implements MCPServerContribution { @Autowired(ITerminalController) protected readonly terminalController: ITerminalController; @Autowired(AppConfig) protected readonly appConfig: AppConfig; @Autowired(ITerminalGroupViewService) protected readonly terminalView: ITerminalGroupViewService; @Autowired(RunCommandHandler) private readonly runCommandHandler: RunCommandHandler; registerMCPServer(registry: IMCPServerRegistry): void { registry.registerMCPTool(this.getToolDefinition()); registry.registerToolComponent('run_terminal_cmd', TerminalToolComponent); } getToolDefinition(): MCPToolDefinition { return { name: 'run_terminal_cmd', label: 'Run Command', order: 2, description: "PROPOSE a command to run on behalf of the user.\nIf you have this tool, note that you DO have the ability to run commands directly on the USER's system.\n\nAdhere to these rules:\n1. Based on the contents of the conversation, you will be told if you are in the same shell as a previous step or a new shell.\n2. If in a new shell, you should `cd` to the right directory and do necessary setup in addition to running the command.\n3. If in the same shell, the state will persist, no need to do things like `cd` to the same directory.\n4. For ANY commands that would use a pager, you should append ` | cat` to the command (or whatever is appropriate). You MUST do this for: git, less, head, tail, more, etc.\n5. For commands that are long running/expected to run indefinitely until interruption, such as server hosted, please run them in the background. To run jobs in the background, set `is_background` to true rather than changing the details of the command.\n6. Dont include any newlines in the command.", inputSchema, handler: this.handler.bind(this), }; } private async handler(args: z.infer & { toolCallId: string }, logger: MCPLogger) { return this.runCommandHandler.handler(args, logger); } }