Skip to main content
Glama

patch

Apply JSON Patch operations to modify specific database records using RFC 6902 standard, converting patches to SurrealDB merge operations for compatibility.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
thingYes
patchesYes
namespaceNo
databaseNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The 'patch' tool handler: an async function decorated with @mcp.tool() that implements JSON Patch operations by converting them to a SurrealDB MERGE via repo_upsert. Handles validation, path conversion, and returns the updated record.
    @mcp.tool()
    async def patch(
        thing: str,
        patches: List[Dict[str, Any]],
        namespace: Optional[str] = None,
        database: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        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.
        """
        try:
            ns, db = resolve_namespace_database(namespace, database)
    
            # Validate thing format
            if ":" not in thing:
                raise ValueError(f"Invalid record ID format: {thing}. Must be 'table:id'")
    
            if not patches or not isinstance(patches, list):
                raise ValueError("Patches must be a non-empty array")
    
            logger.info(f"Applying {len(patches)} patches to {thing}")
    
            # Convert JSON Patch operations to a merge object
            merge_data = {}
            for patch_op in patches:
                op = patch_op.get("op")
                path = patch_op.get("path", "")
                value = patch_op.get("value")
    
                # Remove leading slash and convert path to field name
                field = path.lstrip("/").replace("/", ".")
    
                if op in ["add", "replace"]:
                    merge_data[field] = value
                elif op == "remove":
                    # Note: SurrealDB doesn't support removing fields via MERGE
                    # This would need a custom UPDATE query
                    logger.warning(f"Remove operation on {field} not fully supported")
                else:
                    logger.warning(f"Patch operation '{op}' not supported")
    
            # Extract table name for repo_upsert
            table = thing.split(":", 1)[0]
    
            # Apply the patches via merge - pass full record ID
            result = await repo_upsert(
                table=table, id=thing, data=merge_data, add_timestamp=True, namespace=ns, database=db
            )
    
            # Get the first result
            patched_record = result[0] if result else {}
    
            return {
                "success": True,
                "data": patched_record,
                "applied_patches": len(patches)
            }
        except Exception as e:
            logger.error(f"Patch failed for {thing}: {str(e)}")
            raise Exception(f"Failed to patch {thing}: {str(e)}")
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

Install Server

Other Tools

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