staff-mcp 1.3.0 → 2.0.1

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +158 -55
  3. package/README_zh.md +161 -53
  4. package/dist/src/data/HttpDataSession.d.ts +22 -0
  5. package/dist/src/data/HttpDataSession.js +929 -0
  6. package/dist/src/data/HttpDataSession.js.map +1 -0
  7. package/dist/src/data/node.d.ts +4 -0
  8. package/dist/src/data/node.js +93 -0
  9. package/dist/src/data/node.js.map +1 -0
  10. package/dist/src/data/types.d.ts +56 -0
  11. package/dist/src/data/types.js +2 -0
  12. package/dist/src/data/types.js.map +1 -0
  13. package/dist/src/data-stdio-docker.d.ts +10 -0
  14. package/dist/src/data-stdio-docker.js +140 -0
  15. package/dist/src/data-stdio-docker.js.map +1 -0
  16. package/dist/src/docker-proxy.d.ts +6 -1
  17. package/dist/src/docker-proxy.js +324 -147
  18. package/dist/src/docker-proxy.js.map +1 -1
  19. package/dist/src/extensions/apps.d.ts +12 -0
  20. package/dist/src/extensions/apps.js +85 -0
  21. package/dist/src/extensions/apps.js.map +1 -0
  22. package/dist/src/extensions/config.d.ts +27 -0
  23. package/dist/src/extensions/config.js +91 -0
  24. package/dist/src/extensions/config.js.map +1 -0
  25. package/dist/src/extensions/protocol.d.ts +35 -0
  26. package/dist/src/extensions/protocol.js +47 -0
  27. package/dist/src/extensions/protocol.js.map +1 -0
  28. package/dist/src/extensions/runtime.d.ts +16 -0
  29. package/dist/src/extensions/runtime.js +266 -0
  30. package/dist/src/extensions/runtime.js.map +1 -0
  31. package/dist/src/file-manager/extension.d.ts +21 -0
  32. package/dist/src/file-manager/extension.js +514 -0
  33. package/dist/src/file-manager/extension.js.map +1 -0
  34. package/dist/src/file-manager/file-core.d.ts +128 -0
  35. package/dist/src/file-manager/file-core.js +750 -0
  36. package/dist/src/file-manager/file-core.js.map +1 -0
  37. package/dist/src/file-manager/transfers.d.ts +423 -0
  38. package/dist/src/file-manager/transfers.js +540 -0
  39. package/dist/src/file-manager/transfers.js.map +1 -0
  40. package/dist/src/file-manager/ui/index.html +81 -0
  41. package/dist/src/index.js +276 -131
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/reverse/SseTransport.d.ts +34 -0
  44. package/dist/src/reverse/SseTransport.js +215 -0
  45. package/dist/src/reverse/SseTransport.js.map +1 -0
  46. package/dist/src/reverse/http.d.ts +7 -0
  47. package/dist/src/reverse/http.js +85 -0
  48. package/dist/src/reverse/http.js.map +1 -0
  49. package/dist/src/server.d.ts +4 -2
  50. package/dist/src/server.js +80 -18
  51. package/dist/src/server.js.map +1 -1
  52. package/dist/src/terminal/extension.d.ts +4 -0
  53. package/dist/src/terminal/extension.js +108 -0
  54. package/dist/src/terminal/extension.js.map +1 -0
  55. package/dist/src/terminal/pty.d.ts +14 -0
  56. package/dist/src/terminal/pty.js +121 -0
  57. package/dist/src/terminal/pty.js.map +1 -0
  58. package/dist/src/terminal/session.d.ts +136 -0
  59. package/dist/src/terminal/session.js +422 -0
  60. package/dist/src/terminal/session.js.map +1 -0
  61. package/dist/src/terminal/ui/index.html +183 -0
  62. package/dist/src/tools/file-tools.d.ts +2 -1
  63. package/dist/src/tools/file-tools.js +19 -7
  64. package/dist/src/tools/file-tools.js.map +1 -1
  65. package/dist/src/tools/mcp-client-tools.js +243 -103
  66. package/dist/src/tools/mcp-client-tools.js.map +1 -1
  67. package/dist/src/tools/shell-tools.js +1 -1
  68. package/dist/src/tools/shell-tools.js.map +1 -1
  69. package/dist/src/tools/skills.js +26 -1
  70. package/dist/src/tools/skills.js.map +1 -1
  71. package/dist/src/transports/http.d.ts +15 -2
  72. package/dist/src/transports/http.js +244 -65
  73. package/dist/src/transports/http.js.map +1 -1
  74. package/dist/src/transports/reverse.d.ts +23 -19
  75. package/dist/src/transports/reverse.js +137 -74
  76. package/dist/src/transports/reverse.js.map +1 -1
  77. package/dist/src/transports/stdio.d.ts +5 -2
  78. package/dist/src/transports/stdio.js +130 -20
  79. package/dist/src/transports/stdio.js.map +1 -1
  80. package/dist/src/utils/proxy.d.ts +2 -2
  81. package/dist/src/utils/proxy.js +84 -62
  82. package/dist/src/utils/proxy.js.map +1 -1
  83. package/dist/src/utils/server-activity.d.ts +6 -0
  84. package/dist/src/utils/server-activity.js +46 -0
  85. package/dist/src/utils/server-activity.js.map +1 -0
  86. package/dist/src/utils/server-lifecycle.d.ts +5 -0
  87. package/dist/src/utils/server-lifecycle.js +51 -0
  88. package/dist/src/utils/server-lifecycle.js.map +1 -0
  89. package/docs/file-manager.md +179 -0
  90. package/docs/terminal.md +66 -0
  91. package/package.json +28 -6
  92. package/dist/src/transports/fte-lifecycle.d.ts +0 -13
  93. package/dist/src/transports/fte-lifecycle.js +0 -76
  94. package/dist/src/transports/fte-lifecycle.js.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ ## 2.0.1 — 2026-10-26
