starmux 0.11.0 → 0.13.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/CONTRIBUTING.md +1 -1
- package/README.md +169 -97
- package/SECURITY.md +3 -3
- package/dist/src/access-control.js +23 -20
- package/dist/src/access-control.js.map +1 -1
- package/dist/src/access-dashboard.js +8 -2
- package/dist/src/access-dashboard.js.map +1 -1
- package/dist/src/cli/instances.js +87 -14
- package/dist/src/cli/instances.js.map +1 -1
- package/dist/src/cli/mac-mcp-gateway.js +4 -3
- package/dist/src/cli/mac-mcp-gateway.js.map +1 -1
- package/dist/src/cli/starmux-status.js +122 -0
- package/dist/src/cli/starmux-status.js.map +1 -0
- package/dist/src/cli/starmux.js +222 -49
- package/dist/src/cli/starmux.js.map +1 -1
- package/dist/src/deny-dashboard.js +2 -2
- package/dist/src/deny-dashboard.js.map +1 -1
- package/dist/src/instance-runtime.js +11 -2
- package/dist/src/instance-runtime.js.map +1 -1
- package/dist/src/instance-store.js +3 -1
- package/dist/src/instance-store.js.map +1 -1
- package/dist/src/ops-dashboard.js +4 -4
- package/dist/src/ops-dashboard.js.map +1 -1
- package/dist/src/permissions-dashboard.js +2 -2
- package/dist/src/permissions-dashboard.js.map +1 -1
- package/dist/src/runtime-paths.js +3 -3
- package/dist/src/runtime-paths.js.map +1 -1
- package/dist/src/starmux-migration.js +1 -1
- package/dist/src/starmux-migration.js.map +1 -1
- package/dist/vendor/desktop-commander/LICENSE +21 -0
- package/dist/vendor/desktop-commander/dist/bootstrap.js +22 -0
- package/dist/vendor/desktop-commander/dist/command-manager.js +246 -0
- package/dist/vendor/desktop-commander/dist/config-field-definitions.js +37 -0
- package/dist/vendor/desktop-commander/dist/config-manager.js +634 -0
- package/dist/vendor/desktop-commander/dist/config-recovery.js +81 -0
- package/dist/vendor/desktop-commander/dist/config.js +19 -0
- package/dist/vendor/desktop-commander/dist/custom-stdio.js +358 -0
- package/dist/vendor/desktop-commander/dist/error-handlers.js +15 -0
- package/dist/vendor/desktop-commander/dist/handlers/edit-search-handlers.js +6 -0
- package/dist/vendor/desktop-commander/dist/handlers/filesystem-handlers.js +450 -0
- package/dist/vendor/desktop-commander/dist/handlers/history-handlers.js +67 -0
- package/dist/vendor/desktop-commander/dist/handlers/index.js +7 -0
- package/dist/vendor/desktop-commander/dist/handlers/process-handlers.js +15 -0
- package/dist/vendor/desktop-commander/dist/handlers/search-answers.js +172 -0
- package/dist/vendor/desktop-commander/dist/handlers/search-handlers.js +136 -0
- package/dist/vendor/desktop-commander/dist/handlers/terminal-handlers.js +35 -0
- package/dist/vendor/desktop-commander/dist/index.js +88 -0
- package/dist/vendor/desktop-commander/dist/search-manager.js +1262 -0
- package/dist/vendor/desktop-commander/dist/server.js +1414 -0
- package/dist/vendor/desktop-commander/dist/terminal-manager.js +757 -0
- package/dist/vendor/desktop-commander/dist/tools/config.js +211 -0
- package/dist/vendor/desktop-commander/dist/tools/edit.js +455 -0
- package/dist/vendor/desktop-commander/dist/tools/feedback.js +10 -0
- package/dist/vendor/desktop-commander/dist/tools/filesystem.js +1047 -0
- package/dist/vendor/desktop-commander/dist/tools/fuzzySearch.js +74 -0
- package/dist/vendor/desktop-commander/dist/tools/fuzzySearchCore.js +125 -0
- package/dist/vendor/desktop-commander/dist/tools/improved-process-tools.js +726 -0
- package/dist/vendor/desktop-commander/dist/tools/mime-types.js +28 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/extract-images.js +131 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/index.js +4 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/lib/pdf2md.js +78 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/manipulations.js +112 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/markdown.js +30 -0
- package/dist/vendor/desktop-commander/dist/tools/pdf/utils.js +45 -0
- package/dist/vendor/desktop-commander/dist/tools/process.js +90 -0
- package/dist/vendor/desktop-commander/dist/tools/prompts.js +259 -0
- package/dist/vendor/desktop-commander/dist/tools/schemas.js +242 -0
- package/dist/vendor/desktop-commander/dist/tools/usage.js +24 -0
- package/dist/vendor/desktop-commander/dist/types.js +1 -0
- package/dist/vendor/desktop-commander/dist/ui/config-editor/config-editor-runtime.js +150 -0
- package/dist/vendor/desktop-commander/dist/ui/config-editor/index.html +13 -0
- package/dist/vendor/desktop-commander/dist/ui/config-editor/styles.css +587 -0
- package/dist/vendor/desktop-commander/dist/ui/contracts.js +57 -0
- package/dist/vendor/desktop-commander/dist/ui/file-preview/index.html +16 -0
- package/dist/vendor/desktop-commander/dist/ui/file-preview/preview-runtime.js +471 -0
- package/dist/vendor/desktop-commander/dist/ui/file-preview/shared/preview-file-types.js +59 -0
- package/dist/vendor/desktop-commander/dist/ui/file-preview/styles.css +1631 -0
- package/dist/vendor/desktop-commander/dist/ui/resources.js +93 -0
- package/dist/vendor/desktop-commander/dist/utils/ab-test.js +122 -0
- package/dist/vendor/desktop-commander/dist/utils/atomic-write.js +80 -0
- package/dist/vendor/desktop-commander/dist/utils/capture.js +40 -0
- package/dist/vendor/desktop-commander/dist/utils/dockerPrompt.js +9 -0
- package/dist/vendor/desktop-commander/dist/utils/exit-process.js +31 -0
- package/dist/vendor/desktop-commander/dist/utils/feature-flags.js +18 -0
- package/dist/vendor/desktop-commander/dist/utils/files/base.js +5 -0
- package/dist/vendor/desktop-commander/dist/utils/files/binary.js +65 -0
- package/dist/vendor/desktop-commander/dist/utils/files/docx.js +694 -0
- package/dist/vendor/desktop-commander/dist/utils/files/excel.js +497 -0
- package/dist/vendor/desktop-commander/dist/utils/files/factory.js +168 -0
- package/dist/vendor/desktop-commander/dist/utils/files/image.js +89 -0
- package/dist/vendor/desktop-commander/dist/utils/files/index.js +14 -0
- package/dist/vendor/desktop-commander/dist/utils/files/pdf.js +124 -0
- package/dist/vendor/desktop-commander/dist/utils/files/text.js +423 -0
- package/dist/vendor/desktop-commander/dist/utils/fuzzySearchLogger.js +126 -0
- package/dist/vendor/desktop-commander/dist/utils/internal-facts.js +23 -0
- package/dist/vendor/desktop-commander/dist/utils/lazy-package.js +44 -0
- package/dist/vendor/desktop-commander/dist/utils/lineEndingHandler.js +77 -0
- package/dist/vendor/desktop-commander/dist/utils/logger.js +72 -0
- package/dist/vendor/desktop-commander/dist/utils/mcp-ui-ab-test.js +62 -0
- package/dist/vendor/desktop-commander/dist/utils/open-browser.js +2 -0
- package/dist/vendor/desktop-commander/dist/utils/process-detection.js +260 -0
- package/dist/vendor/desktop-commander/dist/utils/process-tree.js +223 -0
- package/dist/vendor/desktop-commander/dist/utils/rename.js +74 -0
- package/dist/vendor/desktop-commander/dist/utils/ripgrep-resolver.js +69 -0
- package/dist/vendor/desktop-commander/dist/utils/shell.js +187 -0
- package/dist/vendor/desktop-commander/dist/utils/system-info.js +727 -0
- package/dist/vendor/desktop-commander/dist/utils/terminal-timestamps.js +18 -0
- package/dist/vendor/desktop-commander/dist/utils/toolHistory.js +309 -0
- package/dist/vendor/desktop-commander/dist/utils/trackTools.js +55 -0
- package/dist/vendor/desktop-commander/dist/utils/unsupportedParams.js +66 -0
- package/dist/vendor/desktop-commander/dist/utils/usageTracker.js +225 -0
- package/dist/vendor/desktop-commander/dist/utils/welcome-onboarding.js +2 -0
- package/dist/vendor/desktop-commander/dist/utils/withTimeout.js +85 -0
- package/dist/vendor/desktop-commander/dist/version.js +1 -0
- package/dist/vendor/desktop-commander/package.json +15 -0
- package/docs/ACCESS_CONTROL.md +5 -5
- package/docs/CLIENTS.md +11 -19
- package/docs/CONNECT_CHATGPT.md +4 -6
- package/docs/INSTALL.md +9 -5
- package/docs/INSTANCES.md +5 -2
- package/docs/OAUTH.md +6 -14
- package/docs/PLATFORMS.md +4 -4
- package/docs/README.md +2 -11
- package/docs/REMOTE_SETUP.md +13 -13
- package/docs/SECURITY.md +5 -5
- package/docs/assets/starmux-architecture.svg +315 -0
- package/package.json +14 -2
- package/docs/ARCHITECTURE.md +0 -51
- package/docs/MIGRATION.md +0 -37
- package/docs/RELEASE_STATUS.md +0 -31
- package/docs/TYPESCRIPT_MIGRATION.md +0 -56
- package/docs/VALIDATION_OAUTH.md +0 -79
- package/docs/VALIDATION_TUNNEL.md +0 -39
- package/docs/VALIDATION_WORKBUDDY.md +0 -59
- package/docs/assets/mcp-connection-route.svg +0 -104
- package/docs/assets/mcp-gateway-simple.svg +0 -62
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executes a promise with a timeout. If the promise doesn't resolve or reject within
|
|
3
|
+
* the specified timeout, returns the provided default value.
|
|
4
|
+
*
|
|
5
|
+
* @param operation The promise to execute
|
|
6
|
+
* @param timeoutMs Timeout in milliseconds
|
|
7
|
+
* @param operationName Name of the operation (for logs)
|
|
8
|
+
* @param defaultValue Value to return if the operation times out
|
|
9
|
+
* @returns Promise that resolves with the operation result or the default value on timeout
|
|
10
|
+
*/
|
|
11
|
+
export function withTimeout(operation, timeoutMs, operationName, defaultValue) {
|
|
12
|
+
// Don't sanitize operation name for logs - only telemetry will sanitize if needed
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
let isCompleted = false;
|
|
15
|
+
// Set up timeout
|
|
16
|
+
const timeoutId = setTimeout(() => {
|
|
17
|
+
if (!isCompleted) {
|
|
18
|
+
isCompleted = true;
|
|
19
|
+
if (defaultValue !== null) {
|
|
20
|
+
resolve(defaultValue);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Keep the original operation name in the error message
|
|
24
|
+
// Telemetry sanitization happens at the capture level
|
|
25
|
+
reject(`__ERROR__: ${operationName} timed out after ${timeoutMs / 1000} seconds`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}, timeoutMs);
|
|
29
|
+
// Execute the operation
|
|
30
|
+
operation
|
|
31
|
+
.then(result => {
|
|
32
|
+
if (!isCompleted) {
|
|
33
|
+
isCompleted = true;
|
|
34
|
+
clearTimeout(timeoutId);
|
|
35
|
+
resolve(result);
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.catch(error => {
|
|
39
|
+
if (!isCompleted) {
|
|
40
|
+
isCompleted = true;
|
|
41
|
+
clearTimeout(timeoutId);
|
|
42
|
+
if (defaultValue !== null) {
|
|
43
|
+
resolve(defaultValue);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Pass the original error unchanged - sanitization for telemetry happens in capture
|
|
47
|
+
reject(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run an operation under a timeout WITH real cancellation.
|
|
55
|
+
*
|
|
56
|
+
* Unlike withTimeout (which only races a timer and leaves the underlying work
|
|
57
|
+
* running — holding its libuv thread/fd until the OS call returns), this passes
|
|
58
|
+
* an AbortSignal into the operation and aborts it when the timeout fires, so a
|
|
59
|
+
* read/stream that honors the signal is cancelled and its resources released.
|
|
60
|
+
*
|
|
61
|
+
* Rejects with an Error whose `.code` is 'ETIMEDOUT' on timeout (so existing
|
|
62
|
+
* ETIMEDOUT handling / permission-error mapping keeps working).
|
|
63
|
+
*
|
|
64
|
+
* Caveat: an operation wedged inside a single un-interruptible syscall only
|
|
65
|
+
* observes the abort once that syscall returns; library reads that ignore the
|
|
66
|
+
* signal (e.g. Excel/PDF parsers) still get the timeout rejection but keep
|
|
67
|
+
* running in the background until they finish on their own.
|
|
68
|
+
*/
|
|
69
|
+
export function runWithAbortableTimeout(operation, timeoutMs, operationName) {
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
let timeoutId;
|
|
72
|
+
const timeout = new Promise((_, reject) => {
|
|
73
|
+
timeoutId = setTimeout(() => {
|
|
74
|
+
controller.abort();
|
|
75
|
+
const error = new Error(`${operationName} timed out after ${timeoutMs / 1000} seconds`);
|
|
76
|
+
error.code = 'ETIMEDOUT';
|
|
77
|
+
reject(error);
|
|
78
|
+
}, timeoutMs);
|
|
79
|
+
});
|
|
80
|
+
const op = operation(controller.signal);
|
|
81
|
+
// Swallow the late abort rejection so it can't surface as an unhandled
|
|
82
|
+
// rejection after the timeout has already settled the race.
|
|
83
|
+
op.catch(() => { });
|
|
84
|
+
return Promise.race([op, timeout]).finally(() => clearTimeout(timeoutId));
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const VERSION = '0.3.1';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wonderwhy-er/desktop-commander",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Purified zero-telemetry build of Desktop Commander MCP for Starmux",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Eduards Ruzga",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/wonderwhy-er/DesktopCommanderMCP.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"desktop-commander": "dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/docs/ACCESS_CONTROL.md
CHANGED
|
@@ -6,11 +6,11 @@ Authentication decides who can connect. Your instance configuration decides what
|
|
|
6
6
|
|
|
7
7
|
| Mode | Use when | Configure |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| `
|
|
10
|
-
| `api-key` | Your client accepts a Bearer key | `starmux auth key "My
|
|
11
|
-
| `oauth` | Your client uses browser login and consent | [Configure a provider](OAUTH.md), then `starmux auth mode oauth` |
|
|
9
|
+
| `none` *(default)* | Connecting on the same computer, or your tunnel/reverse proxy already restricts callers | `starmux auth mode none` |
|
|
10
|
+
| `api-key` | Your client accepts a Bearer API key header | `starmux auth key "My AI Client"` |
|
|
11
|
+
| `oauth` | Your client uses browser login and consent (e.g., ChatGPT Web) | [Configure a provider](OAUTH.md), then `starmux auth mode oauth` |
|
|
12
12
|
|
|
13
|
-
A new local instance
|
|
13
|
+
A new local instance defaults to `none` (also accepted as `ingress`). For remote access in this mode, your tunnel or reverse proxy must restrict access; HTTPS encrypts traffic but does not authenticate callers. Each instance has one active authentication mode at a time, and all authorized clients share the instance's approved workspace permissions.
|
|
14
14
|
|
|
15
15
|
## API keys
|
|
16
16
|
|
|
@@ -20,7 +20,7 @@ starmux auth
|
|
|
20
20
|
starmux auth revoke CREDENTIAL_ID
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Creating a key
|
|
23
|
+
Creating a key automatically enables `api-key` mode and prints both Form UI fields and a ready-to-paste `mcpServers` JSON snippet. Copy the key when printed; Starmux stores only its digest. New keys begin with `smx_` (migrated `mgw_` keys continue to work). Expiration accepts positive durations (`30m`, `12h`, `30d`, `4w`) or a future ISO timestamp. Omit it for no expiry.
|
|
24
24
|
|
|
25
25
|
Configure your client with `Authorization: Bearer YOUR_KEY`. See the [complete HTTPS example](REMOTE_SETUP.md#2-https--bearer-api-key).
|
|
26
26
|
|
package/docs/CLIENTS.md
CHANGED
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
# AI client compatibility
|
|
2
2
|
|
|
3
|
-
Choose a client you already use, then check its
|
|
3
|
+
Choose a client you already use, then check its recommended connection below. Transport, authentication and host platform are configured independently.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
| Client | Current project validation | Connection guide |
|
|
5
|
+
| Client | Validation status | Connection guide |
|
|
9
6
|
| --- | --- | --- |
|
|
10
|
-
| **ChatGPT
|
|
11
|
-
| **Claude App** | Remote MCP
|
|
12
|
-
| **Codex** | Tested:
|
|
13
|
-
| **WorkBuddy** | Tested:
|
|
14
|
-
| **Doubao (豆包)** |
|
|
15
|
-
|
|
16
|
-
A client listing does not imply every authentication or transport combination has passed. In particular, Claude App is a compatibility target, and ChatGPT direct-HTTPS OAuth remains unverified. [OAuth evidence](OAUTH.md) · [WorkBuddy evidence](VALIDATION_WORKBUDDY.md) · [Protected Tunnel evidence](VALIDATION_TUNNEL.md)
|
|
17
|
-
|
|
18
|
-
## Use WorkBuddy with a Linux workspace
|
|
19
|
-
|
|
7
|
+
| **ChatGPT Web** | ✅ Tested: Secure Tunnel + OAuth (coding, session revocation and login) | [ChatGPT OAuth](REMOTE_SETUP.md#4-configure-starmux-and-chatgpt) |
|
|
8
|
+
| **Claude App** | 🎯 Target: Remote MCP Custom Connector | [Official custom connector setup](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp) |
|
|
9
|
+
| **Codex** | ✅ Tested: Protected Tunnel | [Tunnel setup](CONNECT_CHATGPT.md#2-secure-mcp-tunnel--no-inbound-port) · [HTTP API-key example](REMOTE_SETUP.md#configure-workbuddy-or-another-header-capable-client) |
|
|
10
|
+
| **WorkBuddy** | ✅ Tested: Direct HTTPS + IPv6 + Bearer API key | [API Key setup](REMOTE_SETUP.md#2-https--bearer-api-key) |
|
|
11
|
+
| **Doubao (豆包)** | ✅ Community verified | [Deployment options](REMOTE_SETUP.md) |
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
See [OAuth setup](OAUTH.md) and [remote setup](REMOTE_SETUP.md) for step-by-step configuration.
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
## Use WorkBuddy or Desktop AI Clients with a Linux / NVIDIA Jetson Host
|
|
24
16
|
|
|
25
|
-
**
|
|
17
|
+
**Your AI client's operating system does not have to match your target machine's operating system.** Many AI clients (such as WorkBuddy or ChatGPT Desktop) only offer macOS and Windows desktop apps. You can keep your AI client on your Mac or Windows laptop, run `starmux up --code` on a **Linux (`x64` / `ARM64`)** server or **NVIDIA Jetson** device, and connect over HTTPS + Bearer API Key or Tunnel to edit code and run terminal commands on the target machine remotely.
|
|
26
18
|
|
|
27
|
-
|
|
19
|
+
See [platform support](PLATFORMS.md) for Linux and cross-platform details.
|
|
28
20
|
|
|
29
21
|
|
|
30
22
|
[Choose authentication](ACCESS_CONTROL.md#choose-an-authentication-mode) · [Remote deployment](REMOTE_SETUP.md) · [All documentation](README.md)
|
package/docs/CONNECT_CHATGPT.md
CHANGED
|
@@ -19,9 +19,9 @@ This is a guide for **your own private ChatGPT connection**, not a claim that th
|
|
|
19
19
|
## Before either connection
|
|
20
20
|
|
|
21
21
|
1. Install and start Starmux using [Local installation](INSTALL.md).
|
|
22
|
-
2. Run `starmux status` and confirm
|
|
23
|
-
3. The **local** MCP address is `http://127.0.0.1:<PORT>/mcp`. You don't paste that into ChatGPT: ChatGPT runs in the cloud and cannot dial your
|
|
24
|
-
4. Start with
|
|
22
|
+
2. Run `starmux status` and confirm **`● Starmux is running`**. Note your **actual local port**. The default port is **18893**; use the actual value shown by `status`.
|
|
23
|
+
3. The **local** MCP address is `http://127.0.0.1:<PORT>/mcp`. You don't paste that into ChatGPT Web: ChatGPT runs in the cloud and cannot dial your machine's `localhost` directly.
|
|
24
|
+
4. Start with the default **Read-only** mode (`starmux up`). Switch to **Coding mode** (`starmux up --code`) when you want ChatGPT to edit files or run Shell commands.
|
|
25
25
|
|
|
26
26
|
## 1. Direct HTTPS — your domain, your Gateway
|
|
27
27
|
|
|
@@ -118,7 +118,7 @@ tunnel-client doctor --profile <YOUR_PROFILE> --explain
|
|
|
118
118
|
tunnel-client run --profile <YOUR_PROFILE>
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
Keep both
|
|
121
|
+
Keep both Starmux and `tunnel-client` running.
|
|
122
122
|
|
|
123
123
|
### Step 3 — Choose the Tunnel in ChatGPT
|
|
124
124
|
|
|
@@ -145,6 +145,4 @@ Neither route replaces Desktop Commander or changes your local file permissions.
|
|
|
145
145
|
- **Tools appear, but write is denied:** This may be correct. Check remote caller authorization and local restricted/developer mode. Don't disable security just to make discovery green.
|
|
146
146
|
- **No “Add custom MCP server” option:** ChatGPT's available custom MCP features depend on plan and workspace permissions. See [OpenAI's current connection instructions](https://help.openai.com/en/articles/12584461-connecting-custom-mcp-servers-in-chatgpt).
|
|
147
147
|
|
|
148
|
-
**Community release gate:** Neither route is independently accepted as a public one-click workflow yet; ChatGPT OAuth Tunnel coding and revocation tests passed, while direct-HTTPS OAuth and independent onboarding remain open. No public endpoint should be deployed without verified caller identity and revocation.
|
|
149
|
-
|
|
150
148
|
[Main README](../README.md) · [Local installation](INSTALL.md) · [Security](SECURITY.md)
|
package/docs/INSTALL.md
CHANGED
|
@@ -10,6 +10,14 @@ starmux up
|
|
|
10
10
|
|
|
11
11
|
The first start creates a private configuration and starts a background process on `127.0.0.1:18893`. The terminal returns when the service is ready.
|
|
12
12
|
|
|
13
|
+
Read the **Connect an AI client (MCP settings)** section printed by `up` (also available with `status`):
|
|
14
|
+
|
|
15
|
+
- **None (no token required):** a local client uses Streamable HTTP with authentication set to None. For a web or remote client, connect through a protected HTTPS proxy or tunnel that forwards to `127.0.0.1:18893`.
|
|
16
|
+
- **API key:** configure Bearer token authentication (`Authorization: Bearer <YOUR_API_KEY>`) with the key you saved when creating it. The output shows how many keys are active and the command to create one if needed.
|
|
17
|
+
- **OAuth:** use the configured **URL (Remote)** and complete browser sign-in with an allowed account.
|
|
18
|
+
|
|
19
|
+
`starmux dashboard` opens the local Web Access Console with its owner login so you can view and copy settings in your browser. `--json` retains structured status for scripts.
|
|
20
|
+
|
|
13
21
|
```sh
|
|
14
22
|
starmux verify
|
|
15
23
|
starmux status
|
|
@@ -36,11 +44,7 @@ With API-key or OAuth authentication enabled, give `verify` a valid Bearer crede
|
|
|
36
44
|
|
|
37
45
|
## Connect remotely
|
|
38
46
|
|
|
39
|
-
Continue with [remote setup](REMOTE_SETUP.md): HTTPS + API key, ChatGPT OAuth, or an existing protected
|
|
40
|
-
|
|
41
|
-
## Existing installations
|
|
42
|
-
|
|
43
|
-
Use [migration](MIGRATION.md) to retain your existing workspaces and credentials. New installations store state in `~/.config/starmux` on all platforms.
|
|
47
|
+
Continue with [remote setup](REMOTE_SETUP.md): HTTPS + API key, ChatGPT OAuth, or an existing protected tunnel. A local verification pass confirms the local service; the last step of each remote route is a real tool call from your client.
|
|
44
48
|
|
|
45
49
|
## Install from a checkout
|
|
46
50
|
|
package/docs/INSTANCES.md
CHANGED
|
@@ -9,6 +9,7 @@ starmux ls
|
|
|
9
9
|
starmux status -i work
|
|
10
10
|
starmux logs -f -i blog
|
|
11
11
|
starmux down -i work
|
|
12
|
+
starmux rm blog
|
|
12
13
|
```
|
|
13
14
|
|
|
14
15
|
Names such as `work` and `blog` are arbitrary labels. Names and stable IDs both work with `-i` / `--instance`, before or after the command. Instances share the OS account; coding mode uses that account's permissions.
|
|
@@ -37,7 +38,7 @@ Set `VISUAL` or `EDITOR` to your editor executable for `config edit`. JSONC supp
|
|
|
37
38
|
snapshots/
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
Configuration holds workspace, port, permissions and optional upstream settings. Credentials and secrets live in private state. `config validate` and `config schema` provide diagnostics and the full schema.
|
|
41
|
+
Configuration holds workspace, port, permissions and optional upstream settings. Credentials and secrets live in private state. `config validate` and `config schema` provide diagnostics and the full schema. `starmux config schema` also works before creating an instance.
|
|
41
42
|
|
|
42
43
|
## Import, bind and export
|
|
43
44
|
|
|
@@ -57,13 +58,15 @@ Import makes a private copy. `--link` keeps the external file authoritative. `ma
|
|
|
57
58
|
starmux config copy experiment -i work
|
|
58
59
|
starmux config rename development -i work
|
|
59
60
|
starmux config default development
|
|
60
|
-
starmux config archive -i experiment
|
|
61
|
+
starmux rm experiment # Alias for: starmux config archive -i experiment
|
|
61
62
|
starmux ls --archived
|
|
62
63
|
starmux config restore -i experiment
|
|
63
64
|
```
|
|
64
65
|
|
|
65
66
|
Copies receive a new identity and port, without credentials or private secrets. An authenticated copy needs its authentication configured before startup. Archive stops the instance and retains recoverable data. The first created instance is the CLI default; `config default` changes it explicitly.
|
|
66
67
|
|
|
68
|
+
With no instances, `starmux ls` points to `starmux up` to get started. If all instances are archived, use `starmux ls --archived` and restore one with `starmux config restore -i NAME`. Instance operations reject missing or extra arguments; use `-i NAME` to select the instance to archive or restore.
|
|
69
|
+
|
|
67
70
|
## Snapshots, secrets and automation
|
|
68
71
|
|
|
69
72
|
Concurrent edits return `CONFIG_CONFLICT`; reload before saving again. A failed apply attempts to restore the last successful worker configuration. Credential revocations are never rolled back. `config recover` repairs a missing source from the last successful snapshot without replacing an existing file.
|
package/docs/OAUTH.md
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# OAuth for ChatGPT and other MCP clients
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Starmux acts as the OAuth **resource server**. A separate authorization server (such as Keycloak) owns user login, consent, PKCE authorization codes, token issuance and refresh. Starmux remains loopback-only (`127.0.0.1`); HTTPS or Tunnel transport is configured independently of authorization.
|
|
4
4
|
|
|
5
5
|
**Start here:** [step-by-step remote installation](REMOTE_SETUP.md) covers Keycloak, HTTPS proxy, CLI configuration, ChatGPT fields and the tested Tunnel layout. This document covers provider setup and the OAuth reference contract.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Implementation overview
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
- The first provider contract uses JWT access tokens with `sub`, `azp` (OAuth client ID), `sid` (stable authorization-server session ID), `iat`, `exp`, audience and scope. Opaque tokens/introspection and providers without this contract are not supported.
|
|
13
|
-
- Resource metadata is available without a token only in OAuth mode at `/.well-known/oauth-protected-resource` and the resource-path-specific location. MCP initialization, listing, tools and resources all require authentication. Mixed anonymous/OAuth tools are not enabled.
|
|
14
|
-
- Local signed-token tests do not establish real ChatGPT compatibility. HTTPS and Tunnel end-to-end acceptance must be recorded separately.
|
|
15
|
-
- A reference Keycloak realm generator is provided. Keycloak's resource-indicator and CIMD features are experimental; do not claim full provider compatibility based only on successful discovery.
|
|
9
|
+
- **Supported features:** protected-resource discovery (`/.well-known/oauth-protected-resource`), Bearer challenges, JWT validation, owner subject/client allowlists, tool security metadata, live local session revocation, and CLI / Web Dashboard management.
|
|
10
|
+
- **Token contract:** JWT access tokens with `sub`, `azp` (OAuth client ID), `sid` (stable authorization-server session ID), `iat`, `exp`, audience and scope. Opaque tokens/introspection are not supported.
|
|
11
|
+
- **Discovery:** Resource metadata is available without a token in OAuth mode at `/.well-known/oauth-protected-resource` and the resource-path-specific location. MCP initialization, tool listing, tool calls and resources all require a valid OAuth token.
|
|
16
12
|
|
|
17
13
|
## Configure an existing authorization server
|
|
18
14
|
|
|
@@ -99,11 +95,7 @@ A maximum of 512 remembered OAuth sessions is enforced without evicting revocati
|
|
|
99
95
|
|
|
100
96
|
JWT verification checks signatures, issuer, audience, expiry/not-before, issued-at, client, owner subject, session and scope. A wrong scope/owner is denied before MCP dispatch. The Core does not retry tools when authentication fails. Locally trusted Shell tools remain capable of accessing owner files; OAuth admission does not isolate them from the owner account.
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## Validation history
|
|
105
|
-
|
|
106
|
-
See [client compatibility](CLIENTS.md) and the [OAuth validation archive](VALIDATION_OAUTH.md).
|
|
98
|
+
See [client compatibility](CLIENTS.md) and [remote setup](REMOTE_SETUP.md) for deployment details.
|
|
107
99
|
|
|
108
100
|
## Reproduce the local provider test
|
|
109
101
|
|
package/docs/PLATFORMS.md
CHANGED
|
@@ -20,10 +20,10 @@ starmux down
|
|
|
20
20
|
- State is stored under `~/.config/starmux`; on Windows, `~` is the user profile. Private files use owner-only POSIX permissions or Windows ACLs.
|
|
21
21
|
- Windows runtime control uses authenticated named pipes; Unix hosts use private sockets. Gateway-generated commands use host-appropriate quoting and shells.
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## Supported hosts
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Starmux runs on **macOS** (`Apple Silicon` and `Intel`), **Linux** (`x64`, `ARM64`, and edge devices such as **NVIDIA Jetson**), and **Windows**.
|
|
26
26
|
|
|
27
|
-
The native macOS App is a development build
|
|
27
|
+
The native macOS menu bar App is provided as a development build in [`app/`](../app/README.md).
|
|
28
28
|
|
|
29
|
-
`npm test` uses isolated home directories and ports
|
|
29
|
+
`npm test` uses isolated home directories and ports to verify process lifecycle, workspace permissions, authentication, configuration, and the CLI.
|
package/docs/README.md
CHANGED
|
@@ -9,17 +9,8 @@ Start locally, connect your client, then explore advanced configuration as neede
|
|
|
9
9
|
## Go further
|
|
10
10
|
|
|
11
11
|
- [OAuth and ChatGPT](OAUTH.md)
|
|
12
|
+
- [Connect ChatGPT (HTTPS & Tunnel)](CONNECT_CHATGPT.md)
|
|
12
13
|
- [Instances and JSONC configuration](INSTANCES.md)
|
|
13
|
-
- [Migration from Mac MCP Gateway](MIGRATION.md)
|
|
14
14
|
- [Permissions and security](SECURITY.md)
|
|
15
15
|
- [Client compatibility](CLIENTS.md) and [platform support](PLATFORMS.md)
|
|
16
|
-
- [
|
|
17
|
-
- [Architecture](ARCHITECTURE.md) and [contributing](../CONTRIBUTING.md)
|
|
18
|
-
|
|
19
|
-
## Validation archives
|
|
20
|
-
|
|
21
|
-
These records describe specific tested deployments, not installation instructions:
|
|
22
|
-
|
|
23
|
-
- [WorkBuddy](VALIDATION_WORKBUDDY.md)
|
|
24
|
-
- [Tunnel](VALIDATION_TUNNEL.md)
|
|
25
|
-
- [OAuth](VALIDATION_OAUTH.md)
|
|
16
|
+
- [Contributing](../CONTRIBUTING.md)
|
package/docs/REMOTE_SETUP.md
CHANGED
|
@@ -6,15 +6,13 @@ For help choosing between the three authentication modes, read [the access-contr
|
|
|
6
6
|
|
|
7
7
|
## Choose authentication independently of transport
|
|
8
8
|
|
|
9
|
-
| Authentication | Choose it when |
|
|
9
|
+
| Authentication | Choose it when | CLI Command |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
|
|
|
12
|
-
| Bearer API key | Your client accepts an `Authorization
|
|
13
|
-
| OAuth | Your client
|
|
11
|
+
| **None** (`none` / `ingress`) | Connecting locally, or your tunnel already restricts callers | `starmux auth mode none` |
|
|
12
|
+
| **Bearer API key** | Your client accepts an `Authorization: Bearer <key>` header (e.g., WorkBuddy, Cursor) | `starmux auth key "My AI Client"` |
|
|
13
|
+
| **OAuth 2.0** | Your client requires a browser login/consent flow (e.g., ChatGPT Web) | `starmux auth oauth setup ...` |
|
|
14
14
|
|
|
15
|
-
HTTPS and Tunnel are transport choices; API key and OAuth are authentication choices.
|
|
16
|
-
|
|
17
|
-
A Core has one active authentication mode. Switching to OAuth makes existing API keys unusable on that Core, and vice versa. This guide configures one Core at a time, not simultaneous API-key/OAuth listeners. The separate acceptance instances used during development are not a prerequisite for ordinary installation.
|
|
15
|
+
HTTPS reverse proxy and Tunnel are network transport choices; API key and OAuth are authentication choices. Each Starmux instance has one active authentication mode at a time. Switching to OAuth disables API keys on that instance (and vice versa). See the [client matrix](CLIENTS.md).
|
|
18
16
|
|
|
19
17
|
## 1. Start locally
|
|
20
18
|
|
|
@@ -81,10 +79,12 @@ For WorkBuddy, merge this entry into `~/.workbuddy/mcp.json` without replacing u
|
|
|
81
79
|
```json
|
|
82
80
|
{
|
|
83
81
|
"mcpServers": {
|
|
84
|
-
"
|
|
82
|
+
"starmux": {
|
|
85
83
|
"type": "streamable-http",
|
|
86
84
|
"url": "https://mcp.example.com/mcp",
|
|
87
|
-
"headers": {
|
|
85
|
+
"headers": {
|
|
86
|
+
"Authorization": "Bearer smx_REPLACE_WITH_YOUR_API_KEY"
|
|
87
|
+
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
@@ -110,7 +110,7 @@ Set that variable securely in the environment of the actual Codex process; setti
|
|
|
110
110
|
4. The next MCP request with that key must fail with HTTP 401. A missing/wrong key must also fail. Already-running tools are not canceled.
|
|
111
111
|
5. Create a new key to restore access; update the client's private configuration.
|
|
112
112
|
|
|
113
|
-
Local `starmux verify` in API-key mode reads `STARMUX_TOKEN` from its environment. Local PASS
|
|
113
|
+
Local `starmux verify` in API-key mode reads `STARMUX_TOKEN` from its environment. Local PASS confirms the local endpoint; verify remote access with a real tool call from your client.
|
|
114
114
|
|
|
115
115
|
## 3. OAuth: deploy the authorization server
|
|
116
116
|
|
|
@@ -199,7 +199,7 @@ Validate and run Caddy as in the API-key section. This allowlist is for the **pr
|
|
|
199
199
|
|
|
200
200
|
Before enabling public MCP access, configure Core authentication as below. If the proxy is already running while Core still uses ingress mode, keep the `/mcp` route disabled until OAuth mode is set. Issuer metadata can be exposed first for configuration.
|
|
201
201
|
|
|
202
|
-
## 4. Configure
|
|
202
|
+
## 4. Configure Starmux and ChatGPT
|
|
203
203
|
|
|
204
204
|
```sh
|
|
205
205
|
starmux auth oauth setup \
|
|
@@ -263,8 +263,8 @@ Manage keys/sessions in the local **Dashboard → Access control**. The macOS Ap
|
|
|
263
263
|
| HTTP 401 after revoke or idle expiry | Do not retry tools indefinitely; inspect local revocation state, then use a fresh authorized login if appropriate |
|
|
264
264
|
| HTTP 403 | Allowed owner/client and `gateway:access`; do not expand permissions just to hide a failure |
|
|
265
265
|
| OAuth works but a write is denied | Existing workspace/OS/upstream policy still applies |
|
|
266
|
-
| Web answer/app fails to render | Correlate actual tool/audit results before deciding whether execution failed; never automatically repeat a side-effecting call |
|
|
267
|
-
| CLI changes do not affect the server | Check `
|
|
266
|
+
| Web answer/app fails to render | Correlate actual tool/audit results (`starmux logs -f`) before deciding whether execution failed; never automatically repeat a side-effecting call |
|
|
267
|
+
| CLI changes do not affect the server | Check `starmux ls` and `starmux status` to ensure you are targeting the intended instance (`-i <name>`) |
|
|
268
268
|
|
|
269
269
|
The local App, Core, proxy, database, provider and Tunnel have separate process lifecycles. Stopping Core stops new tool service; it does not automatically shut down the others. Persist private configuration and PostgreSQL/Caddy data, configure service startup deliberately, and repeat acceptance after reboot or deployment changes.
|
|
270
270
|
|
package/docs/SECURITY.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
Starmux is a self-hosted connection and routing layer around real upstream MCP tools. Treat exposure to remote clients as a powerful privilege.
|
|
4
4
|
|
|
5
5
|
- The default **restricted read-only** role enforces project-scoped access and disables arbitrary Shell/write operations.
|
|
6
|
-
- The **trusted
|
|
7
|
-
- HTTP MCP listens on loopback by default. **Never expose the raw loopback port publicly.** Direct HTTPS requires a publicly reachable TLS endpoint **and
|
|
8
|
-
- OpenAI Tunnel is outbound and uses OpenAI's forwarding infrastructure. Tunnel readiness is **not**
|
|
6
|
+
- The **trusted coding** role (`starmux up --code`) can edit files and run commands using your OS account permissions. Migrated macOS Home-only configurations keep their previous sandbox until explicitly changed.
|
|
7
|
+
- HTTP MCP listens on loopback (`127.0.0.1`) by default. **Never expose the raw loopback port publicly.** Direct HTTPS requires a publicly reachable TLS endpoint **and caller authentication**. DNS/TLS alone are insufficient.
|
|
8
|
+
- OpenAI Tunnel is outbound and uses OpenAI's forwarding infrastructure. Tunnel readiness alone is **not** caller authorization unless paired with tunnel access controls or Starmux authentication.
|
|
9
9
|
- **OAuth** mode validates tokens and allowed accounts/clients, and supports local session revocation, including refreshed tokens in that session. A fresh authorized session can restore access; session revocation is not an account ban.
|
|
10
|
-
-
|
|
10
|
+
- **Bearer API key** mode authenticates a client credential on every MCP request and supports instant revocation. The default **`none` (`ingress`)** mode does not verify a token in Starmux. See [access control](ACCESS_CONTROL.md). Keys inherit your instance's workspace permissions.
|
|
11
11
|
- Filesystem permissions, macOS TCC/FDA and permissions in the actual upstream Desktop Commander remain relevant.
|
|
12
12
|
- Do not commit API keys, tunnel runtime profiles, passwords or protected files; use personal private configuration and report vulnerabilities privately.
|
|
13
13
|
- Multi-user/multi-host orchestration and user-defined policy scripts are **not shipped** in this preview.
|
|
14
14
|
|
|
15
|
-
See [connection steps](CONNECT_CHATGPT.md) and [
|
|
15
|
+
See [connection steps](CONNECT_CHATGPT.md) and [platform support](PLATFORMS.md).
|