Self-hosted MCP aggregator

1 endpoint.
Every tool.
Every call governed.

Orcorus puts all of your Model Context Protocol servers behind a single gateway your agents, IDEs, and chat clients can connect to. Each tool runs in an isolated Docker container, every call passes deny-first policies and per-group budgets, and credentials never leave the vault.

JSON-RPC · REST · SSE Deny-first policy engine Vault-backed secrets Docker isolation
POST /mcp · tools/call
Gateway online
  1. 01Authenticate callerwait
  2. 02Resolve identity & groupswait
  3. 03Evaluate policies (deny-first)wait
  4. 04Check quotas & budgetwait
  5. 05Resolve secrets from Vaultwait
  6. 06Launch isolated containerwait
  7. 07Execute & record costwait
group network-ops policy allow · $0.0004
Works with any MCP-compatible client Claude Desktop Claude Code IDE assistants Autonomous agents Custom apps via REST

The problem with MCP sprawl

10 servers, 10 configs, 0 visibility.

MCP made it easy to give models tools. It did nothing to help a team manage them. Orcorus replaces per-user server sprawl with a single governed hub that is shared, observed, and enforced.

Before

Credentials live in client configs

API keys and SSH secrets get pasted into every developer's local MCP config, then forgotten.

Secrets stay in HashiCorp Vault and are injected into the container only at execution time.

Before

Any tool, any time, for anyone

Once a server is running, every model call can invoke every tool. There is no policy layer.

Deny-first policies scoped by user, group, integration, tool, time, and IP gate every call.

Before

Nobody knows what it costs

Tool calls burn compute and third-party quotas with no attribution and no ceiling.

Per-invocation and per-second cost models roll up to daily, weekly, and monthly group budgets.

Architecture

A gateway in front, containers behind, nothing in between.

Clients speak MCP to Orcorus. Orcorus discovers every tool a user can reach, namespaces it as integration/tool_name, and routes the call to the right backend after policy, quota, and budget checks pass.

Clients connect to the Orcorus gateway, which enforces policy, governance, and secrets before routing to isolated Docker containers. PostgreSQL stores state and HashiCorp Vault stores secrets. Chat clients Claude Desktop, web apps IDEs & CLIs Claude Code, editors Agents & services JSON-RPC, REST, SSE /mcp Orcorus Gateway discover · namespace · route Policy engine deny-first · priority ordered Governance & budgets rate · daily cap · concurrency · spend Secrets resolver Vault KV v2 · injected at runtime stdio · http ssh container · 256m · 0.5 cpu ping container · isolated network your-mcp-server any image · remote HTTP endpoint PostgreSQL users · groups · policies · cost ledger Vault Secret values never touch the application database.

Platform

Everything a production MCP gateway needs, in 1 container.

Discovery, execution, governance, and a marketplace, shipped as a single FastAPI service you own.

Unified MCP gateway

Aggregates a user's own integrations and group-shared integrations into 1 tool list, namespaced and routed to the right backend.

POST /mcp · GET /mcp/tools · GET /sse

Docker-backed integrations

Each template declares an image, tool manifest, environment schema, and transport. Containers launch with memory and CPU limits and network isolation.

stdio · HTTP · SSE

Policy engine

JSON policies evaluated by priority with deny-first semantics. Target users or groups, integrations or tools, with time and IP conditions.

effect · subjects · resources · conditions

Governance & quotas

Rate limits, daily invocation caps, concurrency ceilings, and spend budgets applied per group and checked on every call.

daily · weekly · monthly budgets

Vault-backed secrets

Credentials live in HashiCorp Vault KV v2. The database stores only the path. Values are resolved and injected at execution time, then gone.

HashiCorp Vault KV v2

Groups & RBAC

Groups are the unit of control. Member and admin roles, shared integrations, budgets, and quotas all attach to the group.

member · admin · shared integrations

Marketplace

Browse integration templates, inspect tool manifests, and connect with 1 click. Admins publish and manage templates for the whole org.

template-driven onboarding

Cost ledger

Every execution records its cost against a per-invocation plus per-second pricing model, so budgets reflect real usage.

per-invocation + per-second

Admin web UI

A built-in dashboard for integrations, marketplace, groups, policies, secrets, governance, and administration. No extra frontend to deploy.

Jinja2 + Tailwind

Connect

3 transports. 1 tool catalog.

Point any MCP client at the gateway and it sees every tool you are allowed to use. Automation that does not speak MCP can use the REST wrapper instead.