4
+
5
+ - Resolve reverse data paths using the configured reverse origin, without requiring a public URL setting on chat-ai. Upgrade chat-ai and staff-mcp together; extension protocol versions remain v1.
6
+ - Preserve exact-session, same-origin, ticket and binding checks; HTTP/stdio endpoint behavior is unchanged.
7
+ - Require release tags to reference commits already contained in `master` before npm publishing.
8
+
9
+ ## 2.0.0 — 2026-10-26
10
+
11
+ ### Features
12
+
13
+ - Opt-in file workspace with version-checked editing, attachments and prepared uploads/downloads, independent of model tools.
14
+ - Opt-in human terminal with Linux PTY support and rendering-consumption acknowledgements; terminal bytes stay out of model context and chat history.
15
+ - Shared raw HTTP data sessions for files and streams across supported stdio, Docker, HTTP and reverse connections.
16
+
17
+ ### Fixes
18
+
19
+ - Preserve Windows drive/UNC roots during file-path validation without relaxing junction, symlink or workspace boundaries.
20
+ - Keep Docker tool caches writable for same-uid non-root containers and isolated from host-native binaries.
21
+ - Isolate unavailable or incompatible optional extensions from healthy standard MCP tools/resources/prompts; all extensions remain off by default.
22
+ - Tighten HTTP authentication, session capacity/idle expiry and owned-resource cleanup; surface uncertain file publication and potentially incomplete terminal output without automatic replay.
23
+
24
+ ### Breaking changes
25
+
26
+ - Reverse and extensions require chat-ai commit `66461d16090456d6f1fee21ce19088dceefd6658` or a later compatible version, including matching host/descriptors/UI assets.
27
+ - The old reverse handshake is incompatible even with extensions disabled. There is no old-protocol compatibility mode, legacy data fallback or automatic transfer/input resumption after disconnect.
28
+ - Node.js **22.22.2 or newer** is required, including in Docker. Linux/local Linux Docker are the primary full-extension environments. Windows native standard MCP (stdio/HTTP) and Windows Docker standard MCP have been validated; non-Linux Docker launchers disable extensions. macOS is untested.
29
+ - Standard stdio/Streamable HTTP tools, resources and prompts remain supported. No Chat8/schema9/format7/share protocol2 data migration is required.
30
+
31
+ ### Upgrade
32
+
33
+ 1. Finish in-flight operations and back up normal configuration; no data migration is needed.
34
+ 2. Upgrade the matching chat-ai host first, then staff-mcp 2.0.0, coordinating downtime for reverse connections.
35
+ 3. Reconnect MCP, reopen Apps and explicitly enable the extensions you want (`--extensions files`, `--extensions terminal`, or `--extensions files,terminal`).
package/README.md CHANGED
@@ -8,25 +8,56 @@ It provides secure file management, shell execution, LSP-powered code intelligen
8
8
 
9
9
  ---
10
10
 
11
+ ## Compatibility and coordinated upgrades
12
+
13
+ **Breaking release:** reverse connections and optional extensions require a matching chat-ai host: the host must implement reverse v1 and the session-relative data paths described below. Upgrade the host, staff-mcp, descriptors and UI assets together.
14
+
15
+ Standard stdio/Streamable HTTP tools, resources and prompts remain supported. Extensions are **all off by default**; unavailable or incompatible optional capabilities must not break an otherwise healthy standard MCP connection. The old reverse handshake itself is incompatible, even with extensions disabled: extension degradation cannot replace the paired reverse upgrade. There is no old-protocol compatibility mode, automatic transfer resumption or input replay after disconnect.
16
+
17
+ No Chat8/schema9/format7/share protocol2 data migration is required.
18
+
19
+ 1. Finish in-flight operations and back up your normal configuration; no data conversion is needed.
20
+ 2. Upgrade the matching chat-ai host first, then staff-mcp 2.0.1, coordinating downtime for reverse connections.
21
+ 3. Reconnect MCP, reopen Apps and explicitly enable only the extensions you want.
22
+
23
+ See [CHANGELOG](CHANGELOG.md) for the release summary.
24
+
11
25
  ## 🚀 Quick Start
12
26
 
13
- Requires **Node.js 22.22.2 or newer**.
27
+ Requires **Node.js 22.22.2 or newer**, including inside Docker images.
28
+
29
+ Linux and Linux-host local Docker Engine are the primary full-extension environments, subject to the prerequisites below. Windows native standard MCP (stdio and HTTP) and Windows Docker standard MCP have been validated, not full extensions. Non-Linux Docker launchers disable optional extensions. **macOS has not been tested**; path translation is not a claim of platform support.
30
+
31
+ Run staff-mcp 2.0.1 with an explicit package version:
32
+
33
+ ```bash
34
+ npx --yes staff-mcp@2.0.1 --working-dir /path/to/your/project
35
+ ```
36
+
37
+ For a source checkout of staff-mcp 2.0.1, install dependencies and build before using the absolute entrypoint in the examples:
38
+
39
+ ```bash
40
+ npm ci
41
+ npm run build
42
+ ```
43
+
44
+ Replace `/path/to/staff-mcp` with that checkout/build directory. Docker read-only mounts still require a compatible Node/native ABI/libc; in particular an optional PTY built for a different system is not guaranteed to work inside the image.
14
45
 
15
46
  ### 1. Standard Host Mode
16
47
  Run directly on your physical machine or virtual environment.
