MCP OpsBridge
# MCP OpsBridge
Production MCP (Model Context Protocol) server exposing 30 DevOps tools for AI agents with a user approval system that prevents unauthorized write/destructive operations.
## What It Does
Exposes **29 tools + 1 `approve_action` tool** across 4 services, guarded by a risk-based permission gate:
| Service | Tools | Read (Auto) | Write (Gated) | Destructive (Double Approval) |
|---------|-------|-------------|---------------|-------------------------------|
| **GitHub** | 7 | All 7 | — | — |
| **Calendar** | 8 | 4 (`list_calendars`, `query_events`, `get_event_details`, `find_free_slots`) | 3 (`create_event`, `update_event`, `add_attendee`) | 1 (`delete_event`) |
| **Database** | 9 | 3 (`execute_query`, `list_tables`, `describe_table`) | 2 auto + 1 gated (`insert_row`, `update_rows` auto; `delete_rows` gated) | 3 (`truncate_table`, `drop_table`, `migrate_schema`) |
| **Slack** | 5 | 3 (`list_channels`, `get_thread`, `get_channel_history`) | 2 (`send_message`, `send_thread_reply`) | — |
## User Approval System
The **permission gate** intercepts medium+ risk tool calls and returns `pending_approval` instead of executing. The agent presents a structured request to the user, who confirms via the `approve_action` tool.
- **Low risk** → Auto-execute (reads)
- **Medium/High** → Single approval required
- **Critical** → Double approval required (two separate confirms)
- **Timeout** → Stale approvals auto-expire after 5 minutes
## Architecture
```
┌──────────────────────────────────────────────────┐
│ CLIENTS │
│ Claude Desktop (stdio) │ Custom Client (HTTP) │
└────────────┬─────────────────────┬───────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────┐
│ MCP SERVER │
│ ┌────────────────────────────────────────────┐ │
│ │ Transport: stdio | Streamable HTTP │ │
│ │ Rate Limiter: 100 req/min user, 1000/hr IP│ │
│ │ Permission Gate: Risk → Pending/Execute │ │
│ │ Validation: Zod schemas on all inputs │ │
│ └────────────────────────────────────────────┘ │
└────────────┬─────────────────────┬───────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────────────┐
│ EXTERNAL APIs │
│ GitHub │ Google Calendar │ PostgreSQL │ Slack │
└──────────────────────────────────────────────────┘
```
## Quick Start
### Local Development
```bash
npm install
npm run dev # stdio mode (default)
TRANSPORT=http PORT=3099 npm run dev # HTTP mode
```
### With Claude Desktop
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"opsbridge": {
"command": "npx",
"args": ["tsx", "src/cli.ts"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"DATABASE_URL": "postgresql://...",
"SLACK_TOKEN": "xoxb-...",
"CALENDAR_TOKEN": "ya29..."
}
}
}
}
```
### With Docker
```bash
cp .env.example .env
# Edit .env with your tokens
docker compose up -d
```
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `GITHUB_TOKEN` | No* | GitHub token (*required for private repos; public repos work without) |
| `DATABASE_URL` | No* | PostgreSQL connection string (*required for DB tools) |
| `SLACK_TOKEN` | No* | Slack bot token (`xoxb-...`) (*required for Slack tools) |
| `CALENDAR_TOKEN` | No* | Google Calendar OAuth token (*required for Calendar tools) |
| `TRANSPORT` | No | `stdio` (default) or `http` |
| `PORT` | No | HTTP port (default: 3002) |
## Security
- **Permission gate**: Risk-based approval for write/destructive operations; critical ops require double approval
- **Read-only database**: PostgreSQL session set to `READ ONLY` + write keyword blocklist
- **Rate limiting**: LRU cache, 100 requests/minute per user, 1000/hour per IP
- **Scoped tokens**: Each service requires its own token
- **Input validation**: All tool inputs validated with Zod schemas
- **No secrets in code**: All tokens loaded from environment variables
- **5-minute approval timeout**: Stale pending approvals auto-expire
## Development
```bash
npm run build # Compile TypeScript
npm run dev # Start dev server (stdio)
npm test # Run Vitest (71 tests)
npm run lint # Type check
npm run format # Prettier format
```
## Tech Stack
- TypeScript 5.5+
- `@modelcontextprotocol/sdk` v1.29 (MCP protocol)
- Zod (input validation)
- `@octokit/rest` (GitHub API)
- `pg` (PostgreSQL)
- `lru-cache` (rate limiting + approval store)
- Vitest (testing)
## License
MIT
TDQS
Scored across 30 tools
Every tool is clearly namespaced by service (github_, calendar_, db_, slack_) and performs a distinct action. No two tools have overlapping purposes; even similar actions like calendar_query_events and calendar_get_event_details are clearly differentiated.
All tool names follow a consistent snake_case pattern of domain_verb_noun (e.g., github_search_issues, db_execute_query, slack_send_message). The standalone approve_action still fits the verb_noun convention. No naming style mixing.
At 30 tools, the server exceeds the 25+ threshold for 'too many'. While the tools are grouped by service, the overall count is heavy for a single MCP server and could overwhelm agents. Splitting into separate domain servers would be more appropriate.
Calendar, database, and Slack domains have full lifecycle coverage (CRUD and actions). However, the GitHub domain is read-only—no create/update/merge operations—which is a notable gap for an ops bridge. Also missing some actions like Slack message deletion or calendar availability beyond free slots.