Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/mcp/src/automationTools/terminal.ts
3520 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
7
import { ApplicationService } from '../application';
8
import { z } from 'zod';
9
10
/**
11
* Terminal Management Tools
12
*/
13
export function applyTerminalTools(server: McpServer, appService: ApplicationService): RegisteredTool[] {
14
const tools: RegisteredTool[] = [];
15
tools.push(server.tool(
16
'vscode_automation_terminal_create',
17
'Create a new terminal',
18
{
19
expectedLocation: z.enum(['editor', 'panel']).optional().describe('Expected location of terminal (editor or panel)')
20
},
21
async (args) => {
22
const { expectedLocation } = args;
23
const app = await appService.getOrCreateApplication();
24
await app.workbench.terminal.createTerminal(expectedLocation);
25
return {
26
content: [{
27
type: 'text' as const,
28
text: `Created new terminal${expectedLocation ? ` in ${expectedLocation}` : ''}`
29
}]
30
};
31
}
32
));
33
34
tools.push(server.tool(
35
'vscode_automation_terminal_run_command',
36
'Run a command in the terminal',
37
{
38
command: z.string().describe('Command to run in the terminal'),
39
skipEnter: z.boolean().optional().describe('Skip pressing enter after typing command')
40
},
41
async (args) => {
42
const { command, skipEnter } = args;
43
const app = await appService.getOrCreateApplication();
44
await app.workbench.terminal.runCommandInTerminal(command, skipEnter);
45
return {
46
content: [{
47
type: 'text' as const,
48
text: `Ran command in terminal: "${command}"`
49
}]
50
};
51
}
52
));
53
54
// Playwright can probably figure this out
55
// server.tool(
56
// 'vscode_automation_terminal_wait_for_text',
57
// 'Wait for specific text to appear in terminal output',
58
// {
59
// acceptFunction: z.string().describe('JavaScript function body that takes buffer array and returns boolean'),
60
// message: z.string().optional().describe('Optional message for waiting'),
61
// splitIndex: z.number().optional().describe('Split terminal index (0 or 1)')
62
// },
63
// async (args) => {
64
// const { acceptFunction, message, splitIndex } = args;
65
// // Create function from string
66
// const acceptFn = new Function('buffer', acceptFunction) as (buffer: string[]) => boolean;
67
// const terminalSplitIndex = splitIndex === 0 ? 0 : splitIndex === 1 ? 1 : undefined;
68
// await app.workbench.terminal.waitForTerminalText(acceptFn, message, terminalSplitIndex);
69
// return {
70
// content: [{
71
// type: 'text' as const,
72
// text: `Terminal text condition met: ${message || 'custom condition'}`
73
// }]
74
// };
75
// }
76
// );
77
78
tools.push(server.tool(
79
'vscode_automation_terminal_get_groups',
80
'Get current terminal groups information',
81
async () => {
82
const app = await appService.getOrCreateApplication();
83
const groups = await app.workbench.terminal.getTerminalGroups();
84
return {
85
content: [{
86
type: 'text' as const,
87
text: `Terminal groups:\n${JSON.stringify(groups, null, 2)}`
88
}]
89
};
90
}
91
));
92
93
// Seems too niche and redundant with runCommand tool
94
// server.tool(
95
// 'vscode_automation_terminal_run_command_by_id',
96
// 'Run a terminal command by ID',
97
// {
98
// commandId: z.enum([
99
// 'workbench.action.terminal.split',
100
// 'workbench.action.terminal.killAll',
101
// 'workbench.action.terminal.unsplit',
102
// 'workbench.action.terminal.join',
103
// 'workbench.action.terminal.toggleTerminal',
104
// 'workbench.action.createTerminalEditor',
105
// 'workbench.action.createTerminalEditorSide',
106
// 'workbench.action.terminal.moveToTerminalPanel',
107
// 'workbench.action.terminal.moveToEditor',
108
// 'workbench.action.terminal.newWithProfile',
109
// 'workbench.action.terminal.selectDefaultShell',
110
// 'workbench.action.terminal.detachSession',
111
// 'workbench.action.terminal.new'
112
// ]).describe('Terminal command ID to execute'),
113
// expectedLocation: z.enum(['editor', 'panel']).optional().describe('Expected location after command')
114
// },
115
// async (args) => {
116
// const { commandId, expectedLocation } = args;
117
// await app.workbench.terminal.runCommand(commandId as any, expectedLocation);
118
// return {
119
// content: [{
120
// type: 'text' as const,
121
// text: `Executed terminal command: ${commandId}`
122
// }]
123
// };
124
// }
125
// );
126
127
// Playwright can probably figure this out
128
// server.tool(
129
// 'vscode_automation_terminal_split',
130
// 'Split the current terminal',
131
// async () => {
132
// await app.workbench.terminal.clickSplitButton();
133
// return {
134
// content: [{
135
// type: 'text' as const,
136
// text: 'Split terminal'
137
// }]
138
// };
139
// }
140
// );
141
142
return tools;
143
}
144
145