@remcp/runtime 0.2.24 → 0.2.25
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 +1 -1
- package/package.json +2 -2
- package/src/permissions.mjs +23 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ReMCP local runtime
|
|
2
2
|
|
|
3
|
-
`@remcp/runtime` is the local device runtime for [ReMCP](https://remcp.
|
|
3
|
+
`@remcp/runtime` is the local device runtime for [ReMCP](https://remcp.site). It is an MCP
|
|
4
4
|
server that runs on a computer you paired with ReMCP and executes the file, image, search, terminal,
|
|
5
5
|
and process tools that the hosted ReMCP MCP endpoint exposes to ChatGPT and Codex.
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remcp/runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "First-party ReMCP local device runtime: file, search, terminal and process tools over MCP for computers paired with ReMCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"homepage": "https://remcp.
|
|
7
|
+
"homepage": "https://remcp.site",
|
|
8
8
|
"author": "Anton Baider",
|
|
9
9
|
"bin": {
|
|
10
10
|
"remcp-runtime": "src/index.mjs"
|
package/src/permissions.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import path from 'node:path';
|
|
|
9
9
|
// System Settings → Privacy & Security → Full Disk Access → + → the binary that runs the tools
|
|
10
10
|
// These helpers turn those errnos into that instruction. They never widen access — they explain it.
|
|
11
11
|
const MACOS_HOME_FOLDERS = Object.freeze(['Desktop', 'Documents', 'Downloads']);
|
|
12
|
+
const WINDOWS_HOME_FOLDERS = Object.freeze([['Desktop'], ['Documents'], ['Downloads'], ['OneDrive', 'Desktop'], ['OneDrive', 'Documents']]);
|
|
12
13
|
const PERMISSION_CODES = new Set(['EACCES', 'EPERM']);
|
|
13
14
|
|
|
14
15
|
// The protected location a path belongs to ("~/Desktop", "iCloud Drive", "an external volume"), or
|
|
@@ -34,6 +35,20 @@ export function macosProtectedLocation(target, { platform = process.platform, ho
|
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
// Windows 11 ships the same idea as TCC under a different name: Controlled folder access (Windows
|
|
39
|
+
// Security → Virus & threat protection → Ransomware protection) blocks Desktop, Documents and
|
|
40
|
+
// Downloads for every application that is not on its allow list, and the process sees EPERM/EACCES.
|
|
41
|
+
export function windowsProtectedLocation(target, { platform = process.platform, home = os.homedir() } = {}) {
|
|
42
|
+
if (platform !== 'win32') return null;
|
|
43
|
+
const value = typeof target === 'string' ? target.trim() : '';
|
|
44
|
+
if (!value || !home) return null;
|
|
45
|
+
const relative = path.win32.relative(path.win32.resolve(home), path.win32.resolve(value));
|
|
46
|
+
if (!relative || relative.startsWith('..') || path.win32.isAbsolute(relative)) return null;
|
|
47
|
+
const parts = relative.split(path.win32.sep);
|
|
48
|
+
const match = WINDOWS_HOME_FOLDERS.find(entry => entry.every((segment, index) => (parts[index] || '').toLowerCase() === segment.toLowerCase()));
|
|
49
|
+
return match ? `%USERPROFILE%\\${match.join('\\')}` : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
37
52
|
// What the person should do about this failure, or null when the error is not a filesystem permission
|
|
38
53
|
// problem this module has better words for.
|
|
39
54
|
export function filesystemErrorExplanation(error, options = {}) {
|
|
@@ -49,14 +64,22 @@ export function filesystemErrorExplanation(error, options = {}) {
|
|
|
49
64
|
const where = typeof target === 'string' && target.trim() ? target.trim() : 'that path';
|
|
50
65
|
if (code === 'ENOSPC') return 'The disk is full (ENOSPC). Free some space or write to another volume.';
|
|
51
66
|
if (code === 'EROFS') return `${where} is on a read-only file system (EROFS). Write somewhere else, or remount it read-write.`;
|
|
67
|
+
if (code === 'EBUSY') return `${where} is in use by another program (EBUSY). Close whatever holds it and try again.`;
|
|
52
68
|
if (!PERMISSION_CODES.has(code)) return null;
|
|
53
69
|
const protectedLocation = macosProtectedLocation(target, { platform, home });
|
|
54
70
|
if (protectedLocation) {
|
|
55
71
|
return `macOS protects ${protectedLocation} (${code}), and ReMCP runs as a background service, which cannot show the permission prompt. Grant it by hand: System Settings → Privacy & Security → Full Disk Access → + → ${execPath}, then restart the agent with \`remcp start\`. A folder outside Desktop, Documents, Downloads and iCloud Drive needs no new permission.`;
|
|
56
72
|
}
|
|
73
|
+
const windowsLocation = windowsProtectedLocation(target, { platform, home });
|
|
74
|
+
if (windowsLocation) {
|
|
75
|
+
return `Windows Controlled folder access is blocking ${windowsLocation} (${code}). Add the binary that runs the tools (${execPath}) under Windows Security → Virus & threat protection → Ransomware protection → Allow an app through Controlled folder access, then restart the agent with \`remcp start\`. A folder outside Desktop, Documents, Downloads and OneDrive needs no new permission.`;
|
|
76
|
+
}
|
|
57
77
|
if (platform === 'darwin') {
|
|
58
78
|
return `macOS denied access to ${where} (${code}). Check the ownership and permissions of that folder, or add ${execPath} to System Settings → Privacy & Security → Full Disk Access and restart the agent with \`remcp start\`.`;
|
|
59
79
|
}
|
|
80
|
+
if (platform === 'win32') {
|
|
81
|
+
return `Windows denied access to ${where} (${code}). Check whether the file is read-only, open in another program, or inside a Controlled folder access area, then allow ${execPath} through Windows Security (Controlled folder access) and restart the agent with \`remcp start\`.`;
|
|
82
|
+
}
|
|
60
83
|
return `The operating system denied access to ${where} (${code}). Check that this user owns the folder and its parents, or choose another path.`;
|
|
61
84
|
}
|
|
62
85
|
|