Skip to main content

Bifrost MCP Gateway

The Rainbow Bridge - Communications Gateway & Tool Registry for Ravenhelm Agents

Overview

Bifrost provides:

  • Tool Registry - Centralized ownership of all tool definitions with permission-based access
  • Execution Gateway - Routes tool calls to appropriate executors (Norns, n8n, OpenAPI)
  • n8n Auto-Discovery - Automatically discovers and syncs n8n workflows as MCP tools
  • Channel Gateway - Routes messages from multiple channels (Slack, SIP, Web) to agents
  • Admin Portal - Configure channels, tools, and permissions

Services

ServicePortURLPurpose
bifrost-api8000https://bifrost-api.ravenhelm.devTool execution API
bifrost-admin3000https://bifrost.ravenhelm.devAdmin UI (Next.js)

Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│ BIFROST TOOL REGISTRY │
├─────────────────────────────────────────────────────────────────────────┤
│ Tool Sources │ Execution Gateway │
│ ┌─────────────┐ │ ┌─────────────────────────────────┐ │
│ │ Norns │─────┐ │ │ POST /mcp/tools/call │ │
│ │ (delegate) │ │ │ │ │ │
│ ├─────────────┤ │ │ │ ┌─────────────────────────┐ │ │
│ │ n8n │─────┼──────────▶│ │ │ ExecutorRouter │ │ │
│ │ workflows │ │ │ │ │ - NornsDelegateExecutor│ │ │
│ ├─────────────┤ │ │ │ │ - N8nWorkflowExecutor │ │ │
│ │ OpenAPI │─────┘ │ │ │ - OpenAPIExecutor (*) │ │ │
│ │ imports (*)│ │ │ │ - MCPProxyExecutor (*) │ │ │
│ └─────────────┘ │ │ └─────────────────────────┘ │ │
│ │ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘

┌───────────────┼───────────────┐
│ │ │
┌────┴────┐ ┌─────┴─────┐ ┌────┴────┐
│ Norns │ │ Voice │ │ Future │
│ Agent │ │ Gateway │ │ Agents │
└─────────┘ └───────────┘ └─────────┘

(*) = Planned, not yet implemented

n8n Auto-Discovery

Bifrost can automatically discover n8n workflows and register them as MCP tools.

Discovery Criteria

Workflows are discovered when they:

  1. Have the [MCP] prefix in their name (e.g., [MCP] Send Alert), OR
  2. Are tagged with tool:enabled
  3. Have a Webhook trigger node with a valid path
  4. Are active (not draft/inactive)

n8n Integration API

EndpointMethodPurpose
/api/v1/n8n/connectionsGETList configured n8n connections
/api/v1/n8n/discoverGETPreview discoverable workflows
/api/v1/n8n/syncPOSTSync workflows to tool registry
/api/v1/n8n/sync/historyGETView sync history

Discovery Commands

# Preview what will be synced
curl -s "http://localhost:8000/api/v1/n8n/discover" \
-H "X-API-Key: $BIFROST_API_KEY"

# Sync workflows to tool registry
curl -s -X POST "http://localhost:8000/api/v1/n8n/sync" \
-H "X-API-Key: $BIFROST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_name": "default"}'

# Check sync history
curl -s "http://localhost:8000/api/v1/n8n/sync/history" \
-H "X-API-Key: $BIFROST_API_KEY"

Workflow Metadata (YAML Front Matter)

Add metadata to the workflow Notes field for custom tool configuration:

---
mcp_tool:
enabled: true
name: send_alert
description: Send an alert to Slack
domain: notifications
timeout_ms: 30000
input_schema:
type: object
required:
- message
properties:
message:
type: string
description: Alert message
---

Database Tables

-- n8n connection configuration
CREATE TABLE n8n_connections (
connection_id UUID PRIMARY KEY,
org_id UUID NOT NULL,
name VARCHAR(100) NOT NULL,
display_name VARCHAR(255),
n8n_url VARCHAR(500) NOT NULL,
api_key_encrypted TEXT,
auto_sync BOOLEAN DEFAULT false,
sync_interval_minutes INTEGER DEFAULT 5,
status VARCHAR(50) DEFAULT 'active',
last_sync_at TIMESTAMPTZ,
last_sync_status VARCHAR(50)
);

-- Sync history for auditing
CREATE TABLE n8n_sync_history (
sync_id UUID PRIMARY KEY,
connection_id UUID REFERENCES n8n_connections(connection_id),
org_id UUID NOT NULL,
status VARCHAR(50) NOT NULL,
workflows_discovered INTEGER DEFAULT 0,
tools_created INTEGER DEFAULT 0,
tools_updated INTEGER DEFAULT 0,
error_message TEXT,
started_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ,
duration_ms INTEGER
);

