Skip to content

MCP Configuration ​

This guide covers advanced configuration of Sibyl's MCP (Model Context Protocol) server. Connecting a machine does not need any of it: sibyl setup signs the CLI in and installs the skill agents use. Configure MCP for clients that only speak MCP.

Server Architecture ​

Sibyl's MCP server uses the Python SDK's MCPServer and mounts its streamable HTTP app in the main Starlette application:

mermaid
flowchart LR
    APP{{"Sibyl Combined App<br/>Starlette · port 3334"}}
    API["FastAPI REST endpoints"]
    MCP["MCP streamable-http endpoint"]
    WS["WebSocket · real-time updates"]
    BG["Background queue + session management"]
    APP -->|"/api/*"| API
    APP -->|"/mcp"| MCP
    APP -->|"/api/ws"| WS
    APP -->|"Lifespan"| BG

Transport Modes ​

HTTP Mode (Default) ​

Sibyl runs as an HTTP server, accepting MCP requests at /mcp:

bash
uv run sibyld serve
# Server listening on http://localhost:3334
# MCP endpoint: http://localhost:3334/mcp

Configuration:

json
{
  "mcpServers": {
    "sibyl": {
      "type": "http",
      "url": "http://localhost:3334/mcp"
    }
  }
}

Stdio Mode ​

Run Sibyl as a subprocess communicating via stdin/stdout:

bash
uv run sibyld serve -t stdio

Configuration:

json
{
  "mcpServers": {
    "sibyl": {
      "command": "uv",
      "args": ["--directory", "/path/to/sibyl/apps/api", "run", "sibyld", "serve", "-t", "stdio"],
      "env": {
        "SIBYL_OPENAI_API_KEY": "sk-...",
        "SIBYL_JWT_SECRET": "your-secret",
        "SIBYL_SURREAL_URL": "ws://127.0.0.1:8000/rpc"
      }
    }
  }
}

Authentication Modes ​

Auto Mode (Default) ​

Authentication is enabled when SIBYL_JWT_SECRET is set:

bash
SIBYL_MCP_AUTH_MODE=auto  # Default
SIBYL_JWT_SECRET=your-secret  # If set, auth is enabled

Forced On ​

Always require authentication:

bash
SIBYL_MCP_AUTH_MODE=on

Forced Off (Development Only) ​

Disable authentication:

bash
SIBYL_MCP_AUTH_MODE=off

Production Warning Never disable authentication in production. Use auto or on mode.

OAuth Flow ​

When auth is enabled, Sibyl implements OAuth 2.0:

OAuth Endpoints ​

EndpointPurpose
/_oauth/loginLogin form
/_oauth/orgOrganization selection
/mcpToken-authenticated MCP endpoint

Token Acquisition ​

  1. User visits /_oauth/login
  2. Enters credentials
  3. Selects organization
  4. Receives access token
  5. Token used for MCP requests

API Key Authentication ​

For programmatic access, use API keys:

bash
# Create API key
sibyl auth api-key create --name "MCP Client" --scopes mcp

# Use in configuration
{
  "mcpServers": {
    "sibyl": {
      "type": "http",
      "url": "http://localhost:3334/mcp",
      "headers": {
        "Authorization": "Bearer sk_xxx..."
      }
    }
  }
}

Environment Variables ​

Core Settings ​

VariableDefaultDescription
SIBYL_SERVER_HOSTlocalhostHost to bind to
SIBYL_SERVER_PORT3334Port to listen on
SIBYL_PUBLIC_URLhttp://localhost:3337Public base URL for OAuth callbacks/redirects
SIBYL_SERVER_URL-Public API and MCP origin behind a proxy
SIBYL_SERVER_NAMEsibylServer name in MCP responses

Authentication Settings ​

VariableDefaultDescription
SIBYL_JWT_SECRET-JWT signing secret (required for auth)
SIBYL_ACCESS_TOKEN_EXPIRE_MINUTES60Access token TTL in minutes
SIBYL_MCP_AUTH_MODEautoAuth mode: auto, on, off