JSON-RPC 2.0

MCP streamable HTTP

The native protocol: initialize, tools/list, tools/call.

POST /mcp
REST

Simplified wrapper

List and call tools from scripts, CI jobs, and webhooks.

GET /mcp/tools · POST /mcp/tools/call
SSE

Server-Sent Events

Legacy transport with keep-alive for older clients.

GET /sse
// Claude Desktop, Claude Code, Cursor, or any MCP client
{
  "mcpServers": {
    "orcorus": {
      "url": "https://orcorus.internal/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}

// Every tool you can reach shows up namespaced:
//   ssh/run_command   ping/ping   whois/lookup   ...

Execution pipeline

11 steps between a request and a result.

No tool call skips the line. Each step in the orchestrated pipeline can stop the call, and every completed call leaves a cost record behind.

  1. AuthenticateVerify the caller's token.
  2. Resolve identityLoad the user and their group memberships.
  3. Resolve templateFind the integration behind the namespaced tool.
  4. Evaluate policiesDeny-first, priority ordered.
  5. Check quotasRate, daily cap, concurrency.
  6. Check budgetDaily, weekly, or monthly spend.
  7. Resolve secretsFetch values from Vault by path.
  8. Launch containerOr connect to a remote HTTP endpoint.
  9. Execute tool callProxy the MCP request and stream the result.
  10. Record costPer-invocation plus per-second pricing.
  11. CleanupTear the container down. Nothing lingers.

Governance

Limits that hold, set per group.

4 independent controls are enforced on every call. Set them once on a group and every member inherits them.

RateWINDOW

Rate limits

Concurrent and short-window limits smooth bursts before they reach a backend.

DailyCAP

Daily invocations

A hard ceiling on calls per group per day. Resets automatically.

MaxCONCURRENT

Concurrency

Bound the number of containers a group can have running at once.

SpendD / W / M

Budgets

Daily, weekly, or monthly spend limits checked against the cost model before execution.

Integrations

Batteries included. Bring the rest.

3 integrations ship with the platform. Any MCP server that can run in a container, or is reachable over HTTP, can be added as a template.

ssh

bundled

Execute commands on remote hosts over SSH, with keys resolved from Vault.

orcorus-ssh:latest

ping

bundled

Check network connectivity and latency to any host from an isolated container.

orcorus-ping:latest

whois

bundled

Look up WHOIS records for domains and IP addresses.

orcorus-whois:latest

your-server

template

Declare an image, tools manifest, env schema, and transport. Publish it to the marketplace.

stdio · http · sse

Quick start

Up in 1 compose command.

Orcorus ships with a Docker Compose file that brings up the gateway, its database, and Vault. Everything is configured through environment variables prefixed with ORCORUS_.

  1. Clone and start

    Docker and Docker Compose are the only prerequisites.

  2. Sign in

    Open the dashboard on port 8000 with the admin credentials from your compose file.

  3. Connect a tool

    Pick an integration in the marketplace, add its secret to Vault, click Connect.

  4. Point your client at /mcp

    Create a group, set a budget, and share the integration with your team.

$ git clone https://github.com/ceilingduster/orcorus.git
$ cd orcorus
$ docker compose up --build -d

# run migrations
$ docker compose run --rm -e PYTHONPATH=/app orcorus \
    alembic upgrade head

# dashboard
 http://localhost:8000
VariablePurpose
ORCORUS_DATABASE_URLAsync DB URL. SQLite for dev, PostgreSQL for prod.
ORCORUS_VAULT_ADDR / _TOKENWhere secrets live.
ORCORUS_CONTAINER_TIMEOUTExecution timeout per call. Default 300s.
ORCORUS_CONTAINER_MEMORY_LIMITPer-container memory cap. Default 256m.
ORCORUS_CONTAINER_CPU_LIMITPer-container CPU cap. Default 0.5.
ORCORUS_DOCKER_NETWORKIsolated network for tool containers.

Built on

Boring, well-understood infrastructure.

Python 3.12FastAPIUvicornSQLAlchemy 2.0 asyncAlembic PostgreSQLSQLiteHashiCorp VaultDocker SDKJinja2Tailwind CSS

Get Orcorus

Own the gateway your agents run through.

Self-hosted, source available, and free for personal, educational, and non-commercial use. Commercial licenses are available from the author.

Non-Commercial Use License · Copyright © 2026 Ian Redden