@mario.andreschak/mcp-bash 3.39.0
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/dist/index.d.ts +3 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/resources.d.ts +13 -0
- package/dist/resources.js +298 -0
- package/dist/resources.js.map +1 -0
- package/dist/shared.d.ts +24 -0
- package/dist/shared.js +161 -0
- package/dist/shared.js.map +1 -0
- package/dist/tools.d.ts +59 -0
- package/dist/tools.js +1493 -0
- package/dist/tools.js.map +1 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { configureRootsProvider } from './shared.js';
|
|
6
|
+
import { bashCallTool, bashToolDefinitions, shutdownBashSessions } from './tools.js';
|
|
7
|
+
import { bashListResources, bashReadResource, isBashAppUri } from './resources.js';
|
|
8
|
+
export * from './tools.js';
|
|
9
|
+
export * from './resources.js';
|
|
10
|
+
const server = new Server({ name: '@mario.andreschak/mcp-bash', version: '0.1.0' }, {
|
|
11
|
+
capabilities: {
|
|
12
|
+
tools: {},
|
|
13
|
+
resources: {},
|
|
14
|
+
extensions: {
|
|
15
|
+
'io.modelcontextprotocol/ui': {
|
|
16
|
+
mimeTypes: ['text/html;profile=mcp-app'],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
configureRootsProvider(async () => (await server.listRoots()).roots);
|
|
22
|
+
function flujoMetaOf(meta) {
|
|
23
|
+
if (!meta || typeof meta !== 'object')
|
|
24
|
+
return {};
|
|
25
|
+
const flujo = meta.flujo;
|
|
26
|
+
if (!flujo || typeof flujo !== 'object')
|
|
27
|
+
return {};
|
|
28
|
+
const values = flujo;
|
|
29
|
+
const callerNodeId = typeof values.callerNodeId === 'string' && values.callerNodeId.length > 0
|
|
30
|
+
? values.callerNodeId
|
|
31
|
+
: undefined;
|
|
32
|
+
const ownerScope = typeof values.ownerScope === 'string' && values.ownerScope.length > 0
|
|
33
|
+
? values.ownerScope
|
|
34
|
+
: undefined;
|
|
35
|
+
return { callerNodeId, ownerScope };
|
|
36
|
+
}
|
|
37
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: bashToolDefinitions() }));
|
|
38
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
39
|
+
const meta = flujoMetaOf(request.params._meta);
|
|
40
|
+
const progressToken = request.params._meta?.progressToken;
|
|
41
|
+
return bashCallTool(request.params.name, request.params.arguments ?? {}, meta.callerNodeId, meta.ownerScope, {
|
|
42
|
+
signal: extra.signal,
|
|
43
|
+
...(progressToken !== undefined
|
|
44
|
+
? {
|
|
45
|
+
onProgress: async (progress) => {
|
|
46
|
+
await server.notification({
|
|
47
|
+
method: 'notifications/progress',
|
|
48
|
+
params: { progressToken, ...progress },
|
|
49
|
+
}, { relatedRequestId: extra.requestId });
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
: {}),
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => bashListResources());
|
|
56
|
+
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({ resourceTemplates: [] }));
|
|
57
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
58
|
+
const uri = request.params.uri;
|
|
59
|
+
const result = isBashAppUri(uri)
|
|
60
|
+
? bashReadResource(uri)
|
|
61
|
+
: { success: false, error: `Unknown Bash resource: ${uri}`, statusCode: 404 };
|
|
62
|
+
if (!result.success || !result.data) {
|
|
63
|
+
throw new Error(result.error ?? `Could not read ${uri}`);
|
|
64
|
+
}
|
|
65
|
+
return result.data;
|
|
66
|
+
});
|
|
67
|
+
const transport = new StdioServerTransport();
|
|
68
|
+
let closing = false;
|
|
69
|
+
async function shutdown() {
|
|
70
|
+
if (closing)
|
|
71
|
+
return;
|
|
72
|
+
closing = true;
|
|
73
|
+
shutdownBashSessions();
|
|
74
|
+
configureRootsProvider(undefined);
|
|
75
|
+
await server.close().catch(() => undefined);
|
|
76
|
+
}
|
|
77
|
+
process.once('SIGINT', () => void shutdown());
|
|
78
|
+
process.once('SIGTERM', () => void shutdown());
|
|
79
|
+
process.once('SIGHUP', () => void shutdown());
|
|
80
|
+
server.connect(transport).catch((error) => {
|
|
81
|
+
shutdownBashSessions();
|
|
82
|
+
process.stderr.write(`@mario.andreschak/mcp-bash failed: ${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReadResourceResult as MCPReadResourceResult, Resource as MCPResource } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
type MCPServiceResponse<T> = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: T;
|
|
5
|
+
error?: string;
|
|
6
|
+
statusCode?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function bashListResources(): {
|
|
9
|
+
resources: MCPResource[];
|
|
10
|
+
};
|
|
11
|
+
export declare function isBashAppUri(uri: string): boolean;
|
|
12
|
+
export declare function bashReadResource(uri: string): MCPServiceResponse<MCPReadResourceResult>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/** First-party, PTY-backed MCP App for the built-in Bash server. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { BASH_TERMINAL_APP_URI } from './tools.js';
|
|
6
|
+
const MCP_APPS_PROTOCOL_VERSION = '2026-01-26';
|
|
7
|
+
const APP_MIME_TYPE = 'text/html;profile=mcp-app';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
function browserAsset(packageName, relativePath) {
|
|
10
|
+
const entry = require.resolve(packageName);
|
|
11
|
+
const file = relativePath ? path.join(path.dirname(path.dirname(entry)), relativePath) : entry;
|
|
12
|
+
return fs.readFileSync(file, 'utf8');
|
|
13
|
+
}
|
|
14
|
+
function safeInlineScript(source) {
|
|
15
|
+
return source.replace(/<\/script/gi, '<\\/script');
|
|
16
|
+
}
|
|
17
|
+
const XTERM_JS = safeInlineScript(browserAsset('@xterm/xterm'));
|
|
18
|
+
const XTERM_CSS = browserAsset('@xterm/xterm', 'css/xterm.css').replace(/<\/style/gi, '<\\/style');
|
|
19
|
+
const XTERM_FIT_JS = safeInlineScript(browserAsset('@xterm/addon-fit'));
|
|
20
|
+
export function bashListResources() {
|
|
21
|
+
return {
|
|
22
|
+
resources: [
|
|
23
|
+
{
|
|
24
|
+
uri: BASH_TERMINAL_APP_URI,
|
|
25
|
+
name: 'Interactive Terminal',
|
|
26
|
+
title: 'Interactive Terminal',
|
|
27
|
+
mimeType: APP_MIME_TYPE,
|
|
28
|
+
description: 'A real PTY/ConPTY terminal with ANSI rendering, keyboard input, copy/paste, and resize support.',
|
|
29
|
+
_meta: { ui: { csp: {}, permissions: { clipboardWrite: {} }, prefersBorder: true } },
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function isBashAppUri(uri) {
|
|
35
|
+
return uri === BASH_TERMINAL_APP_URI;
|
|
36
|
+
}
|
|
37
|
+
export function bashReadResource(uri) {
|
|
38
|
+
if (!isBashAppUri(uri)) {
|
|
39
|
+
return { success: false, error: `Not a Bash app URI: ${uri}`, statusCode: 404 };
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
data: {
|
|
44
|
+
contents: [
|
|
45
|
+
{
|
|
46
|
+
uri,
|
|
47
|
+
mimeType: APP_MIME_TYPE,
|
|
48
|
+
text: BASH_TERMINAL_APP_HTML,
|
|
49
|
+
_meta: { ui: { csp: {}, permissions: { clipboardWrite: {} }, prefersBorder: true } },
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const BASH_TERMINAL_APP_HTML = `<!doctype html>
|
|
56
|
+
<html lang="en">
|
|
57
|
+
<head>
|
|
58
|
+
<meta charset="utf-8" />
|
|
59
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
60
|
+
<style>${XTERM_CSS}</style>
|
|
61
|
+
<style>
|
|
62
|
+
:root { color-scheme:dark; --bar:#111827; --border:#334155; --fg:#e5e7eb; --muted:#94a3b8; --accent:#60a5fa; --danger:#f87171; }
|
|
63
|
+
* { box-sizing:border-box; }
|
|
64
|
+
html,body { width:100%; height:100%; margin:0; overflow:hidden; background:#050a07; color:var(--fg); font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }
|
|
65
|
+
body { display:flex; flex-direction:column; }
|
|
66
|
+
#toolbar { display:flex; align-items:center; gap:7px; min-height:40px; padding:5px 8px; background:var(--bar); border-bottom:1px solid var(--border); }
|
|
67
|
+
#terminal { flex:1 1 auto; min-height:180px; padding:5px; }
|
|
68
|
+
#status { flex:1 1 auto; min-width:0; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
69
|
+
.live { color:#86efac !important; }
|
|
70
|
+
.error { color:var(--danger) !important; }
|
|
71
|
+
button,select,input { min-height:28px; border:1px solid var(--border); border-radius:5px; background:#0f172a; color:var(--fg); font:inherit; padding:3px 7px; }
|
|
72
|
+
button { cursor:pointer; }
|
|
73
|
+
button:disabled { opacity:.5; cursor:not-allowed; }
|
|
74
|
+
#cwd { width:min(28vw,260px); }
|
|
75
|
+
#shell { max-width:125px; }
|
|
76
|
+
.xterm { height:100%; }
|
|
77
|
+
.xterm-viewport { scrollbar-color:#475569 #07120d; }
|
|
78
|
+
</style>
|
|
79
|
+
<script>${XTERM_JS}</script>
|
|
80
|
+
<script>${XTERM_FIT_JS}</script>
|
|
81
|
+
</head>
|
|
82
|
+
<body>
|
|
83
|
+
<div id="toolbar">
|
|
84
|
+
<select id="shell" aria-label="Shell"><option value="default">Automatic</option><option value="pwsh">PowerShell</option><option value="bash">Bash</option><option value="cmd">cmd</option></select>
|
|
85
|
+
<input id="cwd" aria-label="Working directory" value="." title="Working directory" />
|
|
86
|
+
<button id="new" type="button">New</button>
|
|
87
|
+
<button id="copy" type="button" title="Copy selection">Copy</button>
|
|
88
|
+
<button id="clear" type="button">Clear</button>
|
|
89
|
+
<button id="close" type="button">Close</button>
|
|
90
|
+
<span id="status">Initializing terminal…</span>
|
|
91
|
+
</div>
|
|
92
|
+
<div id="terminal" aria-label="Interactive terminal"></div>
|
|
93
|
+
<script>
|
|
94
|
+
(function () {
|
|
95
|
+
"use strict";
|
|
96
|
+
var nextId = 1;
|
|
97
|
+
var pending = {};
|
|
98
|
+
var sessionId = "";
|
|
99
|
+
var cursor = 0;
|
|
100
|
+
var running = false;
|
|
101
|
+
var pollTimer = null;
|
|
102
|
+
var pollBusy = false;
|
|
103
|
+
var opening = false;
|
|
104
|
+
var inputQueue = "";
|
|
105
|
+
var inputBusy = false;
|
|
106
|
+
var resizeTimer = null;
|
|
107
|
+
var lastToolInput = {};
|
|
108
|
+
|
|
109
|
+
var statusEl = document.getElementById("status");
|
|
110
|
+
var shellEl = document.getElementById("shell");
|
|
111
|
+
var cwdEl = document.getElementById("cwd");
|
|
112
|
+
var terminal = new Terminal({
|
|
113
|
+
cursorBlink:true,
|
|
114
|
+
convertEol:false,
|
|
115
|
+
scrollback:10000,
|
|
116
|
+
fontFamily:'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
|
|
117
|
+
fontSize:13,
|
|
118
|
+
theme:{ background:'#050a07', foreground:'#d1fae5', cursor:'#86efac', selectionBackground:'#2563eb88' }
|
|
119
|
+
});
|
|
120
|
+
var fitAddon = new FitAddon.FitAddon();
|
|
121
|
+
terminal.loadAddon(fitAddon);
|
|
122
|
+
terminal.open(document.getElementById("terminal"));
|
|
123
|
+
fitAddon.fit();
|
|
124
|
+
|
|
125
|
+
function post(message) { window.parent.postMessage(message, "*"); }
|
|
126
|
+
function rpc(method, params) {
|
|
127
|
+
return new Promise(function (resolve, reject) {
|
|
128
|
+
var id = nextId++;
|
|
129
|
+
pending[id] = { resolve:resolve, reject:reject };
|
|
130
|
+
post({ jsonrpc:"2.0", id:id, method:method, params:params || {} });
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function notify(method, params) { post({ jsonrpc:"2.0", method:method, params:params || {} }); }
|
|
134
|
+
function payloadOf(result) {
|
|
135
|
+
if (!result) return null;
|
|
136
|
+
if (result.structuredContent) return result.structuredContent;
|
|
137
|
+
try {
|
|
138
|
+
var text = result.content && result.content[0] && result.content[0].text;
|
|
139
|
+
return text ? JSON.parse(text) : null;
|
|
140
|
+
} catch (e) { return null; }
|
|
141
|
+
}
|
|
142
|
+
async function callTool(name, args) {
|
|
143
|
+
var result = await rpc("tools/call", { name:name, arguments:args || {} });
|
|
144
|
+
var data = payloadOf(result) || {};
|
|
145
|
+
if (result && result.isError) throw new Error(data.error || name + " failed");
|
|
146
|
+
return data;
|
|
147
|
+
}
|
|
148
|
+
function setStatus(message, kind) {
|
|
149
|
+
statusEl.textContent = message;
|
|
150
|
+
statusEl.className = kind || "";
|
|
151
|
+
}
|
|
152
|
+
function schedulePoll(delay) {
|
|
153
|
+
if (pollTimer) clearTimeout(pollTimer);
|
|
154
|
+
pollTimer = sessionId ? setTimeout(poll, delay == null ? (running ? 60 : 500) : delay) : null;
|
|
155
|
+
}
|
|
156
|
+
function acceptSession(data) {
|
|
157
|
+
if (!data || !data.sessionId) return false;
|
|
158
|
+
sessionId = String(data.sessionId);
|
|
159
|
+
cursor = Number(data.cursor || data.nextCursor || 0);
|
|
160
|
+
running = data.running !== false;
|
|
161
|
+
setStatus((running ? "● " : "○ ") + (data.shell || "terminal") + " — " + (data.cwd || sessionId), running ? "live" : "");
|
|
162
|
+
schedulePoll(0);
|
|
163
|
+
terminal.focus();
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
async function openTerminal() {
|
|
167
|
+
if (opening) return;
|
|
168
|
+
opening = true;
|
|
169
|
+
document.getElementById("new").disabled = true;
|
|
170
|
+
try {
|
|
171
|
+
if (sessionId && running) await callTool("terminal_close", { sessionId:sessionId }).catch(function () {});
|
|
172
|
+
terminal.reset();
|
|
173
|
+
terminal.clear();
|
|
174
|
+
var data = await callTool("open_terminal", {
|
|
175
|
+
shell:shellEl.value,
|
|
176
|
+
cwd:cwdEl.value.trim() || ".",
|
|
177
|
+
cols:terminal.cols,
|
|
178
|
+
rows:terminal.rows
|
|
179
|
+
});
|
|
180
|
+
acceptSession(data);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
setStatus(error && error.message ? error.message : String(error), "error");
|
|
183
|
+
terminal.writeln("\\r\\n\\x1b[31m" + (error && error.message ? error.message : String(error)) + "\\x1b[0m");
|
|
184
|
+
} finally {
|
|
185
|
+
opening = false;
|
|
186
|
+
document.getElementById("new").disabled = false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function poll() {
|
|
190
|
+
if (!sessionId || pollBusy) return;
|
|
191
|
+
pollBusy = true;
|
|
192
|
+
try {
|
|
193
|
+
var data = await callTool("terminal_read", { sessionId:sessionId, cursor:cursor });
|
|
194
|
+
if (data.reset) { terminal.reset(); terminal.clear(); }
|
|
195
|
+
if (typeof data.chunk === "string" && data.chunk) terminal.write(data.chunk);
|
|
196
|
+
cursor = Number(data.nextCursor == null ? cursor : data.nextCursor);
|
|
197
|
+
running = data.running !== false;
|
|
198
|
+
setStatus((running ? "● " : "○ ") + (data.shell || "terminal") + " — " + (data.cwd || sessionId) + (running ? "" : " — exited " + String(data.exitCode)), running ? "live" : "");
|
|
199
|
+
} catch (error) {
|
|
200
|
+
running = false;
|
|
201
|
+
setStatus(error && error.message ? error.message : String(error), "error");
|
|
202
|
+
} finally {
|
|
203
|
+
pollBusy = false;
|
|
204
|
+
schedulePoll();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function flushInput() {
|
|
208
|
+
if (inputBusy || !inputQueue || !sessionId || !running) return;
|
|
209
|
+
inputBusy = true;
|
|
210
|
+
var data = inputQueue;
|
|
211
|
+
inputQueue = "";
|
|
212
|
+
try { await callTool("terminal_write", { sessionId:sessionId, data:data }); }
|
|
213
|
+
catch (error) { setStatus(error && error.message ? error.message : String(error), "error"); }
|
|
214
|
+
finally { inputBusy = false; if (inputQueue) setTimeout(flushInput, 0); }
|
|
215
|
+
}
|
|
216
|
+
function sendResize() {
|
|
217
|
+
if (!sessionId || !running) return;
|
|
218
|
+
callTool("terminal_resize", { sessionId:sessionId, cols:terminal.cols, rows:terminal.rows }).catch(function () {});
|
|
219
|
+
}
|
|
220
|
+
function acceptToolResult(result) {
|
|
221
|
+
var data = payloadOf(result) || {};
|
|
222
|
+
acceptSession(data);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
terminal.onData(function (data) {
|
|
226
|
+
inputQueue += data;
|
|
227
|
+
setTimeout(flushInput, 0);
|
|
228
|
+
});
|
|
229
|
+
terminal.onResize(function () {
|
|
230
|
+
if (resizeTimer) clearTimeout(resizeTimer);
|
|
231
|
+
resizeTimer = setTimeout(sendResize, 100);
|
|
232
|
+
});
|
|
233
|
+
window.addEventListener("resize", function () { try { fitAddon.fit(); } catch (e) {} });
|
|
234
|
+
document.getElementById("new").onclick = openTerminal;
|
|
235
|
+
document.getElementById("clear").onclick = function () { terminal.clear(); };
|
|
236
|
+
document.getElementById("copy").onclick = function () {
|
|
237
|
+
var text = terminal.getSelection();
|
|
238
|
+
if (!text) { setStatus("Select terminal text first.", ""); return; }
|
|
239
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
240
|
+
navigator.clipboard.writeText(text).then(function () { setStatus("Selection copied.", ""); }).catch(function () { setStatus("Copy was denied by the host.", "error"); });
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
document.getElementById("close").onclick = async function () {
|
|
244
|
+
if (!sessionId) return;
|
|
245
|
+
await callTool("terminal_close", { sessionId:sessionId }).catch(function () {});
|
|
246
|
+
running = false;
|
|
247
|
+
setStatus("Terminal closed.", "");
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
window.addEventListener("message", function (event) {
|
|
251
|
+
var message = event.data;
|
|
252
|
+
if (!message || message.jsonrpc !== "2.0") return;
|
|
253
|
+
if (message.id !== undefined && (message.result !== undefined || message.error !== undefined)) {
|
|
254
|
+
var waiting = pending[message.id];
|
|
255
|
+
if (!waiting) return;
|
|
256
|
+
delete pending[message.id];
|
|
257
|
+
if (message.error) waiting.reject(new Error(message.error.message || "RPC error"));
|
|
258
|
+
else waiting.resolve(message.result);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (message.method === "ui/notifications/tool-input") {
|
|
262
|
+
lastToolInput = message.params && message.params.arguments || {};
|
|
263
|
+
if (typeof lastToolInput.cwd === "string") cwdEl.value = lastToolInput.cwd;
|
|
264
|
+
if (typeof lastToolInput.shell === "string") shellEl.value = lastToolInput.shell;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (message.method === "ui/notifications/tool-result") { acceptToolResult(message.params && message.params.result ? message.params.result : message.params); return; }
|
|
268
|
+
if (message.method === "ping" && message.id !== undefined) { post({ jsonrpc:"2.0", id:message.id, result:{} }); return; }
|
|
269
|
+
if (message.method === "ui/resource-teardown" && message.id !== undefined) {
|
|
270
|
+
// Dock/fullscreen transitions tear down Views; the owner-scoped PTY stays
|
|
271
|
+
// alive so the replacement View can reattach through terminal_list.
|
|
272
|
+
post({ jsonrpc:"2.0", id:message.id, result:{} });
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
rpc("ui/initialize", {
|
|
277
|
+
appInfo:{ name:"bash-terminal", version:"2.0.0" },
|
|
278
|
+
appCapabilities:{ availableDisplayModes:["inline","fullscreen","pip"] },
|
|
279
|
+
protocolVersion:"${MCP_APPS_PROTOCOL_VERSION}"
|
|
280
|
+
}).then(async function () {
|
|
281
|
+
notify("ui/notifications/initialized", {});
|
|
282
|
+
try { fitAddon.fit(); } catch (e) {}
|
|
283
|
+
setTimeout(async function () {
|
|
284
|
+
if (sessionId) return;
|
|
285
|
+
try {
|
|
286
|
+
var listed = await callTool("terminal_list", {});
|
|
287
|
+
var sessions = Array.isArray(listed.sessions) ? listed.sessions : [];
|
|
288
|
+
var active = sessions.filter(function (item) { return item.running; }).pop();
|
|
289
|
+
if (!acceptSession(active)) await openTerminal();
|
|
290
|
+
} catch (e) { await openTerminal(); }
|
|
291
|
+
}, 350);
|
|
292
|
+
rpc("ui/request-display-mode", { mode:"pip" }).catch(function () {});
|
|
293
|
+
}).catch(function (error) { setStatus("MCP App initialization failed: " + (error && error.message ? error.message : error), "error"); });
|
|
294
|
+
})();
|
|
295
|
+
</script>
|
|
296
|
+
</body>
|
|
297
|
+
</html>`;
|
|
298
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|
package/dist/shared.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
export type DiagnosticLogger = {
|
|
3
|
+
debug(message: string, detail?: unknown): void;
|
|
4
|
+
info(message: string, detail?: unknown): void;
|
|
5
|
+
warn(message: string, detail?: unknown): void;
|
|
6
|
+
error(message: string, detail?: unknown): void;
|
|
7
|
+
};
|
|
8
|
+
export declare function createLogger(scope: string): DiagnosticLogger;
|
|
9
|
+
export declare function getDataDir(): string;
|
|
10
|
+
export declare function getHomeDir(): string;
|
|
11
|
+
export declare function isInside(root: string, candidate: string): boolean;
|
|
12
|
+
export declare function envRoots(envVarNames: string | string[]): string[] | null;
|
|
13
|
+
export type RootsProvider = () => Promise<Array<{
|
|
14
|
+
uri: string;
|
|
15
|
+
}>>;
|
|
16
|
+
export declare function configureRootsProvider(provider: RootsProvider | undefined): void;
|
|
17
|
+
export declare function loadEffectiveRoots(_serverName: string, envVarNames: string | string[], _callerNodeId?: string): Promise<string[]>;
|
|
18
|
+
export declare const ALLOW_PROTECTED_PATHS_ENV = "FLUJO_ALLOW_PROTECTED_PATHS";
|
|
19
|
+
export declare function isProtectedPathsEnabled(): Promise<boolean>;
|
|
20
|
+
export declare function isProtected(candidate: string): {
|
|
21
|
+
denied: boolean;
|
|
22
|
+
matchedRoot?: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function killProcessTree(child: ChildProcess, graceMs?: number): () => void;
|
package/dist/shared.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
function diagnostic(level, scope, message, detail) {
|
|
6
|
+
const suffix = detail === undefined
|
|
7
|
+
? ''
|
|
8
|
+
: ` ${detail instanceof Error ? detail.stack ?? detail.message : safeStringify(detail)}`;
|
|
9
|
+
process.stderr.write(`[${scope}] ${level}: ${message}${suffix}\n`);
|
|
10
|
+
}
|
|
11
|
+
function safeStringify(value) {
|
|
12
|
+
try {
|
|
13
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return String(value);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function createLogger(scope) {
|
|
20
|
+
return {
|
|
21
|
+
debug: (message, detail) => {
|
|
22
|
+
if (process.env.FLUJO_MCP_DEBUG === '1')
|
|
23
|
+
diagnostic('debug', scope, message, detail);
|
|
24
|
+
},
|
|
25
|
+
info: (message, detail) => diagnostic('info', scope, message, detail),
|
|
26
|
+
warn: (message, detail) => diagnostic('warn', scope, message, detail),
|
|
27
|
+
error: (message, detail) => diagnostic('error', scope, message, detail),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function getDataDir() {
|
|
31
|
+
return path.resolve(process.env.FLUJO_DATA_DIR?.trim() || process.cwd());
|
|
32
|
+
}
|
|
33
|
+
export function getHomeDir() {
|
|
34
|
+
return path.resolve(process.env.FLUJO_HOME_DIR?.trim() || os.homedir());
|
|
35
|
+
}
|
|
36
|
+
export function isInside(root, candidate) {
|
|
37
|
+
const rel = path.relative(path.resolve(root), path.resolve(candidate));
|
|
38
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
39
|
+
}
|
|
40
|
+
export function envRoots(envVarNames) {
|
|
41
|
+
const names = Array.isArray(envVarNames) ? envVarNames : [envVarNames];
|
|
42
|
+
for (const name of names) {
|
|
43
|
+
const raw = process.env[name];
|
|
44
|
+
if (!raw?.trim())
|
|
45
|
+
continue;
|
|
46
|
+
const roots = raw.split(path.delimiter).map((root) => root.trim()).filter(Boolean).map((root) => path.resolve(root));
|
|
47
|
+
if (roots.length > 0)
|
|
48
|
+
return roots;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
let rootsProvider;
|
|
53
|
+
export function configureRootsProvider(provider) {
|
|
54
|
+
rootsProvider = provider;
|
|
55
|
+
}
|
|
56
|
+
async function clientRoots(dataDir) {
|
|
57
|
+
if (!rootsProvider)
|
|
58
|
+
return [];
|
|
59
|
+
try {
|
|
60
|
+
const roots = await rootsProvider();
|
|
61
|
+
const resolved = [];
|
|
62
|
+
for (const root of roots) {
|
|
63
|
+
const raw = root?.uri?.trim();
|
|
64
|
+
if (!raw)
|
|
65
|
+
continue;
|
|
66
|
+
if (raw.startsWith('file://')) {
|
|
67
|
+
try {
|
|
68
|
+
resolved.push(path.resolve(fileURLToPath(raw)));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Ignore malformed roots supplied by the client.
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
resolved.push(path.isAbsolute(raw) ? path.resolve(raw) : path.resolve(dataDir, raw));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return Array.from(new Set(resolved));
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
createLogger('mcp-shared/roots').debug('Client does not expose roots/list', error);
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function loadEffectiveRoots(_serverName, envVarNames, _callerNodeId) {
|
|
86
|
+
const dataDir = getDataDir();
|
|
87
|
+
const ceiling = envRoots(envVarNames);
|
|
88
|
+
const configured = await clientRoots(dataDir);
|
|
89
|
+
if (!ceiling)
|
|
90
|
+
return configured.length > 0 ? configured : [dataDir];
|
|
91
|
+
const confined = configured.filter((candidate) => ceiling.some((root) => isInside(root, candidate)));
|
|
92
|
+
return confined.length > 0 ? confined : ceiling;
|
|
93
|
+
}
|
|
94
|
+
function truthy(value) {
|
|
95
|
+
return typeof value === 'string' && /^(1|true|yes|on)$/i.test(value.trim());
|
|
96
|
+
}
|
|
97
|
+
export const ALLOW_PROTECTED_PATHS_ENV = 'FLUJO_ALLOW_PROTECTED_PATHS';
|
|
98
|
+
export async function isProtectedPathsEnabled() {
|
|
99
|
+
if (truthy(process.env[ALLOW_PROTECTED_PATHS_ENV]))
|
|
100
|
+
return false;
|
|
101
|
+
return truthy(process.env.FLUJO_PROTECTED_PATHS_ENABLED);
|
|
102
|
+
}
|
|
103
|
+
function protectedPaths() {
|
|
104
|
+
if (truthy(process.env[ALLOW_PROTECTED_PATHS_ENV]))
|
|
105
|
+
return [];
|
|
106
|
+
const home = getHomeDir();
|
|
107
|
+
const underHome = (...segments) => path.resolve(home, ...segments);
|
|
108
|
+
if (process.platform === 'win32') {
|
|
109
|
+
return ['AppData', 'Downloads', 'Desktop', 'Documents', 'Pictures', 'Music', 'Videos', 'OneDrive'].map((item) => underHome(item));
|
|
110
|
+
}
|
|
111
|
+
if (process.platform === 'darwin') {
|
|
112
|
+
return [
|
|
113
|
+
'Downloads', 'Desktop', 'Documents', 'Pictures', 'Music', 'Movies',
|
|
114
|
+
'Library/Mail', 'Library/Messages', 'Library/Safari', 'Library/Cookies',
|
|
115
|
+
'Library/Calendars', 'Library/Application Support/AddressBook',
|
|
116
|
+
'Library/Application Support/com.apple.TCC', 'Library/PersonalizationPortrait',
|
|
117
|
+
'Library/Metadata/CoreSpotlight', 'Library/Suggestions',
|
|
118
|
+
].map((item) => underHome(item)).concat(['/.Spotlight-V100', '/.fseventsd', '/.DocumentRevisions-V100'].map((item) => path.resolve(item)));
|
|
119
|
+
}
|
|
120
|
+
return ['Documents', 'Downloads', 'Desktop', '.ssh', '.gnupg', '.aws', '.config'].map((item) => underHome(item));
|
|
121
|
+
}
|
|
122
|
+
export function isProtected(candidate) {
|
|
123
|
+
const resolved = path.resolve(candidate);
|
|
124
|
+
const exempt = [getDataDir(), os.tmpdir()].map((item) => path.resolve(item));
|
|
125
|
+
if (exempt.some((root) => isInside(root, resolved)))
|
|
126
|
+
return { denied: false };
|
|
127
|
+
const matchedRoot = protectedPaths().find((root) => isInside(root, resolved));
|
|
128
|
+
return matchedRoot ? { denied: true, matchedRoot } : { denied: false };
|
|
129
|
+
}
|
|
130
|
+
export function killProcessTree(child, graceMs = 2000) {
|
|
131
|
+
const pid = child.pid;
|
|
132
|
+
if (pid === undefined)
|
|
133
|
+
return () => undefined;
|
|
134
|
+
if (process.platform === 'win32') {
|
|
135
|
+
try {
|
|
136
|
+
const killer = spawn('taskkill', ['/pid', String(pid), '/T', '/F']);
|
|
137
|
+
killer.on('error', () => undefined);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// The target is already gone.
|
|
141
|
+
}
|
|
142
|
+
return () => undefined;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
process.kill(-pid, 'SIGTERM');
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// The group is already gone.
|
|
149
|
+
}
|
|
150
|
+
const escalation = setTimeout(() => {
|
|
151
|
+
try {
|
|
152
|
+
process.kill(-pid, 'SIGKILL');
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// The group is already gone.
|
|
156
|
+
}
|
|
157
|
+
}, graceMs);
|
|
158
|
+
escalation.unref?.();
|
|
159
|
+
return () => clearTimeout(escalation);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|