Sibyl validates MCP Host and Origin headers to prevent DNS rebinding. Set SIBYL_SERVER_URL to the public API origin when a loopback-bound daemon sits behind a Host-preserving proxy (for example, https://sibyl.example.com). The configured frontend origin, server origin, bind address, and loopback origins remain allowed.

GitHub OAuth (Optional) ​

VariableDescription
SIBYL_GITHUB_CLIENT_IDGitHub OAuth app client ID
SIBYL_GITHUB_CLIENT_SECRETGitHub OAuth app secret

Database Settings ​

VariableDefaultDescription
SIBYL_SURREAL_URL-SurrealDB connection URL (ws:// / http://)
SIBYL_REDIS_HOST127.0.0.1Optional Redis/Valkey host

moon run dev provisions a local SurrealDB automatically. The memory:// URL is a test-only mode and is rejected by the production config validator.

Embedding Settings ​

VariableDefaultDescription
SIBYL_OPENAI_API_KEY-OpenAI API key (default provider)
SIBYL_EMBEDDING_MODELtext-embedding-3-smallEmbedding model

Gemini and Amazon Bedrock (Cohere Embed v4, no API key) also serve embeddings; see Embeddings.

Server Implementation ​

Tool Registration ​

The MCP server is constructed in server.py and registers 13 tools: search, context, synthesis_plan, synthesis_draft, synthesis_verify, explore, expand_neighbors, fetch_slice, add, remember, reflect, manage, and logs. See Agents & MCP for what each one does.

python
mcp = MCPServer(
    settings.server_name,
    auth=auth_settings,
    auth_server_provider=auth_server_provider,
)

mcp_app = mcp_http_app(mcp, host, port)  # stateless, POST-only /mcp

@mcp.tool()
async def search(...) -> dict:
    """Semantic search across knowledge graph."""
    org_id = await _require_org_id()
    return await _search(..., organization_id=org_id)

Organization Context ​

Every tool extracts organization from the authenticated context:

python
async def _require_org_id() -> str:
    """Require organization ID from MCP context."""
    org_id = await _get_org_id_from_context()
    if not org_id:
        raise ValueError("Organization context required")
    return org_id

Resource Registration ​

MCP resources provide read-only data:

python
@mcp.resource("sibyl://health")
async def health_resource() -> str:
    """Server health status."""
    health = await get_health()
    return json.dumps(health)

@mcp.resource("sibyl://stats")
async def stats_resource() -> str:
    """Graph statistics."""
    stats = await get_stats()
    return json.dumps(stats)

API Scopes ​

API keys can have different scopes:

ScopePermission
mcpAccess MCP endpoint
api:readREST GET/HEAD/OPTIONS
api:writeREST writes (implies read)

Create scoped keys:

bash
# MCP only
sibyl auth api-key create --name "MCP" --scopes mcp

# MCP + read API
sibyl auth api-key create --name "CI/CD" --scopes mcp,api:read

# Full access
sibyl auth api-key create --name "Admin" --scopes mcp,api:write

Load Balancing ​

Sibyl serves MCP statelessly. Each request carries its own bearer credential and protocol version, the server mints no Mcp-Session-Id, and any instance can answer any request. Put instances behind a plain round-robin load balancer with no session affinity:

nginx
upstream sibyl {
    server sibyl1:3334;
    server sibyl2:3334;
}

Clients on the 2026-07-28 protocol send self-contained requests. Clients on the earlier initialize handshake still connect and run without a session id.

For several instances:

  1. Use Redis/Valkey for shared coordination
  2. Point every instance at the same SurrealDB service

Monitoring ​

Health Check ​

bash
curl http://localhost:3334/api/health

MCP Status ​

Access via MCP resource:

sibyl://health
sibyl://stats

Metrics Endpoint ​

bash
curl http://localhost:3334/api/metrics

Troubleshooting ​

Connection Refused ​

  1. Check server is running
  2. Verify port isn't blocked
  3. Check firewall settings

Authentication Failed ​

  1. Verify SIBYL_JWT_SECRET is set
  2. Check API key is valid
  3. Ensure token hasn't expired

Organization Not Found ​

  1. Check user belongs to organization
  2. Verify org_id in token claims
  3. Check organization exists

Slow Responses ​

  1. Check SurrealDB connection and query latency
  2. Verify embedding API connectivity
  3. Review query complexity

Example Configurations ​

Local Development ​

json
{
  "mcpServers": {
    "sibyl": {
      "type": "http",
      "url": "http://localhost:3334/mcp"
    }
  }
}

Production with Auth ​

json
{
  "mcpServers": {
    "sibyl": {
      "type": "http",
      "url": "https://sibyl.example.com/mcp",
      "headers": {
        "Authorization": "Bearer sk_..."
      }
    }
  }
}

Subprocess Mode ​

json
{
  "mcpServers": {
    "sibyl": {
      "command": "uv",
      "args": ["--directory", "/opt/sibyl/apps/api", "run", "sibyld", "serve", "-t", "stdio"],
      "env": {
        "SIBYL_OPENAI_API_KEY": "sk-...",
        "SIBYL_JWT_SECRET": "...",
        "SIBYL_SURREAL_URL": "ws://surrealdb.internal:8000/rpc"
      }
    }
  }
}

Next Steps ​

Released under the Apache-2.0 License.