# Implementing Custom MCP Integrations in Open Notebook: A Complete Guide

> Learn how to implement custom MCP integrations in Open Notebook. This guide shows you how to leverage the MCP server to interact with your notebook data model efficiently.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-06-30

---

**Open Notebook provides a built-in Model Context Protocol (MCP) server that exposes the full notebook data model over JSON-RPC, enabling any MCP-compatible client to read, search, and write notebooks without direct REST API calls.**

Open Notebook ships with a native Model Context Protocol (MCP) integration that bridges AI assistants and external tools with your research data. By implementing custom MCP integrations, developers can programmatically interact with notebooks, sources, and chat sessions through a standardized interface that proxies directly to the core FastAPI backend.

## How MCP Fits into the Open Notebook Architecture

The MCP integration operates as a thin translation layer between external AI clients and Open Notebook's domain logic. Unlike direct REST API calls, the MCP server speaks JSON-RPC and forwards requests to the same internal services that power the web UI.

| Layer | Component | Role |
|------|-----------|------|
| **Frontend / AI client** | MCP-compatible UI (Claude Desktop, VS Code) | Sends MCP commands to the server and receives JSON responses |
| **MCP server** | `open-notebook-mcp` (published on PyPI) | Forwards MCP calls to Open Notebook's internal services (`api/*` routers) and returns results |
| **API backend** | FastAPI (`api/routers/*.py`) | Core REST endpoints implementing notebook, source, note, chat, and search logic |
| **Domain model** | `open_notebook/domain/*.py` | Pydantic-based objects (`Notebook`, `Source`, `Note`, `ChatSession`) encapsulating business logic and SurrealQL queries |
| **Database** | SurrealDB | Stores notebooks, sources, embeddings, and relations |

The MCP server runs as a separate process (typically invoked via `uvx`) that communicates with the FastAPI instance defined in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py). This architecture ensures that all business rules, permission checks, and data validation remain consistent between the web interface and programmatic MCP access.

## Configuration Steps for Custom MCP Integrations

Setting up a custom MCP integration requiresthree configuration steps that connect your client to the running Open Notebook instance.

1. **Install the MCP server** – No manual installation is required; MCP-compatible clients like Claude Desktop automatically invoke the server using `uvx open-notebook-mcp`.