See [[../Automation/n8n#Bifrost MCP Integration]] for workflow creation details.


Executor Framework

Tools are executed through specialized executors based on executor_type:

NornsDelegateExecutor

Forwards tool calls to Norns agent during transition period:

# Flow: Bifrost → Norns /api/tool/execute → LangChain @tool → Result
executor_config = {
"norns_tool_name": "query_tasks", # Tool name in Norns
"timeout_override": 60000 # Optional timeout
}

N8nWorkflowExecutor

Executes n8n workflows via production webhooks:

executor_config = {
"webhook_url": "https://n8n.ravenhelm.dev/webhook/abc123",
"workflow_id": "abc123", # For reference
"webhook_secret": "...", # Optional
"timeout_override": 60000 # Optional
}

Webhook Payload Format:

{
"arguments": {...},
"context": {
"request_id": "uuid",
"org_id": "uuid",
"agent_id": "uuid",
"agent_name": "norns"
}
}

Expected Response:

{
"success": true,
"result": {...},
"metadata": {...}
}

ExecutorRouter

Routes tool calls to appropriate executor:

router = ExecutorRouter(
norns_url="http://docs/AI-ML-Platform/norns-agent:8000",
norns_api_key="...",
n8n_url="https://n8n.ravenhelm.dev",
n8n_api_key="..."
)

result = await router.execute(tool, arguments, context)

API Endpoints

Health Checks

  • GET /health - Basic health
  • GET /health/db - Database connectivity
  • GET /health/docs/infrastructure/redis - Redis connectivity

Organizations

  • GET /api/v1/organizations - List organizations

Channels

  • GET /api/v1/channels - List channels
  • POST /api/v1/channels - Create channel
  • PUT /api/v1/channels/{id} - Update channel
  • DELETE /api/v1/channels/{id} - Delete channel
  • POST /api/v1/channels/{id}/test - Test connectivity

Tools

  • GET /api/v1/tools - List tool definitions
  • POST /api/v1/tools - Create tool
  • PUT /api/v1/tools/{id} - Update tool

n8n Integration

  • GET /api/v1/n8n/connections - List n8n connections
  • GET /api/v1/n8n/discover - Preview discoverable workflows
  • POST /api/v1/n8n/sync - Sync workflows to registry
  • GET /api/v1/n8n/sync/history - View sync history

MCP Protocol (Agent-facing)

  • POST /mcp/tools/list - List available tools (filtered by permissions)
  • POST /mcp/tools/call - Execute a tool

Documentation

  • GET /docs - Swagger UI
  • GET /openapi.json - OpenAPI spec

Tool Registry

See [[Bifrost-Tool-Catalog]] for complete tool documentation with examples.

Current Tools (22)

DomainTools
tasksquery_tasks, create_task, update_task, complete_task, query_projects
calendarcalendar_read, calendar_create
homehome_status, home_command
shoppingadd_shopping_item, query_inventory
navigationget_directions, get_travel_time, search_places
observabilitycontainer_status, query_logs, check_metrics, grafana_dashboard
assistantget_daily_summary
adminonboard_user
systemn8n_echo, bifrost_echo_tool

Tool Execution Flow

1. Agent calls POST /mcp/tools/call
2. Bifrost looks up tool in tool_definitions table
3. ExecutorRouter selects executor based on executor_type
4. Executor invokes target system (Norns, n8n, etc.)
5. Result returned through chain to agent

Database Schema

tool_definitions

CREATE TABLE tool_definitions (
tool_id UUID PRIMARY KEY,
org_id UUID NOT NULL,
name VARCHAR(100) NOT NULL,
description TEXT,
input_schema JSONB NOT NULL,
output_schema JSONB,
executor_type VARCHAR(50) NOT NULL, -- 'norns_delegate', 'n8n_workflow', etc.
executor_config JSONB DEFAULT '{}',
domain VARCHAR(100),
status VARCHAR(50) DEFAULT 'active',
timeout_ms INTEGER DEFAULT 30000,
n8n_connection_id UUID, -- For n8n-synced tools
n8n_workflow_id VARCHAR(255), -- n8n workflow ID
last_synced_at TIMESTAMPTZ, -- Last sync timestamp
created_at TIMESTAMPTZ DEFAULT NOW()
);

tool_executions (Audit Log)

CREATE TABLE tool_executions (
execution_id UUID PRIMARY KEY,
tool_id UUID REFERENCES tool_definitions(tool_id),
org_id UUID NOT NULL,
agent_id VARCHAR(255),
arguments JSONB,
result JSONB,
success BOOLEAN,
error_message TEXT,
execution_time_ms INTEGER,
created_at TIMESTAMPTZ DEFAULT NOW()
);

Authentication

API Authentication

All API endpoints require:

X-API-Key: <bifrost_api_key>

Admin Portal SSO

The admin portal uses Zitadel OIDC via NextAuth.js:

  • Client ID: BIFROST_ZITADEL_CLIENT_ID
  • Issuer: https://auth.ravenhelm.dev

Configuration

Environment Variables

# Database
BIFROST_DB_HOST=postgres
BIFROST_DB_PORT=5432
BIFROST_DB_NAME=ravenmaskos
BIFROST_DB_USER=ravenhelm
BIFROST_DB_PASSWORD=<password>

# Redis
BIFROST_REDIS_HOST=redis
BIFROST_REDIS_PORT=6379
BIFROST_REDIS_PASSWORD=<password>

# Norns Integration
BIFROST_NORNS_URL=http://docs/AI-ML-Platform/norns-agent:8000
NORNS_API_KEY=<key>

# n8n Integration
BIFROST_N8N_URL=https://n8n.ravenhelm.dev
BIFROST_N8N_API_KEY=<key>

# API Security
BIFROST_API_KEY=<key>
BIFROST_ZITADEL_ISSUER=https://auth.ravenhelm.dev

# Admin Portal
AUTH_ZITADEL_CLIENT_ID=<client_id>
AUTH_ZITADEL_CLIENT_SECRET=<secret>
AUTH_SECRET=<nextauth_secret>
NEXTAUTH_URL=https://bifrost.ravenhelm.dev
BIFROST_API_URL=http://bifrost-api:8000

Docker Compose

services:
bifrost-api:
build:
context: ./api
dockerfile: Dockerfile
container_name: bifrost-api
networks:
- ravenhelm_net
environment:
- BIFROST_DB_HOST=postgres
- BIFROST_NORNS_URL=http://docs/AI-ML-Platform/norns-agent:8000
labels:
- "traefik.http.routers.bifrost-api.rule=Host(\`bifrost-api.ravenhelm.dev\`)"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]

bifrost-admin:
build:
context: ./admin
dockerfile: Dockerfile
container_name: bifrost-admin
networks:
- ravenhelm_net
environment:
- NEXTAUTH_URL=https://bifrost.ravenhelm.dev
- BIFROST_API_URL=http://bifrost-api:8000
labels:
- "traefik.http.routers.bifrost-admin.rule=Host(\`bifrost.ravenhelm.dev\`)"
depends_on:
- bifrost-api

Common Operations

Start/Restart

cd ~/ravenhelm/services/bifrost
docker-compose up -d

# View logs
docker-compose logs -f bifrost-api

Test Tool Execution

curl -X POST https://bifrost-api.ravenhelm.dev/mcp/tools/call \
-H "Content-Type: application/json" \
-H "X-API-Key: $BIFROST_API_KEY" \
-d '{
"organization_id": "00000000-0000-0000-0000-000000000001",
"tool_name": "get_daily_summary",
"arguments": {}
}'

