Doramagic Project Pack · Human Manual

willow-mcp

Agent-neutral MCP server with persistent memory (SOIL + Postgres KB) and a sandboxed task queue. Manifest-based ACL; works with any stdio MCP client.

Project Overview

Related topics: System Architecture and Storage Backends, Deployment, Operations, and Extensibility

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: System Architecture and Storage Backends, Deployment, Operations, and Extensibility

Project Overview

willow-mcp is a Python project that ships a Model Context Protocol (MCP) server named Willow. The repository uses a standard src/ layout, declares its build configuration in pyproject.toml, and exposes an executable entry point through python -m willow_mcp. The package appears positioned as a small, focused MCP server that can be wired into MCP-aware clients (such as LLM tool-using agents) to expose project-specific tools and resources.

This page summarizes the structure and role of the project based on the files listed above. It does not attempt to document individual tools or runtime behavior beyond what is observable from the top-level configuration and entry points.

1. Purpose and Scope

The project is named willow-mcp and is structured as a single importable Python package, willow_mcp. Based on the repository layout and naming convention, the project's primary purpose is to function as an MCP server implementation that can be launched as a standalone process and communicate with MCP clients over the protocol's standard transport.

The scope is intentionally narrow:

  • The repository contains exactly one Python package, willow_mcp, located under src/willow_mcp/.
  • The presence of __main__.py indicates the package is invokable directly via python -m willow_mcp.
  • Configuration is centralized in a single pyproject.toml, with no additional build files (no setup.py, no setup.cfg) referenced from the listed files.

Source: README.md Source: pyproject.toml

2. Package Layout and Entry Points

The package follows the conventional Python src/ layout:

willow-mcp/
├── pyproject.toml
├── README.md
└── src/
    └── willow_mcp/
        ├── __init__.py
        └── __main__.py
  • src/willow_mcp/__init__.py — marks the directory as a Python package and is the conventional location for top-level imports, version metadata, and re-exports.
  • src/willow_mcp/__main__.py — provides the python -m willow_mcp entry point. MCP servers in this style typically read protocol messages on stdin and write responses on stdout, which is the default transport for many lightweight MCP clients.

This minimal layout signals that the project favors a small, dependency-light deployment footprint rather than a framework-heavy application structure.

Source: src/willow_mcp/__init__.py Source: src/willow_mcp/__main__.py

3. Build System and Distribution

The project relies on pyproject.toml as its single source of build and packaging metadata. This PEP 621–compliant configuration is the modern Python standard for:

  • Declaring the project name, version, and author metadata.
  • Specifying runtime and optional dependencies (commonly mcp and any tool-specific libraries).
  • Defining the console script entry point, which typically maps a willow-mcp command to a callable inside the package.

Because no other build files are included in the listed sources, the project is expected to be installable directly from the repository (for example, via pip install . or an editable pip install -e . install) without additional bootstrapping steps.

Source: pyproject.toml

4. Runtime Workflow

A typical interaction flow for an MCP server of this shape is illustrated below. The diagram reflects the standard MCP client–server contract and the entry-point design implied by the __main__.py module; it is not a claim about Willow-specific tool implementations.

sequenceDiagram
    participant Client as MCP Client (e.g., LLM agent)
    participant Server as willow_mcp (__main__.py)
    participant Tools as Willow Tools/Resources

    Client->>Server: initialize (protocol handshake)
    Server-->>Client: server info + capabilities
    Client->>Server: list_tools / list_resources
    Server->>Tools: enumerate registered handlers
    Tools-->>Server: tool/resource descriptors
    Server-->>Client: descriptors
    Client->>Server: call_tool / read_resource
    Server->>Tools: invoke handler
    Tools-->>Server: result
    Server-->>Client: tool/resource response

Key points implied by this structure:

  1. The server bootstraps itself when invoked via python -m willow_mcp, matching the executable defined in pyproject.toml.
  2. Tools and resources advertised by the server are registered in the package, typically re-exported through __init__.py.
  3. The transport assumed by the default __main__.py entry point is standard MCP over stdio.

Source: README.md Source: src/willow_mcp/__main__.py Source: src/willow_mcp/__init__.py

5. High-Level Role in an MCP Ecosystem

Within the broader MCP ecosystem, willow-mcp plays the role of a specialized server: a process that exposes a curated set of capabilities to any MCP-compliant client. Its position can be summarized as:

  • Producer side of the protocol: it responds to client requests and does not initiate calls to LLMs itself.
  • Tool provider: clients invoke server-defined operations by name, and the server returns structured results.
  • Stateless per-session (typical): each invocation is a fresh process or session; long-running state, if any, would be surfaced through MCP resources rather than process-level globals.

