Skip to main content
Glama
varunk61

MCP-Native Enterprise Integration Hub

by varunk61
README.md
# MCP-Native Enterprise Integration Hub

## Overview

A governed AI agent platform that exposes GitHub Issues, Jira, and
Slack as MCP (Model Context Protocol) servers. A LangGraph orchestration
agent routes plain-language requests through Pydantic-validated tool
schemas with a mandatory HITL approval checkpoint gating all write
operations before execution. Every agent decision, tool call, and action
outcome is persisted to PostgreSQL for full audit trail, with PGVector
semantic search surfacing relevant historical actions before each new
action is planned.

## Architecture

```mermaid
graph TD
  User -->|POST /agent/run| FastAPI
  FastAPI --> LangGraph
  LangGraph --> ParseIntent
  ParseIntent --> RetrieveSimilar
  RetrieveSimilar -->|PGVector| PostgreSQL
  RetrieveSimilar --> PlanAction
  PlanAction --> HITLGate
  HITLGate -->|Write op| HITLApproval[(PostgreSQL HITLApproval)]
  HITLGate -->|Read op| ExecuteAction
  ExecuteAction --> GitHubMCP
  ExecuteAction --> JiraMCP
  ExecuteAction --> SlackMCP
  ExecuteAction --> LogRun
  LogRun --> PostgreSQL
```

## Required OAuth Scopes

**Slack**: `channels:read`, `channels:history`, `chat:write`
**GitHub**: `repo` (for private repos) or `public_repo`
**Jira**: `read:jira-work`, `write:jira-work`

## Setup

```bash
# 1. Clone and enter the project
git clone <repo-url> mcp-enterprise-hub
cd mcp-enterprise-hub

# 2. Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Configure environment variables
cp .env.example .env
# Edit .env and fill in: ANTHROPIC_API_KEY, OPENAI_API_KEY, GITHUB_TOKEN,
# JIRA_API_TOKEN, JIRA_EMAIL, JIRA_BASE_URL, SLACK_BOT_TOKEN

# 5. Start PostgreSQL (with pgvector)
docker compose up -d postgres

# 6. Initialize the database schema
python src/db/init_db.py

# 7. Run the API server
uvicorn src.api.main:app --reload

# 8. (Optional) Run the test suite
docker compose up -d postgres   # test DB is created automatically on first run
pytest --cov=src --cov-report=term-missing tests/
```

> **Port conflict note**: if you already have a local Postgres instance running
> on port 5432 (common on macOS via Homebrew or Postgres.app), Docker's port
> mapping can silently lose the race for that port — `docker compose up -d`
> will report the container as healthy, but `localhost:5432` will actually
> route to your native Postgres instead, which doesn't have the `mcp_enterprise_hub`
> role/database and will fail with `FATAL: role "postgres" does not exist` or
> similar. Either stop the local Postgres service, or remap the container to a
> free port with a `docker-compose.override.yml`:
> ```yaml
> services:
>   postgres:
>     ports:
>       - "5433:5432"
> ```
> and update `DATABASE_URL` / `TEST_DATABASE_URL` in `.env` to use port `5433`.

## Example API Calls

**1. Read operation (list GitHub issues) — completes immediately:**

```bash
curl -X POST http://localhost:8000/agent/run \
  -H "Content-Type: application/json" \
  -d '{"message": "list open issues in octo/hello"}'
```

```json
{
  "status": "completed",
  "result": {
    "issues": [
      {"id": 1, "number": 42, "title": "Login button unresponsive", "state": "open", "url": "https://github.com/octo/hello/issues/42"}
    ],
    "metadata": {"is_write": false, "connector": "github", "tool_name": "list_issues"}
  },
  "run_id": "6a9b1a2e-4c9b-4c1e-9c0e-7a1f2b3c4d5e",
  "session_id": "d1e2f3a4-5b6c-7d8e-9f0a-1b2c3d4e5f6a"
}
```

**2. Write operation (create a Jira ticket) — returns `pending_approval`:**

```bash
curl -X POST http://localhost:8000/agent/run \
  -H "Content-Type: application/json" \
  -d '{"message": "create a Jira ticket in project ABC titled '\''Login button unresponsive on mobile'\''"}'
```

```json
{
  "status": "pending_approval",
  "approval_id": "9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6",
  "action_plan": {
    "connector": "jira",
    "tool_name": "create_issue",
    "validated_params": {
      "project_key": "ABC",
      "summary": "Login button unresponsive on mobile",
      "description": "Login button unresponsive on mobile",
      "issue_type": "Bug"
    },
    "is_write_operation": true,
    "risk_level": "medium"
  },
  "session_id": "d1e2f3a4-5b6c-7d8e-9f0a-1b2c3d4e5f6a"
}
```

**3. Approve the write — executes and returns the result:**

```bash
curl -X POST http://localhost:8000/agent/approve/9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6 \
  -H "Content-Type: application/json" \
  -d '{"reviewer_notes": "Looks good, approved"}'
```

```json
{
  "status": "approved",
  "result": {
    "key": "ABC-123",
    "url": "https://your-domain.atlassian.net/browse/ABC-123",
    "metadata": {"is_write": true, "connector": "jira", "tool_name": "create_issue"}
  },
  "run_id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}
```

## Test Results

```
$ pytest --cov=src --cov-report=term-missing tests/

collected 52 items

tests/test_agent.py .............                                        [ 25%]
tests/test_api.py ..................                                     [ 59%]
tests/test_mcp_servers.py .....................                          [100%]

================================ tests coverage ================================
Name                               Stmts   Miss  Cover   Missing
----------------------------------------------------------------
src/__init__.py                        0      0   100%
src/agent/__init__.py                  0      0   100%
src/agent/hitl.py                     29      1    97%   33
src/agent/state.py                    13      0   100%
src/agent/workflow.py                189      5    97%   108, 263-266
src/api/__init__.py                    0      0   100%
src/api/main.py                      209      3    99%   150-152
src/db/__init__.py                     0      0   100%
src/db/database.py                    16      0   100%
src/db/init_db.py                     16     16     0%   1-24
src/db/models.py                      60      0   100%
src/db/vector_search.py                7      0   100%
src/mcp_servers/__init__.py            0      0   100%
src/mcp_servers/common.py             11      0   100%
src/mcp_servers/github_server.py      95      3    97%   7, 175-177
src/mcp_servers/jira_server.py        81      3    96%   7, 168-170
src/mcp_servers/slack_server.py       86      4    95%   7, 144, 161-163
----------------------------------------------------------------
TOTAL                                812     35    96%

52 passed in 2.92s
```

**HITL block rate** (measured against the persisted test database after a full
suite run, before per-test truncation):

| Metric | Count |
|---|---|
| Write-intent runs that reached `hitl_gate` | 9 |
| Runs where `hitl_gate` correctly created a `HITLApproval` record | 9 / 9 (**100%**) |
| Real MCP tool executions recorded in `AuditLog` | 4 |
| Of those, executed *without* a prior `APPROVED` approval | **0** |
| Writes rejected and never executed | 2 |

Every write-operation test run was intercepted by the HITL gate before any
MCP tool call could fire; no execution reached `AuditLog` without a matching
`APPROVED` `HITLApproval` row.

## Resume Metrics (for reference)

- 19 agent runs persisted to PostgreSQL during testing
- 85%+ test coverage across MCP servers, agent, and API layers
- HITL gated 100% of write operations in test suite (0 unreviewed writes executed)

Maintenance

ActivityMaintained
ResponsivenessNo issues