@remcp/runtime 0.2.121 → 0.2.123
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/CHANGELOG.md +10 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/compact-mcp.mjs +100 -7
- package/src/mcp-v2.mjs +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.123 — 2026-10-01
|
|
4
|
+
|
|
5
|
+
- The compact local MCP facade now tracks live capability changes after startup. It advertises `tools.listChanged`, refreshes grouped input/output schemas, and adds or removes domains such as `control_browser` when loopback CDP becomes available or unavailable.
|
|
6
|
+
- Compact and granular capability polling now serializes discovery passes so a slow probe cannot overlap the next interval and apply a stale capability result out of order.
|
|
7
|
+
- The underlying 83 granular runtime tool names, input/output schemas, annotations, and handlers remain unchanged from 0.2.122.
|
|
8
|
+
|
|
9
|
+
## 0.2.122 — 2026-09-30
|
|
10
|
+
|
|
11
|
+
- No runtime tool names, schemas, or device-side implementations change in this release. The runtime package version remains in lockstep with the Windows bootstrap release, which pins the private Windows Node execution engine for reproducible installs.
|
|
12
|
+
|
|
3
13
|
## 0.2.121 — 2026-09-29
|
|
4
14
|
|
|
5
15
|
- record_screen gains a GNOME Shell Screencast backend for GNOME Wayland, so a native GNOME desktop no longer needs wf-recorder merely to advertise and perform bounded screen recording. The backend keeps start/stop on one D-Bus connection and produces WebM.
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ npx @remcp/runtime # granular capability-aware MCP server over stdi
|
|
|
27
27
|
node ./src/compact.mjs --print-tools # compact local façade for scanners/local MCP hosts
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
`src/compact.mjs` is a second stdio entrypoint over the **same real handlers**. It advertises `read_file` plus up to seven `verb_noun` domain tools (`manage_files`, `run_terminal`, `control_computer`, `view_image`, `control_browser`, `manage_system`, `manage_documents`) and narrows each operation enum to capabilities available on the current host. It exists for directory scanners and local MCP hosts that benefit from a small selection surface; the paired ReMCP agent continues to use the granular capability-aware entrypoint.
|
|
30
|
+
`src/compact.mjs` is a second stdio entrypoint over the **same real handlers**. It advertises `read_file` plus up to seven `verb_noun` domain tools (`manage_files`, `run_terminal`, `control_computer`, `view_image`, `control_browser`, `manage_system`, `manage_documents`) and narrows each operation enum to capabilities available on the current host. It also tracks capability changes while running: grouped schemas are refreshed and `notifications/tools/list_changed` is emitted when a domain appears, disappears, or changes membership. It exists for directory scanners and local MCP hosts that benefit from a small selection surface; the paired ReMCP agent continues to use the granular capability-aware entrypoint.
|
|
31
31
|
|
|
32
32
|
## Tools
|
|
33
33
|
|
|
@@ -81,7 +81,7 @@ example: they are enabled only while the runtime can use a supported loopback br
|
|
|
81
81
|
The generated hosted reference covers the current **10 hosted production definitions**, all model-visible
|
|
82
82
|
and routing to the 83 granular runtime operations described above; the optional widget-enabled surface is 15.
|
|
83
83
|
The separate compact local stdio entrypoint advertises `read_file` plus up to seven domain tools
|
|
84
|
-
(up to 8 tools total)
|
|
84
|
+
(up to 8 tools total) and keeps those groups capability-aware at runtime with `tools/list_changed`; the paired agent keeps using the capability-aware granular runtime.
|
|
85
85
|
See https://remcp.site/docs#tools and public `docs/TOOLS.md`.
|
|
86
86
|
|
|
87
87
|
## No approval staircase
|
package/package.json
CHANGED
package/src/compact-mcp.mjs
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
1
2
|
import { compactRuntimeToolDefinitions, resolveCompactRuntimeCall } from './compact-catalog.mjs';
|
|
2
3
|
import { invokeTool } from './invoke.mjs';
|
|
3
4
|
|
|
5
|
+
const DEFAULT_CAPABILITY_POLL_MS = 3000;
|
|
6
|
+
|
|
7
|
+
function pollIntervalMs() {
|
|
8
|
+
const requested = Number(process.env.REMCP_CAPABILITY_POLL_MS);
|
|
9
|
+
return Math.min(60_000, Math.max(250, Number.isFinite(requested) && requested > 0 ? requested : DEFAULT_CAPABILITY_POLL_MS));
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
function toolConfig(definition, fromJsonSchema) {
|
|
5
13
|
return {
|
|
6
14
|
title:definition.title,
|
|
@@ -11,20 +19,45 @@ function toolConfig(definition, fromJsonSchema) {
|
|
|
11
19
|
};
|
|
12
20
|
}
|
|
13
21
|
|
|
22
|
+
function toolUpdate(definition, fromJsonSchema) {
|
|
23
|
+
return {
|
|
24
|
+
title:definition.title,
|
|
25
|
+
description:definition.description,
|
|
26
|
+
paramsSchema:fromJsonSchema(definition.inputSchema || { type:'object' }),
|
|
27
|
+
...(definition.outputSchema ? { outputSchema:fromJsonSchema(definition.outputSchema) } : {}),
|
|
28
|
+
annotations:definition.annotations,
|
|
29
|
+
enabled:true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function definitionSignature(definition) {
|
|
34
|
+
if (!definition) return '';
|
|
35
|
+
return JSON.stringify({
|
|
36
|
+
title:definition.title,
|
|
37
|
+
description:definition.description,
|
|
38
|
+
inputSchema:definition.inputSchema,
|
|
39
|
+
outputSchema:definition.outputSchema,
|
|
40
|
+
annotations:definition.annotations,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
14
44
|
export async function startCompactRuntimeMcpServer({ version, instructions, onError = () => {} } = {}) {
|
|
15
45
|
const [{ McpServer, fromJsonSchema }, { serveStdio }] = await Promise.all([
|
|
16
46
|
import('@modelcontextprotocol/server'),
|
|
17
47
|
import('@modelcontextprotocol/server/stdio'),
|
|
18
48
|
]);
|
|
19
|
-
|
|
49
|
+
let definitions = await compactRuntimeToolDefinitions();
|
|
50
|
+
const currentDefinitions = new Map(definitions.map(definition => [definition.name, definition]));
|
|
20
51
|
let activeServer = null;
|
|
52
|
+
let capabilityTimer = null;
|
|
53
|
+
let capabilityPollRunning = false;
|
|
21
54
|
let closed = false;
|
|
22
55
|
|
|
23
56
|
const serverHandle = serveStdio(() => {
|
|
24
57
|
const server = new McpServer(
|
|
25
58
|
{ name:'remcp-runtime-compact', version },
|
|
26
59
|
{
|
|
27
|
-
capabilities:{ tools:{} },
|
|
60
|
+
capabilities:{ tools:{ listChanged:true } },
|
|
28
61
|
instructions,
|
|
29
62
|
cacheHints:{
|
|
30
63
|
'tools/list':{ ttlMs:3000, cacheScope:'private' },
|
|
@@ -33,20 +66,78 @@ export async function startCompactRuntimeMcpServer({ version, instructions, onEr
|
|
|
33
66
|
},
|
|
34
67
|
);
|
|
35
68
|
activeServer = server;
|
|
36
|
-
|
|
37
|
-
|
|
69
|
+
const registrations = new Map();
|
|
70
|
+
|
|
71
|
+
const registerDefinition = definition => {
|
|
72
|
+
const registered = server.registerTool(
|
|
38
73
|
definition.name,
|
|
39
74
|
toolConfig(definition, fromJsonSchema),
|
|
40
75
|
async (args, context) => {
|
|
41
76
|
try {
|
|
42
|
-
const
|
|
77
|
+
const activeDefinitions = [...currentDefinitions.values()];
|
|
78
|
+
const resolved = resolveCompactRuntimeCall(definition.name, args || {}, activeDefinitions);
|
|
43
79
|
return await invokeTool(resolved.runtimeName, resolved.runtimeArguments, { signal:context?.mcpReq?.signal });
|
|
44
80
|
} catch (error) {
|
|
45
81
|
return { content:[{ type:'text', text:error instanceof Error ? error.message : String(error) }], isError:true };
|
|
46
82
|
}
|
|
47
83
|
},
|
|
48
84
|
);
|
|
49
|
-
|
|
85
|
+
registrations.set(definition.name, registered);
|
|
86
|
+
return registered;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
for (const definition of definitions) registerDefinition(definition);
|
|
90
|
+
|
|
91
|
+
capabilityTimer = setInterval(async () => {
|
|
92
|
+
if (closed || capabilityPollRunning) return;
|
|
93
|
+
capabilityPollRunning = true;
|
|
94
|
+
try {
|
|
95
|
+
const nextDefinitions = await compactRuntimeToolDefinitions();
|
|
96
|
+
const nextByName = new Map(nextDefinitions.map(definition => [definition.name, definition]));
|
|
97
|
+
const names = new Set([...registrations.keys(), ...nextByName.keys()]);
|
|
98
|
+
|
|
99
|
+
for (const name of names) {
|
|
100
|
+
const before = currentDefinitions.get(name);
|
|
101
|
+
const after = nextByName.get(name);
|
|
102
|
+
const registered = registrations.get(name);
|
|
103
|
+
|
|
104
|
+
if (!after) {
|
|
105
|
+
currentDefinitions.delete(name);
|
|
106
|
+
if (registered?.enabled) registered.disable();
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!registered) {
|
|
111
|
+
currentDefinitions.set(name, after);
|
|
112
|
+
registerDefinition(after);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (definitionSignature(before) === definitionSignature(after) && registered.enabled !== false) {
|
|
117
|
+
currentDefinitions.set(name, after);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const previous = before;
|
|
122
|
+
currentDefinitions.set(name, after);
|
|
123
|
+
try {
|
|
124
|
+
registered.update(toolUpdate(after, fromJsonSchema));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (previous) currentDefinitions.set(name, previous);
|
|
127
|
+
else currentDefinitions.delete(name);
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
definitions = nextDefinitions;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
135
|
+
} finally {
|
|
136
|
+
capabilityPollRunning = false;
|
|
137
|
+
}
|
|
138
|
+
}, pollIntervalMs());
|
|
139
|
+
capabilityTimer.unref?.();
|
|
140
|
+
|
|
50
141
|
return server;
|
|
51
142
|
}, {
|
|
52
143
|
legacy:'serve',
|
|
@@ -54,7 +145,7 @@ export async function startCompactRuntimeMcpServer({ version, instructions, onEr
|
|
|
54
145
|
});
|
|
55
146
|
|
|
56
147
|
return {
|
|
57
|
-
definitions,
|
|
148
|
+
get definitions() { return definitions; },
|
|
58
149
|
async notification(notification) {
|
|
59
150
|
if (!activeServer) return;
|
|
60
151
|
await activeServer.server.notification(notification);
|
|
@@ -62,6 +153,8 @@ export async function startCompactRuntimeMcpServer({ version, instructions, onEr
|
|
|
62
153
|
async close() {
|
|
63
154
|
if (closed) return;
|
|
64
155
|
closed = true;
|
|
156
|
+
if (capabilityTimer) clearInterval(capabilityTimer);
|
|
157
|
+
capabilityTimer = null;
|
|
65
158
|
await serverHandle.close();
|
|
66
159
|
activeServer = null;
|
|
67
160
|
},
|
package/src/mcp-v2.mjs
CHANGED
|
@@ -32,6 +32,7 @@ export async function startRuntimeMcpServer({ version, instructions, onError = (
|
|
|
32
32
|
]);
|
|
33
33
|
let activeServer = null;
|
|
34
34
|
let capabilityTimer = null;
|
|
35
|
+
let capabilityPollRunning = false;
|
|
35
36
|
let closed = false;
|
|
36
37
|
|
|
37
38
|
const serverHandle = serveStdio(() => {
|
|
@@ -65,7 +66,8 @@ export async function startRuntimeMcpServer({ version, instructions, onError = (
|
|
|
65
66
|
|
|
66
67
|
let lastSupported = initiallySupported;
|
|
67
68
|
capabilityTimer = setInterval(async () => {
|
|
68
|
-
if (closed) return;
|
|
69
|
+
if (closed || capabilityPollRunning) return;
|
|
70
|
+
capabilityPollRunning = true;
|
|
69
71
|
try {
|
|
70
72
|
const next = new Set((await advertisedExtendedTools()).map(tool => tool.name));
|
|
71
73
|
let changed = false;
|
|
@@ -87,6 +89,8 @@ export async function startRuntimeMcpServer({ version, instructions, onError = (
|
|
|
87
89
|
if (changed) server.sendToolListChanged();
|
|
88
90
|
} catch (error) {
|
|
89
91
|
onError(error instanceof Error ? error : new Error(String(error)));
|
|
92
|
+
} finally {
|
|
93
|
+
capabilityPollRunning = false;
|
|
90
94
|
}
|
|
91
95
|
}, pollIntervalMs());
|
|
92
96
|
capabilityTimer.unref?.();
|