Skip to main content
Glama

zk_remove_link

Delete a link between two notes in a Zettelkasten system by specifying source and target note IDs, optionally removing bidirectional connections.

Instructions

Remove a link between two notes. Args: source_id: ID of the source note target_id: ID of the target note bidirectional: Whether to remove the link in both directions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bidirectionalNo
source_idYes
target_idYes

Implementation Reference

  • MCP tool decorator and handler function implementing zk_remove_link. Handles input parameters, calls ZettelService.remove_link, and returns success/error messages.
    @self.mcp.tool(
        name="zk_remove_link",
        description="Remove an existing link between two notes.",
        annotations={
            "readOnlyHint": False,
            "destructiveHint": True,
            "idempotentHint": True,
        },
    )
    def zk_remove_link(
        source_id: str, target_id: str, bidirectional: bool = False
    ) -> str:
        """Remove an existing link between two notes.
    
        Args:
            source_id: The unique ID of the source note
            target_id: The unique ID of the target note
            bidirectional: If true, removes links in both directions (source→target and target→source)
        """
        try:
            # Remove the link
            source_note, target_note = self.zettel_service.remove_link(
                source_id=str(source_id),
                target_id=str(target_id),
                bidirectional=bidirectional,
            )
            if bidirectional:
                return f"Bidirectional link removed between {source_id} and {target_id}"
            else:
                return f"Link removed from {source_id} to {target_id}"
        except Exception as e:
            return self.format_error_response(e)
    
    logger.debug("Tool zk_remove_link registered")
  • ZettelService.remove_link method called by the tool handler. Retrieves notes, calls model remove_link on source (and target if bidirectional), and persists changes.
    def remove_link(
        self,
        source_id: str,
        target_id: str,
        link_type: Optional[LinkType] = None,
        bidirectional: bool = False
    ) -> Tuple[Note, Optional[Note]]:
        """Remove a link between notes."""
        source_note = self.repository.get(source_id)
        if not source_note:
            raise ValueError(f"Source note with ID {source_id} not found")
        
        # Remove link from source to target
        source_note.remove_link(target_id, link_type)
        source_note = self.repository.update(source_note)
        
        # If bidirectional, remove link from target to source
        reverse_note = None
        if bidirectional:
            target_note = self.repository.get(target_id)
            if target_note:
                target_note.remove_link(source_id, link_type)
                reverse_note = self.repository.update(target_note)
        
        return source_note, reverse_note
  • Note model method that implements the core link removal logic by filtering the links list and updating timestamp.
    def remove_link(self, target_id: str, link_type: Optional[LinkType] = None) -> None:
        """Remove a link to another note."""
        if link_type:
            self.links = [
                link for link in self.links 
                if not (link.target_id == target_id and link.link_type == link_type)
            ]
        else:
            self.links = [link for link in self.links if link.target_id != target_id]
        self.updated_at = datetime.datetime.now()
  • Enum defining possible link types used in remove_link operations.
    class LinkType(str, Enum):
        """Types of links between notes."""
        REFERENCE = "reference"        # Simple reference to another note
        EXTENDS = "extends"            # Current note extends another note
        EXTENDED_BY = "extended_by"    # Current note is extended by another note
        REFINES = "refines"            # Current note refines another note
        REFINED_BY = "refined_by"      # Current note is refined by another note
        CONTRADICTS = "contradicts"    # Current note contradicts another note
        CONTRADICTED_BY = "contradicted_by"  # Current note is contradicted by another note
        QUESTIONS = "questions"        # Current note questions another note
        QUESTIONED_BY = "questioned_by"  # Current note is questioned by another note
        SUPPORTS = "supports"          # Current note supports another note
        SUPPORTED_BY = "supported_by"  # Current note is supported by another note
        RELATED = "related"            # Notes are related in some way

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/Liam-Deacon/zettelkasten-mcp'

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