terminator-mcp-agent 0.5.11 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/config.js +280 -0
- package/index.js +35 -227
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -43,7 +43,22 @@ You can also use the CLI to configure your app automatically:
|
|
|
43
43
|
npx -y terminator-mcp-agent --add-to-app [app]
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Replace `[app]` with one of:
|
|
46
|
+
Replace `[app]` with one of:
|
|
47
|
+
|
|
48
|
+
- cursor
|
|
49
|
+
- claude
|
|
50
|
+
- vscode
|
|
51
|
+
- insiders
|
|
52
|
+
- windsurf
|
|
53
|
+
- cline
|
|
54
|
+
- roocode
|
|
55
|
+
- witsy
|
|
56
|
+
- enconvo
|
|
57
|
+
- boltai
|
|
58
|
+
- amazon-bedrock
|
|
59
|
+
- amazonq
|
|
60
|
+
|
|
61
|
+
If you omit `[app]`, the CLI will prompt you to select from all available options.
|
|
47
62
|
|
|
48
63
|
---
|
|
49
64
|
|
package/config.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { execFileSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} ClientConfig
|
|
8
|
+
* @property {Object.<string, any>} mcpServers
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} ClientFileTarget
|
|
13
|
+
* @property {"file"} type
|
|
14
|
+
* @property {string} path
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} ClientCommandTarget
|
|
19
|
+
* @property {"command"} type
|
|
20
|
+
* @property {string} command
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// Initialize platform-specific paths
|
|
24
|
+
const homeDir = os.homedir();
|
|
25
|
+
|
|
26
|
+
const platformPaths = {
|
|
27
|
+
win32: {
|
|
28
|
+
baseDir: process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"),
|
|
29
|
+
vscodePath: path.join("Code", "User", "globalStorage"),
|
|
30
|
+
},
|
|
31
|
+
darwin: {
|
|
32
|
+
baseDir: path.join(homeDir, "Library", "Application Support"),
|
|
33
|
+
vscodePath: path.join("Code", "User", "globalStorage"),
|
|
34
|
+
},
|
|
35
|
+
linux: {
|
|
36
|
+
baseDir: process.env.XDG_CONFIG_HOME || path.join(homeDir, ".config"),
|
|
37
|
+
vscodePath: path.join("Code/User/globalStorage"),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const platform = process.platform;
|
|
42
|
+
const { baseDir, vscodePath } = platformPaths[platform] || platformPaths.linux;
|
|
43
|
+
const defaultClaudePath = path.join(
|
|
44
|
+
baseDir,
|
|
45
|
+
"Claude",
|
|
46
|
+
"claude_desktop_config.json",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Define client paths using the platform-specific base directories
|
|
50
|
+
const clientPaths = {
|
|
51
|
+
claude: { type: "file", path: defaultClaudePath },
|
|
52
|
+
cline: {
|
|
53
|
+
type: "file",
|
|
54
|
+
path: path.join(
|
|
55
|
+
baseDir,
|
|
56
|
+
vscodePath,
|
|
57
|
+
"saoudrizwan.claude-dev",
|
|
58
|
+
"settings",
|
|
59
|
+
"cline_mcp_settings.json",
|
|
60
|
+
),
|
|
61
|
+
},
|
|
62
|
+
roocode: {
|
|
63
|
+
type: "file",
|
|
64
|
+
path: path.join(
|
|
65
|
+
baseDir,
|
|
66
|
+
vscodePath,
|
|
67
|
+
"rooveterinaryinc.roo-cline",
|
|
68
|
+
"settings",
|
|
69
|
+
"mcp_settings.json",
|
|
70
|
+
),
|
|
71
|
+
},
|
|
72
|
+
windsurf: {
|
|
73
|
+
type: "file",
|
|
74
|
+
path: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
|
|
75
|
+
},
|
|
76
|
+
witsy: { type: "file", path: path.join(baseDir, "Witsy", "settings.json") },
|
|
77
|
+
enconvo: {
|
|
78
|
+
type: "file",
|
|
79
|
+
path: path.join(homeDir, ".config", "enconvo", "mcp_config.json"),
|
|
80
|
+
},
|
|
81
|
+
cursor: { type: "file", path: path.join(homeDir, ".cursor", "mcp.json") },
|
|
82
|
+
vscode: {
|
|
83
|
+
type: "command",
|
|
84
|
+
command: process.platform === "win32" ? "code.cmd" : "code",
|
|
85
|
+
},
|
|
86
|
+
"vscode-insiders": {
|
|
87
|
+
type: "command",
|
|
88
|
+
command:
|
|
89
|
+
process.platform === "win32" ? "code-insiders.cmd" : "code-insiders",
|
|
90
|
+
},
|
|
91
|
+
boltai: { type: "file", path: path.join(homeDir, ".boltai", "mcp.json") },
|
|
92
|
+
"amazon-bedrock": {
|
|
93
|
+
type: "file",
|
|
94
|
+
path: path.join(homeDir, "Amazon Bedrock Client", "mcp_config.json"),
|
|
95
|
+
},
|
|
96
|
+
amazonq: {
|
|
97
|
+
type: "file",
|
|
98
|
+
path: path.join(homeDir, ".aws", "amazonq", "mcp.json"),
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {string} [client]
|
|
104
|
+
* @returns {ClientFileTarget|ClientCommandTarget}
|
|
105
|
+
*/
|
|
106
|
+
function getConfigPath(client) {
|
|
107
|
+
const normalizedClient = client ? client.toLowerCase() : "claude";
|
|
108
|
+
verbose(`Getting config path for client: ${normalizedClient}`);
|
|
109
|
+
|
|
110
|
+
const configTarget = clientPaths[normalizedClient] || {
|
|
111
|
+
type: "file",
|
|
112
|
+
path: path.join(
|
|
113
|
+
path.dirname(defaultClaudePath),
|
|
114
|
+
"..",
|
|
115
|
+
client || "claude",
|
|
116
|
+
`${normalizedClient}_config.json`,
|
|
117
|
+
),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
verbose(`Config path resolved to: ${JSON.stringify(configTarget)}`);
|
|
121
|
+
return configTarget;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {string} client
|
|
126
|
+
* @returns {ClientConfig}
|
|
127
|
+
*/
|
|
128
|
+
function readConfig(client) {
|
|
129
|
+
verbose(`Reading config for client: ${client}`);
|
|
130
|
+
try {
|
|
131
|
+
const configPath = getConfigPath(client);
|
|
132
|
+
|
|
133
|
+
// Command-based installers (i.e. VS Code) do not currently support listing servers
|
|
134
|
+
if (configPath.type === "command") {
|
|
135
|
+
return { mcpServers: {} };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
verbose(`Checking if config file exists at: ${configPath.path}`);
|
|
139
|
+
if (!fs.existsSync(configPath.path)) {
|
|
140
|
+
verbose(`Config file not found, returning default empty config`);
|
|
141
|
+
return { mcpServers: {} };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
verbose(`Reading config file content`);
|
|
145
|
+
const rawConfig = JSON.parse(fs.readFileSync(configPath.path, "utf8"));
|
|
146
|
+
verbose(
|
|
147
|
+
`Config loaded successfully: ${JSON.stringify(rawConfig, null, 2)}`,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
...rawConfig,
|
|
152
|
+
mcpServers: rawConfig.mcpServers || {},
|
|
153
|
+
};
|
|
154
|
+
} catch (error) {
|
|
155
|
+
verbose(
|
|
156
|
+
`Error reading config: ${error instanceof Error ? error.stack : JSON.stringify(error)}`,
|
|
157
|
+
);
|
|
158
|
+
return { mcpServers: {} };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {ClientConfig} config
|
|
164
|
+
* @param {string} [client]
|
|
165
|
+
*/
|
|
166
|
+
function writeConfig(configObj, client) {
|
|
167
|
+
verbose(`Writing config for client: ${client || "default"}`);
|
|
168
|
+
verbose(`Config data: ${JSON.stringify(configObj, null, 2)}`);
|
|
169
|
+
|
|
170
|
+
if (!configObj.mcpServers || typeof configObj.mcpServers !== "object") {
|
|
171
|
+
verbose(`Invalid mcpServers structure in config`);
|
|
172
|
+
throw new Error("Invalid mcpServers structure");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const configPath = getConfigPath(client);
|
|
176
|
+
if (configPath.type === "command") {
|
|
177
|
+
writeConfigCommand(configObj, configPath);
|
|
178
|
+
} else {
|
|
179
|
+
writeConfigFile(configObj, configPath);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @param {ClientConfig} config
|
|
185
|
+
* @param {ClientCommandTarget} target
|
|
186
|
+
*/
|
|
187
|
+
function writeConfigCommand(config, target) {
|
|
188
|
+
const args = [];
|
|
189
|
+
for (const [name, server] of Object.entries(config.mcpServers)) {
|
|
190
|
+
args.push("--add-mcp", JSON.stringify({ ...server, name }));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
verbose(`Running command: ${JSON.stringify([target.command, ...args])}`);
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const output = execFileSync(target.command, args);
|
|
197
|
+
verbose(`Executed command successfully: ${output.toString()}`);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
verbose(
|
|
200
|
+
`Error executing command: ${error instanceof Error ? error.message : String(error)}`,
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
if (error && error.code === "ENOENT") {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Command '${target.command}' not found. Make sure ${target.command} is installed and on your PATH`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {ClientConfig} config
|
|
215
|
+
* @param {ClientFileTarget} target
|
|
216
|
+
*/
|
|
217
|
+
function writeConfigFile(config, target) {
|
|
218
|
+
const configDir = path.dirname(target.path);
|
|
219
|
+
|
|
220
|
+
verbose(`Ensuring config directory exists: ${configDir}`);
|
|
221
|
+
if (!fs.existsSync(configDir)) {
|
|
222
|
+
verbose(`Creating directory: ${configDir}`);
|
|
223
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let existingConfig = { mcpServers: {} };
|
|
227
|
+
try {
|
|
228
|
+
if (fs.existsSync(target.path)) {
|
|
229
|
+
verbose(`Reading existing config file for merging`);
|
|
230
|
+
existingConfig = JSON.parse(fs.readFileSync(target.path, "utf8"));
|
|
231
|
+
verbose(
|
|
232
|
+
`Existing config loaded: ${JSON.stringify(existingConfig, null, 2)}`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
verbose(
|
|
237
|
+
`Error reading existing config for merge: ${error instanceof Error ? error.message : String(error)}`,
|
|
238
|
+
);
|
|
239
|
+
// If reading fails, continue with empty existing config
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
verbose(`Merging configs`);
|
|
243
|
+
const mergedConfig = {
|
|
244
|
+
...existingConfig,
|
|
245
|
+
...config,
|
|
246
|
+
};
|
|
247
|
+
verbose(`Merged config: ${JSON.stringify(mergedConfig, null, 2)}`);
|
|
248
|
+
|
|
249
|
+
verbose(`Writing config to file: ${target.path}`);
|
|
250
|
+
fs.writeFileSync(target.path, JSON.stringify(mergedConfig, null, 2));
|
|
251
|
+
verbose(`Config successfully written`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function verbose(msg) {
|
|
255
|
+
if (process.env.MCP_VERBOSE) {
|
|
256
|
+
console.log(`[config] ${msg}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const supportedClients = [
|
|
261
|
+
{ key: "cursor", label: "Cursor" },
|
|
262
|
+
{ key: "claude", label: "Claude" },
|
|
263
|
+
{ key: "vscode", label: "VS Code" },
|
|
264
|
+
{ key: "insiders", label: "VS Code Insiders" },
|
|
265
|
+
{ key: "windsurf", label: "Windsurf" },
|
|
266
|
+
{ key: "cline", label: "Cline" },
|
|
267
|
+
{ key: "roocode", label: "RooCode" },
|
|
268
|
+
{ key: "witsy", label: "Witsy" },
|
|
269
|
+
{ key: "enconvo", label: "Enconvo" },
|
|
270
|
+
{ key: "boltai", label: "BoltAI" },
|
|
271
|
+
{ key: "amazon-bedrock", label: "Amazon Bedrock" },
|
|
272
|
+
{ key: "amazonq", label: "Amazon Q" },
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
module.exports = {
|
|
276
|
+
getConfigPath,
|
|
277
|
+
readConfig,
|
|
278
|
+
writeConfig,
|
|
279
|
+
supportedClients,
|
|
280
|
+
};
|
package/index.js
CHANGED
|
@@ -5,6 +5,8 @@ const path = require("path");
|
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const os = require("os");
|
|
7
7
|
const readline = require("readline");
|
|
8
|
+
const config = require("./config");
|
|
9
|
+
const { supportedClients } = require("./config");
|
|
8
10
|
|
|
9
11
|
function getPlatformInfo() {
|
|
10
12
|
const platform = process.platform;
|
|
@@ -36,209 +38,24 @@ function getPlatformInfo() {
|
|
|
36
38
|
throw new Error(`Unsupported platform: ${platform} ${arch}`);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
function
|
|
40
|
-
return {
|
|
41
|
-
command: "npx",
|
|
42
|
-
args: ["-y", "terminator-mcp-agent"],
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function addToCursorConfig() {
|
|
47
|
-
const home = os.homedir();
|
|
48
|
-
const configDir = path.join(home, ".cursor");
|
|
49
|
-
const configFile = path.join(configDir, "mcp.json");
|
|
50
|
-
if (!fs.existsSync(configDir)) {
|
|
51
|
-
fs.mkdirSync(configDir, { recursive: true });
|
|
52
|
-
}
|
|
53
|
-
let config = {};
|
|
54
|
-
if (fs.existsSync(configFile)) {
|
|
55
|
-
try {
|
|
56
|
-
config = JSON.parse(fs.readFileSync(configFile, "utf8"));
|
|
57
|
-
} catch (e) {
|
|
58
|
-
config = {};
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
62
|
-
config.mcpServers = {};
|
|
63
|
-
}
|
|
64
|
-
config.mcpServers["terminator-mcp-agent"] = getMcpServerEntry();
|
|
65
|
-
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
66
|
-
console.log(`Cursor configuration saved to ${configFile}`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function addToClaudeConfig() {
|
|
70
|
-
const platform = process.platform;
|
|
71
|
-
let configDir, configFile;
|
|
72
|
-
if (platform === "win32") {
|
|
73
|
-
const appData =
|
|
74
|
-
process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
75
|
-
configDir = path.join(appData, "Claude");
|
|
76
|
-
configFile = path.join(configDir, "claude_desktop_config.json");
|
|
77
|
-
} else if (platform === "darwin") {
|
|
78
|
-
configDir = path.join(
|
|
79
|
-
os.homedir(),
|
|
80
|
-
"Library",
|
|
81
|
-
"Application Support",
|
|
82
|
-
"Claude",
|
|
83
|
-
);
|
|
84
|
-
configFile = path.join(configDir, "claude_desktop_config.json");
|
|
85
|
-
} else {
|
|
86
|
-
console.error("Claude desktop is only supported on Windows and macOS.");
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
if (!fs.existsSync(configDir)) {
|
|
90
|
-
console.error(
|
|
91
|
-
`Claude desktop config directory does not exist: ${configDir}\nPlease make sure the Claude desktop app is installed for your platform.`,
|
|
92
|
-
);
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
let config = {};
|
|
96
|
-
if (fs.existsSync(configFile)) {
|
|
97
|
-
try {
|
|
98
|
-
config = JSON.parse(fs.readFileSync(configFile, "utf8"));
|
|
99
|
-
} catch (e) {
|
|
100
|
-
config = {};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
104
|
-
config.mcpServers = {};
|
|
105
|
-
}
|
|
106
|
-
config.mcpServers["terminator-mcp-agent"] = getMcpServerEntry();
|
|
107
|
-
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
108
|
-
console.log(`Claude configuration saved to ${configFile}`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function buildVSCodeMcpJsonArg(mcpJson) {
|
|
112
|
-
// VS Code expects: --add-mcp "{\"name\":\"...\",...}"
|
|
113
|
-
return `"${JSON.stringify(mcpJson).replace(/"/g, '\\"')}"`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function addToVSCodeConfig() {
|
|
117
|
-
// VS Code CLI-based setup
|
|
118
|
-
console.log("Adding Terminator MCP to VS Code via code CLI...");
|
|
119
|
-
const mcpJson = {
|
|
120
|
-
name: "terminator-mcp-agent",
|
|
121
|
-
command: "npx",
|
|
122
|
-
args: ["-y", "terminator-mcp-agent"],
|
|
123
|
-
};
|
|
124
|
-
const jsonArg = buildVSCodeMcpJsonArg(mcpJson);
|
|
125
|
-
const vscodeCmd = "code";
|
|
126
|
-
try {
|
|
127
|
-
const { spawnSync } = require("child_process");
|
|
128
|
-
const result = spawnSync(`${vscodeCmd} --add-mcp ${jsonArg}`, [], {
|
|
129
|
-
stdio: "inherit",
|
|
130
|
-
shell: true,
|
|
131
|
-
});
|
|
132
|
-
if (result.error) {
|
|
133
|
-
if (result.error.code === "ENOENT") {
|
|
134
|
-
console.error(
|
|
135
|
-
"'code' command not found in PATH. Make sure VS Code CLI is installed and available.",
|
|
136
|
-
);
|
|
137
|
-
} else {
|
|
138
|
-
console.error("Failed to launch VS Code CLI:", result.error.message);
|
|
139
|
-
}
|
|
140
|
-
process.exit(1);
|
|
141
|
-
}
|
|
142
|
-
if (result.status !== 0) {
|
|
143
|
-
console.error(`VS Code CLI exited with code ${result.status}`);
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
console.log("Successfully added Terminator MCP to VS Code.");
|
|
147
|
-
} catch (e) {
|
|
148
|
-
console.error("Failed to add MCP to VS Code:", e.message);
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function addToVSCodeInsidersConfig() {
|
|
154
|
-
// VS Code Insiders CLI-based setup
|
|
155
|
-
console.log(
|
|
156
|
-
"Adding Terminator MCP to VS Code Insiders via code-insiders CLI...",
|
|
157
|
-
);
|
|
158
|
-
const mcpJson = {
|
|
159
|
-
name: "terminator-mcp-agent",
|
|
160
|
-
command: "npx",
|
|
161
|
-
args: ["-y", "terminator-mcp-agent"],
|
|
162
|
-
};
|
|
163
|
-
const jsonArg = buildVSCodeMcpJsonArg(mcpJson);
|
|
164
|
-
const codeInsidersCmd = "code-insiders";
|
|
41
|
+
function addToApp(app) {
|
|
165
42
|
try {
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
} else {
|
|
177
|
-
console.error(
|
|
178
|
-
"Failed to launch VS Code Insiders CLI:",
|
|
179
|
-
result.error.message,
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
process.exit(1);
|
|
183
|
-
}
|
|
184
|
-
if (result.status !== 0) {
|
|
185
|
-
console.error(`VS Code Insiders CLI exited with code ${result.status}`);
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
console.log("Successfully added Terminator MCP to VS Code Insiders.");
|
|
43
|
+
const client = (app || "").toLowerCase();
|
|
44
|
+
const mcpServer = {
|
|
45
|
+
command: "npx",
|
|
46
|
+
args: ["-y", "terminator-mcp-agent"],
|
|
47
|
+
};
|
|
48
|
+
const currentConfig = config.readConfig(client);
|
|
49
|
+
currentConfig.mcpServers = currentConfig.mcpServers || {};
|
|
50
|
+
currentConfig.mcpServers["terminator-mcp-agent"] = mcpServer;
|
|
51
|
+
config.writeConfig(currentConfig, client);
|
|
52
|
+
console.log(`Configured MCP for ${client}`);
|
|
189
53
|
} catch (e) {
|
|
190
|
-
console.error(
|
|
54
|
+
console.error(`Failed to configure MCP for ${app}:`, e.message);
|
|
191
55
|
process.exit(1);
|
|
192
56
|
}
|
|
193
57
|
}
|
|
194
58
|
|
|
195
|
-
function addToWindsurfConfig() {
|
|
196
|
-
// Windsurf config: %USERPROFILE%/.codeium/windsurf/mcp_config.json
|
|
197
|
-
const home = os.homedir();
|
|
198
|
-
const configDir = path.join(home, ".codeium", "windsurf");
|
|
199
|
-
const configFile = path.join(configDir, "mcp_config.json");
|
|
200
|
-
if (!fs.existsSync(configDir)) {
|
|
201
|
-
fs.mkdirSync(configDir, { recursive: true });
|
|
202
|
-
}
|
|
203
|
-
let config = {};
|
|
204
|
-
if (fs.existsSync(configFile)) {
|
|
205
|
-
try {
|
|
206
|
-
config = JSON.parse(fs.readFileSync(configFile, "utf8"));
|
|
207
|
-
} catch (e) {
|
|
208
|
-
config = {};
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
212
|
-
config.mcpServers = {};
|
|
213
|
-
}
|
|
214
|
-
config.mcpServers["terminator-mcp-agent"] = getMcpServerEntry();
|
|
215
|
-
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
216
|
-
console.log(`Windsurf configuration saved to ${configFile}`);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function addToApp(app) {
|
|
220
|
-
switch ((app || "").toLowerCase()) {
|
|
221
|
-
case "cursor":
|
|
222
|
-
addToCursorConfig();
|
|
223
|
-
break;
|
|
224
|
-
case "claude":
|
|
225
|
-
addToClaudeConfig();
|
|
226
|
-
break;
|
|
227
|
-
case "vscode":
|
|
228
|
-
addToVSCodeConfig();
|
|
229
|
-
break;
|
|
230
|
-
case "insiders":
|
|
231
|
-
addToVSCodeInsidersConfig();
|
|
232
|
-
break;
|
|
233
|
-
case "windsurf":
|
|
234
|
-
addToWindsurfConfig();
|
|
235
|
-
break;
|
|
236
|
-
default:
|
|
237
|
-
console.error("Unknown app: " + app);
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
59
|
const argv = process.argv.slice(2);
|
|
243
60
|
|
|
244
61
|
if (argv.includes("--add-to-app")) {
|
|
@@ -256,39 +73,27 @@ if (argv.includes("--add-to-app")) {
|
|
|
256
73
|
console.log("========== Terminator MCP Setup ==========");
|
|
257
74
|
console.log("Which app do you want to configure Terminator MCP for?");
|
|
258
75
|
console.log("");
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
76
|
+
const pad = (n) =>
|
|
77
|
+
String(n).padStart(String(supportedClients.length).length, " ");
|
|
78
|
+
supportedClients.forEach((client, idx) => {
|
|
79
|
+
console.log(` ${pad(idx + 1)}. ${client.label}`);
|
|
80
|
+
});
|
|
264
81
|
console.log("");
|
|
265
|
-
rl.question(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
break;
|
|
271
|
-
case "2":
|
|
272
|
-
selectedApp = "claude";
|
|
273
|
-
break;
|
|
274
|
-
case "3":
|
|
275
|
-
selectedApp = "vscode";
|
|
276
|
-
break;
|
|
277
|
-
case "4":
|
|
278
|
-
selectedApp = "insiders";
|
|
279
|
-
break;
|
|
280
|
-
case "5":
|
|
281
|
-
selectedApp = "windsurf";
|
|
282
|
-
break;
|
|
283
|
-
default:
|
|
82
|
+
rl.question(
|
|
83
|
+
`Enter your choice (1-${supportedClients.length}): `,
|
|
84
|
+
(answer) => {
|
|
85
|
+
const idx = parseInt(answer.trim(), 10) - 1;
|
|
86
|
+
if (isNaN(idx) || idx < 0 || idx >= supportedClients.length) {
|
|
284
87
|
console.error("Invalid choice. Skipping app configuration.");
|
|
285
88
|
rl.close();
|
|
286
89
|
process.exit(1);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
90
|
+
}
|
|
91
|
+
const selectedApp = supportedClients[idx].key;
|
|
92
|
+
rl.close();
|
|
93
|
+
addToApp(selectedApp);
|
|
94
|
+
process.exit(0);
|
|
95
|
+
},
|
|
96
|
+
);
|
|
292
97
|
return;
|
|
293
98
|
} else {
|
|
294
99
|
addToApp(app);
|
|
@@ -315,7 +120,10 @@ if (argv.length === 0 || argv.includes("--start")) {
|
|
|
315
120
|
}
|
|
316
121
|
}
|
|
317
122
|
|
|
318
|
-
const child = spawn(binary, [], {
|
|
123
|
+
const child = spawn(binary, [], {
|
|
124
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
125
|
+
shell: true,
|
|
126
|
+
});
|
|
319
127
|
|
|
320
128
|
process.stdin.pipe(child.stdin);
|
|
321
129
|
child.stdout.pipe(process.stdout);
|
package/package.json
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bin": {
|
|
3
|
-
"terminator-mcp": "index.js"
|
|
3
|
+
"terminator-mcp-agent": "index.js"
|
|
4
4
|
},
|
|
5
5
|
"description": "Cross-platform Model Context Protocol (MCP) agent for Terminator",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">= 10"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"index.js"
|
|
10
|
+
"index.js",
|
|
11
|
+
"config.js"
|
|
11
12
|
],
|
|
12
13
|
"name": "terminator-mcp-agent",
|
|
13
14
|
"optionalDependencies": {
|
|
14
|
-
"terminator-mcp-darwin-arm64": "0.5.
|
|
15
|
-
"terminator-mcp-darwin-x64": "0.5.
|
|
16
|
-
"terminator-mcp-linux-x64-gnu": "0.5.
|
|
17
|
-
"terminator-mcp-win32-x64-msvc": "0.5.
|
|
15
|
+
"terminator-mcp-darwin-arm64": "0.5.13",
|
|
16
|
+
"terminator-mcp-darwin-x64": "0.5.13",
|
|
17
|
+
"terminator-mcp-linux-x64-gnu": "0.5.13",
|
|
18
|
+
"terminator-mcp-win32-x64-msvc": "0.5.13"
|
|
18
19
|
},
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
@@ -26,5 +27,5 @@
|
|
|
26
27
|
"sync-version": "node ./utils/sync-version.js",
|
|
27
28
|
"update-badges": "node ./utils/update-badges.js"
|
|
28
29
|
},
|
|
29
|
-
"version": "0.5.
|
|
30
|
+
"version": "0.5.13"
|
|
30
31
|
}
|