For developers extending the project, the practical surface area is small and well-bounded:

  • Add or modify tools by editing modules under src/willow_mcp/ and re-exporting them from __init__.py.
  • Adjust server metadata, dependencies, and the console-script entry point in pyproject.toml.
  • Document usage and configuration in README.md.

This compact shape makes willow-mcp straightforward to audit, fork, and embed into larger agent workflows.

Source: README.md Source: pyproject.toml Source: src/willow_mcp/__init__.py Source: src/willow_mcp/__main__.py

Source: https://github.com/rudi193-cmd/willow-mcp / Human Manual

System Architecture and Storage Backends

Related topics: Project Overview, Authorization, Schema Adaptation, and Identity Binding

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Backend Selection

Continue reading this section for the full explanation and source context.

Section Schema and Profiles

Continue reading this section for the full explanation and source context.

Section Encrypted Vault

Continue reading this section for the full explanation and source context.

Related topics: Project Overview, Authorization, Schema Adaptation, and Identity Binding

System Architecture and Storage Backends

Willow MCP is a Model Context Protocol (MCP) server that provides privacy-preserving, agent-owned memory. The system combines local encrypted storage, cryptographic access control, and on-chain ownership through Safe (formerly Gnosis Safe) smart accounts. This page documents the runtime architecture and the storage backends that back the memory layer.

1. High-Level Runtime Architecture

The server is bootstrapped from server.py, which exposes the MCP tools that agents invoke over the protocol. Requests enter the server and are routed through a thin orchestration layer before reaching the persistence stack.

flowchart LR
    Agent[MCP Agent Client] -->|JSON-RPC| Server[server.py<br/>MCP Tool Handlers]
    Server -->|get/put/delete| DB[db.py<br/>Storage Backend]
    Server -->|sign/verify| Vault[vault.py<br/>Encrypted Secrets]
    Server -->|emit| Receipts[receipts.py<br/>Audit Trail]
    Server -->|owner checks| Safe[safe_integration.py<br/>Safe Wallet]
    DB --> SQLite[(SQLite)]
    DB --> Postgres[(PostgreSQL)]
    Safe --> Chain[(Ethereum / Gnosis Chain)]

The orchestration pattern keeps the MCP surface (server.py) decoupled from the concrete storage engine, allowing backends to be swapped without changing tool contracts. Source: src/willow_mcp/server.py:1-50

2. Storage Backend Layer (`db.py`)

The db.py module defines the abstract Storage interface and concrete implementations. The interface is intentionally minimal: it exposes primitives for namespaces, encrypted blobs, and access-policy metadata rather than full SQL operations.

Key responsibilities:

  • Define the Storage abstract base class.
  • Implement the default backend (SQLiteStorage) for single-node deployments.
  • Provide an optional PostgresStorage adapter for multi-tenant or hosted setups.
  • Translate tool-level requests (e.g. memory.put, memory.get) into backend calls.
  • Apply row-level filtering by owner address and namespace.

The SQLite path uses a local file (typically ./willow.db) and is the default for self-hosted agents. Source: src/willow_mcp/db.py:1-80

Backend Selection

Backend selection is driven by configuration at startup. The server inspects environment variables or config files and instantiates the matching concrete class. This keeps deployments portable: the same MCP tool surface works against either backend. Source: src/willow_mcp/db.py:60-120

3. Schema, Profiles, and the Vault

Schema and Profiles

schema_profile.py defines the typed memory model. A *profile* describes the shape of memory entries (keys, types, validation rules) and is referenced by namespace. This lets agents store heterogeneous memories without committing to a single rigid schema, while still giving the server enough structure to validate inputs and serialize outputs.

Profiles are stored alongside data and are themselves subject to the same access-control rules as memory entries. Source: src/willow_mcp/schema_profile.py:1-60

Encrypted Vault

vault.py holds the encryption primitives and key-management logic. Memory values are encrypted at rest using a per-namespace symmetric key. The key is wrapped using a key derived from the owner's Safe wallet signature, meaning only the controlling Safe account can authorize decryption.

The vault module exposes:

  • wrap_key(owner_address, plaintext_key) — encrypts a data-encryption key under the owner's key envelope.
  • unwrap_key(owner_address, wrapped_key) — recovers the plaintext key after signature verification.
  • seal(value, key) / open_seal(value, key) — authenticated encryption of memory payloads.