List Tools

curl https://bifrost-api.ravenhelm.dev/api/v1/tools \
-H "X-API-Key: $BIFROST_API_KEY"

Sync n8n Tools

# Discover available workflows
curl https://bifrost-api.ravenhelm.dev/api/v1/n8n/discover \
-H "X-API-Key: $BIFROST_API_KEY"

# Sync to registry
curl -X POST https://bifrost-api.ravenhelm.dev/api/v1/n8n/sync \
-H "X-API-Key: $BIFROST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_name": "default"}'

Troubleshooting

Tool Execution Fails

  1. Check Bifrost logs:

    docker logs bifrost-api --tail=100
  2. Verify executor target is healthy:

    • Norns: curl http://docs/AI-ML-Platform/norns-agent:8000/health
    • n8n: curl https://n8n.ravenhelm.dev/healthz
  3. Check tool_executions table for error details:

    SELECT * FROM tool_executions
    WHERE success = false
    ORDER BY created_at DESC LIMIT 10;

n8n Tool Not Discovered

  1. Verify workflow is active in n8n
  2. Check workflow has [MCP] prefix OR tool:enabled tag
  3. Verify webhook node exists with valid path
  4. Check n8n API key is configured in Bifrost

Admin Portal Auth Issues

  1. Verify Zitadel configuration
  2. Check NextAuth logs: docker logs bifrost-admin
  3. Confirm callback URL is registered in Zitadel

Connection Errors

  1. Verify containers are on same network:

    docker network inspect ravenhelm_net
  2. Test internal DNS resolution:

    docker exec bifrost-api nslookup norns-agent

Roadmap

  • N8nWorkflowExecutor - Execute n8n workflows as tools
  • n8n Auto-Discovery - Automatically sync workflows as tools
  • OpenAPI Executor - Import external APIs as tools
  • MCP Proxy Executor - Forward to external MCP servers
  • Native Executor - In-process Python functions
  • Tool permissions - Fine-grained access control
  • Rate limiting - Per-tool and per-agent limits
  • Caching - Result caching for idempotent tools
  • Auto-sync scheduling - Periodic discovery without manual trigger

See Also

  • [[Norns-Agent]] - Primary AI agent
  • [[../DevOps/MCP-Servers]] - MCP server integration
  • [[../Automation/n8n]] - Workflow automation with Bifrost integration