Portus MCP is a high-performance, policy-bounded MCP server for AI-assisted software engineering across local workstations, remote machines, and VMs. Tools are policy-bounded adapters where a connected agent interacts with pre-registered project workspaces through a unified, secure ten-tool surface.
Portus MCP exposes a fixed, high-leverage 10-tool surface:
| Tool Name | Key Parameters | Description |
|---|---|---|
project_context |
projectAlias (opt), include (opt) |
Inspect project tree, scripts, git status, active policy capabilities, and registered aliases. |
project_read |
requests[] (path, projectAlias, startLine, endLine) |
Batched ordered file reads with raw SHA-256 hashes and line-bounded slicing. |
project_search |
requests[] (query, projectAlias, pathFilter, caseSensitive) |
Batched regex search across code files respecting .gitignore. |
project_edit |
projectAlias, operations[], batchMode (opt) |
Staged or ordered exact text replacement, range edits, and file/directory creation/deletion. |
project_patch |
mode (prepare | apply), patch, projectAlias |
Multi-file unified diff and structured hunk preparation and application with safety guards. |
project_run |
projectAlias, requests[] (command, args, timeoutMs) |
Batched execution of allowlisted terminal commands with streaming process tracking. |
project_policy |
operation (check_path, check_command, audit_log, etc.) |
Read-only policy inspection, path/command authorization pre-checks, and audit administration. |
project_screenshot |
operation (capture_running, capture_launch, app_discovery, etc.) |
Session-owned GUI window capture and installed host application discovery. |
subagent_task |
operation (spawn, steer, terminate), task, template |
Spawn, steer, and manage isolated Flue subprocess subagents. |
subagent_context |
sessionId, include (status, events, output, artifacts) |
Inspect subagent execution state, streaming events, and output artifacts. |
Clone the repository and install Node dependencies:
git clone https://github.com/PerceivingAI/portus-mcp.git
cd portus-mcp
npm installRequirements: Node.js
>=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1 <27with bundled npm11.19.1from the pinned24.22.1runtime, and Git..nvmrcand CI select24.22.1; do not bypassengine-strict.
Choose your preferred connection method:
Run the interactive setup wizard to install tunnel-client, validate credentials, and initialize the profile:
npm run setup:tunnelOr run the platform script directly:
- Windows (PowerShell):
.\scripts\setup-tunnel.ps1 - Linux / macOS (Bash):
chmod +x ./scripts/setup-tunnel.sh && ./scripts/setup-tunnel.sh
Ensure Tailscale is installed and logged in on your machine. See docs/TAILSCALE.md for complete details.
Portus MCP enforces strict, fail-closed multi-project confinement: if no projects are registered, the agent has zero access to your machine.
Copy .env.example to .env:
cp .env.example .envRegister your local project paths using alias=path format:
Windows:
PORTUS_MCP_PROJECTS='
web=C:\work\web-app
api=C:\work\api-server
'Linux / macOS:
PORTUS_MCP_PROJECTS='
web=/home/user/work/web-app
api=/home/user/work/api-server
'Use a standalone launcher to start a backend, or attach a Tailscale companion to an existing backend:
| Connection Target | Command | Description |
|---|---|---|
| ChatGPT via OpenAI Tunnel | npm run start:tunnel |
Launches Portus MCP (8789) + tunnel-client daemon concurrently. |
| Public Agents (Perplexity) | npm run start:funnel |
Launches Portus MCP + Tailscale Funnel for public cloud access. |
| Private Mesh (Personal Devices) | npm run start:serve |
Launches Portus MCP + Tailscale Serve for private Tailnet access. |
| Local HTTP Direct | npm start |
Launches the standalone HTTP server on http://127.0.0.1:8789/mcp. |
| Private Mesh, Existing Backend | npm run attach:serve |
Starts only a Tailscale Serve companion for the configured backend. |
| Public Agents, Existing Backend | npm run attach:funnel |
Starts only a Tailscale Funnel companion for the configured backend. |
Each standalone launcher owns its backend. Do not run two standalone launchers on the same host/port. To keep OpenAI and Tailscale on one backend, run npm run start:tunnel in terminal 1 and an attach:* command in terminal 2.
Press Ctrl+C to stop the processes owned by that launcher. Stopping an attach companion leaves the backend and OpenAI tunnel running. If you manually restart the backend at the same host, port, and MCP path, the companion stays running and subsequent requests reach the restarted backend. Failed or interrupted tool calls are not replayed.
MCP and new companions start only when explicitly launched. After a reboot, launch them again manually. Bearer authentication is optional in every mode, including Funnel; an unauthenticated public endpoint exposes its tools to anyone who can reach it. See docs/TAILSCALE.md for ownership and bounded attach-companion recovery.
- Navigate to Settings -> Plugins (or Connectors) -> Browse plugins.
- Click + (add plugin), select Tunnel, and choose your configured tunnel device.
- Select No Auth, accept the disclaimer, and click Create -> Connect.
Provide your public or mesh URL directly:
https://machine.tailnet.ts.net/mcp
Portus ships with portus-mcp.policy.json as its complete default policy. To maintain private operator settings without committing local paths or credentials to Git:
- Copy
portus-mcp.policy.jsontoportus-mcp.policy.local.json(automatically Git-ignored). - Set
PORTUS_MCP_POLICY_PATH=./portus-mcp.policy.local.jsonin.env. - The selected policy file is a strict replacement, never an overlay.
The selected policy is validated once at backend startup and held as an immutable snapshot. External policy edits require an explicit backend restart; they do not change the running backend. project_policy is read-only and reports the effective policy, not pending file edits.
Portus enforces strict executable allowlisting under main_agent.permissions.allowedCommands:
- Specify executable basenames only (e.g.,
["git", "cargo", "npm"]). - Omit OS-specific extensions (
.exe,.cmd,.bat). - Granting interpreters (
bash,powershell,python,node) grants broad host authority under the Portus OS account. - Spawned subagents use a separate, isolated allowlist under
subagents.permissions.allowedCommands.
Portus treats skills as read-only filesystem packages. Two independent audiences are configured via .env:
AGENT_SKILL_PATHS=./skills
SUBAGENTS_SKILL_PATHS=./skillsAGENT_SKILL_PATHS: Populates the skill catalog exposed to the connected MCP client viaproject_contextwithinclude.skills=true.SUBAGENTS_SKILL_PATHS: Populates the read-only/skills/<name>mounts available inside spawned Flue subagent workspaces.- Multiple directories can be separated with semicolons.
- Skills are loaded as startup snapshots; restart Portus after modifying skills.
Spawned subagents (subagent_task) are autonomous processes executing inside ephemeral Flue workspaces:
- Isolated directory sandbox under
.portus-mcp/flue-workspaces/<sessionId>. - Granular permissions:
main_agent.permissions.subagentTaskcontrols lifecycle actions;subagentContextcontrols event and output retrieval. - Subagents execute tasks with independent retry behavior configured in
portus-mcp.config.json.
The project_screenshot tool enables visual feedback and app interaction:
app_discovery: Lists configured GUI apps installed on the host without exposing absolute paths.capture_running: Captures visible application windows owned by an activeproject_runexecution session.capture_launch: Launches a configured application shortcut and captures its visible window.closeSessionrequirement: Must explicitly declare whether to terminate (true) or preserve (false) the target process tree.- Platform Support: Native worker supports Windows, macOS, and Linux (X11). Wayland fails closed with
unsupported_session_window_capture.
Run Portus MCP across multiple machines simultaneously. Naming each MCP entry allows independent project roots and policies:
Portus_Workstation (Local Desktop)
Portus_LinuxVM (Dev / Build VM)
Portus_RemoteGPU (Compute Server)
The connected agent can switch across connections within the same conversation, with each node strictly bounded by its local policy.
Run the comprehensive test suite covering tool contracts, permission gates, Git-ignore policies, screenshot attestation, and subagent lifecycles:
npm run check # TypeScript typecheck
npm test # Full test suite (265 tests)
npm run build # Production build
npm run flue:check # Subagent integration validationdocs/BROAD_MOBILITY_SURFACE.md— Architectural principles and batching design.docs/TOOLS.md— Complete 10-tool input/output contract specifications.docs/CONFIG.md— Configuration schemas and environment variables.docs/TAILSCALE.md— Authoritative guide for Tailscale Serve and Funnel.docs/TUNNEL_CLIENT.md— OpenAI Secure MCP Tunnel setup guide.docs/MULTI_MACHINE.md— Multi-node deployment architectures.docs/TROUBLESHOOTING.md— Diagnostics and error resolution.SECURITY.md— Threat model, sandbox boundaries, and vulnerability reporting.