Skip to main content
Glama

Delete Block

delete_block

Remove a block from a Mnemosyne knowledge graph document by its ID, with an option to delete all related child blocks in a cascade operation.

Instructions

Delete a block by its ID. Use cascade=true to also delete all subsequent blocks with higher indent (indent-based children). Returns the list of deleted block IDs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
graph_idYes
document_idYes
block_idYes
cascadeNo

Implementation Reference

  • The MCP tool handler for 'delete_block', including the @server.tool decorator that registers it. Handles authentication, input validation, document connection, transaction-based deletion via helper, and structured response.
    @server.tool(
        name="delete_block",
        title="Delete Block",
        description=(
            "Delete a block by its ID. Use cascade=true to also delete all subsequent blocks "
            "with higher indent (indent-based children). Returns the list of deleted block IDs."
        ),
    )
    async def delete_block_tool(
        graph_id: str,
        document_id: str,
        block_id: str,
        cascade: bool = False,
        context: Context | None = None,
    ) -> dict:
        """Delete a block and optionally its indent-children.
    
        Args:
            graph_id: The graph containing the document
            document_id: The document containing the block
            block_id: The block to delete
            cascade: If True, also delete indent-children
        """
        auth = MCPAuthContext.from_context(context)
        auth.require_auth()
    
        if not graph_id or not graph_id.strip():
            raise ValueError("graph_id is required")
        if not document_id or not document_id.strip():
            raise ValueError("document_id is required")
        if not block_id or not block_id.strip():
            raise ValueError("block_id is required")
    
        try:
            await hp_client.connect_document(graph_id.strip(), document_id.strip())
    
            deleted_ids: list[str] = []
    
            def perform_delete(doc: Any) -> None:
                nonlocal deleted_ids
                writer = DocumentWriter(doc)
                deleted_ids = writer.delete_block_by_id(
                    block_id.strip(), cascade_children=cascade
                )
    
            await hp_client.transact_document(
                graph_id.strip(),
                document_id.strip(),
                perform_delete,
            )
    
            result = {
                "success": True,
                "graph_id": graph_id.strip(),
                "document_id": document_id.strip(),
                "deleted_block_ids": deleted_ids,
                "cascade": cascade,
            }
            return result
    
        except Exception as e:
            logger.error(
                "Failed to delete block",
                extra_context={
                    "graph_id": graph_id,
                    "document_id": document_id,
                    "block_id": block_id,
                    "error": str(e),
                },
            )
            raise RuntimeError(f"Failed to delete block: {e}")
  • Core implementation of block deletion in DocumentWriter class, supporting optional cascade deletion of subsequent higher-indent child blocks. Called by the tool handler.
    def delete_block_by_id(self, block_id: str, cascade_children: bool = False) -> list[str]:
        """Delete a block by its ID, optionally cascading to indent-children.
    
        Args:
            block_id: The block ID to delete
            cascade_children: If True, also delete all subsequent blocks with
                             higher indent (indent-based children)
    
        Returns:
            List of deleted block IDs.
    
        Raises:
            ValueError: If block not found.
        """
        result = self.find_block_by_id(block_id)
        if result is None:
            raise ValueError(f"Block not found: {block_id}")
    
        index, elem = result
        deleted_ids = [block_id]
    
        fragment = self.get_content_fragment()
    
        with self._doc.transaction():
            if cascade_children:
                # Find children by indent
                parent_indent = _get_attr_safe(elem.attributes, "indent", 0)
                if isinstance(parent_indent, str):
                    try:
                        parent_indent = int(parent_indent)
                    except ValueError:
                        parent_indent = 0
    
                children = list(fragment.children)
                # Collect indices to delete (in reverse order to maintain positions)
                indices_to_delete = [index]
    
                for i in range(index + 1, len(children)):
                    child = children[i]
                    if not hasattr(child, "attributes"):
                        break
                    child_indent = _get_attr_safe(child.attributes, "indent", 0)
                    if isinstance(child_indent, str):
                        try:
                            child_indent = int(child_indent)
                        except ValueError:
                            child_indent = 0
    
                    if child_indent <= parent_indent:
                        break  # No longer a child
    
                    indices_to_delete.append(i)
                    child_id = _get_attr_safe(child.attributes, "data-block-id", None)
                    if child_id:
                        deleted_ids.append(child_id)
    
                # Delete in reverse order to maintain indices
                for idx in reversed(indices_to_delete):
                    del fragment.children[idx]
            else:
                del fragment.children[index]
    
        return deleted_ids
  • The @server.tool decorator registers the delete_block tool with the MCP server, defining its name, title, description (input/output schema), and handler function.
    @server.tool(
        name="delete_block",
        title="Delete Block",
        description=(
            "Delete a block by its ID. Use cascade=true to also delete all subsequent blocks "
            "with higher indent (indent-based children). Returns the list of deleted block IDs."
        ),
    )
    async def delete_block_tool(
        graph_id: str,
        document_id: str,
        block_id: str,
        cascade: bool = False,
        context: Context | None = None,
    ) -> dict:
        """Delete a block and optionally its indent-children.
    
        Args:
            graph_id: The graph containing the document
            document_id: The document containing the block
            block_id: The block to delete
            cascade: If True, also delete indent-children
        """
        auth = MCPAuthContext.from_context(context)
        auth.require_auth()
    
        if not graph_id or not graph_id.strip():
            raise ValueError("graph_id is required")
        if not document_id or not document_id.strip():
            raise ValueError("document_id is required")
        if not block_id or not block_id.strip():
            raise ValueError("block_id is required")
    
        try:
            await hp_client.connect_document(graph_id.strip(), document_id.strip())
    
            deleted_ids: list[str] = []
    
            def perform_delete(doc: Any) -> None:
                nonlocal deleted_ids
                writer = DocumentWriter(doc)
                deleted_ids = writer.delete_block_by_id(
                    block_id.strip(), cascade_children=cascade
                )
    
            await hp_client.transact_document(
                graph_id.strip(),
                document_id.strip(),
                perform_delete,
            )
    
            result = {
                "success": True,
                "graph_id": graph_id.strip(),
                "document_id": document_id.strip(),
                "deleted_block_ids": deleted_ids,
                "cascade": cascade,
            }
            return result
    
        except Exception as e:
            logger.error(
                "Failed to delete block",
                extra_context={
                    "graph_id": graph_id,
                    "document_id": document_id,
                    "block_id": block_id,
                    "error": str(e),
                },
            )
            raise RuntimeError(f"Failed to delete block: {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 discloses key behavioral traits: the destructive nature ('Delete'), the cascade effect for children blocks, and the return value ('Returns the list of deleted block IDs'). This covers the core behavior, though it doesn't mention permissions, error conditions, or rate limits, which would enhance transparency further.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose in the first sentence, followed by parameter guidance and return value in subsequent sentences. Each sentence earns its place by adding value: defining the action, explaining a key parameter, and stating the output. No wasted words, and it's appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations, 0% schema coverage, and no output schema, the description provides a basic but incomplete picture. It covers the destructive behavior and cascade effect, which is essential, but lacks details on permissions, error handling, or the structure of the returned list. For a mutation tool with multiple parameters, more context would be beneficial to ensure safe and correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description must compensate. It adds meaning for the 'cascade' parameter by explaining its effect ('to also delete all subsequent blocks with higher indent'), which is crucial beyond the schema's basic type. However, it doesn't clarify the semantics of 'graph_id', 'document_id', or 'block_id', leaving those parameters undocumented in both schema and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Delete a block by its ID') and resource ('block'), which is specific and unambiguous. It distinguishes from siblings like 'delete_folder' or 'delete_graph' by specifying the resource type. However, it doesn't explicitly differentiate from 'update_block' or 'batch_update_blocks' in terms of destructive intent beyond the verb 'Delete'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides implied usage guidance by mentioning the 'cascade' parameter effect ('to also delete all subsequent blocks with higher indent'), which suggests when to use this option. However, it lacks explicit when-to-use vs. alternatives (e.g., compared to 'delete_graph' or 'update_block' for partial modifications), and no prerequisites or exclusions are stated.

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/sophia-labs/mnemosyne-mcp'

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