npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

staff-mcp

v2.0.5

Published

[English](./README.md) | [简体中文](./README_zh.md)

Readme

staff-mcp

English | 简体中文

A next-generation Model Context Protocol (MCP) server that transforms any AI assistant into a highly capable, container-aware, and role-adaptable digital employee.

It provides secure file management, shell execution, LSP-powered code intelligence, a 5-tier Skill & Profile ecosystem, and a revolutionary Docker Transparent Proxy Mode.


Compatibility and coordinated upgrades

Version 2.0.5: removes the 100 MiB file transfer cap. Upgrade chat-ai to commit cfd7a2815f46d105b2da01d3980987c818ab0d39 or a compatible descendant for streaming App uploads, native browser downloads and cross-MCP relay. Upgrade all participating staff-mcp endpoints as well; inline previews remain limited to 2 MiB. See the large-file limits and release checklist below.

Version 2.0.4: adds Windows native ConPTY terminal support and extensions for eligible Windows Docker Desktop Linux containers. It retains the Linux PTY prebuild delivery, explicit terminal startup errors and reverse heartbeat fixes from 2.0.3. Upgrade chat-ai to commit 88f86aeb136bc2440da35b540868f9606d34ac58 or a descendant for the matching Bash/CMD/PowerShell command generator and earlier App window fixes.

Upgrade from 2.0.3: the Windows features require staff-mcp 2.0.4; updating chat-ai alone does not add them to an existing staff process. The node-pty dependency pin and extension protocol versions are unchanged.

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.

Standard stdio/Streamable HTTP tools, resources and prompts remain supported. Extensions are all off by default; optional discovery/data negotiation failures preserve an otherwise healthy standard MCP connection. Explicitly requesting terminal with unavailable platform/native/shell prerequisites fails startup instead of silently disabling it; files degradation is unchanged. 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.

No Chat8/schema9/format7/share protocol2 data migration is required.

  1. Finish in-flight operations and back up your normal configuration; no data conversion is needed.
  2. Upgrade the matching chat-ai host first, then staff-mcp 2.0.5, coordinating downtime for reverse connections.
  3. Reconnect MCP, reopen Apps and explicitly enable only the extensions you want.

See CHANGELOG for the release summary.

🚀 Quick Start

Requires Node.js 22.22.2 or newer, including inside Docker images.

Current source supports Linux PTY and Windows native ConPTY, subject to native loading and executable-shell checks. Windows build 18309 or newer is necessary, not sufficient. Windows Docker Desktop with a verified local Linux-container daemon can enable files/terminal; the launcher OS alone does not decide availability. Windows arm64 and macOS have not been validated on real hardware; musl/Alpine terminal support is not promised. Path translation or a shipped N-API prebuild is not a platform-support guarantee.

Run staff-mcp with an explicit package version:

npx --yes [email protected] --working-dir /path/to/your/project

For a source checkout, install dependencies and build before using the absolute entrypoint in the examples:

npm ci
npm run build

Replace /path/to/staff-mcp with that checkout/build directory. Docker still read-only mounts the host package and node_modules, not an isolated container dependency installation. The optional dependency node-pty remains pinned exactly to the official prerelease 1.2.0-beta.18, which includes N-API prebuilds for Linux x64/arm64 with glibc >= 2.28. The runtime still needs system libraries such as libstdc++ and libgcc. This addresses prebuilt delivery for normal installs, not arbitrary local build leftovers or architecture/libc/platform mismatches; N-API does not remove those limits. No user image is upgraded automatically; terminal support is not promised for musl/Alpine.

1. Standard Host Mode

Run directly on your physical machine or virtual environment.

node /path/to/staff-mcp/dist/src/index.js --working-dir /path/to/your/project

2. Docker Transparent Proxy Mode (Cyber-Shell)

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. Extension preflight checks the daemon OS and endpoint, not the launcher OS: all Docker extensions require a Linux-container daemon; HTTP/stdio additionally require a verified local Unix socket or named pipe (npipe) endpoint. This allows Windows Docker Desktop Linux containers, subject to the existing package/native-library and bind-mount prerequisites; Windows containers are not supported for extensions, and macOS is untested.

# Standard MCP only, no terminal: debug inside an Alpine container
node /path/to/staff-mcp/dist/src/index.js --docker node:22-alpine

# Perform security analysis inside a custom reverse-engineering image
node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest --profile android-reverse

3. Claude Desktop Configuration

Add the following to your claude_desktop_config.json:

{
  "mcpServers": {
    "staff-mcp": {
      "command": "node",
      "args": [
        "/path/to/staff-mcp/dist/src/index.js",
        "--working-dir",
        "/path/to/your/project"
      ]
    }
  }
}

4. Reverse MCP Mode (Intranet Penetration)

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; no public-origin environment variable on chat-ai is required. Reconnect creates fresh sessions and never replays tool calls, transfer handles or terminal input.

node /path/to/staff-mcp/dist/src/index.js -t reverse \
  --ru https://chat.example.com/api/mcp/reverse \
  --rt your_secure_token_here \
  --rn my-workstation

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.

5. Authenticated HTTP Mode

HTTP authentication is optional. Set --ht / --http-token to a strong, random token to require authentication:

node /path/to/staff-mcp/dist/src/index.js -t http -p 3000 \
  --http-token your_secure_token_here --working-dir /path/to/your/project

When a token is configured, clients must send Authorization: Bearer <token> on every MCP control request. For a full Authorization-header field, enter Bearer <token>; for a Bearer-token field, enter only the token. Raw tokens without the Bearer scheme are rejected. Missing or incorrect credentials return HTTP 401, including requests with an existing mcp-session-id. Authentication covers /mcp and the legacy /sse and /messages routes. CORS OPTIONS preflight remains public and cannot invoke MCP. The raw /mcp/data/... routes use their own negotiated, connection-bound data Bearer token plus X-Data-Binding, not the shared MCP control token.

Omitting --http-token leaves MCP control on the HTTP listener unauthenticated. Anyone who can reach such a server can invoke its tools, so use this mode only on trusted networks. An explicitly empty token or one containing whitespace is rejected at startup. --docker forwards --http-token to the container command only when provided. Command-line tokens may be visible in shell history and process listings; keep access to those restricted. Stdio and reverse use separate authentication paths; --reverse-token does not configure HTTP auth. Use HTTPS through a reverse proxy for remote access, since plain HTTP does not protect the token in transit. This is a shared server token, not an OAuth flow.


Reverse v1 and protocol boundary

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.

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.

Only responses to recognized inbound standard MCP ping requests use a separate bounded POST send lane. All other POSTs remain FIFO; no request/input replay, protocol version change or extra flag is added, and timeouts are not extended. Slow-send diagnostics distinguish queue wait from POST elapsed time using metadata only, never tokens, URLs or bodies. The host also records App resource-read timing and byte-count metadata.

Optional CLI timeouts (milliseconds, forwarded in Docker mode):

  • --reverse-connect-timeout: 15000; 0 disables only the SSE connection deadline.
  • --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.
  • --reverse-read-timeout: 45000; heartbeat liveness, not tool execution duration.
  • --reverse-stable-time: 30000; stable lifetime before retry reset (0 resets immediately).

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.

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.

🛠️ Core Capabilities

The behavior below describes staff-mcp 2.0.4. Extensions remain opt-in.

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.

# Files only, with the default main root at --working-dir
node /path/to/staff-mcp/dist/src/index.js --extensions files -w /workspace
# Terminal only; does not enable the file app
node /path/to/staff-mcp/dist/src/index.js --extensions terminal
# Both apps; explicitly authorize assets for tools and the file app
node /path/to/staff-mcp/dist/src/index.js --extensions files,terminal -w /workspace \
  -d /srv/assets
# Explicit full-filesystem authorization for tools and files on a suitable Linux host (not a default)
node /path/to/staff-mcp/dist/src/index.js --extensions files -d /

With files enabled, roots reuse the standard tool authorization: main is --working-dir, followed by the resolved, deduplicated --allowed-dir directories in order as extra1, extra2, etc. Explicit -d authorization is therefore visible in the file UI as well as tools; no system root is added automatically. Relative directories resolve from the launching process cwd. -d / explicitly authorizes the filesystem visible to staff for both tools and files, subject to OS permissions; it grants no OS privileges or shell sandbox. The library accepts ExtensionOptions: {enabled?:('files'|'terminal')[]}, with enabled defaulting to [].

--file-root, --shell, --http-max-sessions and --http-session-idle-ms have been removed and now fail as unknown options. Remove them from launch configurations; use -w / -d for file authorization. Linux uses the normal SHELL environment; Windows selects PowerShell or CMD automatically as described below. There is no compatibility fallback.

Independent file workspace

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 for exact methods, lifecycle, limits and packaging.

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.

Human terminal (explicit extension opt-in)

--extensions terminal needs Linux or Windows (build >= 18309), a loadable optional node-pty, an executable shell and negotiated streams/data v1 with a usable duplex dataSession over supported local stdio/Docker, direct HTTP or reverse. Unavailable platform/native PTY/shell prerequisites make an explicit terminal request fail startup with an error, including when files is also requested; terminal is not silently omitted. The default disabled state never loads native PTY code. Linux uses a valid absolute executable $SHELL, otherwise /bin/bash, with -i and normal startup profiles unchanged; if unavailable it fails without further shell fallback. Windows uses native ConPTY, preferring executable pwsh.exe, then powershell.exe with -NoLogo -NoProfile, then ComSpec/system cmd.exe with /d; there is no public --shell option. The shell inherits staff's environment except exact internal control keys documented in the terminal contract. Windows profile loading is disabled, but shell/program/system history recording is not guaranteed absent. 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.

The PTY starts at the staff workspace (main) by default, independently of file roots, and runs under the staff process's operating-system identity: 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; cleanup is best effort, not rollback. Linux retains TERM-to-KILL cleanup; Windows closes the owned ConPTY console. Neither promises to remove all detached descendants or undo filesystem/network effects.

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.

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.

1. Seamless Containerization (--docker)

Never pollute your host machine again. By simply appending --docker <image>, staff-mcp:

  • Instantly injects itself into the container via read-only bind mounts (no npm install inside the container).
  • Automatically translates Windows/Mac paths to Linux container paths.
  • 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.
  • 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.
  • Allows --docker-args for compatible hardware/environment settings (e.g., ADB USB debugging or GPUs). Unsupported stdio data topologies fail an explicit terminal request; files-only requests retain optional-extension degradation; overrides of managed bootstrap/mapping and container lifecycle controls remain errors.

For supported local Docker stdio with a Linux-container daemon and 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.

Docker files reuse only the existing workspace (/workspace, root main) and allowed-directory bind mounts; no separate file-root mounts are created. Explicit -d / is deliberately broad host access through the allowed-directory mapping, subject to Docker/OS permissions and topology. Terminal cwd stays /workspace, independent of extra roots.

Docker reuses the allowed-directory mounts for both tools and the file UI. A host filesystem root such as / is mapped to /opt/staff-allowed/root-N because Docker forbids mounting onto container /. Windows drive/UNC allowed directories are translated into a POSIX container namespace rather than passed through as Windows paths. Inner -d paths and protected staging aliases follow the same mapping; overlapping mounts do not bypass staging protection.

This application-data path requires a local daemon and the host client/wrapper sharing reachable loopback, with compatible bridge/port publication. Preflight verifies the Linux-container daemon OS, with local Unix socket/npipe endpoint checks for HTTP/stdio; Windows Docker Desktop Linux containers are eligible, not arbitrary Desktop/remote contexts. A non-Linux container daemon, a nonlocal HTTP/stdio daemon or incompatible stdio networking (host/container) fails an explicit terminal request. Without terminal requested, files retains warning-and-disable degradation and ordinary MCP control/tools remain when Docker itself can start. HTTP/reverse do not need this extra stdio data-port mapping. HTTP still requires a verified local daemon and reachable host loopback; reverse retains Linux-container and valid-existing-mount prerequisites without this stdio loopback publication. 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.

Optional negotiation failures versus explicit terminal startup errors

Availability is determined separately for files, terminal and the per-connection data channel. A missing terminal runtime fails startup only when terminal is explicitly requested; with terminal disabled no native PTY is loaded. An unavailable configured file root still 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.

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.

2. Skill & Profile Ecosystem (--profile)

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:

| Priority | Tier | Path | Watch | |:---:|:---|:---|:---:| | 1 (Highest) | Project | <cwd>/.staff/skills | ✅ 实时生效(自动创建目录) | | 2 | Project Profile | <cwd>/.staff/profiles/<profile>/skills | 🔄 需重启 | | 3 | Global Profile | ~/.staff/profiles/<profile>/skills | 🔄 需重启 | | 4 | Global | ~/.staff/skills | 🔄 需重启 | | 5 (Lowest) | Built-in | staff-mcp/builtin-profiles | 🔄 需重启 |

Profile is an additive parameter — tiers 1 and 4 are always loaded regardless of profile. Tiers 2, 3, and 5 append profile-specific paths. When skills with the same name exist at multiple tiers, the higher-priority one wins (merge with override, not whole-tier replacement).

Only the project-level .staff/skills/ directory is live-watched. The directory is auto-created on startup if absent, and auto-recovered if deleted at runtime. All other tiers require restart.

Switch roles on the fly:

node /path/to/staff-mcp/dist/src/index.js --profile default
node /path/to/staff-mcp/dist/src/index.js --profile android-reverse

HTTP session capacity and lifetime

Each HTTP listener admits at most 64 sessions, a fixed internal limit. 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. This is independent of --max-mcp-sessions, which still limits managed child MCP servers and retains explicit start/stop.

HTTP sessions have no idle-expiry timer. They remain until explicit DELETE/SDK close, failed initialization, transport closure or listener shutdown; clients should explicitly close unused sessions. An abandoned session can retain a capacity slot until closed or shutdown. File/terminal leases, data-consumption deadlines and resource cleanup still apply independently and do not close the MCP session merely because it is idle. Unknown or closed session IDs return HTTP 404; reconnect explicitly without the old ID, with no replay of tools, file commits or terminal input. This is not a global quota for background commands, nested MCP sessions or LSP servers.

Session shutdown

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.

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 lifetime follow the policy above; there is no listener idle eviction.

Managed child MCP sessions

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.

3. Built-in skill-manager

Out of the box, the AI assistant knows how to manage its own skills! You can simply ask it to:

"Install the official Anthropic canvas-design skill into my project." It will securely download, configure, and reload the skill without you lifting a finger.

4. Advanced Shell & Code Intelligence

  • 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.
  • LSP Integration: Extract symbols, get diagnostics, go to definitions, and find references for TypeScript, Python, and more.
    • 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.
  • 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.

🎛️ CLI Arguments

| Option | Description | Default | | :--- | :--- | :--- | | -w, --working-dir | Staff workspace and default file root / terminal cwd; not an OS sandbox | process.cwd() | | -d, --allowed-dir | Extra directories authorized for tools and, when enabled, file-app roots | [] | | -r, --profile | The active profile for skills (e.g., android-reverse) | default | | --enable-lsp | Enable LSP capabilities (disabled by default) | false | | --docker | Run inside a Docker container using this image | undefined | | -D, --docker-args | Extra args for docker run (e.g., -e FOO=BAR) | [] | | -t, --transport | Transport type (stdio, http, or reverse) | stdio | | -p, --port | Port for HTTP server | 3000 | | -h, --host | Host for HTTP server | 127.0.0.1 | | --ht, --http-token | Optional bearer token for HTTP transport | undefined (no authentication) | | --ru, --reverse-url | Explicit HTTP(S) Web /api/mcp/reverse base endpoint | undefined | | --rt, --reverse-token | Security token for Reverse MCP | undefined | | --rn, --reverse-name | Server name for Reverse MCP | undefined | | --extensions | Comma-separated files, terminal, or both; apps/data dependencies are automatic | [] (all off) | | --proxy | HTTP(S) proxy for supported HTTP clients and reverse control/data HTTP requests | undefined |

🌐 Proxy Support (Corporate Networks)

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.

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.

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.

Hardware Pass-through Example (Android Reverse Engineering)

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:

# 1. Start ADB Server on the host machine listening on all interfaces:
# adb kill-server && adb -a nodaemon server start

# 2. Start staff-mcp with the ADB_SERVER_SOCKET environment variable injected
# On Mac/Windows, if this hostname and the local Docker topology are available:
node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:host.docker.internal:5037"

# On Native Linux, use the actual reachable bridge address (example only):
node /path/to/staff-mcp/dist/src/index.js --docker chineseastar/security:latest -D "-e ADB_SERVER_SOCKET=tcp:172.17.0.1:5037"

# stdio automatic data publication does not support --network host.

Large file transfers (2.0.5)

files-v1 cross-MCP relay and file App uploads no longer have a 100 MiB per-file hard cap. With the matching chat-ai host, ordinary App downloads use the native browser download manager rather than a whole-file page Blob. “Save to device” starts receiving bytes; verified HTTP transfer is not proof of successful local disk persistence. Inline readBytes previews remain bounded to 2 MiB; text/Resource limits are unchanged.

Upgrade the host and all participating endpoints, reconnect MCP and reopen Apps. staff-mcp through 2.0.4 retains the remote cap. Source snapshots and destination staging require disk space. Existing 30-second preparation RPC/remote lease, bounded data windows, cancellation, authorization and no-automatic-replay behavior remain; slow disks and deployment proxy limits can still reject large transfers. There is no unbounded-resource or resumable-transfer guarantee. Source changes are not npm publication.

Release workflow

Merge the verified release changes into master first. From an up-to-date master checkout, confirm that the intended feature commit is included and all three package/lock versions equal the explicit target version, not merely each other; finalize the changelog, then create and push the new version tag. A check that HEAD belongs to master alone does not prove the feature branch was merged. The checklist stops on any failed command and rejects an existing 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. .github/workflows/publish.yml runs Node 24 and OIDC trusted publishing with provenance; npm must trust the matching repository/workflow. Run npm ci, npm run build and npm pack --dry-run in the release checkout before tagging. After Actions succeeds, verify the exact version with npm view [email protected] version, update the package at each endpoint and restart it. See the step-by-step release checklist; version/tag examples must be advanced for later releases.

📄 License

MIT