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

> Discover how Omi MCP integration leverages the Model Context Protocol to provide AI memory access. Enable LLMs to read and write personal knowledge via Streamable-HTTP and SSE.

- Repository: [omi/omi](https://github.com/basedhardware/omi)
- Tags: how-to-guide
- Published: 2026-02-26

---

**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`](https://github.com/basedhardware/omi/blob/main/mcp/src/mcp_server_omi/server.py) implements the **MCP server** logic. The [`server.py`](https://github.com/basedhardware/omi/blob/main/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`](https://github.com/basedhardware/omi/blob/main/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`](https://github.com/basedhardware/omi/blob/main/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:

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

```

This executes [`mcp_server_omi/__main__.py`](https://github.com/basedhardware/omi/blob/main/mcp_server_omi/__main__.py), which calls `main()` → `serve()` in [`server.py`](https://github.com/basedhardware/omi/blob/main/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_MEMORIES` → `get_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.

```python

# 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:

```python
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`](https://github.com/basedhardware/omi/blob/main/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`](https://github.com/basedhardware/omi/blob/main/mcp/src/mcp_server_omi/server.py) (tool logic), [`backend/utils/mcp_client.py`](https://github.com/basedhardware/omi/blob/main/backend/utils/mcp_client.py) (discovery), and [`backend/routers/mcp_sse.py`](https://github.com/basedhardware/omi/blob/main/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`](https://github.com/basedhardware/omi/blob/main/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`](https://github.com/basedhardware/omi/blob/main/backend/routers/mcp_sse.py).