2. **Add the server definition to your client's configuration** – Use the following JSON format for Claude Desktop (macOS/Linux) or VS Code's [`mcp.json`](https://github.com/lfnovo/open-notebook/blob/main/mcp.json):

```json
{
  "mcpServers": {
    "open-notebook": {
      "command": "uvx",
      "args": ["open-notebook-mcp"],
      "env": {
        "OPEN_NOTEBOOK_URL": "http://localhost:5055",
        "OPEN_NOTEBOOK_PASSWORD": "your_password_here"
      }
    }
  }
}

```

The `OPEN_NOTEBOOK_URL` environment variable points to your running Open Notebook API ([`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py)), while `OPEN_NOTEBOOK_PASSWORD` is optional and only required if you have enabled password protection in the web UI.

3. **Restart the client** – Once restarted, the MCP server connects to the specified URL and exposes methods like `list_notebooks`, `search`, and `create_note`.

## Core MCP Capabilities and Method Mapping

All MCP methods ultimately invoke the same domain functions found in [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py) and [`open_notebook/domain/source.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/source.py), ensuring single-source-of-truth behavior across interfaces.

| MCP method | Description | Underlying code |
|------------|-------------|-----------------|
| `list_notebooks` | Returns all notebooks with `source_count` and `note_count` metadata | [`api/routers/notebooks.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebooks.py) → `get_notebooks` |
| `get_notebook` | Fetches a single notebook with full metadata | [`api/routers/notebooks.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebooks.py) → `get_notebook` |
| `add_source_to_notebook` | Creates a reference between a source and a notebook | [`api/routers/notebooks.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebooks.py) → `add_source_to_notebook` |
| `search` | Executes vector or text search across sources and notes | [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py) → `vector_search` / `text_search` |
| `create_note` | Adds a note and triggers async embedding | [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py) → `Note.save` |
| `create_chat` | Starts a new chat session linked to a notebook | [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py) → `ChatSession` methods |
| `list_models` | Lists configured AI providers | [`api/routers/models.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/models.py) |

## Security and Authentication

When implementing custom MCP integrations, authentication follows the same middleware pipeline as the REST API. If password protection is enabled in [`api/routers/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/auth.py), you must include `OPEN_NOTEBOOK_PASSWORD` in your MCP client configuration.

The MCP server forwards this password via HTTP headers to the FastAPI layer, which validates credentials using identical logic to the web UI authentication flow. This ensures that programmatic access respects the same permission boundaries as manual user interactions.

## Practical Implementation Examples

The following Python examples demonstrate how to call the Open Notebook MCP server directly from custom scripts, bypassing the need for specific MCP client applications.

### Listing Notebooks via MCP

```python
import json
import urllib.request

MCP_URL = "http://127.0.0.1:5000"  # Default MCP server port

def mcp_call(method: str, params: dict):
    payload = json.dumps({
        "jsonrpc": "2.0",
        "id": 1,
        "method": method,
        "params": params,
    }).encode()
    req = urllib.request.Request(
        MCP_URL, 
        data=payload, 
        headers={"Content-Type": "application/json"}
    )
    with urllib.request.urlopen(req) as resp:
        return json.load(resp)

# Retrieve all notebooks with metadata

response = mcp_call("list_notebooks", {})
print(response["result"])  # List of notebook dictionaries

```

### Adding Sources to Notebooks

```python

# Link an existing source to a specific notebook

params = {
    "notebook_id": "notebook:123",
    "source_id": "source:abc"
}
result = mcp_call("add_source_to_notebook", params)
print(result["result"]["message"])

```

This method corresponds to the `add_source_to_notebook` function in [`api/routers/notebooks.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebooks.py), which validates the relationship before persisting it to SurrealDB.

### Searching the Knowledge Base

```python
search_params = {
    "keyword": "machine learning",
    "results": 5,
    "source": True,
    "note": True
}
search_result = mcp_call("search", search_params)

for hit in search_result["result"]:
    print(f"{hit['type']}: {hit['title']} (score: {hit['score']})")

```

The search method delegates to `vector_search` and `text_search` in [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py), utilizing the vector embeddings stored in [`open_notebook/database/repository.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/repository.py).

### Creating Notes Programmatically

```python
note_params = {
    "notebook_id": "notebook:123",
    "title": "Summary of recent paper",
    "content": "The paper demonstrates that..."
}
note_resp = mcp_call("create_note", note_params)
print("Note created with ID:", note_resp["result"]["id"])

```

When creating notes via MCP, the `Note.save` method in [`open_notebook/domain/note.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/note.py) automatically triggers an embedding job to ensure the new content is searchable.

## Summary

- **Open Notebook exposes its full data model** through a dedicated MCP server (`open-notebook-mcp`) that translates JSON-RPC calls into FastAPI requests.
- **Configuration requires environment variables** (`OPEN_NOTEBOOK_URL` and optionally `OPEN_NOTEBOOK_PASSWORD`) to connect the MCP client to your running instance.
- **All MCP methods map to domain logic** in [`open_notebook/domain/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/domain/notebook.py) and [`api/routers/notebooks.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebooks.py), ensuring consistent behavior across interfaces.
- **Security is handled transparently** by forwarding authentication headers from the MCP server to the FastAPI middleware defined in [`api/routers/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/auth.py).
- **Custom integrations can leverage standard JSON-RPC** over HTTP to programmatically manage notebooks, sources, and search indices.

## Frequently Asked Questions

### What is the Model Context Protocol (MCP) and why does Open Notebook use it?

The Model Context Protocol is a standardized JSON-RPC interface designed for AI assistants and external tools to interact with data sources. Open Notebook implements MCP to allow clients like Claude Desktop, VS Code extensions, and custom scripts to access notebook data without requiring custom REST API wrappers, while maintaining the same security and business logic as the web interface.

### How do I authenticate my custom MCP client with Open Notebook?

If you have enabled password protection in your Open Notebook instance, include the `OPEN_NOTEBOOK_PASSWORD` environment variable in your MCP client configuration. The MCP server forwards this credential to the FastAPI backend defined in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py), which validates it against the same authentication middleware used by the web UI. If password protection is disabled, only `OPEN_NOTEBOOK_URL` is required.

### Can I use custom MCP integrations without installing the Open Notebook frontend?

Yes. The MCP server communicates directly with the FastAPI backend ([`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py)) and does not require the Streamlit frontend to be running. As long as the Open Notebook API server is accessible and the database connection is configured, MCP clients can perform all CRUD operations on notebooks, sources, and notes through the JSON-RPC interface.

### What is the difference between the MCP server and the REST API in Open Notebook?

The REST API (`api/routers/*.py`) provides HTTP endpoints typically consumed by the web UI, while the MCP server (`open-notebook-mcp`) is a separate PyPI package that translates JSON-RPC calls into internal service invocations. Both ultimately execute the same domain logic in `open_notebook/domain/*.py`, but the MCP server offers a standardized protocol specifically designed for AI tool integration, whereas the REST API follows standard OpenAPI patterns for web application consumption.