Kater is an open-source capability fabric for AI agents. It brings toolkits, integrations, plugins, and MCP providers behind one discoverable surface while keeping credentials, connection state, and provider wiring out of agent prompts. MCP is an important Kater transport, not the whole product.
Agent (Cursor / Claude / ChatGPT / API)
│
▼
┌─────────────────────────────────────────────┐
│ KATER │
│ │
│ Toolkits integrations plugins │
│ GitHub auth/bindings bundles │
│ Linear API/MCP/bridge extension│
│ Cloudflare health/status registry │
│ │
│ discovery · profiles · audit · telemetry │
│ │
│ Surfaces: MCP · REST · CLI · WebSocket │
└─────────────────────────────────────────────┘
- Toolkit — an agent-facing capability bundle such as GitHub, Linear, or Cloudflare.
- Integration — the concrete provider binding/adapter behind a toolkit, including auth and health.
- Plugin — an installable bundle that can contribute toolkits, capabilities, and provider wiring.
- MCP — one transport and exposure surface for Kater; providers may also use HTTP, native, or bridge transports.
The product catalog is available at /api/fabric and can be filtered into
/api/toolkits, /api/integrations, /api/plugins, and /api/mcp/catalog.
These rich catalog routes require unrestricted capability discovery; capability-restricted
callers receive 403 and retain access to the existing capability-filtered discovery
and invocation APIs. The q and profile parameters filter the view, not authorization.
Catalog metadata excludes launch arguments, environment/header templates and credential
references. HTTP endpoint and homepage URLs expose only their origin, without userinfo,
paths, queries or fragments.
Existing connector and MCP-server APIs remain compatible.
uv sync
kater up # init + Cursor MCP config + serve (profile: ops)Open http://localhost:9091 for the dashboard. Cursor is pointed at
http://127.0.0.1:9090/sse via .cursor/mcp.json.
Put adapter secrets in .kater/.env (created by kater up / kater init).
That file is loaded automatically — no manual export required:
# .kater/.env
KATER_PROFILE=ops
LINEAR_API_KEY=lin_api_...Proxy backends turn on automatically when secrets for the active profile are
present. Force with kater serve --proxy / --no-proxy, or set KATER_PROXY=1|0.
Minimal native-only (no adapters):
kater serve --profile core --no-proxyConnect your agent to http://127.0.0.1:9090/sse. Proxied tools are prefixed
(linear__list_issues, …). Validate with ./scripts/e2e-mcp.sh while the server
is running.
Client-side multi-server configs remain available via kater config --profile ops.
- Toolkit catalog: discover agent-facing provider capability bundles
- Integration catalog: separate provider availability from concrete connection readiness
- Plugin catalog: group built-in and extension-provided toolkits into installable bundles
- Unified MCP surface: proxy 29+ MCP servers behind one endpoint when MCP is the chosen transport
- Capability discovery: search machine-readable capabilities without loading every schema into context
- Profile gating: expose only the tools relevant to the current task
- Web dashboard: routing table, server catalog, evals, deploy configs
- REST API: product catalog, capability, connector, and operational endpoints with OpenAPI at
/api/spec - Auth and connections: API key/OAuth2 with PKCE plus secret references and provider bindings
- Telemetry: SQLite-backed tool call tracking, success rates, latency
- Deploy: Docker, Cloudflare Tunnel, Tailscale Funnel, systemd, K8s, stdio
| Command | Description |
|---|---|
kater serve |
Start API + MCP + WebSocket in one process |
kater up |
Init + Cursor MCP config + start gateway |
kater status |
Live instance overview |
kater doctor |
Diagnostics + autofix |
kater catalog |
Browse toolkits, integrations, plugins, and MCP surfaces |
kater toolkits |
List agent-facing capability bundles |
kater integrations |
List provider bindings and connection readiness |
kater plugins |
List installed plugin bundles |
kater mcp list |
Browse all 29 MCP servers |
kater mcp status <name> |
Server detail with launch config |
kater connector add connector.json |
Register a new dynamic connector (disabled by default) |
kater connector validate <id> |
Discover and validate connector capabilities |
kater connector enable <id> --profile ops --level read |
Grant a profile and enable the connector |
kater enable <name> |
Enable a server |
kater disable <name> |
Disable a server |
kater toggle <name> |
Toggle server on/off |
kater config --profile ops |
Render MCP config for a profile |
kater deploy render docker |
Generate Docker Compose config |
kater deploy render cloudflare --domain x.com |
Generate Cloudflare Tunnel config |
kater tunnel |
Show tunnel status (CF + Tailscale) |
kater tunnel start -p cloudflare |
Start Cloudflare Tunnel |
kater auth set apikey --key <key> |
Configure API key auth |
kater auth set oauth |
Configure OAuth mode |
kater init |
Bootstrap .kater/ in a project |
kater telemetry |
View raw telemetry events |
kater evals |
Aggregated tool performance metrics |
kater profiles |
List profiles |
kater tools --profile ops |
List tools for a profile |
kater search-tools "create a Linear issue" --profile ops |
Search registered connector capabilities |
kater execute <capability> --profile ops --args '{}' |
Execute one capability through policy and audit |
kater chains |
List tool chains |
kater chain run <name> |
Execute a chain |
kater version |
Show version |
All commands support --json for structured output.
Kater keeps provider tools behind the connector catalog. Agents can search the catalog with kater_tool_search, then run one result with kater_execute. The executor reuses connector auth, profile permissions, transport dispatch, and capability audit. See docs/executor.md.
| Server | Transport | Profiles |
|---|---|---|
| github | stdio | ops, code |
| gitlab | stdio | ops, code |
| linear | http (/mcp) |
ops |
| sentry | http | ops |
| exa | http | research, web |
| firecrawl | stdio | research, web |
| huggingface | http | research, cloud |
| cloudflare | stdio | cloud, ops |
| upstash | stdio | cloud, ops |
| sanity | http | content |
| notion | stdio | content, ops |
| context7 | stdio | code, research, docs |
| deepwiki | stdio | code, research, docs |
| browser | stdio | web |
| puppeteer | stdio | web |
| resend | stdio | email, content |
| slack | http | email, ops |
| figma | stdio | image, content |
| postgres | stdio | cloud, ops |
| sqlite | stdio | code |
| filesystem | stdio | code |
| brave-search | stdio | research, web |
| fetch | stdio | research, web |
| quiverai | http | image |
| everart | stdio | image |
| memory | stdio | reasoning |
| sequential-thinking | stdio | reasoning, research |
| time | stdio | utils |
Open http://localhost:9091 in any browser. The dashboard is a single,
dependency-free document (inline HTML/CSS/JS) with a dark, ops-focused design:
- Overview: triage-first exception strip (ready / needs-credentials / disabled), live KPI tiles with sparklines + trend deltas, a 5-state routing table, and an activity log with a canvas latency strip, burst grouping, pause, and an errors-only filter
- Catalog: browse all servers, toggle on/off, filter by profile
- Performance: per-tool success bars and latency pills
- Deploy: generate configs for any platform
- Settings: auth mode, CORS, rate limit, storage backend
Keyboard: 1-5 switch views, ⌘/Ctrl+K opens the command palette, j/k move
through the routing table and Enter opens detail, / focuses search, r
refreshes the current view. View, profile, search and filters sync into the
URL so investigations are shareable.
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check |
/api/status |
GET | Instance overview |
/api/catalog |
GET | Server catalog with grouping |
/api/mcp/servers |
GET | List all servers |
/api/mcp/servers/{name} |
GET | Server detail |
/api/mcp/servers/{name}/{action} |
POST | Enable/disable/toggle |
/api/settings |
GET/POST | View/update settings |
/api/telemetry |
GET | Raw events |
/api/evals |
GET | Aggregated metrics |
/api/deploy |
GET | Deployment formats |
/api/deploy/{format} |
GET | Render config |
/api/spec |
GET | OpenAPI 3.1 spec |
/authorize |
GET | OAuth consent page |
/token |
POST | OAuth token exchange |
/register |
POST | OAuth client registration; public mode requires explicit opt-in |
/.well-known/oauth-authorization-server |
GET | OAuth discovery |
Full spec: GET /api/spec
Local dev binds to loopback with auth disabled. Public exposure (Cloudflare Tunnel, Tailscale Funnel, public IP) requires auth — set KATER_PUBLIC=1.
Pre-flight:
KATER_PUBLIC=1 KATER_AUTH_MODE=oauth kater doctorPublic dynamic OAuth registration is disabled by default. Enable it only for an operator-controlled bootstrap flow:
export KATER_ALLOW_DYNAMIC_REGISTRATION=1
export KATER_REGISTRATION_TOKEN="$(openssl rand -hex 24)"Use KATER_ADMIN_KEY for public dashboard/API settings changes and Catalog
Connect mutations. Public Connect will not persist OAuth tokens to local
settings; see docs/ops/catalog-connect.md.
cp .env.example .env
docker compose up -dcloudflared tunnel login # once
export KATER_PUBLIC=1
export KATER_AUTH_MODE=oauth
export KATER_ADMIN_KEY="$(openssl rand -hex 24)"
./scripts/deploy-cloudflare.sh kater.yourdomain.com katerResult: https://kater.yourdomain.com/sse — paste into ChatGPT Settings → MCP.
Dashboard: https://kater.yourdomain.com/dashboard (OAuth sign-in).
export KATER_PUBLIC=1
export KATER_AUTH_MODE=apikey
export KATER_API_KEY="$(openssl rand -hex 24)"
export KATER_ADMIN_KEY="$(openssl rand -hex 24)"
uv run kater serveSee docs/deploy-server.md and SECURITY.md.
Org-specific profiles and adapters can live in a separate private repo and load at
runtime via KATER_EXTENSIONS_MODULE (see src/kater/extensions.py and
docs/ops/private-overlays.md).
With KATER_PUBLIC=1 (also true, yes, or on), catalog endpoints omit
sources and persisted connectors scoped only to PRIVATE_PROFILES. Persisted
records cannot reintroduce a hidden source. Mixed-profile entries retain only
their public profile names. Plugin catalogs apply the same visibility rule to
profiles and toolkit references; private-only bundles are omitted. Non-public
deployments retain the complete catalog. This presentation filter does not
replace capability authorization.
export KATER_EXTENSIONS_MODULE=your_package.extensions
uv run kater-capabilities list
uv run kater-capabilities discover --profile core --intent "search" --jsonKATER_PUBLIC=1 KATER_AUTH_MODE=apikey KATER_API_KEY=... kater tunnel start -p tailscalekater deploy render systemd # systemd unit file
kater deploy render k8s # Kubernetes manifests
kater deploy render stdio # Claude Desktop config
kater deploy render sse # Cursor/ChatGPT SSE configuv sync --dev
uv run ruff check .
uv run pytest -v
./scripts/smoke.sh
./scripts/e2e-mcp.sh # requires `kater serve` with KATER_PROXY=1- Cursor agents — MCP wiring, hooks, and Cloud vs desktop verify: docs/cursor-setup.md, AGENTS.md
- Connectors — vendor MCP/API catalog behind the native tool surface: docs/connectors.md
src/kater/
├── cli.py CLI entry point (Typer)
├── runtime.py KaterRuntime: ordered startup/shutdown of all servers
├── serve.py Thin wrapper over KaterRuntime
├── api.py REST API: Request/Response pipeline + RouteTable
├── authgate.py Single source of truth for auth policy
├── websocket.py WebSocket server (RFC 6455)
├── mcp_server.py MCP SSE server (FastMCP + authgate middleware)
├── proxy/ MCP Proxy Engine
│ ├── manager.py Lifecycle + routing + circuit breaker
│ ├── base.py BaseBackend: shared MCP session ceremony
│ ├── stdio_backend.py subprocess transport (env-whitelisted)
│ ├── sse_backend.py upstream SSE transport
│ ├── aggregator.py tool registry + prefix resolution
│ └── models.py proxy data models
├── web/dashboard.py Web dashboard (inline HTML/CSS/JS, per-view seams)
├── profiles.py MCP server catalog (29+)
├── connectors/ Persistent connector catalog (not extra native tools)
├── settings.py Auth, CORS, storage, ListenConfig (bind SSOT)
├── storage.py SQLite + JSONL telemetry
├── telemetry.py Event recording + evals
├── oauth.py OAuth2 + PKCE (locked, atomic state)
├── tunnel.py CF Tunnel + Tailscale
├── deploy.py Deployment config generation
├── ansi.py CLI formatting
└── openapi_spec.py OpenAPI 3.1 generation (drift-guarded)
Contributions welcome — see CONTRIBUTING.md. Report security issues via SECURITY.md (private advisories, not public issues).
MIT — see LICENSE.
v1.1.0 — see CHANGELOG.md. Loopback-by-default; OAuth/API-key auth for public deploys. Package version lives in pyproject.toml and src/kater/__init__.py (must match). Tags exist only after a bump PR lands on main.