WikifitaGitHub live67e8de5
outro · co-fita/co-fita-mcp-servers

MCP Server Ecosystem — Odysseus Dashboard

The four built-in Model Context Protocol servers in the Odysseus dashboard: email, memory, RAG, and image generation, with their tool schemas, transport model, and integration patterns.

Baixar raw

MCP Server Ecosystem

The Odysseus dashboard ships with four built-in MCP (Model Context Protocol) servers that expose domain-specific tools to the LLM agent loop. Each server runs as a separate stdio process, communicating with the host via the MCP protocol. Admin-configurable MCP servers can also be registered through the database and UI, extending the tool palette dynamically. This page documents the built-in servers, their tool schemas, and the integration pattern that connects them to the co-fita-odysseus harness.

What Is MCP?

The Model Context Protocol is a standardized interface for exposing tools, resources, and prompts to LLM agents. Each MCP server:

  1. Declares a set of tools with JSON Schema input specifications
  2. Receives call_tool requests from the agent loop
  3. Returns structured TextContent responses
  4. Runs as an isolated process (stdio transport) or HTTP endpoint (SSE transport)

The dashboard uses the mcp Python library for server implementation and manages server lifecycle through src/mcp_manager.py.

Architecture Pattern

graph LR
    subgraph AgentLoop["Agent Loop"]
        AL["agent_loop.py"]
        TI["tool_implementations.py"]
    end

    subgraph Host["Host Process (FastAPI)"]
        MCPMgr["mcp_manager.py<br>(server lifecycle)"]
        MCPRoutes["routes/mcp_routes.py<br>(admin CRUD)"]
        DB[("mcp_servers table<br>(SQLAlchemy)")]
    end

    subgraph BuiltIn["Built-in MCP Servers (stdio)"]
        EMail["email_server.py"]
        Mem["memory_server.py"]
        RAG["rag_server.py"]
        IMG["image_gen_server.py"]
    end

    subgraph External["External MCP Servers (admin-configured)"]
        Ext1["stdio: custom_command"]
        Ext2["sse: http://remote:port"]
    end

    AL --> TI
    TI --> MCPMgr
    MCPMgr --> EMail
    MCPMgr --> Mem
    MCPMgr --> RAG
    MCPMgr --> IMG
    MCPMgr --> Ext1
    MCPMgr --> Ext2
    MCPRoutes --> DB
    MCPMgr --> DB

Integration Flow

  1. Startup: mcp_manager.py reads enabled servers from the mcp_servers database table
  2. Process launch: For stdio servers, a child process is spawned with the configured command and args. For SSE servers, an HTTP connection is established.
  3. Tool discovery: The agent loop calls list_tools() on each server to learn available tools
  4. Tool dispatch: When the LLM requests a tool call, tool_implementations.py routes it to the appropriate MCP server
  5. Response: The server returns TextContent which is injected into the conversation context
  6. Shutdown: Server processes are cleaned up on application exit

Admins can configure additional MCP servers through /api/mcp routes, specifying transport type, command, arguments, environment variables, and optional OAuth credentials.

Server 1: Email (email_server.py)

The email MCP server provides tools for reading and managing email through the dashboard's IMAP integration. It connects to local Dovecot IMAP or remote IMAP servers, reads from the AI summary cache for fast access, and supports multi-account email management.

Server Identity

PropertyValue
Nameemail
Filemcp_servers/email_server.py
Lines~2,197
Transportstdio
Dependenciesimaplib, smtplib, sqlite3, email (stdlib)

Configuration

The server reads account credentials from the email_accounts database table (Fernet-encrypted passwords). Multi-account support allows multiple IMAP/SMTP configurations per user, with exactly one default per owner.

Environment variables:

VariableDefaultPurpose
EMAIL_SOCKET_TIMEOUT20IMAP connection timeout (seconds)
ODYSSEUS_MCP_OWNER--Owner scope for account filtering

Tool Schema

