Skip to main content

LangChain integration for Daftari — wrap a Daftari MCP vault as LangChain tools.

Project description

langchain-daftari

The store that knows when it's wrong.

langchain-daftari wraps a Daftari MCP vault as LangChain tools so a LangGraph agent can read, search, write, and curate a long-lived, file-backed knowledge base — instead of re-deriving the same answer every session.

Why

Vector RAG retrieves passages. Daftari stores compiled answers — markdown notes with frontmatter (status, confidence, provenance, decay), git history, and an advisory linter. The vault is the agent's memory across runs.

Plug it into any LangChain/LangGraph workflow and you get four properties for free:

  • Search before derive. The wrapper marks vault_search as CRITICAL: Call this BEFORE synthesizing an answer from scratch.
  • Long-lived state. Notes persist between sessions. Git history is the audit log.
  • Curation. vault_lint flags stale, low-confidence, or unsourced notes.
  • Provenance. Every write is auto-committed; vault_provenance traces who added what when.

Install

pip install langchain-daftari
# also install daftari itself (Node.js MCP server)
npm install -g daftari

Requirements:

  • Python ≥ 3.10
  • Node.js ≥ 18 (Daftari is shipped on npm)

Quick start

from langchain_daftari import DaftariClient, create_daftari_tools
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic

with DaftariClient(vault_path="./my-vault", user="me", role="admin") as client:
    tools = create_daftari_tools(client)
    agent = create_react_agent(
        ChatAnthropic(model="claude-sonnet-4-6"),
        tools=tools,
    )
    result = agent.invoke({"messages": [
        ("system", "Search the vault before answering."),
        ("user", "What's our current take on Daftari vs vanilla RAG?"),
    ]})
    print(result["messages"][-1].content)

Don't have a vault yet? Scaffold one with npx daftari --init ./my-vault.

What you get: 14 tools

Category Tools
Read vault_read, vault_index, vault_status
Search vault_search, vault_search_related, vault_themes, vault_reindex
Write vault_write, vault_append, vault_promote, vault_deprecate
Curate vault_tension_log, vault_lint, vault_provenance

Tool names, descriptions, and argument schemas come from the live MCP server's tools/list response — never from baked-in copies — so the wrapper layer tracks server changes automatically when you upgrade daftari.

vault_search description override

The wrapper layer prepends one line to vault_search's server-side description:

CRITICAL: Call this BEFORE synthesizing an answer from scratch. The vault may already contain a compiled, reviewed answer.

The override is wrapper-side only — daftari's own description stays neutral so other MCP clients (Claude Code, raw MCP) aren't strong-armed into a LangGraph-specific workflow.

The search-before-derive pattern

Pair the description override with a system prompt that reinforces the discipline:

SEARCH_BEFORE_DERIVE = """\
Core discipline: SEARCH BEFORE YOU DERIVE.

1. Before answering any non-trivial question, call vault_search.
2. If the vault has a compiled note, answer from it and cite the path.
3. If not, do the work, then vault_write a draft so future-you can find it.
4. If a note is stale or incomplete, vault_append or vault_promote.
"""

See examples/demo_research_agent.py for a runnable three-day simulation that asserts the agent actually searches before answering on day 2 and day 3.

Filtering the tool surface

# only read-side tools for a "research-only" agent
tools = create_daftari_tools(client, include={
    "vault_search", "vault_search_related", "vault_read", "vault_status",
})

# everything except destructive curation
tools = create_daftari_tools(client, exclude={"vault_deprecate", "vault_tension_log"})

Architecture

┌─────────────────────────┐
│  LangGraph ReAct agent  │
└────────────┬────────────┘
             │  StructuredTool.invoke / ainvoke
             ▼
┌─────────────────────────┐
│  create_daftari_tools   │   builds one StructuredTool per MCP tool
└────────────┬────────────┘
             │  DaftariClient.call_tool / acall_tool
             ▼
┌─────────────────────────┐
│      DaftariClient      │   subprocess + ClientSession on a
│   (transport primitive) │   dedicated background event loop
└────────────┬────────────┘
             │  JSON-RPC over stdio (MCP)
             ▼
┌─────────────────────────┐
│  daftari MCP server     │   Node.js, manages vault + SQLite index + git
└─────────────────────────┘

DaftariClient runs the MCP session on its own background event loop so a single client can be shared safely by multi-threaded sync callers and async event-loop callers without each call having to spawn a fresh subprocess.

Reference: DaftariClient

DaftariClient(
    *,
    vault_path: str,                          # required
    user: str = "guest",
    role: str = "guest",
    command: list[str] | None = None,         # default: ["npx", "daftari"]
    env: dict[str, str] | None = None,
    timeout: float = 30.0,
)
  • Pass command=["daftari"] for a global npm install.
  • Pass command=["node", "/path/to/daftari/dist/cli.js"] to run a local clone.
  • Pass command=["npx", "-y", "daftari@1.12.6"] to pin a version.

Sync surface: client.call_tool(name, args) returns DaftariResponse. Async surface: await client.acall_tool(name, args) does the same, safe from any event loop.

DaftariResponse has:

  • .text — concatenated text content blocks
  • .data — parsed JSON if the text looks like JSON, otherwise the raw string
  • .is_error — whether the MCP server flagged the call as an error
  • .raw — the underlying mcp.types.CallToolResult for advanced inspection

Compatibility

langchain-daftari is compatible with daftari ≥ 1.12.0, < 2.0.0 on npm.

The compatibility line is documented here rather than pinned as a Python dependency because daftari ships as an npm package, not a Python package. The package will get a major version bump on the Python side if any of the following happens server-side:

  • A tool is removed.
  • A tool's input schema changes in a breaking way.
  • The MCP protocol version changes.

Tool additions and non-breaking schema changes do not require a major bump because the wrapper layer reads schemas live from tools/list.

Development

cd integrations/langchain
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"

pytest                            # all 34 tests (28 mock + 6 integration)
pytest -m "not integration"       # mock-only, no Node.js required

The integration tests boot a real daftari subprocess via npx. They skip themselves cleanly if npx isn't on PATH.

Status & roadmap

This is phase 1 — a thin LangChain tool wrapper over the daftari MCP surface. DaftariClient is deliberately LangChain-free so the same transport primitive can carry phase 2:

  • Phase 2DaftariStore(BaseStore) for LangGraph long-term memory, so daftari can sit behind the store= arg on create_react_agent and behind MemorySaver for thread-scoped state.

Out of scope for this release: an async-first user surface, LangServe deployers, and any opinionated retriever / chain abstractions on top of the raw tools.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_daftari-0.1.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_daftari-0.1.0-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

Details for the file langchain_daftari-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_daftari-0.1.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for langchain_daftari-0.1.0.tar.gz
Algorithm Hash digest
SHA256 682d0e2f1a24a5916bf943464f295c9b3c8652b4e1a4dc25bae869be30d03aac
MD5 e177574e0249d4a94cfb93d86114fb86
BLAKE2b-256 617843bfbfb5bc7578aa74527535d98cacf833b6711b365d31500d3041285dc7

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_daftari-0.1.0.tar.gz:

Publisher: workflow.yml on mavaali/daftari

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file langchain_daftari-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langchain_daftari-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91f143c547362fa937ca1dfe267f9b24d526223e9026240b1c017e52a93a11f2
MD5 e44056cfabc2c689af1f8cc740696e58
BLAKE2b-256 beb0b47587af8c8d5550e4cf13976111c7836906685a2d7ed7e05a4b5d7041d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_daftari-0.1.0-py3-none-any.whl:

Publisher: workflow.yml on mavaali/daftari

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page