@remcp/runtime 0.2.80 → 0.2.82

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 CHANGED
@@ -1,7 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.82 — 2026-09-21
4
+
5
+ - Clarified `set_config_value` routing so local runtime preferences stay separate from hosted account-level `device_action` administration.
6
+ - Runtime functionality remains at 83 release tools; this release keeps client/runtime versions in lockstep with the hosted MCP catalog consolidation.
7
+
3
8
  ## Unreleased
4
9
 
10
+ ## 0.2.81 — 2026-09-21
11
+
12
+ - `record_screen` is advertised only when the current OS/session has a recorder backend the runtime can actually invoke.
13
+ - macOS/Windows require `ffmpeg`; Linux Wayland requires `wf-recorder + timeout`; Linux X11 requires `ffmpeg`.
14
+ - Availability errors are platform-specific, and regression coverage locks the capability matrix.
15
+ - Lockstep patch release with the ReMCP client/server at `0.2.81`.
16
+
5
17
  ## 0.2.80 — 2026-09-21
6
18
 
7
19
  - Wayland `type_text` can replace text in an inactive explicitly targeted native window without compositor focus when exactly one editable accessibility control is present.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/runtime",
3
- "version": "0.2.80",
3
+ "version": "0.2.82",
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",
package/src/catalog.mjs CHANGED
@@ -814,7 +814,7 @@ export const toolDefinitions = [
814
814
  {
815
815
  name: 'set_config_value',
816
816
  title: 'Change runtime setting',
817
- description: 'Change one of this local runtime’s own preferences on the selected computer: telemetryEnabled, maxReadLines, maxBufferedLines or maxOutputBytes. This does not rename the paired device; use hosted rename_device for that label. Access roots, blocked commands, shell/guardrails and the write limit remain local-only.',
817
+ description: 'Change one of this local runtime’s own preferences on the selected computer: telemetryEnabled, maxReadLines, maxBufferedLines or maxOutputBytes. This is not account-level device administration; use hosted device_action for ping, rename, enable/disable or removal. Access roots, blocked commands, shell/guardrails and the write limit remain local-only.',
818
818
  inputSchema: {
819
819
  type: 'object',
820
820
  properties: {
@@ -9,7 +9,7 @@ import { isWaylandSession } from '../screenshot-portal.mjs';
9
9
  import { waylandPortalCandidate } from '../wayland-remote-desktop.mjs';
10
10
  import { commandExists, runFile } from './common.mjs';
11
11
  import { desktopHandlers } from './desktop.mjs';
12
- import { diagnosticHandlers } from './diagnostics.mjs';
12
+ import { diagnosticHandlers, recordScreenAvailable } from './diagnostics.mjs';
13
13
  import { documentHandlers } from './documents.mjs';
14
14
 
15
15
  const readOnly = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
@@ -623,7 +623,7 @@ export async function capabilitySnapshot() {
623
623
  apps: win || mac || commandExists('dpkg-query') || commandExists('rpm'),
624
624
  audio: win || mac || commandExists('wpctl') || commandExists('pactl') || commandExists('amixer'),
625
625
  power: win || mac || commandExists('systemctl') || commandExists('loginctl'),
626
- record: win || mac || commandExists('wf-recorder') || commandExists('ffmpeg'),
626
+ record: recordScreenAvailable({ platform:process.platform, wayland }),
627
627
  ooxml: win || (commandExists('zip') && commandExists('unzip')),
628
628
  };
629
629
  }
@@ -5,6 +5,7 @@ import path from 'node:path';
5
5
  import process from 'node:process';
6
6
  import { stat } from 'node:fs/promises';
7
7
  import { assertAllowedCommand } from '../policy.mjs';
8
+ import { isWaylandSession } from '../screenshot-portal.mjs';
8
9
  import { resolveSafePath, text } from '../util.mjs';
9
10
  import {
10
11
  clamp,
@@ -243,6 +244,19 @@ export async function powerAction(args) {
243
244
  return text(`${policy.note ? `${policy.note}\n` : ''}Power action ${action} requested.`);
244
245
  }
245
246
 
247
+ export function recordScreenAvailable({
248
+ platform = process.platform,
249
+ wayland = platform === 'linux' ? isWaylandSession() : false,
250
+ commandExistsFn = commandExists,
251
+ } = {}) {
252
+ if (platform === 'linux') {
253
+ if (wayland) return commandExistsFn('wf-recorder') && commandExistsFn('timeout');
254
+ return commandExistsFn('ffmpeg');
255
+ }
256
+ if (platform === 'darwin' || platform === 'win32') return commandExistsFn('ffmpeg');
257
+ return false;
258
+ }
259
+
246
260
  export async function recordScreen(args) {
247
261
  const seconds = clamp(args.duration_seconds, 5, 1, 120);
248
262
  const fps = clamp(args.fps, 15, 1, 60);
@@ -251,7 +265,14 @@ export async function recordScreen(args) {
251
265
  const result = await runFile('timeout', ['--signal=INT', `${seconds}s`, 'wf-recorder', '-f',destination,'-r',String(fps),'-c','libx264'], { label:'screen recording', timeout:(seconds+10)*1000, allowFailure:true });
252
266
  if (![0, 124, 130].includes(Number(result.code))) throw new Error(result.stderr.trim() || `wf-recorder exited ${result.code}`);
253
267
  } else {
254
- if (!commandExists('ffmpeg')) unavailable('Screen recording', 'install wf-recorder on Wayland or ffmpeg');
268
+ if (process.platform === 'linux' && isWaylandSession()) {
269
+ unavailable('Screen recording', 'wf-recorder and timeout are required on Wayland');
270
+ }
271
+ if (!commandExists('ffmpeg')) {
272
+ if (process.platform === 'darwin') unavailable('Screen recording', 'ffmpeg is required on macOS');
273
+ if (process.platform === 'win32') unavailable('Screen recording', 'ffmpeg is required on Windows');
274
+ unavailable('Screen recording', 'ffmpeg is required on X11');
275
+ }
255
276
  let argv;
256
277
  if (process.platform === 'win32') argv=['-y','-f','gdigrab','-framerate',String(fps),'-i','desktop','-t',String(seconds),'-pix_fmt','yuv420p',destination];
257
278
  else if (process.platform === 'darwin') argv=['-y','-f','avfoundation','-framerate',String(fps),'-i','1:none','-t',String(seconds),'-pix_fmt','yuv420p',destination];