17
48
  ```bash
18
- npx -y staff-mcp@latest --working-dir /path/to/your/project
49
+ node /path/to/staff-mcp/dist/src/index.js --working-dir /path/to/your/project
19
50
  ```
20
51
 
21
52
  ### 2. Docker Transparent Proxy Mode (Cyber-Shell)
22
- Seamlessly spawn the AI assistant **inside any Docker container** while keeping the protocol connection with the host. It mounts your project and the `staff-mcp` binary automatically—zero overhead, instant startup!
53
+ Run staff-mcp inside a compatible Docker image while keeping standard MCP control connected to the host. The wrapper mounts the project and package; image startup, Node/native ABI/libc and mount permissions still apply. Linux host + local Docker Engine is the full-extension path. Non-Linux Docker launchers disable optional Apps/files/terminal extensions with a warning; Windows Docker standard MCP has been validated, while macOS is untested; base Docker connectivity still requires a reachable daemon and valid bind mounts.
23
54
 
24
55
  ```bash
25
56
  # Debug a Node.js project inside a pure Alpine container
26
- npx -y staff-mcp@latest --docker node:22-alpine
57
+ node /path/to/staff-mcp/dist/src/index.js --docker node:22-alpine
27
58
 
28
59
  # Perform security analysis inside a custom reverse-engineering image
29
- npx -y staff-mcp@latest --docker chineseastar/security:latest --profile android-reverse
60
+ node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest --profile android-reverse
30
61
  ```
31
62
 
32
63
  ### 3. Claude Desktop Configuration
