Skip to main content
Glama
README.md
# 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

B3.3/5.0

Scored across 30 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count2/5

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.

Completeness3/5

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.

Maintenance

ActivitySlowing
ResponsivenessNo issues