Skip to main content
Glama

Manifold

Self-hosted MCP gateway. One Docker image serves many MCP endpoints, each registered in claude.ai as its own connector.

Read SPEC.md for what it is and DECISIONS.md for why it is built the way it is.

Endpoints

/                     admin UI (Phase 3)
/healthz              liveness
/<toolset>            MCP Streamable HTTP endpoint, bearer token required
/<toolset>/healthz    toolset health, open
/oauth/authorize      consent step, behind Cloudflare Access
/oauth/token, /oauth/register, /oauth/revoke
/.well-known/oauth-authorization-server
/.well-known/oauth-protected-resource/<toolset>

claude.ai is given https://<host>/<toolset> as a custom connector. It discovers the OAuth server from the 401, registers itself and runs the code flow. The only human login is Cloudflare Access on the authorize page. OAuth clients and tokens live in SQLite under /data, so restarts and updates do not disconnect claude.ai.

Related MCP server: BeefChicken MCP

Local development

Requires uv and pnpm. Python is pinned to 3.12 through uv.

cp .env.example .env            # then set a real MANIFOLD_MASTER_KEY
uv sync
uv run pytest
uv run ruff check . && uv run ruff format .
set -a; source .env; set +a; uv run python -m manifold

Or with Docker:

docker compose -f deploy/docker-compose.yml up --build

Admin UI

ui/ is an Astro static build with a small vanilla TypeScript app. Build it with pnpm --dir ui build; the Dockerfile does the same in a Node stage. The app talks to /api only. Mutating requests carry X-Manifold-Request: 1, which the API requires.

To work on the UI locally you need a request with a Cloudflare Access identity. Run the app behind a tiny wrapper that injects the Cf-Access-Authenticated-User-Email header, never expose that wrapper anywhere.

New native toolsets are registered disabled. Enable them from the dashboard, or in an emergency from the database on the NAS:

docker exec manifold python -c "import sqlite3; c=sqlite3.connect('/data/manifold.db'); c.execute(\"UPDATE toolsets SET enabled=1 WHERE key='sheets'\"); c.commit()"

Live Google test

tests/live runs against a real spreadsheet and skips itself in CI. Point it at a service account key and a throwaway spreadsheet shared with that account as Editor:

MANIFOLD_TEST_SA_JSON=/path/to/sa.json MANIFOLD_TEST_SPREADSHEET_ID=1abc... uv run pytest tests/live -q

Toolsets in the image

  • manifold: gateway self-management, always on.

  • sheets: Google Sheets by spreadsheet ID, service account or Google OAuth.

  • unraid: the NAS through the Unraid 7.2 API with an api_key credential.

Proxy toolsets, such as n8n, are rows in the config store created from the admin UI.

Adding a native toolset

Create manifold/toolsets/<name>/__init__.py exposing MANIFEST, build() and healthcheck(). See manifold/toolsets/manifold for the shape. The contract tests in tests/contract pick it up automatically and it is served at /<MANIFEST.key> after a restart.

Deployment

The image is published to ghcr.io/mannilie/manifold by GitHub Actions on every push to main. It runs as UID 99 GID 100 and keeps all state under /data. Port 8800 is bound to the NAS loopback only; cloudflared runs with host networking and reaches it at localhost:8800. It is never exposed on a LAN interface. See deploy/unraid/manifold.xml and SPEC.md section 11.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude.ai to connect to a Hermes MCP server via OAuth 2.1 authorization code flow with PKCE, acting as a reverse proxy and single-user authorization gateway.
    -
  • A
    license
    B
    quality
    B
    maintenance
    A lightweight OpenAPI proxy MCP server that turns any openapi.yaml into MCP tools with zero code, including a built-in OAuth 2.1 server for Claude.ai Web connection.
    4
    3 npm
    3
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Self-hosted MCP connector for Claude.ai that provides multi-account IMAP/SMTP email management via OAuth 2.1 + DCR + PKCE shim and an admin backoffice.
    -