surreal-mcp
The SurrealDB MCP Server enables AI assistants to interact with SurrealDB databases through a standardized interface, providing comprehensive database operations for the graph database.
Execute Raw SurrealQL Queries: Run any valid SurrealQL query including complex SELECTs, JOINs, aggregations, graph traversals, transactions, and schema definitions
CRUD Operations: Create records with auto-generated IDs, select records by ID or entire tables, update entire records, and delete records with their associated graph edges
Advanced Update Operations: Merge specific fields without affecting others, apply JSON Patch operations (RFC 6902) for granular modifications, and upsert to create or update records with specific IDs
Bulk Operations: Efficiently insert multiple records in a single operation
Graph Database Features: Create relationships (edges) between records with optional relation data, supporting complex relationship modeling and graph traversals
Multi-Database Support: Override namespace and database per tool call to work with multiple databases in a single session
Connection Management: Efficient connection pooling with environment variable configuration for optimal performance
Enables AI assistants to interact with SurrealDB databases, supporting SurrealQL queries, CRUD operations, graph relationship management, and bulk operations while handling SurrealDB's unique features like record IDs and graph edges.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@surreal-mcpshow me all users in the customers table"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SurrealDB MCP Server
A Model Context Protocol (MCP) server that enables AI assistants to interact with SurrealDB databases
=� 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: dbmcp
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-mcpUsing uv (Recommended for Development)
# 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.pyUsing 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 |
| SurrealDB connection URL |
|
| Database username |
|
| Database password |
|
Optional Variables (can be overridden per tool call)
Variable | Description | Example |
| Default SurrealDB namespace |
|
| Default SurrealDB database |
|
Note: If
SURREAL_NAMESPACEandSURREAL_DATABASEare not set as environment variables, you must providenamespaceanddatabaseparameters 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 credentialsOr 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'")<<<<<<< HEAD
<� Architecture
=======
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
main
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 overrideWriting Tests
The test suite includes fixtures for common test data:
clean_db- Ensures clean database statesample_user_data- Sample user datacreated_user- Pre-created user recordcreated_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.
Fork the repository
Create your feature branch (
git checkout -b feature/AmazingFeature)Commit your changes (
git commit -m 'Add some AmazingFeature')Push to the branch (
git push origin feature/AmazingFeature)Open a Pull Request
=� License
This project is licensed under the MIT License - see the LICENSE file for details.
=O Acknowledgments
SurrealDB for the amazing graph database
FastMCP for simplifying MCP server development
Model Context Protocol for the standardized AI-tool interface
=� Support
=� Email: your.email@example.com
=� Discord: Join our server
= Issues: GitHub Issues
Available Tools
10 toolscreateA
Create a new record in a SurrealDB table with the specified data.
This tool creates a new record with an auto-generated ID. The system will automatically:
Generate a unique ID for the record
Add created/updated timestamps
Validate the data against any defined schema
Args: table: The name of the table to create the record in (e.g., "user", "product") data: A dictionary containing the field values for the new record. Examples: - {"name": "Alice", "email": "alice@example.com", "age": 30} - {"title": "Laptop", "price": 999.99, "category": "electronics"} namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if creation was successful - data: The created record including its generated ID and timestamps - id: The ID of the newly created record (convenience field) - error: Error message if creation failed (only present on failure)
Examples: >>> await create("user", {"name": "Alice", "email": "alice@example.com"}) { "success": true, "data": {"id": "user:ulid", "name": "Alice", "email": "alice@example.com", "created": "2024-01-01T10:00:00Z"}, "id": "user:ulid" }
Note: If you need to specify a custom ID, use the 'upsert' tool instead.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| data | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and does well by disclosing key behaviors: auto-generated ID, automatic timestamp addition, schema validation, and fallback to environment variables for namespace/database. It doesn't mention error handling specifics or rate limits, but covers most critical aspects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, system behavior, args, returns, examples, note). Every sentence adds value - no redundancy. The information is front-loaded with the core purpose first, followed by supporting details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters with 0% schema coverage and no annotations, the description provides comprehensive coverage: purpose, usage guidelines, parameter details with examples, return format, and sibling differentiation. The output schema exists, so return values don't need explanation in the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate. It provides detailed parameter explanations with examples for 'data', clarifies optional vs. required parameters, explains default behaviors for namespace/database, and gives concrete examples of valid inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Create a new record in a SurrealDB table with the specified data.' It specifies the verb ('create'), resource ('record in a SurrealDB table'), and distinguishes from siblings by mentioning auto-generated ID and pointing to 'upsert' for custom IDs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use alternatives: 'If you need to specify a custom ID, use the 'upsert' tool instead.' It also clarifies the default behavior (auto-generated ID) and when to use optional parameters (namespace/database overrides).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deleteA
Delete a specific record from the database by its ID.
This tool permanently removes a record from the database. Use with caution as this operation cannot be undone. The deletion will also:
Remove any graph edges (relations) connected to this record
Trigger any defined deletion events/hooks
Fail if the record is referenced by FOREIGN KEY constraints
Args: thing: The full record ID to delete in format "table:id" (e.g., "user:john", "product:laptop-123") namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if deletion was successful - deleted: The ID of the deleted record - data: The deleted record data (if available) - error: Error message if deletion failed (only present on failure)
Examples: >>> await delete("user:john") {"success": true, "deleted": "user:john", "data": {"id": "user:john", "name": "John Doe"}}
>>> await delete("product:nonexistent")
{"success": true, "deleted": "product:nonexistent", "data": null} # No error even if record didn't existNote: This operation is irreversible. Consider using soft deletes (status fields) for recoverable deletions.
| Name | Required | Description | Default |
|---|---|---|---|
| thing | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It thoroughly explains the irreversible nature, cascading effects (removing graph edges, triggering hooks), failure conditions (FOREIGN KEY constraints), and even includes edge-case behavior (no error if record doesn't exist). This provides comprehensive behavioral context beyond basic parameter documentation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, warnings, args, returns, examples, notes) and every sentence adds value. While comprehensive, it could be slightly more concise by integrating some details more tightly, but the information density is high and organization supports quick scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation tool with no annotations, 3 parameters, and 0% schema coverage, this description is exceptionally complete. It covers purpose, behavioral consequences, all parameters, return values (though output schema exists), examples, warnings, and even suggests alternatives. Nothing essential is missing given the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description fully compensates by explaining all three parameters. It clarifies 'thing' as 'the full record ID in format "table:id"' with examples, and explains the optional 'namespace' and 'database' parameters with their default behaviors from environment variables. This adds substantial meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verb ('Delete') and resource ('a specific record from the database by its ID'). It distinguishes itself from sibling tools like 'create', 'update', and 'patch' by focusing on permanent removal rather than creation or modification.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context about when to use this tool ('permanently removes a record') and includes a cautionary note about irreversibility. It suggests an alternative ('Consider using soft deletes') but doesn't explicitly contrast with specific sibling tools like 'patch' or 'update' for partial modifications.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
insertA
Insert multiple records into a table in a single operation.
This tool is optimized for bulk inserts when you need to create many records at once. It's more efficient than calling 'create' multiple times. Each record will get:
An auto-generated unique ID
Automatic created/updated timestamps
Schema validation (if defined)
Args: table: The name of the table to insert records into (e.g., "user", "product") data: Array of dictionaries, each representing a record to insert. Example: [ {"name": "Alice", "email": "alice@example.com"}, {"name": "Bob", "email": "bob@example.com"}, {"name": "Charlie", "email": "charlie@example.com"} ] namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if insertion was successful - data: Array of all inserted records with their generated IDs - count: Number of records successfully inserted - error: Error message if insertion failed (only present on failure)
Examples: >>> await insert("user", [ ... {"name": "Alice", "role": "admin"}, ... {"name": "Bob", "role": "user"} ... ]) { "success": true, "data": [ {"id": "user:ulid1", "name": "Alice", "role": "admin", "created": "..."}, {"id": "user:ulid2", "name": "Bob", "role": "user", "created": "..."} ], "count": 2 }
Note: For single record creation, use the 'create' tool instead.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| data | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and does well. It discloses behavioral traits: bulk operation optimization, automatic ID generation, timestamp handling, schema validation, and fallback behavior for namespace/database parameters. It doesn't mention error handling specifics beyond the return structure, but covers most key behaviors for a write operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and appropriately sized. It starts with the core purpose, then provides optimization context, behavioral details, parameter explanations with examples, return format, usage example, and finally sibling tool guidance. Every section adds value with no wasted sentences, and information is front-loaded effectively.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of a bulk insert operation with 4 parameters, no annotations, but with an output schema, the description is complete. It covers purpose, usage guidelines, behavioral traits, parameter semantics with examples, return format explanation, and sibling tool differentiation. The output schema existence means the description doesn't need to detail return structure, which it acknowledges while still explaining key aspects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed parameter semantics. It explains each parameter's purpose, provides examples for the 'data' array, and clarifies default behavior for optional parameters. The description adds substantial meaning beyond what the bare schema provides, making parameter usage clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Insert multiple records into a table in a single operation.' It specifies the verb ('insert'), resource ('records into a table'), and scope ('multiple records in a single operation'). It also distinguishes from sibling 'create' tool in the Note section, making it specific and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool: 'optimized for bulk inserts when you need to create many records at once' and 'more efficient than calling 'create' multiple times.' It also explicitly states when not to use it: 'For single record creation, use the 'create' tool instead.' This gives clear alternatives and context for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mergeA
Merge data into a specific record, updating only the specified fields.
This tool performs a partial update, only modifying the fields provided in the data parameter. All other fields remain unchanged. This is useful when you want to:
Update specific fields without affecting others
Add new fields to an existing record
Modify nested properties without replacing the entire object
Args: thing: The full record ID to merge data into in format "table:id" (e.g., "user:john") data: Dictionary containing only the fields to update. Examples: - {"email": "newemail@example.com"} - updates only email - {"profile": {"bio": "New bio"}} - updates nested field - {"tags": ["python", "mcp"]} - replaces the tags array namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if merge was successful - data: The complete record after merging, with all fields - modified_fields: List of field names that were modified - error: Error message if merge failed (only present on failure)
Examples: >>> await merge("user:john", {"email": "john.new@example.com", "verified": true}) { "success": true, "data": {"id": "user:john", "name": "John Doe", "email": "john.new@example.com", "verified": true, "age": 30}, "modified_fields": ["email", "verified"] }
Note: This is equivalent to the 'patch' tool but uses object merging syntax instead of JSON Patch.
| Name | Required | Description | Default |
|---|---|---|---|
| thing | Yes | ||
| data | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly explains this is a partial update operation that only modifies specified fields while leaving others unchanged. It describes the return structure in detail and mentions the tool's equivalence to 'patch' but with different syntax. However, it doesn't mention authentication requirements, rate limits, or error handling beyond the error field in returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, usage scenarios, Args, Returns, Examples, Note) and front-loads the core functionality. While comprehensive, some sections like the detailed examples and note could be slightly condensed. Every sentence adds value, but the overall length is substantial for a tool description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (mutation operation with 4 parameters, 0% schema coverage, and sibling tools), the description provides complete context. It explains the partial update behavior, provides detailed parameter semantics, includes a comprehensive return structure, offers practical examples, and positions the tool relative to siblings. The presence of an output schema reduces the need to explain return values, which the description acknowledges by documenting the return structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed parameter explanations. Each parameter (thing, data, namespace, database) is clearly explained with examples, format requirements, and default behavior. The data parameter receives particularly thorough treatment with multiple examples showing different update scenarios.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose as 'Merge data into a specific record, updating only the specified fields' with the specific verb 'merge' and resource 'record'. It explicitly distinguishes from the sibling 'patch' tool in the note section, stating this uses object merging syntax instead of JSON Patch.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool: 'This is useful when you want to:' followed by three specific scenarios. It also explicitly compares to the 'patch' sibling tool, indicating this is an alternative with different syntax. The examples further illustrate appropriate usage contexts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
patchA
Apply JSON Patch operations to a specific record (RFC 6902).
This tool applies a sequence of patch operations to modify a record. However, since SurrealDB doesn't natively support JSON Patch, this implementation converts patches to a merge operation. Supported operations:
add: Add a new field or array element
remove: Remove a field (limited support)
replace: Replace a field value
Args: thing: The full record ID to patch in format "table:id" (e.g., "user:john") patches: Array of patch operations. Each operation should have: - op: The operation type ("add", "remove", "replace", "move", "copy", "test") - path: The field path (e.g., "/email", "/profile/bio") - value: The value for add/replace operations namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if patch was successful - data: The complete record after applying patches - applied_patches: Number of patch operations applied - error: Error message if patch failed (only present on failure)
Examples: >>> await patch("user:john", [ ... {"op": "replace", "path": "/email", "value": "john@newdomain.com"}, ... {"op": "add", "path": "/verified", "value": true} ... ]) { "success": true, "data": {"id": "user:john", "email": "john@newdomain.com", "verified": true, ...}, "applied_patches": 2 }
Note: This provides compatibility with JSON Patch but internally uses SurrealDB's merge. Complex operations like "move" or "test" are not fully supported.
| Name | Required | Description | Default |
|---|---|---|---|
| thing | Yes | ||
| patches | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It effectively discloses behavioral traits: it's a mutation tool (implied by 'modify'), explains the internal conversion to merge, lists supported operations, and notes limitations. However, it lacks details on permissions, rate limits, or error handling beyond the return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for purpose, usage, args, returns, examples, and notes. It is appropriately sized but could be more front-loaded; the detailed parameter explanations are valuable but make it slightly verbose. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (mutation tool with 4 parameters, 0% schema coverage, no annotations) and the presence of an output schema, the description is complete. It covers purpose, usage, parameters with examples, return values, and limitations, providing all necessary context for effective tool use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate fully. It adds significant meaning beyond the schema: explains 'thing' format, details 'patches' structure with examples, and clarifies 'namespace' and 'database' defaults. This provides comprehensive parameter semantics not in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Apply JSON Patch operations to a specific record (RFC 6902).' It specifies the exact action ('apply'), resource ('record'), and standard ('RFC 6902'), distinguishing it from siblings like 'update' or 'merge' by focusing on patch operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool: for applying JSON Patch operations to modify records. It mentions an alternative ('merge') and notes limitations ('Complex operations like "move" or "test" are not fully supported'), but does not explicitly state when to choose this over siblings like 'update' or 'merge'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queryA
Execute one or more SurrealQL queries against the connected SurrealDB database.
This tool allows you to run any valid SurrealQL queries directly. Use this for complex queries that don't fit the other tool patterns, such as:
Complex SELECT queries with JOINs, GROUP BY, or aggregations
Custom DEFINE statements for schemas
Transaction blocks with BEGIN/COMMIT
Graph traversal queries
Queries are executed sequentially. If a query fails, execution continues with the remaining queries, and the error is captured in that query's result.
Args: queries: A list of SurrealQL queries to execute. Examples: - ["SELECT * FROM user WHERE age > 18"] - ["SELECT * FROM user", "SELECT * FROM product"] - ["CREATE user:alice SET name = 'Alice'", "CREATE user:bob SET name = 'Bob'"] namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if at least one query executed successfully - results: Array of per-query results, each containing: - success: Boolean indicating if this specific query succeeded - data: The query results (only present on success) - error: Error message (only present on failure) - total: Total number of queries executed - succeeded: Number of queries that succeeded - failed: Number of queries that failed
Example: >>> await query(["SELECT * FROM user", "SELECT * FROM product"]) { "success": true, "results": [ {"success": true, "data": [{"id": "user:1", "name": "Alice"}]}, {"success": true, "data": [{"id": "product:1", "name": "Laptop"}]} ], "total": 2, "succeeded": 2, "failed": 0 }
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and delivers well. It discloses key behavioral traits: queries execute sequentially, failure doesn't stop execution (error captured per query), and namespace/database fallback to environment variables. It doesn't mention authentication needs, rate limits, or side effects, but covers execution flow thoroughly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured and appropriately sized. Front-loaded with purpose and usage guidelines, followed by parameter details, return format, and example. Every sentence earns its place: no fluff, clear sections with headings (Args, Returns, Example). Efficient communication of complex functionality.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 3 parameters with 0% schema coverage, no annotations, but with output schema (Returns section), the description is complete. It explains all parameters thoroughly, describes execution behavior, provides usage guidance versus siblings, and documents the return structure. The example solidifies understanding. No gaps for a general-purpose query tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate fully. It does: each parameter (queries, namespace, database) is explained with meaning, optionality, defaults, and examples. The 'queries' parameter gets extensive examples showing array usage and query types. This adds significant value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool 'Execute one or more SurrealQL queries against the connected SurrealDB database' with specific verb ('Execute') and resource ('SurrealQL queries'). It distinguishes from siblings by mentioning 'complex queries that don't fit the other tool patterns' and listing specific sibling-incompatible use cases like JOINs, DEFINE statements, and transactions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: 'Use this for complex queries that don't fit the other tool patterns' with concrete examples (SELECT with JOINs, DEFINE, transactions, graph traversal). This clearly indicates when to use this tool versus the simpler sibling tools like select, create, update, etc.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
relateA
Create a graph relation (edge) between two records in SurrealDB.
This tool creates relationships in SurrealDB's graph structure, allowing you to:
Connect records with named relationships
Store data on the relationship itself
Build complex graph queries later
Model many-to-many relationships efficiently
Args: from_thing: The source record ID in format "table:id" (e.g., "user:john") relation_name: The name of the relation/edge table (e.g., "likes", "follows", "purchased") to_thing: The destination record ID in format "table:id" (e.g., "product:laptop-123") data: Optional dictionary containing data to store on the relation itself. Examples: - {"rating": 5, "review": "Great product!"} - {"quantity": 2, "price": 99.99} - {"since": "2024-01-01", "type": "friend"} namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if relation was created successfully - data: The created relation record(s) - relation_id: The ID of the created relation - error: Error message if creation failed (only present on failure)
Examples: >>> await relate("user:john", "likes", "product:laptop-123", {"rating": 5}) { "success": true, "data": [{"id": "likes:xyz", "in": "user:john", "out": "product:laptop-123", "rating": 5}], "relation_id": "likes:xyz" }
>>> await relate("user:alice", "follows", "user:bob")
{
"success": true,
"data": [{"id": "follows:abc", "in": "user:alice", "out": "user:bob"}],
"relation_id": "follows:abc"
}Note: You can query these relations later using graph syntax: SELECT * FROM user:john->likes->product SELECT * FROM user:alice->follows->user
| Name | Required | Description | Default |
|---|---|---|---|
| from_thing | Yes | ||
| relation_name | Yes | ||
| to_thing | Yes | ||
| data | No | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes that this creates relationships, stores data on relationships, enables future graph queries, and models many-to-many relationships. It also explains the return structure and includes error handling information. The main gap is lack of information about permissions, rate limits, or idempotency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, bullet points, args, returns, examples, note). While comprehensive, it's appropriately sized for a complex tool with 6 parameters. The front-loaded purpose statement is excellent, though some redundancy exists between the bullet points and later content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, graph operations), no annotations, and an output schema that only defines structure without semantics, the description provides excellent completeness. It covers purpose, parameters with examples, return values with examples, and even includes query syntax for future use. The combination of structured sections and practical examples makes it highly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed parameter explanations. Each parameter is clearly defined with format examples (e.g., 'table:id'), the optional nature of 'data', 'namespace', and 'database' is explained, and concrete examples show how parameters work together. This adds significant value beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Create a graph relation'), identifies the resource ('between two records in SurrealDB'), and distinguishes from siblings like create/insert/update by focusing on graph relationships rather than general record operations. The bullet points further clarify the purpose and benefits.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool ('Create a graph relation between two records'), and the examples demonstrate typical use cases. However, it doesn't explicitly state when NOT to use it or mention alternatives among the sibling tools for similar operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
selectA
Select all records from a table or a specific record by ID.
This tool provides a simple way to retrieve data from SurrealDB tables. Use this when you need to:
Fetch all records from a table
Retrieve a specific record by its ID
Get data for display or further processing
Args: table: The name of the table to select from (e.g., "user", "product", "order") id: Optional ID of a specific record to select. Can be: - Just the ID part (e.g., "john") - will be combined with table name - Full record ID (e.g., "user:john") - will be used as-is - None/omitted - selects all records from the table namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if the selection was successful - data: Array of records (even for single record selection) - count: Number of records returned - error: Error message if selection failed (only present on failure)
Examples: >>> await select("user") # Get all users {"success": true, "data": [...], "count": 42}
>>> await select("user", "john") # Get specific user
{"success": true, "data": [{"id": "user:john", "name": "John Doe", ...}], "count": 1}
>>> await select("product", "product:laptop-123") # Using full ID
{"success": true, "data": [{"id": "product:laptop-123", ...}], "count": 1}| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| id | No | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It effectively communicates this is a read-only operation (implied by 'select', 'retrieve', 'get data'), describes the return format in detail, and provides examples of successful outcomes. It doesn't mention error handling beyond the return structure or rate limits, but covers core behavioral aspects well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, usage guidelines, args, returns, examples). While somewhat lengthy, every section adds value. The front-loaded purpose and usage guidelines are efficient, though the detailed parameter explanations and examples make it comprehensive rather than minimal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read operation tool with 4 parameters, 0% schema coverage, no annotations, but with an output schema, this description is exceptionally complete. It covers purpose, usage, all parameters, return format, and provides multiple examples. The output schema means the description doesn't need to explain return values, which it does anyway, adding extra clarity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing comprehensive parameter documentation. It explains all 4 parameters (table, id, namespace, database), their purposes, formats, optionality, and default behaviors. The id parameter gets particularly detailed treatment with multiple format examples and the None case explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('select all records', 'retrieve a specific record') and resources ('from a table', 'by its ID'). It distinguishes this read operation from sibling tools like create, delete, update, etc. which are write operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly provides when-to-use guidance with bullet points ('Fetch all records', 'Retrieve a specific record', 'Get data for display or further processing'). It distinguishes this from other tools by being the primary read operation tool in a set that includes many write operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
updateA
Update a specific record with new data, completely replacing its content.
This tool performs a full update, replacing all fields (except ID and timestamps) with the provided data. For partial updates that only modify specific fields, use 'merge' or 'patch' instead.
Args: thing: The full record ID to update in format "table:id" (e.g., "user:john", "product:laptop-123") data: Complete new data for the record. All existing fields will be replaced except: - The record ID (cannot be changed) - The 'created' timestamp (preserved from original) - The 'updated' timestamp (automatically set to current time) namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if update was successful - data: The updated record with all new values - error: Error message if update failed (only present on failure)
Examples: >>> await update("user:john", {"name": "John Smith", "email": "john.smith@example.com", "age": 31}) { "success": true, "data": {"id": "user:john", "name": "John Smith", "email": "john.smith@example.com", "age": 31, "updated": "2024-01-01T10:00:00Z"} }
Warning: This replaces ALL fields. If you only want to update specific fields, use 'merge' instead.
| Name | Required | Description | Default |
|---|---|---|---|
| thing | Yes | ||
| data | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does an excellent job disclosing behavioral traits. It explains the destructive nature ('completely replacing its content'), specifies what fields are preserved/excluded (ID, timestamps), describes the automatic timestamp update, mentions environment variable fallbacks, and documents the return structure. It doesn't mention authentication or rate limits, but covers most critical behavioral aspects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, args, returns, examples, warning) and front-loads the most important information. While comprehensive, it could be slightly more concise as some information is repeated (e.g., the warning about using 'merge' for partial updates appears twice).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given this is a mutation tool with no annotations, 4 parameters, 0% schema coverage, but with an output schema, the description provides complete context. It covers purpose, usage guidelines, parameter semantics, behavioral details, return values, and includes examples. The output schema existence means the description doesn't need to explain return structure in detail, which it acknowledges by summarizing rather than fully specifying.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed semantic explanations for all parameters. It explains the 'thing' parameter format with examples, clarifies that 'data' must contain 'complete new data', and describes the optional 'namespace' and 'database' parameters with their environment variable fallback behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('update a specific record', 'completely replacing its content') and distinguishes it from siblings like 'merge' and 'patch'. It explicitly identifies the resource as a 'record' and specifies it's a full replacement operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool versus alternatives: 'For partial updates that only modify specific fields, use 'merge' or 'patch' instead.' It also includes a warning section reinforcing this distinction and names specific sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upsertA
Upsert a record: create if it doesn't exist, merge/update if it does.
This tool is perfect when you want to ensure a record exists with specific data, regardless of whether it already exists. It will:
Create a new record with the specified ID if it doesn't exist
Merge the provided data into the existing record if it does exist
Always succeed (unless there's a database error)
Args: thing: The full record ID in format "table:id" (e.g., "user:john", "settings:global") data: The data for the record. If record exists, this will be merged with existing data namespace: Optional SurrealDB namespace override. If not provided, uses SURREAL_NAMESPACE env var. database: Optional SurrealDB database override. If not provided, uses SURREAL_DATABASE env var.
Returns: A dictionary containing: - success: Boolean indicating if upsert was successful - data: The record after upserting - created: Boolean indicating if a new record was created (vs updated) - error: Error message if upsert failed (only present on failure)
Examples: >>> await upsert("user:john", {"name": "John Doe", "email": "john@example.com"}) {"success": true, "data": {"id": "user:john", "name": "John Doe", ...}, "created": true}
>>> await upsert("user:john", {"email": "newemail@example.com"}) # Update existing
{"success": true, "data": {"id": "user:john", "name": "John Doe", "email": "newemail@example.com", ...}, "created": false}
>>> await upsert("settings:global", {"theme": "dark", "language": "en"})
{"success": true, "data": {"id": "settings:global", "theme": "dark", "language": "en"}, "created": true}| Name | Required | Description | Default |
|---|---|---|---|
| thing | Yes | ||
| data | Yes | ||
| namespace | No | ||
| database | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: the conditional create/merge logic, success conditions ('always succeed unless there's a database error'), and return structure. It could improve by mentioning potential side effects or performance implications, but covers core behavior well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, behavior, args, returns, examples) and uses bullet points effectively. It's appropriately detailed for a complex tool but could be slightly more concise in the examples section, which includes three detailed examples.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (conditional create/update logic), 4 parameters with 0% schema coverage, and no annotations, the description provides comprehensive coverage. It explains purpose, usage, behavior, parameters, and return values in detail. The presence of an output schema reduces the need to fully document returns, but the description still provides helpful context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing detailed semantic information for all parameters. It explains the format and purpose of 'thing' (record ID format), the behavior of 'data' (merged if record exists), and the optional nature and defaults for 'namespace' and 'database' parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('create if it doesn't exist, merge/update if it does') and identifies the resource ('record'). It distinguishes this from siblings like 'create', 'update', 'merge', and 'patch' by explaining the conditional logic that combines their functionalities.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool ('perfect when you want to ensure a record exists with specific data, regardless of whether it already exists'). It distinguishes it from alternatives by explaining its unique upsert behavior, which differs from separate create or update operations available among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
10 tool updates
v1.0.0- Changed
create4 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / table / titleRemoved value: -"Table"
- Changed
delete3 fields changed- added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / thing / titleRemoved value: -"Thing"
- Changed
insert4 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / table / titleRemoved value: -"Table"
- Changed
merge4 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / thing / titleRemoved value: -"Thing"
- Changed
patch4 fields changed- added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / patches / titleRemoved value: -"Patches" - removed
Input schema / properties / thing / titleRemoved value: -"Thing"
- Changed
query5 fields changed- added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / queriesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - removed
Input schema / properties / query_stringRemoved value: -{ - "title": "Query String", - "type": "string" -} - changed
Input schema / requiredPrevious value: -[ - "query_string" -]New value: +[ + "queries" +]
- Changed
relate6 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / from_thing / titleRemoved value: -"From Thing" - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / relation_name / titleRemoved value: -"Relation Name" - removed
Input schema / properties / to_thing / titleRemoved value: -"To Thing"
- Changed
select4 fields changed- added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / id / titleRemoved value: -"Id" - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / table / titleRemoved value: -"Table"
- Changed
update4 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / thing / titleRemoved value: -"Thing"
- Changed
upsert4 fields changed- removed
Input schema / properties / data / titleRemoved value: -"Data" - added
Input schema / properties / databaseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / namespaceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - removed
Input schema / properties / thing / titleRemoved value: -"Thing"
10 tool updates
- First observed
create - First observed
delete - First observed
insert - First observed
merge - First observed
patch - First observed
query - First observed
relate - First observed
select - First observed
update - First observed
upsert
TDQS
Most tools have distinct purposes, but there is some overlap between 'merge', 'patch', and 'update' that could cause confusion. 'merge' and 'patch' both handle partial updates with different syntaxes, and 'update' is for full replacements, which might be misselected by an agent. However, descriptions clarify these differences, and other tools like 'create', 'delete', and 'select' are clearly distinct.
All tool names follow a consistent verb-only pattern (e.g., create, delete, insert, merge, patch, query, relate, select, update, upsert). There are no deviations in style or convention, making the naming highly predictable and readable across the set.
With 10 tools, the server is well-scoped for a SurrealDB MCP server, covering essential CRUD operations, bulk inserts, queries, and graph relations. Each tool serves a clear purpose, and the count is neither too sparse nor overwhelming for database interaction tasks.
The tool set provides comprehensive coverage for SurrealDB operations, including create, read (select, query), update (update, merge, patch, upsert), delete, bulk operations (insert), and graph relations (relate). There are no obvious gaps; agents can perform full lifecycle management and complex queries without dead ends.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for AI dialogue using various LLM models via AceDataCloud
NeuralBrain MCP Server - RAG, Vector Memory, LLM Routing, Agent Identity, x402 Payments
Cloud-hosted MCP server for durable AI memory
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP-Server from your Database optimized for LLMs and AI-Agents. Supports PostgreSQL, MySQL, ClickHouse, Snowflake, MSSQL, BigQuery, Oracle Database, SQLite, ElasticSearch, DuckDB547Apache 2.0
- AlicenseAqualityCmaintenanceDatabase MCP server for MySQL, MariaDB, PostgreSQL & SQLite630MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server enabling AI assistants to perform CRUD operations on a Supabase database via a standardized interface.194MIT
- AlicenseNot gradedqualityDmaintenanceZero-config MCP server that empowers AI agents to safely query SQL and NoSQL databases like PostgreSQL, MySQL, SQLite, MongoDB, and Redis.241MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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