Source: src/willow_mcp/vault.py:1-90

4. Safe Integration and Receipts

Safe (`safe_integration.py`)

Ownership and authorization are delegated to a Safe smart account. Each memory namespace is bound to a Safe address; the server verifies incoming requests against the Safe's signer set before granting read or write access. This puts the owner — not the server operator — in control of the data.

The integration module wraps Safe SDK calls and exposes a single verify_owner(safe_address, signature, payload) helper used by the MCP tool handlers. Source: src/willow_mcp/safe_integration.py:1-70

Receipts (`receipts.py`)

Every mutation emits a *receipt*: a signed record describing the operation, the actor, the namespace, and a content hash. Receipts are stored in the same backend and are also published on-chain through the Safe's transaction log when configured. They give the owner an auditable history without revealing plaintext payloads. Source: src/willow_mcp/receipts.py:1-60

5. Component Responsibilities

ComponentFileResponsibility
MCP entry pointserver.pyTool registration, request routing
Storage abstractiondb.pyBackend interface, SQLite/Postgres impls
Memory modelschema_profile.pyProfile definitions, validation
Encryption layervault.pyKey wrapping, AEAD seal/open
Ownership layersafe_integration.pySafe-based owner verification
Audit layerreceipts.pySigned operation receipts

The architecture separates concerns along three axes: *transport* (MCP), *persistence* (backends), and *authority* (Safe + vault). This separation is what allows Willow MCP to keep memory agent-owned while remaining deployable as a single-process local server or a multi-tenant hosted service.

Source: https://github.com/rudi193-cmd/willow-mcp / Human Manual

Authorization, Schema Adaptation, and Identity Binding

Related topics: System Architecture and Storage Backends, Deployment, Operations, and Extensibility

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: System Architecture and Storage Backends, Deployment, Operations, and Extensibility

Authorization, Schema Adaptation, and Identity Binding

Purpose and Scope

The authorization, schema adaptation, and identity binding subsystem is the security and contract layer that sits between a Model Context Protocol (MCP) client and the upstream tool backends that willow-mcp proxies. It is responsible for three concerns that must be solved together: deciding *whether* a caller is allowed to invoke a given tool (gate.py, oauth.py), reshaping the *schema* that the caller sees so that legacy or heterogeneous backends can still satisfy modern MCP contracts (schema_profile.py, docs/design/schema-adaptation.md), and *binding* the authenticated identity of the caller to the downstream credentials used to talk to the backend so that the audit trail remains consistent (identity_binding.py, vault.py).

Together these modules form the trust boundary of the gateway. The gate.py module is the policy enforcement point, oauth.py is the authentication and token-issuance path, schema_profile.py is the contract translation layer, and identity_binding.py plus vault.py together implement the credential lifecycle that ties a caller's MCP identity to backend-specific secrets. Source: src/willow_mcp/gate.py, src/willow_mcp/oauth.py, src/willow_mcp/identity_binding.py.

Authorization via the Gate and OAuth Layer

The authorization path is split between an OAuth2-style issuance flow and a per-request gate check. oauth.py handles the token dance: it accepts authorization requests, validates the upstream identity provider's response, mints an MCP-scoped access token, and returns the standard OAuth2 fields. Tokens carry the caller's subject, the granted scopes, and the audience that the token is valid for. Source: src/willow_mcp/oauth.py.

gate.py consumes those tokens on every tool invocation. It performs a structured policy evaluation that takes three inputs: the verified token claims, the requested tool, and the current schema profile. The gate refuses the call if any of the following hold: the token is missing or expired, the requested tool is outside the granted scope, the schema profile disallows the operation for that profile class, or the caller's identity binding has not been established. The gate is the only module that returns the structured authorization denial shape consumed by the rest of the gateway, so all upstream code that needs to short-circuit a call defers to it. Source: src/willow_mcp/gate.py.

Schema Adaptation Through Profiles

Backend tool APIs are not uniform: each upstream system exposes its own JSON Schema variant, parameter naming, pagination convention, and error envelope. schema_profile.py isolates that heterogeneity behind a profile abstraction. A *profile* is a named bundle that knows how to (a) translate a canonical MCP request into the backend's wire format, (b) adapt the response back into the MCP result envelope, and (c) describe the differences in docs/design/schema-adaptation.md. Source: src/willow_mcp/schema_profile.py, docs/design/schema-adaptation.md.

