Skip to content

feat(keep-mcp): v0.1 read-only MCP server (sidecar container)#6619

Draft
harisrujanc wants to merge 3 commits into
keephq:mainfrom
harisrujanc:keep-mcp-skeleton
Draft

feat(keep-mcp): v0.1 read-only MCP server (sidecar container)#6619
harisrujanc wants to merge 3 commits into
keephq:mainfrom
harisrujanc:keep-mcp-skeleton

Conversation

@harisrujanc

Copy link
Copy Markdown
Contributor

Closes #6618.

Adds keep-mcp — a Model Context Protocol server for Keep, shipped as a sidecar container next to keep-backend / keep-frontend (same pattern as keep-websocket-server). Thin adapter over the Keep REST API; no direct DB or secret-manager access. RBAC and tenancy stay in keep-backend.

v0.1 surface (read-only)

Tools

  • search_alerts(cel, limit, offset)
  • list_incidents(status, severity, limit, offset, cel) — defaults to active (firing + acknowledged)
  • get_incident(incident_id)
  • list_incident_alerts(incident_id, limit, offset)
  • get_topology(service)

Transports

  • stdio — for local desktop clients (Claude Desktop, Copilot CLI, Cursor)
  • streamable-http — for remote deployments (OAuth 2.1 planned for v0.2)

Try it

KEEP_MCP_KEEP_API_KEY=<your-key> docker compose --profile mcp up keep-mcp
curl http://localhost:8090/healthz

What's in the diff

  • keep-mcp/ — standalone Poetry package (~300 LOC): config, httpx client, FastMCP entrypoint, 5 unit tests
  • docker/Dockerfile.mcp — Alpine python:3.13.5, non-root UID 1000, mirrors Dockerfile.api
  • docker-compose.yml / docker-compose.common.ymlkeep-mcp service behind the mcp profile

keep-backend is not modified in this PR.

Verified

  • pytest → 5/5 pass
  • docker compose config --services unchanged for default profile; keep-mcp only appears under --profile mcp
  • MCP initialize + tools/list handshake returns all 5 tools
  • /healthz → 200, /readyz → 503 when backend unreachable (correct)

Deferred to follow-up PRs

  • v0.2: POST /providers/{id}/invoke/{method} in keep-backend + LGTM passthrough tools (Loki / Mimir / Tempo / Grafana) + triage_alert MCP prompt + new grafana_tempo_provider
  • v0.3: mutating tools (enrich_alert, create_incident, run_workflow) with idempotency + dry-run + audit, gated by MCP_ENABLE_MUTATING_TOOLS
  • Ops: OAuth 2.1 for streamable-http, OTel wiring, .github/workflows/mcp.yml, Helm sub-chart in keephq/helm-charts

Marking as draft for early feedback on shape/direction before I add CI + docs.

Copilot AI and others added 3 commits July 5, 2026 14:58
Introduces keep-mcp/ — a standalone Python package that exposes Keep's
alerts, incidents, and topology to LLM agents via the Model Context
Protocol. Ships as an independent container alongside keep-backend and
keep-frontend, matching the existing keep-websocket-server sidecar
pattern.

Tools (v0.1, read-only):
- search_alerts(cel, limit, offset)
- list_incidents(status, severity, limit, offset, cel)
- get_incident_with_alerts(incident_id, alerts_limit)
- get_topology(service)

Resources:
- keep://alerts
- keep://incidents
- keep://topology

Transports: stdio (local desktop clients) and streamable-http (remote).
Auth: X-API-KEY forwarded from KEEP_MCP_KEEP_API_KEY; no direct DB or
secret-manager access — RBAC and tenancy stay in keep-backend.

Ops: /healthz + /readyz, Docker HEALTHCHECK, Alpine python:3.13.5 base
matching Dockerfile.api, non-root user (UID 1000).

Wired into docker-compose behind the 'mcp' profile so it stays out of
the default 'docker compose up'.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- delete KeepAPIError + _extract_detail; rely on httpx.raise_for_status
- delete get_alerts_by_fingerprints (no v0.1 caller)
- delete client.ping(); inline into /readyz
- delete INCIDENT_STATUSES/SEVERITIES/_validate_subset (backend already 422s)
- delete keep://alerts/incidents/topology resources (tools cover it)
- split get_incident_with_alerts into get_incident + list_incident_alerts
- inline build_server() into main() — one caller, no fake factory
- drop starlette (transitive via mcp) and ruff (unwired) deps
- delete empty tests/__init__.py
- update tests to expect httpx.HTTPStatusError

All 5 tests pass; MCP handshake + tools/list verified end-to-end.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ harisrujanc
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[➕ Feature]: Official MCP (Model Context Protocol) server for Keep

3 participants