staff-mcp 1.2.0 → 2.0.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +178 -49
  3. package/README_zh.md +176 -47
  4. package/dist/src/data/HttpDataSession.d.ts +22 -0
  5. package/dist/src/data/HttpDataSession.js +925 -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 +54 -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 +289 -128
  42. package/dist/src/index.js.map +1 -1
  43. package/dist/src/lsp/manager.d.ts +2 -0
  44. package/dist/src/lsp/manager.js +22 -10
  45. package/dist/src/lsp/manager.js.map +1 -1
  46. package/dist/src/reverse/SseTransport.d.ts +34 -0
  47. package/dist/src/reverse/SseTransport.js +215 -0
  48. package/dist/src/reverse/SseTransport.js.map +1 -0
  49. package/dist/src/reverse/http.d.ts +7 -0
  50. package/dist/src/reverse/http.js +85 -0
  51. package/dist/src/reverse/http.js.map +1 -0
  52. package/dist/src/server.d.ts +4 -2
  53. package/dist/src/server.js +80 -18
  54. package/dist/src/server.js.map +1 -1
  55. package/dist/src/terminal/extension.d.ts +4 -0
  56. package/dist/src/terminal/extension.js +108 -0
  57. package/dist/src/terminal/extension.js.map +1 -0
  58. package/dist/src/terminal/pty.d.ts +14 -0
  59. package/dist/src/terminal/pty.js +121 -0
  60. package/dist/src/terminal/pty.js.map +1 -0
  61. package/dist/src/terminal/session.d.ts +136 -0
  62. package/dist/src/terminal/session.js +422 -0
  63. package/dist/src/terminal/session.js.map +1 -0
  64. package/dist/src/terminal/ui/index.html +183 -0
  65. package/dist/src/tools/file-tools.d.ts +2 -1
  66. package/dist/src/tools/file-tools.js +19 -7
  67. package/dist/src/tools/file-tools.js.map +1 -1
  68. package/dist/src/tools/mcp-client-tools.js +244 -104
  69. package/dist/src/tools/mcp-client-tools.js.map +1 -1
  70. package/dist/src/tools/shell-tools.js +1 -1
  71. package/dist/src/tools/shell-tools.js.map +1 -1
  72. package/dist/src/tools/skills.js +26 -1
  73. package/dist/src/tools/skills.js.map +1 -1
  74. package/dist/src/tools/system-tools.d.ts +9 -3
  75. package/dist/src/tools/system-tools.js +31 -48
  76. package/dist/src/tools/system-tools.js.map +1 -1
  77. package/dist/src/transports/http.d.ts +16 -2
  78. package/dist/src/transports/http.js +261 -59
  79. package/dist/src/transports/http.js.map +1 -1
  80. package/dist/src/transports/reverse.d.ts +23 -19
  81. package/dist/src/transports/reverse.js +130 -74
  82. package/dist/src/transports/reverse.js.map +1 -1
  83. package/dist/src/transports/stdio.d.ts +6 -2
  84. package/dist/src/transports/stdio.js +131 -19
  85. package/dist/src/transports/stdio.js.map +1 -1
  86. package/dist/src/utils/proxy.d.ts +3 -3
  87. package/dist/src/utils/proxy.js +84 -62
  88. package/dist/src/utils/proxy.js.map +1 -1
  89. package/dist/src/utils/server-activity.d.ts +6 -0
  90. package/dist/src/utils/server-activity.js +46 -0
  91. package/dist/src/utils/server-activity.js.map +1 -0
  92. package/dist/src/utils/server-lifecycle.d.ts +5 -0
  93. package/dist/src/utils/server-lifecycle.js +51 -0
  94. package/dist/src/utils/server-lifecycle.js.map +1 -0
  95. package/docs/file-manager.md +179 -0
  96. package/docs/terminal.md +66 -0
  97. package/package.json +40 -19
  98. package/dist/src/transports/fte-lifecycle.d.ts +0 -13
  99. package/dist/src/transports/fte-lifecycle.js +0 -76
  100. package/dist/src/transports/fte-lifecycle.js.map +0 -1
  101. package/dist/tests/docker-proxy.test.d.ts +0 -1
  102. package/dist/tests/docker-proxy.test.js +0 -395
  103. package/dist/tests/docker-proxy.test.js.map +0 -1
  104. package/dist/tests/file-write-queue.test.d.ts +0 -1
  105. package/dist/tests/file-write-queue.test.js +0 -105
  106. package/dist/tests/file-write-queue.test.js.map +0 -1
  107. package/dist/tests/fte-lifecycle.test.d.ts +0 -1
  108. package/dist/tests/fte-lifecycle.test.js +0 -118
  109. package/dist/tests/fte-lifecycle.test.js.map +0 -1
  110. package/dist/tests/lsp-client.test.d.ts +0 -1
  111. package/dist/tests/lsp-client.test.js +0 -52
  112. package/dist/tests/lsp-client.test.js.map +0 -1
  113. package/dist/tests/package-info.test.d.ts +0 -1
  114. package/dist/tests/package-info.test.js +0 -54
  115. package/dist/tests/package-info.test.js.map +0 -1
  116. package/dist/tests/proxy-no-proxy.test.d.ts +0 -1
  117. package/dist/tests/proxy-no-proxy.test.js +0 -156
  118. package/dist/tests/proxy-no-proxy.test.js.map +0 -1
  119. package/dist/tests/proxy.test.d.ts +0 -1
  120. package/dist/tests/proxy.test.js +0 -89
  121. package/dist/tests/proxy.test.js.map +0 -1
  122. package/dist/tests/reverse-reconnect.test.d.ts +0 -1
  123. package/dist/tests/reverse-reconnect.test.js +0 -89
  124. package/dist/tests/reverse-reconnect.test.js.map +0 -1
  125. package/dist/tests/security.test.d.ts +0 -1
  126. package/dist/tests/security.test.js +0 -21
  127. package/dist/tests/security.test.js.map +0 -1
  128. package/dist/tests/shell-tools.test.d.ts +0 -1
  129. package/dist/tests/shell-tools.test.js +0 -113
  130. package/dist/tests/shell-tools.test.js.map +0 -1
  131. package/dist/tests/test_files/test.d.ts +0 -1
  132. package/dist/tests/test_files/test.js +0 -4
  133. package/dist/tests/test_files/test.js.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## 2.0.0 — 2026-10-26