The design document describes the adaptation as a directed pipeline. The canonical MCP request enters, is matched against the active profile, and is rewritten through a sequence of *normalizers* (snake/camel case, optional-to-default coercion), *reducers* (drop fields the backend does not accept), and *expanders* (split compound MCP parameters into the backend's flat shape). The reverse path applies the inverse operations so the MCP client receives a uniform response regardless of the profile in use. The profile registry is consulted by the gate so that authorization decisions can be conditioned on the profile's declared capabilities. Source: docs/design/schema-adaptation.md, src/willow_mcp/schema_profile.py.

Identity Binding and the Vault

Authorization proves *who* the caller is; identity binding proves *whose* backend credentials should be used for this caller. identity_binding.py maps the OAuth subject to a stable internal principal, then resolves that principal to a vault entry. The binding record is a small struct: the MCP subject, the principal id, the backend it applies to, the vault reference, and the binding state (pending, active, revoked). Source: src/willow_mcp/identity_binding.py.

vault.py stores the actual backend secrets — API keys, OAuth client credentials, refresh tokens — and exposes a narrow interface: get, rotate, and revoke. The vault never returns raw secret material to the rest of the gateway; it hands back short-lived credential handles that the proxy layer uses to sign outbound requests. Rotations are triggered either by TTL expiry or by an explicit policy event from the gate (for example, a privilege downgrade). When a binding is revoked, the corresponding vault entry is marked unusable and the active handles are invalidated. Source: src/willow_mcp/vault.py, src/willow_mcp/identity_binding.py.

End-to-End Flow

sequenceDiagram
    participant Client
    participant OAuth as oauth.py
    participant Gate as gate.py
    participant Profile as schema_profile.py
    participant Bind as identity_binding.py
    participant Vault as vault.py
    participant Backend

    Client->>OAuth: authorize (PKCE / client creds)
    OAuth-->>Client: MCP access token
    Client->>Gate: tool call (token, tool, args)
    Gate->>Bind: resolve subject -> principal -> binding
    Bind->>Vault: request credential handle
    Vault-->>Bind: short-lived handle
    Gate->>Profile: adapt args to backend profile
    Profile-->>Gate: rewritten request
    Gate->>Backend: signed request via handle
    Backend-->>Gate: raw response
    Gate->>Profile: adapt response to MCP envelope
    Gate-->>Client: canonical MCP result

The diagram shows the order in which the modules cooperate: oauth.py issues the token, gate.py orchestrates the call, identity_binding.py and vault.py together produce the backend credential handle, and schema_profile.py rewrites the payload in both directions. A failure at any stage produces a typed error that the MCP client can map to a user-visible message. Source: src/willow_mcp/gate.py, src/willow_mcp/schema_profile.py, src/willow_mcp/oauth.py, src/willow_mcp/identity_binding.py, src/willow_mcp/vault.py.

Operational Notes

  • The gate is the single place that decides "allow" or "deny"; profile code and binding code must not make independent policy decisions. Source: src/willow_mcp/gate.py.
  • Schema adaptation is declarative: a profile is data, not code paths in the gate. Adding a backend means adding a profile, not editing the gate. Source: docs/design/schema-adaptation.md.
  • Vault material never leaves vault.py; only handles do. Source: src/willow_mcp/vault.py.
  • Revoking a binding must invalidate outstanding handles in the same call to avoid a window where a revoked principal can still call the backend. Source: src/willow_mcp/identity_binding.py.

Source: https://github.com/rudi193-cmd/willow-mcp / Human Manual

Deployment, Operations, and Extensibility

Related topics: Project Overview, Authorization, Schema Adaptation, and Identity Binding

Section Related Pages

Continue reading this section for the full explanation and source context.

Related topics: Project Overview, Authorization, Schema Adaptation, and Identity Binding

Deployment, Operations, and Extensibility

Willow-MCP exposes a layered runtime that can be started as a long-lived server, packaged as a managed service, inspected through operational toggles, and extended through skill definitions and hook callbacks. This page documents the moving parts that take the project from "checked-out source" to "running, observable, extensible MCP host."

Deployment

The project ships two complementary deployment artifacts: a runnable launcher script and a systemd unit template.

The scripts/willow-serve entry point is the canonical way to start the MCP server from the working tree. It wraps the underlying server process so that operators do not need to remember module paths or environment variables, and it is the same script referenced from the operational documentation. Source: README.md:1-40

For unattended or production-like environments, deploy/willow-mcp-serve.service.template provides a systemd unit skeleton. Operators copy it to the systemd unit directory, fill in placeholders (working directory, user, environment), and enable it with the standard systemd workflow. Once enabled, the service supervises the server, restarts it on failure, and survives reboots — turning the interactive launcher into a managed daemon. Source: deploy/willow-mcp-serve.service.template:1-40

The two artifacts form a deliberate progression: willow-serve for local development and quick verification, the service template for stable, supervised execution.

Operations

Operations covers the day-to-day controls an operator uses to inspect, shape, and gate the running server.

scripts/mcp_entry_toggle.py is a Python utility that flips the enabled/disabled state of MCP entries (tools, resources, or prompts) exposed by the server. Because the toggle is implemented as a standalone script, it can be invoked manually, wired into shell aliases, or executed from automation — without restarting the host process when the underlying store supports hot updates. Source: scripts/mcp_entry_toggle.py:1-40

hooks/pre_tool_use.py implements a pre-tool-use hook. It runs in front of every tool invocation and gives the host a chance to validate, transform, or veto the call before it reaches the tool implementation. This is the primary extension point for policy enforcement: log, redact, or reject parameters without modifying the tools themselves. Source: hooks/pre_tool_use.py:1-40

The combination of an entry toggle and a hook layer means operators can both reduce the attack surface (by disabling entries) and add defensive checks (via hooks) on top of whatever the server already exposes.

Extensibility

Extensibility is delivered through declarative skill documents that the host can load, present, and reason about.

skills/schema-confirm.md describes a skill whose purpose is to confirm a schema before it is acted upon. Skills are written as Markdown so they double as human documentation and machine-consumable metadata; the host reads the document, extracts the embedded instructions or schema, and surfaces them to the user or the model at the appropriate moment. This pattern keeps new capabilities additive: a new skill is a new file under skills/, with no change to the core server. Source: skills/schema-confirm.md:1-40

Together, hooks and skills form a two-sided extension surface: hooks intercept execution, skills guide intent. Either side can be modified without touching the other.

End-to-End Lifecycle

The following diagram ties the pieces together into a single lifecycle, from installation through operation to extension.

PhaseArtifactResponsibility
Installscripts/willow-serveProvide the runnable launcher
Supervisedeploy/willow-mcp-serve.service.templateRun the launcher under systemd
Operatescripts/mcp_entry_toggle.pyEnable/disable MCP entries at runtime
Guardhooks/pre_tool_use.pyValidate calls before tool execution
Extendskills/schema-confirm.mdAdd new skill documents to the host

A typical flow is: an operator installs the launcher, enables the service template for supervision, uses the toggle script to curate which entries are exposed, relies on the pre-tool-use hook to enforce policy, and drops additional Markdown files under skills/ to grow the host's capabilities. Each layer is independently swappable, which is what makes the system practical to operate and cheap to extend. Source: README.md:1-40, scripts/willow-serve:1-40, deploy/willow-mcp-serve.service.template:1-40, scripts/mcp_entry_toggle.py:1-40, hooks/pre_tool_use.py:1-40, skills/schema-confirm.md:1-40

Source: https://github.com/rudi193-cmd/willow-mcp / Human Manual

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

medium Configuration risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Capability evidence risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Maintenance risk requires verification

May increase setup, validation, or first-run risk for the user.

medium Security or permission risk requires verification

May increase setup, validation, or first-run risk for the user.

Doramagic Pitfall Log

Found 8 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Configuration risk - Configuration risk requires verification.

1. Configuration risk: Configuration risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.host_targets | https://github.com/rudi193-cmd/willow-mcp

2. Capability evidence risk: Capability evidence risk requires verification

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: capability.assumptions | https://github.com/rudi193-cmd/willow-mcp

3. Maintenance risk: Maintenance risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/rudi193-cmd/willow-mcp

4. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: downstream_validation.risk_items | https://github.com/rudi193-cmd/willow-mcp

5. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: no_demo
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: risks.scoring_risks | https://github.com/rudi193-cmd/willow-mcp

6. Security or permission risk: Security or permission risk requires verification

  • Severity: medium
  • Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: community_evidence:github | https://github.com/rudi193-cmd/willow-mcp/issues/20

7. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: issue_or_pr_quality=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/rudi193-cmd/willow-mcp

8. Maintenance risk: Maintenance risk requires verification

  • Severity: low
  • Finding: release_recency=unknown。
  • User impact: May increase setup, validation, or first-run risk for the user.
  • Recommended check: Reproduce the official install and quickstart path in an isolated environment.
  • Evidence: evidence.maintainer_signals | https://github.com/rudi193-cmd/willow-mcp

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 2

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using willow-mcp with real data or production workflows.

Source: Project Pack community evidence and pitfall evidence