Skip to main content
Glama

SurrealDB MCP Server

A Model Context Protocol (MCP) server that enables AI assistants to interact with SurrealDB databases

Test Python Version FastMCP SurrealDB

=� Overview

The SurrealDB MCP Server bridges the gap between AI assistants and SurrealDB, providing a standardized interface for database operations through the Model Context Protocol. This enables LLMs to:

  • Execute complex SurrealQL queries

  • Perform CRUD operations on records

  • Manage graph relationships

  • Handle bulk operations efficiently

  • Work with SurrealDB's unique features like record IDs and graph edges

Related MCP server: Snowflake Cube Server

Features

  • Full SurrealQL Support: Execute any SurrealQL query directly

  • Comprehensive CRUD Operations: Create, read, update, delete with ease

  • Graph Database Operations: Create and traverse relationships between records

  • Bulk Operations: Efficient multi-record inserts

  • Smart Updates: Full updates, merges, and patches

  • Type-Safe: Proper handling of SurrealDB's RecordIDs

  • Connection Pooling: Efficient database connection management

  • Multi-Database Support: Override namespace/database per tool call

  • Detailed Documentation: Extensive docstrings for AI comprehension

=� Prerequisites

  • Python 3.10 or higher

  • SurrealDB instance (local or remote)

  • MCP-compatible client (Claude Desktop, MCP CLI, etc.)

=� Installation

Using uvx (Simplest - No Installation Required)

# Run directly from PyPI (once published) uvx surreal-mcp # Or run from GitHub uvx --from git+https://github.com/yourusername/surreal-mcp.git surreal-mcp
# Clone the repository git clone https://github.com/yourusername/surreal-mcp.git cd surreal-mcp # Install dependencies uv sync # Run the server (multiple ways) uv run surreal-mcp # or uv run python -m surreal_mcp # or uv run python main.py

Using pip

# Clone the repository git clone https://github.com/yourusername/surreal-mcp.git cd surreal-mcp # Create virtual environment python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install package pip install -e . # Run the server surreal-mcp # or python -m surreal_mcp

� Configuration

The server uses environment variables for configuration.

Required Variables (at startup)

Variable

Description

Example

SURREAL_URL

SurrealDB connection URL

ws://localhost:8000/rpc

SURREAL_USER

Database username

root

SURREAL_PASSWORD

Database password

root

Optional Variables (can be overridden per tool call)

Variable

Description

Example

SURREAL_NAMESPACE

Default SurrealDB namespace

test

SURREAL_DATABASE

Default SurrealDB database

test

Note: If SURREAL_NAMESPACE and SURREAL_DATABASE are not set as environment variables, you must provide namespace and database parameters in each tool call.

Setting Environment Variables

You can copy .env.example to .env and update with your values:

cp .env.example .env # Edit .env with your database credentials

Or set them manually:

export SURREAL_URL="ws://localhost:8000/rpc" export SURREAL_USER="root" export SURREAL_PASSWORD="root" export SURREAL_NAMESPACE="test" export SURREAL_DATABASE="test"

MCP Client Configuration

Add to your MCP client settings (e.g., Claude Desktop):

Using uvx (recommended):

{ "mcpServers": { "surrealdb": { "command": "uvx", "args": ["surreal-mcp"], "env": { "SURREAL_URL": "ws://localhost:8000/rpc", "SURREAL_USER": "root", "SURREAL_PASSWORD": "root", "SURREAL_NAMESPACE": "test", "SURREAL_DATABASE": "test" } } } }

Using local installation:

{ "mcpServers": { "surrealdb": { "command": "uv", "args": ["run", "surreal-mcp"], "env": { "SURREAL_URL": "ws://localhost:8000/rpc", "SURREAL_USER": "root", "SURREAL_PASSWORD": "root", "SURREAL_NAMESPACE": "test", "SURREAL_DATABASE": "test" } } } }

=' Available Tools

All tools support optional namespace and database parameters to override the default values from environment variables.

1. query

Execute raw SurrealQL queries for complex operations.

-- Example: Complex query with graph traversal SELECT *, ->purchased->product FROM user WHERE age > 25
# Query with namespace/database override query("SELECT * FROM user", namespace="production", database="main")

2. select

Retrieve all records from a table or a specific record by ID.

# Get all users select("user") # Get specific user select("user", "john") # Select from a different database select("user", namespace="other_ns", database="other_db")

3. create

Create a new record with auto-generated ID.

create("user", { "name": "Alice", "email": "alice@example.com", "age": 30 })

4. update

Replace entire record content (preserves ID and timestamps).

update("user:john", { "name": "John Smith", "email": "john.smith@example.com", "age": 31 })

5. delete