4
+
5
+ ### Features
6
+
7
+ - Opt-in file workspace with version-checked editing, attachments and prepared uploads/downloads, independent of model tools.
8
+ - Opt-in human terminal with Linux PTY support and rendering-consumption acknowledgements; terminal bytes stay out of model context and chat history.
9
+ - Shared raw HTTP data sessions for files and streams across supported stdio, Docker, HTTP and reverse connections.
10
+
11
+ ### Fixes
12
+
13
+ - Preserve Windows drive/UNC roots during file-path validation without relaxing junction, symlink or workspace boundaries.
14
+ - Keep Docker tool caches writable for same-uid non-root containers and isolated from host-native binaries.
15
+ - Isolate unavailable or incompatible optional extensions from healthy standard MCP tools/resources/prompts; all extensions remain off by default.
16
+ - Tighten HTTP authentication, session capacity/idle expiry and owned-resource cleanup; surface uncertain file publication and potentially incomplete terminal output without automatic replay.
17
+
18
+ ### Breaking changes
19
+
20
+ - Reverse and extensions require chat-ai commit `66461d16090456d6f1fee21ce19088dceefd6658` or a later compatible version, including matching host/descriptors/UI assets.
21
+ - 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.
22
+ - 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.
23
+ - Standard stdio/Streamable HTTP tools, resources and prompts remain supported. No Chat8/schema9/format7/share protocol2 data migration is required.
24
+
25
+ ### Upgrade
26
+
27
+ 1. Finish in-flight operations and back up normal configuration; no data migration is needed.
28
+ 2. Upgrade the matching chat-ai host first, then staff-mcp 2.0.0, coordinating downtime for reverse connections.
29
+ 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,23 +8,56 @@ It provides secure file management, shell execution, LSP-powered code intelligen
8
8
 
9
9
  ---
10
10
 
11
+ ## 2.0.0 compatibility and upgrade
12
+
13
+ **Breaking release:** reverse connections and optional extensions require a matching chat-ai host: commit `66461d16090456d6f1fee21ce19088dceefd6658` or a later compatible version. 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.0, 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
 
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 the published package directly with an explicit version:
32
+
33
+ ```bash
34
+ npx --yes staff-mcp@2.0.0 --working-dir /path/to/your/project
35
+ ```
36
+
37
+ For a source checkout of staff-mcp 2.0.0, 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.
45
+
13
46
  ### 1. Standard Host Mode
14
47
  Run directly on your physical machine or virtual environment.
15
48
  ```bash
16
- 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
17
50
  ```
18
51
 
19
52
  ### 2. Docker Transparent Proxy Mode (Cyber-Shell)
20
- 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.
21
54
 