ToolDescriptionKey Parameters
manage_emailFull email lifecycle managementaction (list/read/draft/send/trash/archive/search/sync), account, uid, folder, query, to, subject, body

The server supports:

  • Listing unread/unresponded emails across folders
  • Reading full email content with header parsing
  • Drafting replies as email documents in the dashboard
  • Sending composed emails via SMTP
  • Searching across email content
  • Syncing IMAP folders to the local cache
  • Multi-account routing via the account parameter

Owner Scoping

Email data is strictly owner-scoped. The _account_visible_to_owner function ensures each user only sees their own configured accounts. The _odysseus_owner argument is injected by the host process to enforce this boundary.

Server 2: Memory (memory_server.py)

The memory MCP server exposes the dashboard's persistent memory system to the agent loop. It provides CRUD operations on fact storage and integrates with the vector store for semantic search.

Server Identity

PropertyValue
Namememory
Filemcp_servers/memory_server.py
Transportstdio
Dependenciesservices/memory/ (MemoryManager, MemoryVectorStore)

Architecture

The memory system has two layers:

  • MemoryManager: Flat JSON-based fact storage in data/memory.json. Each entry has text, category, source, timestamp, and owner.
  • MemoryVectorStore: ChromaDB-backed semantic search using fastembed embeddings. Enables natural-language retrieval of stored facts.

Lazy initialization ensures the memory managers are only created on first use, avoiding startup overhead when the memory MCP server is configured but not actively used.

Owner Scoping

Memory entries are strictly owner-scoped when any entry has an owner field. The _scope_entries function enforces this:

  1. Load all entries from the JSON store
  2. If any entry has an owner, only return entries matching the configured ODYSSEUS_MCP_MEMORY_OWNER
  3. If no entry has an owner (legacy single-user), return all unowned entries
  4. If the store is owner-scoped but no owner is configured, return an error

Tool Schema

ToolDescriptionKey Parameters
manage_memoryMemory CRUD + searchaction (list/add/edit/delete/search), text, category, query, id

Categories include: fact, preference, instruction, context, skill.

Server 3: RAG (rag_server.py)

The RAG (Retrieval-Augmented Generation) MCP server manages indexed document directories. It provides tools for listing, adding, and removing document directories from the vector index, enabling the agent to search over personal documents.

Server Identity

PropertyValue
Namerag
Filemcp_servers/rag_server.py
Transportstdio
Dependenciessrc/rag_singleton.py (RAGManager), src/personal_docs.py (PersonalDocsManager)

Integration

The RAG server bridges two internal managers:

  • RAGManager (src/rag_singleton.py): Singleton that owns the ChromaDB collection and embedding pipeline. Handles document chunking, embedding, and semantic search.
  • PersonalDocsManager (src/personal_docs.py): Manages the data/personal/ directory as a document workspace. Tracks which directories are indexed and provides file listing.

Tool Schema

ToolDescriptionKey Parameters
manage_ragRAG document managementaction (list/add_directory/remove_directory), directory

Actions:

  • list: Returns all currently indexed files
  • add_directory: Indexes a new directory recursively
  • remove_directory: Removes a directory from the index

Server 4: Image Generation (image_gen_server.py)

The image generation MCP server provides text-to-image generation through OpenAI-compatible APIs. It auto-detects available image models and manages the generation workflow.

Server Identity

PropertyValue
Nameimage_gen
Filemcp_servers/image_gen_server.py
Transportstdio
Dependencieshttpx, src/settings.py, src/ai_interaction.py

Model Auto-Detection

The server probes for image-capable models in priority order:

  1. gpt-image-1.5 (preferred)
  2. gpt-image-1
  3. dall-e-3

If no model is explicitly configured, it uses _resolve_model from ai_interaction.py to find the first available image model from registered endpoints.

Tool Schema

ToolDescriptionKey Parameters
generate_imageGenerate an image from textprompt (required), model, size, quality