Permanently remove a record from the database.

delete("user:john")

6. merge

Partially update specific fields without affecting others.

merge("user:john", { "email": "newemail@example.com", "verified": True })

7. patch

Apply JSON Patch operations (RFC 6902) to records.

patch("user:john", [ {"op": "replace", "path": "/email", "value": "new@example.com"}, {"op": "add", "path": "/verified", "value": True} ])

8. upsert

Create or update a record with specific ID.

upsert("settings:global", { "theme": "dark", "language": "en" })

9. insert

Bulk insert multiple records efficiently.

insert("product", [ {"name": "Laptop", "price": 999.99}, {"name": "Mouse", "price": 29.99}, {"name": "Keyboard", "price": 79.99} ])

10. relate

Create graph relationships between records.

relate( "user:john", # from "purchased", # relation name "product:laptop-123", # to {"quantity": 1, "date": "2024-01-15"} # relation data )

=� Examples

Basic CRUD Operations

# Create a user user = create("user", {"name": "Alice", "email": "alice@example.com"}) # Update specific fields merge(user["id"], {"verified": True, "last_login": "2024-01-01"}) # Query with conditions results = query("SELECT * FROM user WHERE verified = true ORDER BY created DESC") # Delete when done delete(user["id"])

Working with Relationships

# Create entities user = create("user", {"name": "John"}) product = create("product", {"name": "Laptop", "price": 999}) # Create relationship relate(user["id"], "purchased", product["id"], { "quantity": 1, "total": 999, "date": "2024-01-15" }) # Query relationships purchases = query(f"SELECT * FROM {user['id']}->purchased->product")

Bulk Operations

# Insert multiple records products = insert("product", [ {"name": "Laptop", "category": "Electronics", "price": 999}, {"name": "Mouse", "category": "Electronics", "price": 29}, {"name": "Desk", "category": "Furniture", "price": 299} ]) # Bulk update with query query("UPDATE product SET on_sale = true WHERE category = 'Electronics'")

Multi-Database Operations

You can work with multiple databases in a single session by using the namespace and database parameters:

# Create a record in the production database create("user", {"name": "Alice"}, namespace="prod", database="main") # Query from staging database select("user", namespace="staging", database="main") # Copy data between databases users = select("user", namespace="staging", database="main") for user in users["data"]: create("user", user, namespace="prod", database="main")

Behavior Summary:

Scenario

Result

Env vars set, no params

Uses pooled connection (best performance)

Env vars set, params provided

Uses override connection with specified namespace/database

No env vars, params provided

Uses override connection with specified namespace/database

No env vars, no params

Fails with clear error message

<� Architecture

The server is built with:

  • FastMCP: Simplified MCP server implementation

  • SurrealDB Python SDK: Official database client

  • Connection Pooling: Efficient connection management

  • Async/Await: Non-blocking database operations

>� Testing

The project includes a comprehensive test suite using pytest.

Prerequisites

  • SurrealDB instance running locally

  • Test database access (uses temporary test databases)

Running Tests

# Make sure SurrealDB is running surreal start --user root --pass root # Run all tests uv run pytest # Run with coverage uv run pytest --cov=surreal_mcp # Run specific test file uv run pytest tests/test_tools.py # Run specific test class or method uv run pytest tests/test_tools.py::TestQueryTool uv run pytest tests/test_tools.py::TestQueryTool::test_query_simple # Run with verbose output uv run pytest -v # Run only tests matching a pattern uv run pytest -k "test_create"

Test Structure

tests/ ├── __init__.py ├── conftest.py # Fixtures and test configuration ├── test_tools.py # Tests for all MCP tools ├── test_server.py # Tests for server configuration └── test_namespace_override.py # Tests for namespace/database override

Writing Tests

The test suite includes fixtures for common test data:

  • clean_db - Ensures clean database state

  • sample_user_data - Sample user data

  • created_user - Pre-created user record

  • created_product - Pre-created product record

Example test:

@pytest.mark.asyncio async def test_create_user(clean_db, sample_user_data): result = await mcp._tools["create"].func( table="user", data=sample_user_data ) assert result["success"] is True assert result["data"]["email"] == sample_user_data["email"]

> Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository

  2. Create your feature branch (git checkout -b feature/AmazingFeature)

  3. Commit your changes (git commit -m 'Add some AmazingFeature')

  4. Push to the branch (git push origin feature/AmazingFeature)

  5. Open a Pull Request

=� License

This project is licensed under the MIT License - see the LICENSE file for details.

=O Acknowledgments

=� Support


One-click Deploy
A
security – no known vulnerabilities
A
license - permissive license
A
quality - confirmed to work

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lfnovo/surreal-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server