Zettelkasten MCP Server

repository·main·Indexed 41 days ago

https://github.com/entanglr/zettelkasten-mcp

A Model Context Protocol (MCP) implementation of the Zettelkasten knowledge management method. Version 1.2.1 allows AI clients like Claude to create, link, and explore atomic notes stored as Markdown files, utilizing a SQLite index for efficient graph traversal and querying.

Tokens
21K
Snippets
75
Records
90
Agent score
50%

What's inside Zettelkasten MCP

  1. How MCP Servers, Resources, Tools, and Prompts work together

    main

    The Model Context Protocol (MCP) standardizes how LLM applications interact with external data and functionality:

    • Server: The core interface (e.g., FastMCP) that manages connections, protocol compliance, and message routing.
    • Resources: Similar to GET endpoints in REST; they provide read-only data to be loaded into the LLM's context (e.g., config://app).
    • Tools: Similar to POST endpoints; they allow the LLM to execute code or perform actions that have side effects (e.g., calculate_bmi).
    • Prompts: Reusable templates that define interaction patterns for the LLM (e.g., a review_code template).
  2. Manage server lifecycle with the Low-Level Lifespan API

    main

    For advanced control, use the low-level Server implementation. The lifespan API allows you to manage resource initialization and cleanup (e.g., database connections) using an asynccontextmanager.

    Initialized resources are made available to request handlers via the server.request_context.lifespan_context dictionary.

    from contextlib import asynccontextmanager
    from collections.abc import AsyncIterator
    from mcp.server import Server
    
    @asynccontextmanager
    async def server_lifespan(server: Server) -> AsyncIterator[dict]:
        """Manage server startup and shutdown lifecycle."""
        # Initialize resources on startup
        db = await Database.connect()
        try:
            yield {"db": db}
        finally:
            # Clean up on shutdown
            await db.disconnect()
    
    # Pass lifespan to server
    server = Server("example-server", lifespan=server_lifespan)
    
    # Access lifespan context in handlers
    @server.call_tool()
    async def query_db(name: str, arguments: dict) -> list:
        ctx = server.request_context
        db = ctx.lifespan_context["db"]
        return await db.query(arguments["query"])
  3. Understand the Zettelkasten methodology used by the MCP server

    main

    The Zettelkasten MCP server implements a knowledge management system based on the Zettelkasten method. This method treats information as a directed graph where each note (a 'Zettel') is a node containing content and edge definitions (links).

    Key principles for interacting with the system include:

    • Atomicity: Each note should focus on a single, discrete concept.
    • Autonomy: Notes should be able to stand alone while maintaining connections to the rest of the network.
    • Explicit Linking: Knowledge is built through bidirectional references and non-linear connections rather than rigid hierarchies.
    • Identifier System: Notes are addressed using unique identifiers (e.g., timestamp-based like 202503261423 or alphanumeric branching like 12a1b2) which allow for temporal sequencing and conceptual branching.

    When using the tools, aim to create notes that follow these principles to ensure the graph remains traversable and useful for emergent knowledge discovery.

  4. Understand Zettelkasten Note Types

    main

    The Zettelkasten system uses specific note types to manage the lifecycle of an idea. Use these types when creating notes to maintain organizational clarity:

    • Fleeting notes: Temporary, unprocessed thoughts for quick capture.
    • Literature notes: Extracted ideas from external reading material, including proper citations.
    • Permanent notes: Well-formulated, standalone ideas written in your own words (the core of the system).
    • Structure notes: Maps or indexes that organize groups of notes on a specific topic.
    • Hub notes: Broad entry points into the Zettelkasten for major areas of interest.
  5. MCP Core Primitives

    main

    The MCP protocol is built on three core primitives:

    PrimitiveControlDescriptionExample Use
    PromptsUser-controlledInteractive templates invoked by user choiceSlash commands, menu options
    ResourcesApplication-controlledContextual data managed by the client applicationFile contents, API responses
    ToolsModel-controlledFunctions exposed to the LLM to take actionsAPI calls, data updates
  6. Identify Zettelkasten note types and link types

    main

    The system recognizes specific typologies for notes and connections to structure the knowledge graph:

    Note Typologies

    • Literature Notes: Extracted concepts from external sources.
    • Permanent Notes: Processed, individual units of knowledge.
    • Structure Notes: Topical indexes used to organize related notes.
    • Hub Notes: Curated entry points into specific subject areas.
    • Sequential Links: Fixed paths or temporal sequences.
    • Structural Links: Hierarchical relationships.
    • Associative Links: Conceptual connections between ideas.

    Technical Syntax

    • Internal References: Uses a standardized syntax, typically [[note-id]].
    • Metadata: Often utilizes YAML frontmatter for attribute frameworks and tagging.
  7. Use the Semantic Linking System

    main

    To build a rich knowledge network, use specific semantic link types instead of generic connections. This helps define the relationship between ideas:

    Link TypeUse When
    referenceSimply connecting related information
    extendsOne note builds upon another
    refinesOne note clarifies or improves another
    contradictsOne note presents opposing views
    questionsOne note poses questions about another
    supportsOne note provides evidence for another
    relatedGeneric relationship when others don't fit
  8. Understand the Zettelkasten storage architecture

    main

    The system uses a dual storage approach to balance human readability with machine performance:

    1. Markdown Files (Source of Truth): All notes are stored as Markdown files with YAML frontmatter. You can edit these directly in any text editor or manage them via Git.
    2. SQLite Database (Indexing Layer): An index used for efficient querying, searching, and rapid knowledge graph traversal by the LLM.

    Important: If you edit Markdown files directly outside of the MCP tools, you must run the zk_rebuild_index tool to synchronize the SQLite database with your files. The database can be safely deleted and will be regenerated from the Markdown files.

  9. Quickstart: Create a simple MCP server with FastMCP

    main

    Use FastMCP to quickly build a server that exposes tools (functions that perform actions) and resources (data endpoints).

    from mcp.server.fastmcp import FastMCP
    
    # Create an MCP server
    mcp = FastMCP("Demo")
    
    # Add an addition tool
    @mcp.tool()
    def add(a: int, b: int) -> int:
        """Add two numbers"""
        return a + b
    
    # Add a dynamic greeting resource
    @mcp.resource("greeting://{name}")
    def get_greeting(name: str) -> str:
        """Get a personalized greeting"""
        return f"Hello, {name}!"
  10. Install the Zettelkasten MCP Server

    main

    To install the Zettelkasten MCP server, clone the repository and set up a virtual environment using uv.

    # Clone the repository
    git clone https://github.com/entanglr/zettelkasten-mcp.git
    cd zettelkasten-mcp
    
    # Create a virtual environment with uv
    uv venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    
    # Install dependencies
    uv add "mcp[cli]"
    
    # Install dev dependencies
    uv sync --all-extras
  11. Start the simple MCP server

    main

    You can start the server using either the default stdio transport or the sse (Server-Sent Events) transport. If using SSE, you must specify a port.

    Transport Options

    • stdio: The default transport method.
    • sse: Requires the --transport sse flag and a --port flag.
    # Using stdio transport (default)
    uv run mcp-simple-tool
    
    # Using SSE transport on custom port
    uv run mcp-simple-tool --transport sse --port 8000