Skip to main content
Glama
README.md
# OpsMCP

MCP (Model Context Protocol) server that exposes eight typed tools so an AI
agent can operate GitHub, Postgres, deploy status, and a sandboxed local
filesystem. Credentials stay in the server process; tool inputs are treated as
untrusted.

**Live:** https://tanmays0.github.io/ops-mcp/  
**GitHub:** https://github.com/tanmays0/ops-mcp


| Artifact | Location |
|----------|----------|
| MCP server (stdio) | `uv run python -m ops_mcp` |
| Eight tools | registered in `src/ops_mcp/server.py` |
| Companion UI | `site/` → GitHub Pages (catalog, setup, simulated playground) |
| Seeded demo database | `docker compose up -d` → Postgres `users` / `orders` / `products` |
| Automated tests | `uv run pytest` (path sandbox, SQL guard, GitHub mocks, Postgres) |
| CI | GitHub Actions workflow `.github/workflows/ci.yml` |
| Pages deploy | `.github/workflows/pages.yml` |
| Container image | `Dockerfile` |
| Agent wiring example | `.cursor/mcp.json.example` |

## Architecture

```text
Agent (stdio) → FastMCP server
                  ├── tools/       domain tools
                  ├── security/    path sandbox, SQL allowlist, redaction, rate limit
                  ├── adapters/    GitHub HTTP, Postgres
                  └── config.py    Pydantic Settings (env / .env)
```

## Tools

| Tool | System | Behavior |
|------|--------|----------|
| `github_list_issues` | GitHub API | List issues/PRs by repo, state, labels |
| `github_create_issue` | GitHub API | Create issue; default `dry_run=true` |
| `github_pr_diff_summary` | GitHub API | PR file list and diff stats (no patches) |
| `postgres_query_readonly` | Postgres | Parameterized SELECT only |
| `postgres_explain` | Postgres | `EXPLAIN (FORMAT TEXT)` only (no `ANALYZE`) |
| `deploy_status` | GitHub Actions | Latest workflow run for a branch |
| `fs_search` | Local FS | Literal search under allowlisted roots |
| `fs_read_file` | Local FS | Read file with sandbox and size limit |

## Safety

| Control | Implementation |
|---------|----------------|
| Filesystem | Resolve-then-compare allowlist after symlink resolution |
| SQL | sqlglot AST: single SELECT / WITH…SELECT; DDL/DML/multi-statement rejected before connect |
| GitHub writes | `dry_run=true` unless explicitly disabled |
| Secrets | `SecretStr` for token and DSN; log redaction; never returned in tool payloads |
| Outbound HTTP | Token-bucket rate limit |

## Stack

Python 3.12 · FastMCP · httpx · psycopg · sqlglot · Pydantic Settings · pytest · Docker

## Run

```bash
git clone https://github.com/tanmays0/ops-mcp.git
cd ops-mcp
uv sync
docker compose up -d
cp .env.example .env
uv run pytest
uv run python -m ops_mcp
```

Populate `.env` from `.env.example` (`OPS_MCP_FS_ROOTS`, `OPS_MCP_DATABASE_URL`, `OPS_MCP_GITHUB_TOKEN`). MCP client config: copy `.cursor/mcp.json.example` to `.cursor/mcp.json` with absolute paths. Secrets load from `.env` only (`.env` and `.cursor/mcp.json` are gitignored).

## Configuration

| Variable | Purpose |
|----------|---------|
| `OPS_MCP_FS_ROOTS` | Colon-separated allowlisted directories |
| `OPS_MCP_FS_MAX_READ_BYTES` | Max bytes for `fs_read_file` |
| `OPS_MCP_DATABASE_URL` | Postgres DSN |
| `OPS_MCP_GITHUB_TOKEN` | GitHub fine-grained or classic PAT |
| `OPS_MCP_HTTP_RATE_PER_SECOND` | Outbound API rate |
| `OPS_MCP_LOG_LEVEL` | Log level |

## Verification flows

Documented end-to-end flows: [DEMO.md](DEMO.md).

## Spec

Project principles: [`.specify/memory/constitution.md`](.specify/memory/constitution.md)  
Requirements: [`specs/001-ops-mcp-server/spec.md`](specs/001-ops-mcp-server/spec.md)

TDQS

A3.6/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct resource and action: filesystem search/read, GitHub issues/PR summary, Postgres query/explain, and deployment status. Even the PR-related tools are clearly separated by list vs. diff-summary purpose.

Naming Consistency3/5

Names use consistent resource prefixes (fs_, github_, postgres_, deploy_) and many follow verb_noun, but github_pr_diff_summary and deploy_status are noun phrases without a verb, and postgres_query_readonly mixes verb/noun with an adjective. The pattern is readable but not uniform.

Tool Count5/5

Eight tools is a reasonable, focused set for an ops-oriented server spanning filesystem inspection, GitHub workflows, and read-only Postgres access. Each tool has a clear purpose and none feel redundant or superfluous.

Completeness4/5

The tool surface covers the main read-only investigation workflows: file lookup, GitHub issue triage and PR diff summaries, Postgres querying/explaining, and deployment status. Minor gaps exist such as no directory listing, no GitHub PR list endpoint, and no database schema introspection, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues