Omi MCP Integration: How Model Context Protocol Powers AI Memory Access

Omi implements MCP as a Python-based tool server that exposes the Memories and Conversations APIs as standardized, discoverable tools, enabling any LLM to read and write personal knowledge through automatic transport negotiation between Streamable-HTTP and SSE.

The basedhardware/omi repository provides a complete Model Context Protocol (MCP) integration that bridges large language models with personal data storage. This architecture transforms Omi's REST endpoints into callable functions that LLMs can discover and invoke autonomously, using either direct stdio communication or HTTP-based JSON-RPC routing.

Architecture Overview

The integration consists of three coordinated components that handle server operations, client discovery, and transport bridging.

The MCP Server Component

At the core, mcp/src/mcp_server_omi/server.py implements the MCP server logic. The server.py file creates a Server("mcp-omi") instance and registers available tools through the @server.list_tools() decorator. It defines the OmiTools enum (including GET_MEMORIES, CREATE_MEMORY, DELETE_MEMORY, and conversation tools) and maps each tool name to specific HTTP helper functions like get_memories() and create_memory().

Client Discovery Layer

The backend/utils/mcp_client.py module provides the discovery client that negotiates connections. The discover_mcp_tools() function attempts a Streamable-HTTP POST request first, sending JSON-RPC messages (initialize, notifications/initialized, tools/list), and automatically falls back to SSE (Server-Sent Events) via _discover_tools_via_sse() if the primary transport fails.

HTTP-to-SSE Bridge

For environments that cannot spawn stdio processes, backend/routers/mcp_sse.py exposes a JSON-RPC endpoint at /v1/mcp/sse. This router parses incoming tools/list and tools/call requests and forwards them to the same internal implementation used by the stdio server, effectively bridging HTTP traffic to the MCP protocol.

How the MCP Server Works

Understanding the flow requires examining how the server starts, exposes capabilities, and handles execution.

Server Startup and Tool Registration

The server launches via Docker as a standalone process:

docker run --rm -i -e OMI_API_KEY=your_api_key omiai/mcp-server

This executes mcp_server_omi/__main__.py, which calls main()serve() in server.py. During initialization, the server registers tools with complete JSON schemas generated from Pydantic models (e.g., GetMemories, CreateMemory) using model_json_schema(). These schemas define parameters like api_key, categories, limit, and offset that LLMs use to construct valid requests.

Tool Discovery Flow

When an LLM client connects, the discover_mcp_tools() helper manages transport negotiation:

  1. Streamable-HTTP attempt: Sends a POST with three JSON-RPC messages to establish the session and retrieve the tool list via _mcp_post().
  2. SSE fallback: If HTTP fails, opens an event stream using _discover_tools_via_sse() to fetch the same tools/list response.
  3. Object construction: Converts raw tool definitions into ChatTool objects containing endpoint URLs, HTTP methods, and transport flags.

The discovery process returns ready-to-call tool definitions that conform to the MCP specification, allowing frameworks like LangChain or Claude Desktop to consume them immediately.

Tool Execution Flow

When an LLM invokes a tool, the server receives a JSON-RPC tools/call request handled by the call_tool() coroutine. The handler:

  1. Parses arguments and resolves the API key (defaulting to the OMI_API_KEY environment variable).
  2. Maps the tool name to the corresponding helper function (e.g., OmiTools.GET_MEMORIESget_memories()).
  3. Forwards the request to Omi's REST API endpoints (/v1/mcp/memories, /v1/mcp/conversations).
  4. Returns results wrapped in TextContent objects containing plain-text JSON.

# Example handler logic from server.py

elif name == OmiTools.GET_MEMORIES:
    result = get_memories(
        logger,
        api_key,
        offset=arguments.get("offset", 0),
        limit=arguments.get("limit", 100),
        categories=categories_enum,
    )
    return [TextContent(type="text", text=json.dumps(result, indent=2))]

Connecting LLMs to Omi

You can integrate the Omi MCP server with LangChain agents using the standard MCP client pattern:

from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import initialize_agent, Tool

# Configure the Omi MCP server

client = MultiServerMCPClient(
    servers=[{
        "name": "omi",
        "command": "docker",
        "args": ["run", "--rm", "-i", "-e", "OMI_API_KEY=YOUR_KEY", "omiai/mcp-server"]
    }]
)

# Discover and convert tools

mcp_tools = await client.discover_tools()
langchain_tools = [
    Tool(
        name=t.name,
        description=t.description,
        func=lambda **kw: client.call_tool("omi", t.name, kw)
    )
    for t in mcp_tools
]

# Initialize agent with memory access

agent = initialize_agent(
    tools=langchain_tools,
    llm=ChatOpenAI(),
    agent="zero-shot-react-description",
    verbose=True,
)

This pattern leverages the automatic discovery mechanism in backend/utils/mcp_client.py, ensuring the agent receives the correct tool schemas regardless of whether the server operates over stdio, HTTP, or SSE transport.

Summary

  • Omi exposes personal memories and conversations via the omiai/mcp-server Docker container, implementing the full Model Context Protocol specification.
  • Three-file architecture powers the integration: mcp/src/mcp_server_omi/server.py (tool logic), backend/utils/mcp_client.py (discovery), and backend/routers/mcp_sse.py (HTTP bridge).
  • Automatic transport negotiation attempts Streamable-HTTP first, falling back to SSE for maximum compatibility with different LLM clients.
  • Standardized returns use TextContent objects containing JSON, ensuring consistent parsing across Python, TypeScript, and other language implementations.
  • Framework agnostic design supports LangChain, Claude Desktop, and any MCP-compatible agent without custom API code.

Frequently Asked Questions

What transports does Omi's MCP integration support?

The implementation supports Streamable-HTTP (preferred), Server-Sent Events (SSE), and stdio (via Docker). The client automatically negotiates the best available transport when calling discover_mcp_tools(), attempting HTTP POST first and falling back to SSE if the connection fails.

Where are the MCP tool definitions located in the codebase?

Tool definitions reside in mcp/src/mcp_server_omi/server.py within the OmiTools enum. Each tool maps to a specific function—get_memories(), create_memory(), delete_memory(), get_conversations(), and get_conversation_by_id()—which forward requests to Omi's REST endpoints at /v1/mcp/memories and /v1/mcp/conversations.

How does authentication work for MCP requests?

The server accepts an OMI_API_KEY environment variable during startup (docker run -e OMI_API_KEY=...). Individual tool calls can also override this by passing an api_key argument in the request payload. The server validates this key when forwarding requests to Omi's protected REST endpoints.

Can I use the Omi MCP server without Docker?

While the Docker image (omiai/mcp-server) provides the easiest deployment, you can run the server directly by installing the Python package and executing python -m mcp_server_omi, provided you set the OMI_API_KEY environment variable. For HTTP-only access without managing a process, use the /v1/mcp/sse endpoint defined in backend/routers/mcp_sse.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →