octoport
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@octoportshow me the live tool call log"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π octoport
See every MCP tool call your AI agents make β and exactly where they fail.
A local-first debugger, flight recorder, and control layer for MCP.
npx octoport up --openYour agents call MCP tools all day. When something breaks β an expired OAuth token, a crashing server, a tool that silently changed its schema β you get a vague client error and zero visibility. octoport sits on the path of every MCP call and turns that darkness into a live, diagnosable record:
15:04:12 Claude Code β github / create_pull_request WRITE Β· MEDIUM β 381ms
15:04:18 Claude Code β supabase / execute_sql DATABASE_WRITE Β· MEDIUM β 4.2s AUTH Β· token_expired
15:04:30 Cursor β playwright / browser_click UNKNOWN Β· LOW β 12.7sLive Activity β every call, live: client, identity, server, tool, latency, risk badge, and a canonical failure diagnosis. The home screen.
Failure diagnosis β every failed call is classified deterministically into a canonical taxonomy (
AUTH Β· token_expired,NETWORK Β· dns,SERVER Β· circuit_open, β¦) instead of a raw stack trace.Reliability β per server and per tool: success rate, p50/p95/p99, timeout and auth-failure counts, top failure categories, and deterministic anomaly alerts (consecutive failures, restart loops, latency spikes).
octoport doctorβ "why won't this MCP setup work?" answered with evidence and a concrete fix, in the CLI and the dashboard (same engine).Tool surface integrity β every server's tool catalog is snapshotted and diffed. A server that quietly grows
delete_repositorytriggers a risk-classified warning you must Accept β or Block the tool for every client with one click.Local-first privacy β everything stays on your machine in SQLite. Secret-looking argument keys are redacted before they ever hit disk, and metadata-only mode (
logPayloads: false) never stores args/results at all. The dashboard always states which mode is active.
Quickstart β one command, then it's all web
npx octoport up --openThe dashboard walks you through the rest:
We found your MCP servers β octoport scans your Claude Code / Claude Desktop / Cursor / Windsurf / VS Code configs (global and project-scoped).
Connect your AI client β copy one snippet per client.
Make a test call β and watch it appear in Live Activity, live.
Optionally clean up the now-duplicate direct entries (per-file preview, timestamped backups, restorable from Settings).
From then on your clients talk to one endpoint, and octoport sees everything:
add/edit/toggle servers centrally, and new servers propagate to every connected
client live (tools/list_changed), no restarts.
Until the npm package is published, run from source:
git clone https://github.com/nullarch/octoport && cd octoport && npm install && npm run build && node dist/cli.js up --open
Start at login:
octoport autostart # launchd (macOS) / systemd --user (Linux) / schtasks (Windows)
octoport autostart --removePort 6286 is "OCTO" on a phone keypad. Change it with octoport up --port <n>.
Related MCP server: MCPHub
When MCP breaks
$ octoport doctor
SERVER
β github: error β AUTH Β· token_expired
The credential has expired β re-authenticate.
raw: Error POSTing to endpoint (HTTP 401): Unauthorized
fix: Reauthorize "github": revoke the stored grant (Servers β github β Grants)
and authorize again, or refresh the credential in its headers/env.Doctor checks the environment (Node, config permissions), your clients
(detected configs, whether they point at the hub, whether a session ever
connected), every server (status, classified failure, stderr tail, last
successful call), and the gateway (tokens, privacy mode, policy, IdP
reachability). --json for scripts; the dashboard's Doctor tab runs the same
engine.
One endpoint for everything
Under the observability layer, octoport is a full MCP gateway β that's why it sees every call:
One endpoint β N clients Γ M servers becomes 1 Γ M.
Process supervision β stdio servers run as child processes with crash isolation, jittered backoff restart, start/call timeouts, a circuit breaker after 8 straight failures, and a per-server stderr ring buffer.
Hosted servers with OAuth β add a hosted MCP URL; if it wants OAuth the server card shows Authorize (PKCE, one-time state, dynamic client registration). Tokens live in your config dir,
0600.Full catalog aggregation β tools, prompts (
server__prompt), and resources (URIs pass through, reads routed to the owning server). The call log records all three kinds.Server-initiated requests relayed β
sampling/elicitation/rootsanswered by the client whose call is executing on that server.Named access tokens β one per person or machine; revoking kills live sessions on the spot. Scopes:
admin(dashboard) vsmcp(endpoint).Local security by default β
127.0.0.1binding, Host/Origin validation (DNS-rebinding protection), per-install bearer token. The MCP Inspector RCE (CVE-2025-49596) happened because a localhost tool skipped exactly these.Blocked tools β a per-server denylist (globs) enforced at
tools/listand on every call; the "Block" button on surface-change warnings writes it.
Remote access (optional, explicit)
octoport never exposes itself beyond loopback unless you say so, twice.
Recommended: Tailscale. Keep the default loopback bind, or bind the tailnet address; nothing touches the public internet:
octoport up --host 100.x.y.z --allow-host hub.tailnet-name.ts.net --behind-proxyReverse proxy (Caddy) with a real domain. octoport does not terminate TLS β your proxy does:
# Caddyfile
hub.example.com {
reverse_proxy 127.0.0.1:6286
}octoport up --allow-host hub.example.com --behind-proxy --public-url https://hub.example.com--public-url makes snippets, the dashboard, and OAuth callbacks use the
external address; the dashboard WebSocket switches to wss:// on HTTPS.
GET /healthz answers without a token for proxy health checks. A non-loopback
bind refuses to start without --allow-host and --behind-proxy;
X-Forwarded-Host is deliberately ignored.
Small team setup: run octoport on a shared box behind Tailscale, one named token per teammate, and Live Activity becomes a team-level "which agent did what" record.
Organization mode (experimental)
Status: functional, not yet pilot-verified. The organization gateway is feature-complete for a first pilot and covered by the test suite (including user-boundary attack repros), but has not yet been run end-to-end against a real IdP and real MCP clients in production. Treat it as alpha. Personal mode is stable.
One MCP endpoint for every employee: IT registers servers once, employees add one URL and sign in with company SSO, access follows group profiles, per-user services are authorized individually, and every call is centrally audited under a verified identity.
Company SSO (generic OIDC).
// config.json
"oidc": {
"issuer": "https://login.example.com/realms/acme",
"audience": "octoport", // aud your IdP mints for this hub
"groupsClaim": "groups", // default
"adminGroups": ["platform-admins"] // these groups may open the dashboard
}Tokens validate against the IdP's JWKS (discovery, cache, rotation; RS256/384/
512 + ES256/384; iss/aud/exp/nbf enforced). Unauthenticated requests get a
WWW-Authenticate challenge pointing at
/.well-known/oauth-protected-resource (RFC 9728). Add loginClientId for a
browser Sign in with SSO flow (/login, Authorization Code + PKCE).
Disable the account at the IdP and access dies β octoport has no user database
of its own, on purpose.
Profiles (group-based access). Once any profile exists the MCP surface is
default-deny. Enforced at tools/list and on every call; denials are logged.
Settings has a policy simulator ("what would this identity see?").
"profiles": {
"backend-engineer": {
"groups": ["engineering"],
"servers": ["github", "jira", "sentry"],
"denyTools": ["kubernetes__delete_*"] // globs on public names; deny wins
},
"ci": { "tokens": ["github-actions"], "servers": ["github"] }
}Per-user OAuth downstream. "credentialMode": "per_user_oauth" gives
every identity its own connection and OAuth grant β employee A's GitHub is
never employee B's GitHub. Employees self-serve at /my; admins can
revoke any grant (kills its live connection). Secrets can be references
(file://β¦, vault://β¦) instead of literals.
Central audit. Every row records the verified subject, including policy
denials. Admin actions get their own event trail (GET /api/events, Audit
tab); GET /metrics serves Prometheus.
Deployment: Dockerfile + deploy/docker-compose.yml
(+ a Keycloak demo); guides in
docs/deploy.md and docs/idp.md; design in
docs/threat-model.md.
Commands
Command | What it does |
| Start the hub |
| Diagnose client/server/gateway problems, with fixes |
| Start at login (launchd/systemd) |
| CLI import (the wizard does this too) |
| Print connection snippets |
| Inspect or export the call log |
| List tokens / rotate the default token (live rotation: dashboard β Rotate) |
Data & privacy principles
Local-first by default β SQLite on your machine,
0600.Metadata-only is first-class:
logPayloads: falsestores no args/results.Secrets are redacted before persistence, in every mode.
The dashboard always states exactly what is stored.
Catalog snapshots store hashes, not tool descriptions/schemas.
What octoport is not
Not a finished enterprise governance product. SSO, profiles, per-user OAuth, and verified audit exist (see Organization mode), but there's no SCIM, no tenant separation, and no compliance claims yet.
Not agent mind-reading. octoport sees transport truth β what was called, what failed, what changed. It does not claim to know why a model chose a tool; that requires client-side context it doesn't collect today.
Not a context optimizer for Claude Code. Claude Code ships native MCP tool search; octoport doesn't compete with it.
Not magic. Tool names are namespaced
server__tool(capped at 48 chars with deterministic hashing) and routed through a mapping table β never string-parsed back.
Known limitations (v0.10)
Server-initiated relay (sampling/elicitation/roots) on a shared server uses in-flight correlation, and refuses when two identities call it at once (mark such servers
per_user_oauthto use those features safely).Catalog snapshots/diffs cover shared servers; per-user servers can legitimately show different surfaces per identity and are not snapshotted.
Config edits outside the dashboard need a restart (dashboard changes apply hot); rotate a token live from Settings β Rotate.
autostartrequires a permanent install (npm i -g octoportor a repo checkout) β refuses to point launchd at an ephemeral npx cache.Personal-mode tokens are full-admin by default; org mode uses scoped (
admin/mcp) tokens, per-user OAuth, and profiles.
Support expectations
MIT-licensed, provided as is β a solo-maintained project, so no response-time promises. Issues and PRs are welcome and read; small, focused PRs with tests have the best odds. If you need guarantees, fork freely.
Development
npm install
npm test # 207 tests: unit + E2E incl. mock-OAuth, mock-OIDC, mock-Vault
npm run build
node dist/cli.js up --openThe telemetry/event schema is documented in docs/events.md. Product direction and priorities live in PIVOT.md (it supersedes ROADMAP.md for ordering); the organization-gateway details stay in ROADMAP.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Real-time chat hub for AI agents β Claude Code, Cursor, Cline, Codex over MCP or REST.
Nifty's MCP server β exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceMCP Hub aggregates and proxies multiple Model Context Protocol servers into a unified Streamable HTTP interface. It allows users to combine diverse stdio, SSE, and HTTP-based servers while providing tool namespacing, health monitoring, and secure authentication.700 npm-
- FlicenseNot gradedqualityDmaintenanceA centralized management platform that aggregates multiple Model Context Protocol (MCP) servers into a single unified endpoint for AI agents. It provides a web interface for hot-swappable tool management, proxying of existing servers, and AI-powered generation of custom MCP plugins.1-
- AlicenseNot gradedqualityDmaintenanceMCPGate aggregates multiple MCP servers into a single unified endpoint, enabling centralized tool management with granular filtering, automatic namespacing, and observability. Features a real-time web dashboard and optional PostgreSQL-backed audit trails for monitoring and controlling AI tool access across local and remote deployments.6 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceSelf-hosted MCP proxy and aggregation platform. Register multiple upstream MCP servers and expose them through a single unified endpoint with namespace routing, multi-transport support (HTTP/SSE, stdio, OpenAPIβMCP), per-tool overrides, and a web admin UI.17MIT