22
55
  ```bash
23
56
  # Debug a Node.js project inside a pure Alpine container
24
- npx -y staff-mcp@latest --docker node:20-alpine
57
+ node /path/to/staff-mcp/dist/src/index.js --docker node:22-alpine
25
58
 
26
59
  # Perform security analysis inside a custom reverse-engineering image
27
- 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
28
61
  ```
29
62
 
30
63
  ### 3. Claude Desktop Configuration
@@ -34,10 +67,9 @@ Add the following to your `claude_desktop_config.json`:
34
67
  {
35
68
  "mcpServers": {
36
69
  "staff-mcp": {
37
- "command": "npx",
70
+ "command": "node",
38
71
  "args": [
39
- "-y",
40
- "staff-mcp@latest",
72
+ "/path/to/staff-mcp/dist/src/index.js",
41
73
  "--working-dir",
42
74
  "/path/to/your/project"
43
75
  ]
@@ -47,38 +79,117 @@ Add the following to your `claude_desktop_config.json`:
47
79
  ```
48
80
 
49
81
  ### 4. Reverse MCP Mode (Intranet Penetration)
50
- 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. The administrator explicitly configures `MCP_REVERSE_URL` on chat-ai; it is not guessed from a private port. Reconnect creates fresh sessions and never replays tool calls, transfer handles or terminal input.
51
83
 
52
84
  ```bash
53
- npx -y staff-mcp@latest -t reverse \
54
- --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 \
55
87
  --rt your_secure_token_here \
56
- --rn my-macbook-pro
88
+ --rn my-workstation
89
+ ```
90
+
91
+ ### 5. Authenticated HTTP Mode
92
+
93
+ HTTP authentication is optional. Set `--ht` / `--http-token`
94
+ to a strong, random token to require authentication:
95
+
96
+ ```bash
97
+ node /path/to/staff-mcp/dist/src/index.js -t http -p 3000 \
98
+ --http-token your_secure_token_here --working-dir /path/to/your/project
57
99
  ```
58
100
 
101
+ When a token is configured, clients must send `Authorization: Bearer <token>` on every MCP control request.
102
+ For a full Authorization-header field, enter `Bearer <token>`; for a Bearer-token
103
+ field, enter only the token. Raw tokens without the `Bearer` scheme are rejected.
104
+ Missing or incorrect credentials return HTTP 401, including requests with an
105
+ existing `mcp-session-id`. Authentication covers `/mcp` and the legacy `/sse` and
106
+ `/messages` routes. CORS `OPTIONS` preflight remains public and cannot invoke MCP.
107
+ The raw `/mcp/data/...` routes use their own negotiated, connection-bound data
108
+ Bearer token plus `X-Data-Binding`, not the shared MCP control token.
109
+
110
+ Omitting `--http-token` leaves MCP control on the HTTP listener unauthenticated.
111
+ Anyone who can reach such a server can invoke its tools, so use this mode only
112
+ on trusted networks. An explicitly empty token or one containing whitespace is
113
+ rejected at startup. `--docker` forwards `--http-token` to the container command
114
+ only when provided.
115
+ Command-line tokens may be visible in shell history and process listings; keep
116
+ access to those restricted. Stdio and reverse use separate authentication paths;
117
+ `--reverse-token` does not configure HTTP auth.
118
+ Use HTTPS through a reverse proxy for remote access, since plain HTTP does not
119
+ protect the token in transit. This is a shared server token, not an OAuth flow.
120
+
59
121
  ---
60
122
 
61
- ## Reverse 1.2 upgrade notes
123
+ ## Reverse v1 and protocol boundary
124
+
125
+ 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.
62
126
 
63
- Reverse mode uses `mcp-reverse@1.4.0` and MCP SDK `1.30.0`. Readiness is reported only after MCP initialization, and short-lived connections no longer reset exponential backoff. Reconnection never replays tool calls.
127
+ 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.
64
128
 
65
- Optional CLI controls (milliseconds, also forwarded in Docker mode):
129
+ Optional CLI timeouts (milliseconds, forwarded in Docker mode):
66
130
 
67
- - `--reverse-connect-timeout`: 15000; 0 disables the HTTP/SSE connection deadline.
68
- - `--reverse-initialization-timeout`: 15000; must be positive.
69
- - `--reverse-read-timeout`: 45000; liveness monitoring, not tool execution duration.
70
- - `--reverse-stable-time`: 30000; lifetime required before resetting the retry cycle (0 restores immediate reset).
131
+ - `--reverse-connect-timeout`: 15000; 0 disables only the SSE connection deadline.
132
+ - `--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.
133
+ - `--reverse-read-timeout`: 45000; heartbeat liveness, not tool execution duration.
134
+ - `--reverse-stable-time`: 30000; stable lifetime before retry reset (0 resets immediately).
71
135
 
72
- `skill` and `read_skill_file` return `_meta: { persistent: true }` instead of putting this host hint in business `structuredContent`. Upgrade chat-ai's result converter first: older chat-ai still calls tools but does not recognize this new history-enrichment hint. Updated chat-ai accepts both the legacy boolean marker and `_meta`, preferring the latter. No new wire protocol or storage migration is required.
136
+ `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.
137
+
138
+ 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.
73
139
 
74
140
  ## 🛠️ Core Capabilities
75
141
 
142
+ 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.
143
+
144
+ ```bash
145
+ # Files only, with the default main root at --working-dir
146
+ node /path/to/staff-mcp/dist/src/index.js --extensions files -w /workspace
147
+ # Terminal only; does not enable the file app
148
+ node /path/to/staff-mcp/dist/src/index.js --extensions terminal --shell /bin/bash
149
+ # Both apps, with explicit file roots replacing the default main root
150
+ node /path/to/staff-mcp/dist/src/index.js --extensions files,terminal -w /workspace \
151
+ --file-root main=/workspace --file-root assets=/srv/assets
152
+ # Explicit full-filesystem file access on a suitable Linux host (not a default)
153
+ node /path/to/staff-mcp/dist/src/index.js --extensions files --file-root system=/
154
+ ```
155
+
156
+ `--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 `[]`.
157
+
158
+ ### Independent file workspace
159
+
160
+ 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.
161
+
162
+ 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.
163
+
164
+ ### Human terminal (explicit extension opt-in)
165
+
166
+ `--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.
167
+
168
+ 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.
169
+
170
+ 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).
171
+
172
+ 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).
173
+
76
174
  ### 1. Seamless Containerization (`--docker`)
77
175
  Never pollute your host machine again. By simply appending `--docker <image>`, `staff-mcp`:
78
176
  - Instantly injects itself into the container via read-only bind mounts (no `npm install` inside the container).
79
177
  - Automatically translates Windows/Mac paths to Linux container paths.
80
178
  - 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`.
81
- - Provides a `--docker-args` backdoor for hardware pass-through (e.g., ADB USB debugging, GPUs, host network).
179
+ - 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.
180
+ - 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.
181
+
182
+ 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.
183
+
184
+ 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.
185
+
186
+ 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.
187
+
188
+ ### Optional extensions do not define MCP connectivity
189
+
190
+ 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.
191
+
192
+ 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.
82
193
 
83
194
  ### 2. Skill & Profile Ecosystem (`--profile`)
84
195
  `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:
@@ -97,10 +208,36 @@ Only the project-level `.staff/skills/` directory is live-watched. The directory
97
208
 
98
209
  Switch roles on the fly:
99
210
  ```bash
100
- npx -y staff-mcp@latest --profile default
101
- npx -y staff-mcp@latest --profile android-reverse
211
+ node /path/to/staff-mcp/dist/src/index.js --profile default
212
+ node /path/to/staff-mcp/dist/src/index.js --profile android-reverse
102
213
  ```
103
214
 
215
+ ### HTTP session capacity and idle expiry
216
+
217
+ 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.
218
+
219
+ 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.
220
+
221
+ 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.
222
+
223
+ 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.
224
+
225
+ ```bash
226
+ node /path/to/staff-mcp/dist/src/index.js -t http -p 3000 \
227
+ --http-token your_secure_token_here \
228
+ --http-max-sessions 64 --http-session-idle-ms 1800000
229
+ ```
230
+
231
+ ### Session shutdown
232
+
233
+ 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.
234
+
235
+ 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.
236
+
237
+ ### Managed child MCP sessions
238
+
239
+ `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.
240
+
104
241
  ### 3. Built-in `skill-manager`
105
242
  Out of the box, the AI assistant knows how to manage its own skills! You can simply ask it to:
106
243
  > *"Install the official Anthropic canvas-design skill into my project."*
@@ -109,7 +246,8 @@ It will securely download, configure, and reload the skill without you lifting a
109
246
  ### 4. Advanced Shell & Code Intelligence
110
247
  - **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.
111
248
  - **LSP Integration**: Extract symbols, get diagnostics, go to definitions, and find references for TypeScript, Python, and more.
112
- - **Secure Sandbox**: Strictly confines the AI to the specified working directory and user-defined allowed paths.
249
+ - 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.
250
+ - **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.
113
251
 
114
252
  ---
115
253
 
@@ -117,8 +255,8 @@ It will securely download, configure, and reload the skill without you lifting a
117
255
 
118
256
  | Option | Description | Default |
119
257
  | :--- | :--- | :--- |
120
- | `-w, --working-dir` | Root directory for the sandbox | `process.cwd()` |
121
- | `-d, --allowed-dir` | Extra directories allowed for access | `[]` |
258
+ | `-w, --working-dir` | Staff workspace and default file root / terminal cwd; not an OS sandbox | `process.cwd()` |
259
+ | `-d, --allowed-dir` | Extra directories for standard tools; does not add file-app roots | `[]` |
122
260
  | `-r, --profile` | The active profile for skills (e.g., android-reverse) | `default` |
123
261
  | `--enable-lsp` | Enable LSP capabilities (disabled by default) | `false` |
124
262
  | `--docker` | Run inside a Docker container using this image | `undefined` |
@@ -126,47 +264,38 @@ It will securely download, configure, and reload the skill without you lifting a
126
264
  | `-t, --transport` | Transport type (`stdio`, `http`, or `reverse`) | `stdio` |
127
265
  | `-p, --port` | Port for HTTP server | `3000` |
128
266
  | `-h, --host` | Host for HTTP server | `127.0.0.1` |
129
- | `--ru, --reverse-url` | URL for Reverse MCP Gateway | `undefined` |
267
+ | `--ht, --http-token` | Optional bearer token for HTTP transport | `undefined` (no authentication) |
268
+ | `--ru, --reverse-url` | Explicit HTTP(S) Web `/api/mcp/reverse` base endpoint | `undefined` |
130
269
  | `--rt, --reverse-token` | Security token for Reverse MCP | `undefined` |
131
270
  | `--rn, --reverse-name` | Server name for Reverse MCP | `undefined` |
132
- | `--proxy` | HTTP(S) proxy URL for outbound requests | `undefined` |
271
+ | `--extensions` | Comma-separated `files`, `terminal`, or both; apps/data dependencies are automatic | `[]` (all off) |
272
+ | `--file-root` | Repeatable `id=path`; explicit file roots replace the default and apply only when files is enabled | `main=<working-dir>` |
273
+ | `--shell` | Absolute executable PTY shell path | Valid absolute `$SHELL`, otherwise `/bin/bash` |
274
+ | `--proxy` | HTTP(S) proxy for supported HTTP clients and reverse control/data HTTP requests | `undefined` |
133
275
 
134
276
  ### 🌐 Proxy Support (Corporate Networks)
135
277
 
136
- 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:
137
-
138
- ```bash
139
- export HTTPS_PROXY=http://proxy.company.com:8080
140
- export NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.example.com
141
- # NO_PROXY supports: exact hosts/IPs, domain suffixes (.example.com or bare example.com),
142
- # "*" wildcard, host:port qualifiers, and IPv4/IPv6 CIDR ranges (e.g. 172.16.0.0/12, fd00::/8)
143
- npx -y staff-mcp@latest -t reverse --ru https://chat.example.com/api/mcp/reverse --rt <token> --rn myserver
144
- ```
278
+ 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`.
145
279
 
146
- Alternatively, force a proxy explicitly (takes precedence over env vars; `NO_PROXY` is not applied):
147
-
148
- ```bash
149
- npx -y staff-mcp@latest --proxy http://proxy.company.com:8080 ...
150
- ```
280
+ 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.
151
281
 
152
- 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`.
282
+ 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.
153
283
 
154
284
  ### Hardware Pass-through Example (Android Reverse Engineering)
155
- 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:
285
+ 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:
156
286
 
157
287
  ```bash
158
288
  # 1. Start ADB Server on the host machine listening on all interfaces:
159
289
  # adb kill-server && adb -a nodaemon server start
160
290
 
161
291
  # 2. Start staff-mcp with the ADB_SERVER_SOCKET environment variable injected
162
- # On Mac/Windows:
163
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:host.docker.internal:5037"
292
+ # On Mac/Windows, if this hostname and the local Docker topology are available:
293
+ node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:host.docker.internal:5037"
164
294
 
165
- # On Native Linux (If not using --network host, point to the docker bridge IP):
166
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:172.17.0.1:5037"
295
+ # On Native Linux, use the actual reachable bridge address (example only):
296
+ node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:172.17.0.1:5037"
167
297
 
168
- # Alternative for Native Linux (Share host network stack completely):
169
- npx -y staff-mcp@latest --docker chineseastar/security:latest -D "--network host"
298
+ # stdio automatic data publication does not support --network host.
170
299
  ```
171
300
 
172
301
  ---