agent-mesh-mcp
by openbiocure
README.md
# agent-mesh-mcp
MCP server for a distributed AI agent mesh. Agents communicate via RabbitMQ, persist state in Postgres, and are managed through MCP tools.
Part of the **Agent Mesh** ecosystem:
| Repo | What | Language |
|------|------|----------|
| **[agent-mesh-mcp](https://github.com/openbiocure/agent-mesh-mcp)** | MCP server — tools, events, webhooks, channels | JavaScript |
| **[agent-mesh-worker](https://github.com/openbiocure/agent-mesh-worker)** | Worker daemon — warm sessions, scheduling, RabbitMQ | Python |
| **[agent-mesh-lib](https://github.com/openbiocure/agent-mesh-lib)** | Shared library — identity, guardrails, memory, hooks | Python |
| **[agent-mesh-hooks](https://github.com/openbiocure/agent-mesh-hooks)** | CLI hooks for Claude Code — auto-inject prompts + memory | Python |
| **[agent-mesh-memory](https://github.com/openbiocure/agent-mesh-memory)** | Temporal knowledge graph memory (Graphiti + FalkorDB) | Python |
## Architecture

[PlantUML source](docs/architecture.puml) — regenerate with `plantuml docs/architecture.puml`
## Agent Addressing
Agents use a `slug@repo:scope` address format:
```
devops-engineer # unique role, no repo needed
js-engineer@obc-connectors # same role, different repos
js-engineer@obc-platform
architect@obc-datalake:landing # same role + repo, different scopes
architect@obc-datalake:warehouse
```
Each address produces a **deterministic UUID** (v5) — identical in Python and JS. No DB lookup needed to know an agent's ID.
## Transports
- **stdio** (`index.mjs`) — for local Claude Code / Cursor
- **HTTP** (`server.mjs`) — remote access via Streamable HTTP + Keycloak OAuth
## Install
```bash
npm install -g agent-mesh-mcp
```
## Tools
### Agents
| Tool | Description |
|------|-------------|
| `create_agent` | Create agent with slug, prompt, model, config |
| `update_agent` | Update prompt (bumps version), model, config |
| `get_agent` | Full details: prompt, guardrails, online workers |
| `list_agents` | All registered + online agents |
| `ask_agent` | Send a message to another agent via RabbitMQ |
| `get_task_result` | Poll async task result |
| `cancel_agent` | Cancel a running task |
| `tail_agent` | Live activity feed from a running agent |
### Guardrails
Pre-execution tool call validation. Three layers (fast to slow):
1. **regex** — pattern match on tool input (microseconds)
2. **validator** — Guardrails AI (DetectPII, ToxicLanguage, etc.)
3. **llm_judge** — LLM evaluates criteria before allowing
| Tool | Description |
|------|-------------|
| `create_guardrail` | Create a guardrail rule (global or per-agent) |
| `list_guardrails` | List all rules, filter by agent |
| `delete_guardrail` | Remove a rule |
```
# Block git push to prod for all agents
create_guardrail(tool="Bash", pattern="git push.*prod", action="block")
# PII detection on all tool inputs for a specific agent
create_guardrail(tool="*", type="validator", agent="js-engineer@obc-connectors",
config={"validator":"DetectPII","params":["EMAIL_ADDRESS"]})
```
### Scheduling
| Tool | Description |
|------|-------------|
| `create_schedule` | Cron or interval schedule for an agent |
| `list_schedules` | All schedules with run history |
| `delete_schedule` | Remove a schedule |
| `run_schedule` | Fire a schedule immediately |
### Incidents
| Tool | Description |
|------|-------------|
| `create_incident` | Track a P1/P2/P3 incident |
| `list_incidents` | Filter by severity/status |
| `update_incident` | Change status, assign agent, link PR |
| `resolve_incident` | Mark as resolved |
### Releases
| Tool | Description |
|------|-------------|
| `create_release` | Track a deployment with steps + rollback |
| `list_releases` | All releases by status |
| `get_release` | Full release details |
| `update_release` | Update status (with transition validation) |
| `close_release` | Mark deployed/rolled back |
### Approvals
| Tool | Description |
|------|-------------|
| `request_approval` | Request human approval (notifies via Telegram) |
| `get_approval` | Check approval status |
| `list_approvals` | All pending/approved/rejected |
| `approve` / `reject` | Respond to an approval |
| `comment_approval` | Add context to an approval |
### Other
| Tool | Description |
|------|-------------|
| `create_feature` | Track a feature request |
| `list_features` | All features by status |
| `update_feature` | Change status/priority |
| `report_mesh_bug` | Report a bug in the mesh itself |
| `list_mesh_bugs` | All mesh bugs |
| `update_mesh_bug` | Fix/close a mesh bug |
| `search_conversations` | Search agent conversation history |
| `notify` | Send a notification via Telegram |
| `get_setting` / `set_setting` / `list_settings` | Mesh configuration |
## Events
Domain events are emitted on state changes and published to RabbitMQ:
```
incident.created → notifies Telegram (P1/P2), publishes to event.incident.created
release.status_changed → notifies subscribers, triggers deploy queue
approval.requested → sends Telegram buttons, publishes event
feature.created → publishes event
mesh.shutdown → all workers stop consuming
mesh.resume → workers restart
```
Workers can bind to event topics in their `worker.json`:
```json
{
"event_topics": ["event.incident.*", "event.release.*"]
}
```
## Kill Switch
```
POST /mesh/shutdown → MESH_ENABLED=false, pauses schedules, broadcasts event
POST /mesh/resume → MESH_ENABLED=true, resumes schedules
GET /mesh/status → current state
```
Also available via Telegram: `/shutdown`, `/resume`, `/meshstatus`
## Status Transitions
YAML-based validation stored in `mesh_settings`. Prevents invalid state changes:
```yaml
incident:
open: [investigating]
investigating: [fix_submitted, resolved]
fix_submitted: [resolved, investigating]
release:
ready: [approved, cancelled]
approved: [deploying]
deploying: [deployed, rolled_back]
```
## Worker (agent-mesh-worker)
The worker is a separate Python package: [agent-mesh-worker](https://github.com/openbiocure/agent-mesh-worker)
**worker.json:**
```json
{
"slug": "js-engineer",
"cwd": "/path/to/repo",
"scope": "hotfix",
"prompt_file": ".claude/agents/js-engineer.md"
}
```
Repo is derived from `basename(cwd)`. Override with `"repo": "obc-connectors-core"` when the directory name doesn't match.
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `RABBITMQ_URL` | `amqp://guest:guest@localhost:5672/` | RabbitMQ connection |
| `RABBITMQ_MGMT_URL` | `http://localhost:15672` | RabbitMQ management API |
| `EXCHANGE_NAME` | `agents` | RabbitMQ exchange |
| `AGENT_NAME` | `unknown` | Calling agent's address (set by worker) |
| `AGENT_ID` | — | Calling agent's UUID (set by worker) |
| `WORKER_ID` | — | Worker instance UUID (set by worker) |
| `ASK_TIMEOUT` | `900` | Reply timeout in seconds |
| `MCP_PORT` | `3100` | HTTP server port |
| `KEYCLOAK_URL` | `http://localhost:8080` | Keycloak base URL |
| `KEYCLOAK_REALM` | `master` | Keycloak realm |
| `KEYCLOAK_CLIENT_ID` | `agent-mesh` | OAuth client ID |
| `KEYCLOAK_CLIENT_SECRET` | — | OAuth client secret |
| `DATABASE_URL` | — | Postgres connection (Prisma) |
## License
MIT
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessSyncing