@remcp/runtime 0.2.63 → 0.2.65
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 +5 -4
- package/package.json +2 -3
- package/src/tools/terminal.mjs +24 -9
package/README.md
CHANGED
|
@@ -52,8 +52,8 @@ support and emits `notifications/tools/list_changed` when that capability set ch
|
|
|
52
52
|
The hosted ReMCP endpoint adds eleven account/presentation tools — `list_devices`, `ping_device`,
|
|
53
53
|
`who_am_i`, `create_pairing_command`, `get_recent_tool_calls`, `get_usage_statistics`,
|
|
54
54
|
`get_configuration`, `render_file_preview`, `render_image_preview`, `render_terminal_preview`, and
|
|
55
|
-
`rename_device` — for a 94-tool MCP Apps catalog.
|
|
56
|
-
three presentation-only render tools are
|
|
55
|
+
`rename_device` — for a 94-tool MCP Apps catalog. Native-only deployments receive 91 tools because the
|
|
56
|
+
three presentation-only render tools are disabled by configuration.
|
|
57
57
|
|
|
58
58
|
`computer_snapshot` and `computer_action` keep OCR inside the compact high-level surface: when a local `tesseract` binary is available, snapshot can return bounded OCR text/boxes and click targeting can fall back through Accessibility → browser DOM/CDP → OCR → coordinates. OCR is optional and never adds another MCP tool or bundled OCR dependency.
|
|
59
59
|
|
|
@@ -73,8 +73,9 @@ A running device can advertise a smaller capability-aware subset; the runtime de
|
|
|
73
73
|
agent forwards the refreshed tool names to the hosted relay. Browser/CDP tools are the primary dynamic
|
|
74
74
|
example: they are enabled only while the runtime can use a supported loopback browser endpoint.
|
|
75
75
|
|
|
76
|
-
The
|
|
77
|
-
|
|
76
|
+
The generated hosted reference covers the full **94-tool production surface** with custom widgets enabled: 83 device tools,
|
|
77
|
+
8 account/fleet tools, and 3 chat-presentation tools. Setting `REMCP_CUSTOM_WIDGETS_ENABLED=false` on the hosted server exposes
|
|
78
|
+
the 91-tool native-only surface. See https://remcp.site/docs#tools and public `docs/TOOLS.md`.
|
|
78
79
|
|
|
79
80
|
## No approval staircase
|
|
80
81
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remcp/runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.65",
|
|
4
4
|
"description": "First-party ReMCP local device runtime: filesystem, terminal, computer-use, browser, diagnostics and document tools over MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,8 +28,7 @@
|
|
|
28
28
|
"@modelcontextprotocol/server": "^2.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@modelcontextprotocol/client": "^2.0.0"
|
|
32
|
-
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
31
|
+
"@modelcontextprotocol/client": "^2.0.0"
|
|
33
32
|
},
|
|
34
33
|
"repository": {
|
|
35
34
|
"type": "git",
|
package/src/tools/terminal.mjs
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
waitForProcessExit,
|
|
18
18
|
waitForProcessActivity,
|
|
19
19
|
} from '../sessions.mjs';
|
|
20
|
-
import { clampInteger, fail, requireInteger, requireString, structured, text } from '../util.mjs';
|
|
20
|
+
import { clampInteger, fail, requireInteger, requireString, structured, text, truncate } from '../util.mjs';
|
|
21
21
|
|
|
22
22
|
function shellCommand() {
|
|
23
23
|
if (runtimeConfig.defaultShell) return runtimeConfig.defaultShell;
|
|
@@ -51,6 +51,21 @@ function throwIfAborted(signal) {
|
|
|
51
51
|
if (signal?.aborted) throw abortError();
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
// Terminal results have strict tool-specific output schemas. The generic structured() helper uses a
|
|
55
|
+
// schema-agnostic {truncated,bytes,preview} envelope above 256 KiB, which is valid for extended
|
|
56
|
+
// free-form tools but invalid for start_process/read_process_output and friends. Bound the few
|
|
57
|
+
// potentially large terminal strings before mirroring them so structuredContent always keeps the
|
|
58
|
+
// declared terminal shape.
|
|
59
|
+
function terminalStructured(value, fallbackText) {
|
|
60
|
+
const bounded = { ...value };
|
|
61
|
+
if (typeof bounded.output === 'string') bounded.output = truncate(bounded.output, 128 * 1024);
|
|
62
|
+
if (typeof bounded.partial === 'string') bounded.partial = truncate(bounded.partial, 64 * 1024);
|
|
63
|
+
if (typeof bounded.command === 'string') bounded.command = truncate(bounded.command, 16 * 1024);
|
|
64
|
+
if (typeof bounded.warning === 'string') bounded.warning = truncate(bounded.warning, 8 * 1024);
|
|
65
|
+
if (typeof bounded.pattern === 'string') bounded.pattern = truncate(bounded.pattern, 16 * 1024);
|
|
66
|
+
return structured(bounded, fallbackText);
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
export async function startProcessTool(args, extra = {}) {
|
|
55
70
|
const command = requireString(args.command, 'command');
|
|
56
71
|
const verdict = assertAllowedCommand(command);
|
|
@@ -101,7 +116,7 @@ export async function startProcessTool(args, extra = {}) {
|
|
|
101
116
|
const warning = verdict.note ? String(verdict.note) : '';
|
|
102
117
|
const rendered = [warning, headline, output, partial].filter(Boolean).join('\n');
|
|
103
118
|
const status = describeSession(session);
|
|
104
|
-
return
|
|
119
|
+
return terminalStructured({
|
|
105
120
|
...status,
|
|
106
121
|
command,
|
|
107
122
|
output,
|
|
@@ -141,7 +156,7 @@ export async function readProcessOutputTool(args, extra = {}) {
|
|
|
141
156
|
const status = describeSession(session);
|
|
142
157
|
const header = `pid ${pid} ${status.status} · lines ${range}`;
|
|
143
158
|
const output = slice.join('\n');
|
|
144
|
-
return
|
|
159
|
+
return terminalStructured({
|
|
145
160
|
...status,
|
|
146
161
|
range,
|
|
147
162
|
output,
|
|
@@ -187,7 +202,7 @@ export async function waitForProcessOutputTool(args, extra = {}) {
|
|
|
187
202
|
? `pid ${pid} ${status.status} · pattern matched${bufferedMatch ? ' (already buffered)' : ''}`
|
|
188
203
|
: `pid ${pid} ${status.status} · pattern not matched within ${timeoutMs}ms`;
|
|
189
204
|
const output = slice.join('\n');
|
|
190
|
-
return
|
|
205
|
+
return terminalStructured({
|
|
191
206
|
...status,
|
|
192
207
|
pattern,
|
|
193
208
|
matched,
|
|
@@ -226,7 +241,7 @@ export async function interactWithProcessTool(args, extra = {}) {
|
|
|
226
241
|
const slice = readNewOutput(session);
|
|
227
242
|
const status = describeSession(session);
|
|
228
243
|
const output = slice.join('\n');
|
|
229
|
-
return
|
|
244
|
+
return terminalStructured({
|
|
230
245
|
...status,
|
|
231
246
|
output,
|
|
232
247
|
}, [`pid ${pid} ${status.status}`, output].filter(Boolean).join('\n'));
|
|
@@ -238,7 +253,7 @@ export async function forceTerminateTool(args) {
|
|
|
238
253
|
if (!session) fail(`No ReMCP session with pid ${pid}`);
|
|
239
254
|
if (session.exited) {
|
|
240
255
|
const status = describeSession(session);
|
|
241
|
-
return
|
|
256
|
+
return terminalStructured({ ...status, terminated:false, alreadyExited:true, escalated:false }, `Process ${pid} already exited.`);
|
|
242
257
|
}
|
|
243
258
|
killSessionTree(session, 'SIGTERM');
|
|
244
259
|
const deadline = Date.now() + 2000;
|
|
@@ -250,7 +265,7 @@ export async function forceTerminateTool(args) {
|
|
|
250
265
|
await waitForProcessActivity(session, 1000);
|
|
251
266
|
}
|
|
252
267
|
const status = describeSession(session);
|
|
253
|
-
return
|
|
268
|
+
return terminalStructured(
|
|
254
269
|
{ ...status, terminated:Boolean(session.exited), alreadyExited:false, escalated },
|
|
255
270
|
`Terminated session ${pid}${status.status.startsWith('exited') ? '' : ' (still running)'}. Status: ${status.status}.`,
|
|
256
271
|
);
|
|
@@ -263,11 +278,11 @@ export async function listSessionsTool() {
|
|
|
263
278
|
const blocked = session.exited ? '' : session.partial ? 'blocked-possibly' : 'idle-or-running';
|
|
264
279
|
return { ...status, blocked, command:session.command.slice(0, 120) };
|
|
265
280
|
});
|
|
266
|
-
if (!facts.length) return
|
|
281
|
+
if (!facts.length) return terminalStructured({ sessions:[] }, 'No active terminal sessions.');
|
|
267
282
|
const rows = facts.map(session =>
|
|
268
283
|
`pid ${session.pid} · ${session.status} · ${Math.round(session.runtimeMs / 1000)}s · ${session.blocked} · ${session.command}`
|
|
269
284
|
);
|
|
270
|
-
return
|
|
285
|
+
return terminalStructured({ sessions:facts }, rows.join('\n'));
|
|
271
286
|
}
|
|
272
287
|
|
|
273
288
|
export const terminalToolHandlers = {
|