Parameters:

  • prompt: Text description of the image to generate
  • model: Specific model name (auto-detected if omitted)
  • size: Output dimensions (default: 1024x1024)
  • quality: low, medium, high, or auto (default: medium)

Generated images are saved to the GENERATED_IMAGES_DIR and tracked in the gallery_images database table.

Admin-Configurable MCP Servers

Beyond the four built-in servers, admins can register external MCP servers through the UI or API. These are stored in the mcp_servers database table:

ColumnTypePurpose
nameStringDisplay name
transportString"stdio" or "sse"
commandStringExecutable path (stdio)
argsJSON textCommand arguments array
envJSON textEnvironment variables object
urlStringServer URL (SSE)
is_enabledBooleanActive/inactive toggle
oauth_configJSON textProvider, keys file, token file, scopes
disabled_toolsJSON textTool names hidden from LLM
oauth_tokensEncryptedTextOAuth tokens (Fernet-encrypted at rest)

Transport Modes

stdio (default): The dashboard spawns a child process and communicates via stdin/stdout. Suitable for local tools, scripts, and CLI wrappers.

SSE (Server-Sent Events): The dashboard connects to a remote HTTP endpoint. Suitable for shared services, cloud-hosted tools, and multi-user deployments.

Per-Tool Visibility

Admins can hide specific tools from the LLM by adding them to the disabled_tools JSON array. This prevents the agent from invoking tools that are inappropriate for its current context while keeping the server running for other consumers.

OAuth Support

MCP servers that require OAuth authentication (e.g. Google, GitHub) can be configured with:

  • oauth_config: JSON object specifying the provider, client ID/secret file paths, token file path, and required scopes
  • oauth_tokens: Encrypted storage of access and refresh tokens, managed by the dashboard's OAuth flow

Route API

The routes/mcp_routes.py module exposes administrative endpoints for managing MCP servers:

EndpointMethodPurpose
/api/mcp/serversGETList all configured MCP servers
/api/mcp/serversPOSTCreate a new MCP server configuration
/api/mcp/servers/{id}GETGet server details + discovered tools
/api/mcp/servers/{id}PUTUpdate server configuration
/api/mcp/servers/{id}DELETERemove server configuration
/api/mcp/servers/{id}/toolsGETList tools discovered from this server
/api/mcp/servers/{id}/togglePOSTEnable/disable server

Relationship to the Tool System

The MCP servers feed into the broader tool architecture:

ComponentFileRole
Tool schemassrc/tool_schemas.pyJSON Schema definitions for all tools
Tool indexsrc/tool_index.pyRAG-based tool retrieval from ChromaDB
Tool implementationssrc/tool_implementations.py33 do_* functions including MCP dispatch
Tool securitysrc/tool_security.pyOwner-scoped tool blocking
Tool policysrc/tool_policy.pyGuide-only directives, plan-mode restrictions

MCP tools are discovered at startup and merged into the global tool registry. The agent loop's prompt assembly includes MCP tool schemas alongside built-in tools, so the LLM sees a unified tool palette.

Cross-References

Design Decisions

stdio over SSE for built-in servers: All four built-in servers use stdio transport. This keeps them process-isolated (a crash in the email server does not bring down the dashboard), simplifies deployment (no port management), and aligns with the single-host design philosophy. SSE is reserved for external/admin-configured servers that may run on separate machines.

Lazy initialization: Memory, RAG, and image servers defer their heavy dependencies (ChromaDB, fastembed, model resolution) until the first tool call. This avoids startup latency when these servers are configured but not immediately used.

Owner scoping everywhere: Every MCP server that handles user data (email, memory) enforces owner-based access control. The host process injects _odysseus_owner to prevent cross-user data leakage, even if the LLM attempts to specify a different owner in tool arguments.

Encrypted at rest: OAuth tokens, email passwords, and API keys are stored Fernet-encrypted in SQLite. The encryption key lives at data/.app_key (mode 0o600, gitignored). This protects against stolen database backups while accepting that a live process with key access can read everything.