@@ -36,10 +67,9 @@ Add the following to your `claude_desktop_config.json`:
36
67
  {
37
68
  "mcpServers": {
38
69
  "staff-mcp": {
39
- "command": "npx",
70
+ "command": "node",
40
71
  "args": [
41
- "-y",
42
- "staff-mcp@latest",
72
+ "/path/to/staff-mcp/dist/src/index.js",
43
73
  "--working-dir",
44
74
  "/path/to/your/project"
45
75
  ]
@@ -49,66 +79,119 @@ Add the following to your `claude_desktop_config.json`:
49
79
  ```
50
80
 
51
81
  ### 4. Reverse MCP Mode (Intranet Penetration)
52
- Connect your local machine to a centralized remote gateway (like `chat-ai`) from behind NAT/Firewalls. No local open ports required! It automatically handles disconnects and infinite retries.
82
+ Connect outward from behind NAT/firewalls to chat-ai's existing Web entrypoint, without an inbound listener on staff. Control uses SSE + POST; remote-initiated raw HTTP GET/PUT carries file/terminal bytes on that same Web port. chat-ai provides the current session data path, which staff resolves against the existing `--ru` origin; `MCP_REVERSE_URL` is only an optional connection hint on chat-ai, not a data-channel prerequisite. Reconnect creates fresh sessions and never replays tool calls, transfer handles or terminal input.
53
83
 
54
84
  ```bash
55
- npx -y staff-mcp@latest -t reverse \
56
- --ru https://chat.your-domain.com/api/mcp-reverse \
85
+ node /path/to/staff-mcp/dist/src/index.js -t reverse \
86
+ --ru https://chat.example.com/api/mcp/reverse \
57
87
  --rt your_secure_token_here \
58
- --rn my-macbook-pro
88
+ --rn my-workstation
59
89
  ```
60
90
 
91
+ The reverse client resolves the exact session data path against its existing `--ru` origin; chat-ai does not need `MCP_REVERSE_URL` to enable Apps. Only that session path or the already-supported exact absolute URL is accepted, before any data request or business admission; ticket, binding, authorization and redirect restrictions remain unchanged. HTTP and stdio still use absolute data endpoints. Upgrade chat-ai and staff-mcp together for this fix; no version-specific compatibility layer or extra negotiation flag is added.
92
+
61
93
  ### 5. Authenticated HTTP Mode
62
94
 
63
- HTTP authentication is optional for backward compatibility. Set `--ht` / `--http-token`
95
+ HTTP authentication is optional. Set `--ht` / `--http-token`
64
96
  to a strong, random token to require authentication:
65
97
 
66
98
  ```bash
67
- npx -y staff-mcp@latest -t http -p 3000 \
99
+ node /path/to/staff-mcp/dist/src/index.js -t http -p 3000 \
68
100
  --http-token your_secure_token_here --working-dir /path/to/your/project
69
101
  ```
70
102
 
71
- When a token is configured, clients must send `Authorization: Bearer <token>` on every request.
103
+ When a token is configured, clients must send `Authorization: Bearer <token>` on every MCP control request.
72
104
  For a full Authorization-header field, enter `Bearer <token>`; for a Bearer-token
73
105
  field, enter only the token. Raw tokens without the `Bearer` scheme are rejected.
74
106
  Missing or incorrect credentials return HTTP 401, including requests with an
75
107
  existing `mcp-session-id`. Authentication covers `/mcp` and the legacy `/sse` and
76
108
  `/messages` routes. CORS `OPTIONS` preflight remains public and cannot invoke MCP.
109
+ The raw `/mcp/data/...` routes use their own negotiated, connection-bound data
110
+ Bearer token plus `X-Data-Binding`, not the shared MCP control token.
77
111
 
78
- Omitting `--http-token` preserves existing unauthenticated HTTP deployments.
112
+ Omitting `--http-token` leaves MCP control on the HTTP listener unauthenticated.
79
113
  Anyone who can reach such a server can invoke its tools, so use this mode only
80
114
  on trusted networks. An explicitly empty token or one containing whitespace is
81
115
  rejected at startup. `--docker` forwards `--http-token` to the container command
82
116
  only when provided.
83
117
  Command-line tokens may be visible in shell history and process listings; keep
84
- access to those restricted. Stdio and reverse transports are unchanged;
118
+ access to those restricted. Stdio and reverse use separate authentication paths;
85
119
  `--reverse-token` does not configure HTTP auth.
86
120
  Use HTTPS through a reverse proxy for remote access, since plain HTTP does not
87
121
  protect the token in transit. This is a shared server token, not an OAuth flow.
88
122
 
89
123
  ---
90
124
 
91
- ## Reverse 1.2 upgrade notes
125
+ ## Reverse v1 and protocol boundary
126
+
127
+ The authoritative custom protocol is `chat-ai/docs/protocol/README.md` at the compatible host version specified above. chat-ai, staff-mcp and third parties can implement it independently; no extension SDK is required. The official MCP SDK, standard stdio/Streamable HTTP and tools/resources/prompts remain unchanged. There is no old FTE chunk or WS fallback, and no chat database migration.
128
+
129
+ Reverse GETs `<base>/sse` with `Authorization: Bearer <token>` and `X-MCP-Server-Name`; an SSE endpoint event supplies the POST message URL. SSE message events contain ordinary MCP JSON-RPC, not a private envelope. Explicit HTTP and HTTPS are accepted; HTTP logs one plaintext warning per start and does not protect tokens or payloads. Use HTTPS on untrusted networks; HTTPS verifies CA and target identity without automatic downgrade. The configured base URL has no credentials, query or fragment. No WebSocket upgrade, gateway process, launcher or private host leg is required. SDK initialization, data-session readiness and current user authorization remain separate checks; short-lived connections do not reset exponential backoff.
92
130
 
93
- Reverse mode uses `mcp-reverse@1.4.0` and MCP SDK `1.32.1`. Readiness is reported only after MCP initialization, and short-lived connections no longer reset exponential backoff. Reconnection never replays tool calls.
131
+ Optional CLI timeouts (milliseconds, forwarded in Docker mode):
94
132
 
95
- Optional CLI controls (milliseconds, also forwarded in Docker mode):
133
+ - `--reverse-connect-timeout`: 15000; 0 disables only the SSE connection deadline.
134
+ - `--reverse-initialization-timeout`: 15000; must be positive. Starts after the SSE connection and endpoint are established, not while waiting to connect; remains active when the connection deadline is disabled.
135
+ - `--reverse-read-timeout`: 45000; heartbeat liveness, not tool execution duration.
136
+ - `--reverse-stable-time`: 30000; stable lifetime before retry reset (0 resets immediately).
96
137
 
97
- - `--reverse-connect-timeout`: 15000; 0 disables the HTTP/SSE connection deadline.
98
- - `--reverse-initialization-timeout`: 15000; must be positive.
99
- - `--reverse-read-timeout`: 45000; liveness monitoring, not tool execution duration.
100
- - `--reverse-stable-time`: 30000; lifetime required before resetting the retry cycle (0 restores immediate reset).
138
+ `skill` / `read_skill_file` continue returning `_meta: { persistent: true }`. chat-ai consumes this host metadata hint, not `structuredContent.persistent`; it is not an MCP storage option. This does not relax the new reverse/extension compatibility requirement or change Chat8/schema9/format7/share protocol2.
101
139
 
102
- `skill` and `read_skill_file` return `_meta: { persistent: true }` instead of putting this host hint in business `structuredContent`. Updated chat-ai reads tool-result metadata only from `_meta`; the incorrect `structuredContent.persistent` format is not supported. Older chat-ai can still connect and call tools, but does not recognize the new history-enrichment hint. Publishing or upgrading staff-mcp does not require deploying chat-ai first; cross-turn skill enrichment requires a receiver that recognizes `_meta.persistent`. No new wire protocol or storage migration is required.
140
+ The two reverse transport sources (`src/reverse/SseTransport.ts` and chat-ai's `ReverseSseTransport.ts`) can later be extracted into MCP Client (host)/Server (remote) SDKs: SDK/standard-library imports plus injected URL/endpoint, headers and fetch, with transparent JSON-RPC and no data-protocol interception. No SDK package is being split out now. `src/reverse/http.ts` (Undici/TLS/proxy policy), `src/transports/reverse.ts` (server factory, extension/data setup, initialization and reconnect backoff), and host Web auth/management stay in integration, outside the pure transport boundary. The endpoint uses `session`, with no old `sessionId` compatibility or replay.
103
141
 
104
142
  ## 🛠️ Core Capabilities
105
143
 
144
+ Extensions are **all off by default**. Use `--extensions files`, `--extensions terminal`, or `--extensions files,terminal`; apps/data dependencies and terminal's streams v1 manifest are added automatically, not selected separately. Disabled features advertise no manifest entry and register no corresponding UI Resource or business handler. With both off there is no extension manifest or application data listener/session; ordinary MCP tools and non-UI Resources remain. HTTP mode still opens its normal MCP listener.
145
+
146
+ ```bash
147
+ # Files only, with the default main root at --working-dir
148
+ node /path/to/staff-mcp/dist/src/index.js --extensions files -w /workspace
149
+ # Terminal only; does not enable the file app
150
+ node /path/to/staff-mcp/dist/src/index.js --extensions terminal --shell /bin/bash
151
+ # Both apps, with explicit file roots replacing the default main root
152
+ node /path/to/staff-mcp/dist/src/index.js --extensions files,terminal -w /workspace \
153
+ --file-root main=/workspace --file-root assets=/srv/assets
154
+ # Explicit full-filesystem file access on a suitable Linux host (not a default)
155
+ node /path/to/staff-mcp/dist/src/index.js --extensions files --file-root system=/
156
+ ```
157
+
158
+ `--file-root id=path` may repeat; IDs must be unique lowercase letters/digits/hyphens, and relative paths resolve from the launching process cwd. Explicit roots replace, rather than append to, the default `main`. They affect the file app and its standard file Resources only when files is enabled, not the standard tools' `--working-dir` / `--allowed-dir` scope or terminal's default workspace cwd. Selecting `/` explicitly exposes the filesystem visible to the staff identity; it does not elevate privileges or create an OS security boundary. The library accepts [`ExtensionOptions`](src/extensions/config.ts): `{enabled?:('files'|'terminal')[],fileRoots?:{rootId:string,directory:string}[],shell?:string}`, with `enabled` defaulting to `[]`.
159
+
160
+ ### Independent file workspace
161
+
162
+ With `--extensions files`, the file manager is discovered under `experimental["cc.qqxing/extensions"]` (apps/files/data v1), then `cc.qqxing/apps/v1/list`, independently of model Tools. File CRUD, drafts, attachments and explicit download saving retain their existing behavior. The app and `transfer_file` share files v1 and the same public HTTP dataSession used by terminal: `cc.qqxing/data/v1/configure {binding}`, then `open` binds a prepared resource. Local stdio lazily opens loopback, local Docker stdio maps it automatically, direct HTTP shares the MCP port, and reverse actively GETs/PUTs the host Web port. Raw binary and cumulative consumption ACKs use a 256 KiB sliding window, not Base64 or per-chunk stop-and-wait. Clients that do not negotiate apps can still use ordinary tools and non-UI Resources. File roots do not broaden tool permissions; no FTE fallback. See [File manager contract and UI build](docs/file-manager.md) for exact methods, lifecycle, limits and packaging.
163
+
164
+ New Apps reusing supported RPC/Resources, files or streams need only their own descriptor, business handlers and UI, not host-core business branches. Truly new host permissions/capabilities require explicit registration at the host discovery/validation, server resource-module and browser-bridge composition roots. Unknown capabilities hide that App; malformed known ones remain validation errors.
165
+
166
+ ### Human terminal (explicit extension opt-in)
167
+
168
+ `--extensions terminal` needs Linux, a loadable optional `node-pty`, an executable shell and negotiated streams/data v1 with a usable duplex dataSession over local stdio/Docker, direct HTTP or reverse. If Linux/native PTY/shell requirements are unavailable, staff warns on stderr and omits terminal/streams from discovery; standard MCP and an available files extension remain usable. The default disabled state never loads the native PTY. `--shell` accepts an absolute executable path; otherwise a valid absolute executable `$SHELL` is used, falling back to `/bin/bash`. The interactive shell honors normal startup files and inherits staff's environment except exact internal control keys documented in the [terminal contract](docs/terminal.md). chat-ai uses the existing current-chat MCP grant and same-origin browser requests, with no extra terminal permission switch or high-risk confirmation. Terminal follows the host site's HTTP/HTTPS deployment policy without a terminal-specific TLS gate or origin allowlist. HTTPS is recommended for the entire site to protect login sessions, tool calls and terminal traffic; allowing HTTP does not encrypt those requests.
169
+
170
+ The PTY starts at the staff workspace (`main`) by default, independently of file roots, and runs as the staff process uid: its starting root/cwd is **not a sandbox** and shell filesystem/network effects are not restricted by file-tool path checks. Terminal bytes never enter model context or chat history. Each stream uses one same-origin browser-to-chat-ai WebSocket at `/api/mcp/app-stream` (`chat-app-stream-v1`) for input, output, resize, presence and real xterm consumption ACKs. The backend remains the shared HTTP dataSession. Browser presence refreshes every 10 seconds with a separate 120-second host deadline; the host generic stream module schedules remote renewal from each returned lease (staff defaults to 30 seconds). Opening the Shell App starts one PTY without another open button or confirmation. Exit, PTY failure or disconnection leaves the app shell for manual reconnect; ordinary hidden views keep read/ACK/presence but reject new input and resize. Actual page exit, close, revocation or expiry cleans up; descendant cleanup is best effort, not rollback.
171
+
172
+ Current descriptors and iframe assets keep **bridge v1** with explicit `scope:"workspace"` for files and `scope:"chat"` for terminal. The file App declares `capabilities.files:{version:1,upload:true,download:true}`; terminal declares `capabilities.streams:{version:1,purpose,create,renew,status,close,commands}` and requires streams/data v1. Its business RPC and data purpose remain `cc.qqxing/terminal`; host lifecycle methods use generic envelopes and opaque metadata, not PTY fields. The 2.0.0 extension contract requires matching host/descriptors/assets; deploy them together and reopen Apps, with no legacy compatibility path. Files-v1 adds its own `stat` for force-copy version checks, independent of the file-manager App; byte budgets owned by chat-ai are not remote business limits. See the [host/bridge boundary](docs/file-manager.md#host-boundary-and-bridge-v1).
173
+
174
+ Backpressured PTY exit may have incomplete output. Current source reports remote `status.error:{code:"OUTPUT_INCOMPLETE",message:string}` and host generic stream frame `incomplete?:boolean` / `error?:{code:string,message:string}` for abnormal close/status, with UI warning handling. The generic boolean is `incomplete`; the app-local terminal adapter maps it to its own presentation warning. It is not a remote status field. These diagnostics detect possible loss; they do not recover missing bytes or guarantee lossless output, even with exit code 0 or EOF. See [Terminal UI contract](docs/terminal.md).
175
+
106
176
  ### 1. Seamless Containerization (`--docker`)
107
177
  Never pollute your host machine again. By simply appending `--docker <image>`, `staff-mcp`:
108
178
  - Instantly injects itself into the container via read-only bind mounts (no `npm install` inside the container).
109
179
  - Automatically translates Windows/Mac paths to Linux container paths.
110
180
  - Names containers after their launch context (e.g. `staff-mcp-myproj-3000-a1b2c3` = workspace `myproj`, HTTP port `3000`, random suffix `a1b2c3`), so multiple sessions are easy to tell apart in `docker ps`.
111
- - Provides a `--docker-args` backdoor for hardware pass-through (e.g., ADB USB debugging, GPUs, host network).
181
+ - Mounts a dedicated Docker tools cache (`<staff-global>/tools/docker`) at `/opt/.staff/tools`, alongside the existing skills/profiles mounts. A matching non-root uid can write tools without creating directories in the image, and container-installed tools do not overwrite the host tool cache. Existing mount permissions still apply; no automatic chown or chmod.
182
+ - Allows `--docker-args` for compatible hardware/environment settings (e.g., ADB USB debugging or GPUs). Unsupported stdio data topologies disable optional extensions, not the MCP control connection; overrides of managed bootstrap/mapping and container lifecycle controls remain errors.
183
+
184
+ For **supported Linux local Docker stdio with at least one effective extension enabled**, the existing wrapper reserves a private container port published to a random **127.0.0.1** host port and inspects only its own cidfile container. A read-only mount of a host **0600 metadata file** supplies the reachable base URL without rewriting stdin/stdout or asking users to discover container IPs. The application listener remains lazy until `data/v1/configure`. With all extensions off, `dataAuto` is false: no application-data port publication, metadata mount or bootstrap is created. Ordinary workspace/package mounts are unchanged. Non-Docker stdio also has no application listener before configure. HTTP/reverse add no such publication; disabled extensions create no dataSession, while HTTP retains its MCP listener.
185
+
186
+ When files is enabled, each explicit Docker `--file-root id=path` bind-mounts that host path at `/opt/staff-file-roots/<id>`. Thus `--file-root system=/` explicitly binds the host root there, rather than referring only to the container root. This is a deliberate wide filesystem exposure, not automatic host privilege acquisition or a claim of support across all platforms; actual OS/container permissions and Docker topology still apply. Default file `main` and terminal cwd use the existing workspace mount.
187
+
188
+ This application-data path requires a local daemon and the host client/wrapper sharing reachable loopback, with compatible bridge/port publication. Non-Linux Docker launchers and incompatible stdio data topologies (remote/TCP/SSH daemon or host/container networking) warn and omit optional extensions; they retain ordinary MCP control/tools when Docker itself can start. HTTP/reverse do not need this stdio mapping. A failed data bootstrap or unavailable data configuration must not terminate an otherwise healthy MCP connection: data-dependent Apps stay unavailable, with no legacy byte fallback or operation replay. Loopback publication is not isolation from hostile containers. Metadata stays 0600 and must be readable by the container uid; workspace/global-directory permissions and PTY ABI/libc still apply. No automatic chown, permission relaxation or browser-user identity switch is performed. Normal exit/signals still clean the owned container, publication and metadata; no cross-restart resource recovery is promised.
189
+
190
+ ### Optional extensions do not define MCP connectivity
191
+
192
+ Availability is determined separately for files, terminal and the per-connection data channel. A missing terminal runtime disables terminal only; an unavailable configured file root disables the optional file extension while preserving the standard workspace tools/resources. Unknown or incompatible extension versions do not enable their handlers or Apps. chat-ai keeps successfully initialized standard tools/resources/prompts if optional Apps discovery or data configuration fails. Warnings go to stderr, never stdio JSON-RPC stdout.
193
+
194
+ This is not an authentication or lifecycle bypass: malformed CLI arguments, Docker launch failure, invalid credentials, and failed standard MCP transport/initialization remain errors. Workspace/global-mount access errors still fail the affected startup or file/tool operation; optional-extension degradation does not grant access or promise that every directory is prevalidated. Old/new incompatible reverse control protocols still require paired upgrades; optional capability degradation does not make those wire protocols compatible. No failed or uncertain file commit/tool/terminal input is automatically retried.
112
195
 
113
196
  ### 2. Skill & Profile Ecosystem (`--profile`)
114
197
  `staff-mcp` acts as an "AI Workspace Configurator". It uses a **5-tier Cascade Resolution** architecture to load role-specific skills (SOPs & Prompts) dynamically, all under the unified `.staff` directory convention:
@@ -127,10 +210,36 @@ Only the project-level `.staff/skills/` directory is live-watched. The directory
127
210
 
128
211
  Switch roles on the fly:
129
212
  ```bash
130
- npx -y staff-mcp@latest --profile default
131
- npx -y staff-mcp@latest --profile android-reverse
213
+ node /path/to/staff-mcp/dist/src/index.js --profile default
214
+ node /path/to/staff-mcp/dist/src/index.js --profile android-reverse
132
215
  ```
133
216
 
217
+ ### HTTP session capacity and idle expiry
218
+
219
+ Each HTTP listener admits at most **64 sessions** by default. Starting sessions and sessions whose cleanup is still pending or failed count toward that limit. A full listener returns HTTP **429** for new initialization without evicting an existing session; successful cleanup frees the slot. Use `--http-max-sessions <positive integer>` to configure it. This is independent of `--max-mcp-sessions`, which limits managed child MCP servers.
220
+
221
+ An HTTP session becomes eligible for cleanup after **30 minutes of observed inactivity** (`--http-session-idle-ms <milliseconds>`, 1..2147483647). A single sweep runs at most once per minute (or at the shorter configured timeout). A valid incoming MCP control message restarts the idle grace. Idle GET/SSE connections, server notifications, invalid HTTP requests and unauthenticated data attempts do not keep a session alive.
222
+
223
+ Running request handlers (even after HTTP disconnect/cancellation), file preparation/valid leases/in-flight writes or commits, pending data setup/open channels, and owned PTYs or output/exit draining prevent idle eviction. These facts come from their existing owners; the idle policy does not renew business leases or equate cancellation with completion. After activity settles, the next idle observation starts a full grace interval. Completed result records and an empty configured data session alone do not pin the connection.
224
+
225
+ An expired session ID returns HTTP **404**, including with an initialize body. Reconnect explicitly without the old ID; no tool, file commit or terminal input is replayed. Keeping an App iframe or an unsaved browser draft open does not pin an otherwise inactive server connection. The draft stays client-owned, but server operations require a new connection/App after expiry. This timeout applies only to HTTP listener sessions, not stdio or reverse. Docker HTTP forwards both flags. It is not a global quota for process-owned background commands, nested MCP sessions or LSP servers, and genuinely unsettled work/failed cleanup can continue occupying a slot.
226
+
227
+ ```bash
228
+ node /path/to/staff-mcp/dist/src/index.js -t http -p 3000 \
229
+ --http-token your_secure_token_here \
230
+ --http-max-sessions 64 --http-session-idle-ms 1800000
231
+ ```
232
+
233
+ ### Session shutdown
234
+
235
+ Normal SDK close, stdio EOF, and CLI SIGINT/SIGTERM/SIGHUP close session resources before process exit. Docker host-pipe EOF follows the same path. Cleanup fences new work immediately, closes skills watchers and debounce timers, and waits for file staging, accepted commits, data listeners and owned PTY exit. Repeated close waits the same cleanup; failures are reported rather than called successful. Synchronous exit cleanup remains a fallback until asynchronous cleanup finishes. SIGKILL/crashes and daemonized descendants are not guaranteed cleanups, and an unsettled underlying operation can delay graceful exit.
236
+
237
+ A new HTTP session requires a POST initialize request without an MCP session ID. Unknown or closed IDs return HTTP 404; GET/DELETE/malformed requests do not create replacement sessions. Failed initialization releases its resources. Listener shutdown closes active and initializing sessions. Reverse reconnect creates a fresh server after the previous session cleanup completes; it never reuses closed watchers or replays operations. HTTP listener capacity and idle expiry follow the policy above; stdio and reverse are not idle-evicted.
238
+
239
+ ### Managed child MCP sessions
240
+
241
+ `manage_mcp_session` reserves its session ID and capacity before asynchronous startup. A starting session can be stopped; late connection completion cannot restore it. Stopping attempts owned HTTP process-group cleanup even when SDK close fails, and reports incomplete cleanup as an error while retaining the session for retry. Connection/process exits no longer leave a ready session. These sessions expose standard nested tools, not a transparent Apps/data proxy or per-chat OS sandbox.
242
+
134
243
  ### 3. Built-in `skill-manager`
135
244
  Out of the box, the AI assistant knows how to manage its own skills! You can simply ask it to:
136
245
  > *"Install the official Anthropic canvas-design skill into my project."*
@@ -140,7 +249,7 @@ It will securely download, configure, and reload the skill without you lifting a
140
249
  - **Unified Shell Execution**: A single `execute_command` entry point for everything — quick commands, builds, and dev servers. If a command outlives its wait window (default 10s), it is NOT killed: it moves to the background and returns a task ID with its recent output. Follow up via `manage_background_task` (`logs` with optional blocking `wait`, `stop` kills the whole process group, `list`). Auto-detects and upgrades to `/bin/bash` if available, supporting complex pipelines.
141
250
  - **LSP Integration**: Extract symbols, get diagnostics, go to definitions, and find references for TypeScript, Python, and more.
142
251
  - TypeScript/JavaScript LSP keeps a local TypeScript 5.9.3 fallback toolchain. A usable workspace TypeScript is preferred; TypeScript 7 workspaces fall back because the current LSP ecosystem still depends on the tsserver API.
143
- - **Secure Sandbox**: Strictly confines the AI to the specified working directory and user-defined allowed paths.
252
+ - **File path boundary**: File operations check configured roots and protected paths. This is not an OS sandbox for shell commands or the optional PTY; use separately configured OS/container isolation for that boundary.
144
253
 
145
254
  ---
146
255
 
@@ -148,8 +257,8 @@ It will securely download, configure, and reload the skill without you lifting a
148
257
 
149
258
  | Option | Description | Default |
150
259
  | :--- | :--- | :--- |
151
- | `-w, --working-dir` | Root directory for the sandbox | `process.cwd()` |
152
- | `-d, --allowed-dir` | Extra directories allowed for access | `[]` |
260
+ | `-w, --working-dir` | Staff workspace and default file root / terminal cwd; not an OS sandbox | `process.cwd()` |
261
+ | `-d, --allowed-dir` | Extra directories for standard tools; does not add file-app roots | `[]` |
153
262
  | `-r, --profile` | The active profile for skills (e.g., android-reverse) | `default` |
154
263
  | `--enable-lsp` | Enable LSP capabilities (disabled by default) | `false` |
155
264
  | `--docker` | Run inside a Docker container using this image | `undefined` |
@@ -158,51 +267,45 @@ It will securely download, configure, and reload the skill without you lifting a
158
267
  | `-p, --port` | Port for HTTP server | `3000` |
159
268
  | `-h, --host` | Host for HTTP server | `127.0.0.1` |
160
269
  | `--ht, --http-token` | Optional bearer token for HTTP transport | `undefined` (no authentication) |
161
- | `--ru, --reverse-url` | URL for Reverse MCP Gateway | `undefined` |
270
+ | `--ru, --reverse-url` | Explicit HTTP(S) Web `/api/mcp/reverse` base endpoint | `undefined` |
162
271
  | `--rt, --reverse-token` | Security token for Reverse MCP | `undefined` |
163
272
  | `--rn, --reverse-name` | Server name for Reverse MCP | `undefined` |
164
- | `--proxy` | HTTP(S) proxy URL for outbound requests | `undefined` |
273
+ | `--extensions` | Comma-separated `files`, `terminal`, or both; apps/data dependencies are automatic | `[]` (all off) |
274
+ | `--file-root` | Repeatable `id=path`; explicit file roots replace the default and apply only when files is enabled | `main=<working-dir>` |
275
+ | `--shell` | Absolute executable PTY shell path | Valid absolute `$SHELL`, otherwise `/bin/bash` |
276
+ | `--proxy` | HTTP(S) proxy for supported HTTP clients and reverse control/data HTTP requests | `undefined` |
165
277
 
166
278
  ### 🌐 Proxy Support (Corporate Networks)
167
279
 
168
- staff-mcp automatically honors the standard proxy environment variables for **all** outbound requests (Reverse MCP SSE connections, message POSTs, and remote MCP client calls), on any supported Node.js version — no `NODE_USE_ENV_PROXY` flag required:
169
-
170
- ```bash
171
- export HTTPS_PROXY=http://proxy.company.com:8080
172
- export NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.example.com
173
- # NO_PROXY supports: exact hosts/IPs, domain suffixes (.example.com or bare example.com),
174
- # "*" wildcard, host:port qualifiers, and IPv4/IPv6 CIDR ranges (e.g. 172.16.0.0/12, fd00::/8)
175
- npx -y staff-mcp@latest -t reverse --ru https://chat.example.com/api/mcp/reverse --rt <token> --rn myserver
176
- ```
280
+ staff-mcp configures its Undici HTTP clients from `HTTP_PROXY` / `HTTPS_PROXY` (and lowercase equivalents), with `NO_PROXY` matching for exact hosts/IPs, domain suffixes, `*`, host:port and IPv4/IPv6 CIDRs. Explicit `--proxy` takes precedence for those clients and reverse connections, bypassing `NO_PROXY`.
177
281
 
178
- Alternatively, force a proxy explicitly (takes precedence over env vars; `NO_PROXY` is not applied):
282
+ Reverse control and data share an injected Undici HTTP pool. Without explicit `--proxy`, `selectProxyForOrigin` selects HTTP(S) environment proxies and applies target `NO_PROXY`; HTTPS uses `HTTPS_PROXY` with `HTTP_PROXY` fallback, including lowercase variants. An explicit proxy overrides that selection. Proxy and target certificate verification remain enabled and redirects are not followed. This does not replace proxy authentication, CA trust, DNS or target reachability. Validate corporate WAN streaming/SSE and cancellation in the target network; local results do not establish that path's availability.
179
283
 
180
- ```bash
181
- npx -y staff-mcp@latest --proxy http://proxy.company.com:8080 ...
182
- ```
183
-
184
- In `--docker` mode the same logic runs inside the container: proxy env vars injected by Docker (e.g. via `~/.docker/config.json`) are picked up automatically, or pass them / `--proxy` through explicitly. If your proxy performs TLS interception, add its CA via `NODE_EXTRA_CA_CERTS=/path/to/ca.pem`.
284
+ In `--docker` mode the HTTP-client and reverse proxy settings are evaluated inside the container; Docker environment injection or explicit `--proxy` can supply them. For TLS interception, `NODE_EXTRA_CA_CERTS=/path/to/ca.pem` adds trust rather than disabling certificate verification; certificate files must be visible inside the container, and native ABI/libc compatibility remains a deployment requirement.
185
285
 
186
286
  ### Hardware Pass-through Example (Android Reverse Engineering)
187
- If you need the AI to interact with an Android device connected via USB while running inside a container, utilizing network-based ADB pass-through is the most reliable cross-platform solution:
287
+ If you need the AI to interact with an Android device connected via USB while running inside a container, network-based ADB can be configured separately. These examples do not verify Docker Desktop stdio data mapping or device access; restrict ADB exposure to trusted peers:
188
288
 
189
289
  ```bash
190
290
  # 1. Start ADB Server on the host machine listening on all interfaces:
191
291
  # adb kill-server && adb -a nodaemon server start
192
292
 
193
293
  # 2. Start staff-mcp with the ADB_SERVER_SOCKET environment variable injected
194
- # On Mac/Windows:
195
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:host.docker.internal:5037"
294
+ # On Mac/Windows, if this hostname and the local Docker topology are available:
295
+ node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:host.docker.internal:5037"
196
296
 
197
- # On Native Linux (If not using --network host, point to the docker bridge IP):
198
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:172.17.0.1:5037"
297
+ # On Native Linux, use the actual reachable bridge address (example only):
298
+ node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:172.17.0.1:5037"
199
299
 
200
- # Alternative for Native Linux (Share host network stack completely):
201
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "--network host"
300
+ # stdio automatic data publication does not support --network host.
202
301
  ```
203
302
 
204
303
  ---
205
304
 
305
+ ## Release workflow
306
+
307
+ Merge the verified release changes into `master` first. From an up-to-date `master` checkout, confirm that `package.json`, the root package-lock versions and the release tag agree; finalize the changelog, then create and push the new version tag. The npm workflow rejects a tag whose commit is not contained in remote `master`. Do not publish from a development branch or move an existing release tag. Merging code alone does not publish to npm.
308
+
206
309
  ## 📄 License
207
310
 
208
311
  MIT