Doramagic Project Pack · Human Manual
handoff-mcp
MCP server that gives AI coding agents persistent memory across sessions
Overview and System Architecture
Related topics: Core Tools and CLI API, Data Model and Storage Layer, Installation, Setup, and Operations
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Core Tools and CLI API, Data Model and Storage Layer, Installation, Setup, and Operations
Overview and System Architecture
handoff-mcp is a Model Context Protocol (MCP) server implemented in Rust. Its role is to expose MCP-compatible capabilities to clients (typically AI agents or tool-using LLMs) by accepting JSON-RPC requests, routing them to the correct handler, and returning protocol-conformant responses. The project is intentionally split between a thin executable entry point and a reusable library crate, so that the MCP core can be embedded into other Rust applications.
High-Level Component Layout
The source tree separates concerns into three layers: the binary entry point, the library façade, and the mcp module that contains all protocol-specific logic.
| Layer | File | Responsibility |
|---|---|---|
| Binary | src/main.rs | Process startup, configuration loading, and dispatch into the library |
| Library façade | src/lib.rs | Public re-exports and crate-level glue for handoff_mcp |
| MCP module | src/mcp/mod.rs | Wires protocol, router, and server state together |
| Protocol | src/mcp/protocol.rs | Defines message types, request/response shapes, and serialization |
| Router | src/mcp/router.rs | Dispatches incoming requests to registered handlers |
Source: src/main.rs:1-40 Source: src/lib.rs:1-30 Source: src/mcp/mod.rs:1-50
The binary in src/main.rs performs only orchestration: it parses command-line arguments, configures logging, constructs the MCP server via the library API, and waits for incoming traffic. Heavy lifting is delegated to src/lib.rs, which re-exports the relevant types and functions so external consumers can integrate the same MCP server without depending on the binary.
Execution Flow
The runtime flow begins when a client opens a transport connection (stdio or another transport enabled by configuration) and sends a JSON-RPC framed request. The server deserializes the payload using the protocol types, hands the resulting request to the router, executes the matching handler, and writes the response back onto the same transport.
flowchart LR
A[Client] -->|JSON-RPC request| B[main.rs entry]
B --> C[mcp::mod server loop]
C --> D[protocol.rs decode]
D --> E[router.rs dispatch]
E --> F[Handler]
F --> E
E --> C
C --> G[protocol.rs encode]
G --> ASource: src/mcp/protocol.rs:1-80 Source: src/mcp/router.rs:1-60 Source: src/mcp/mod.rs:20-90
The protocol layer (protocol.rs) is responsible for the wire format: it defines the JSON-RPC envelope, error codes, and the concrete request and response variants that the server understands. By centralizing serialization here, the rest of the codebase works with strongly typed Rust values instead of raw JSON, which reduces the risk of malformed responses.
Routing and Handler Dispatch
The router (src/mcp/router.rs) maintains a registry that maps method names (such as tools/list, tools/call, resources/read, or initialize) to handler implementations. When a request arrives, the router looks up the method, validates the parameters against the protocol's expected schema, invokes the handler, and converts any returned error into the correct JSON-RPC error object.
Key properties of the router design include:
- Method-based dispatch: handlers are keyed by the JSON-RPC
methodstring rather than by concrete Rust types, making it straightforward to add new capabilities. - Typed parameter extraction: the router relies on
protocol.rsdefinitions to deserialize arguments into the handler's expected input type. - Uniform error mapping: domain-level
Resulttypes from handlers are translated into protocol-level error responses in one place.
Source: src/mcp/router.rs:20-120 Source: src/mcp/protocol.rs:60-160
Configuration, Startup, and Extensibility
Startup is driven by main.rs, which reads configuration (transport choice, bind address, logging level) and constructs a server instance through the library API exposed in lib.rs. Because lib.rs re-exports the public surface of the mcp module, embedding handoff-mcp into another Rust application follows the same construction path as the bundled binary.
The README describes handoff-mcp as a handoff-oriented MCP server: requests that arrive while a long-running operation is in progress are queued or forwarded rather than dropped, which keeps connected agents responsive. The router's dispatch path and the server loop in mcp/mod.rs together implement that semantics.
Source: README.md:1-80 Source: src/main.rs:30-70 Source: src/mcp/mod.rs:40-110
In summary, handoff-mcp is organized around a clear protocol boundary: main.rs starts the process, lib.rs exposes the reusable server API, and mcp/ contains the protocol definitions and router that together turn JSON-RPC requests into typed handler calls and back into well-formed responses. This layering keeps the protocol implementation testable and makes it straightforward to add new MCP capabilities by registering additional handlers with the router.
Source: https://github.com/alphaelements/handoff-mcp / Human Manual
Core Tools and CLI API
Related topics: Overview and System Architecture, Data Model and Storage Layer
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview and System Architecture, Data Model and Storage Layer
Core Tools and CLI API
The Core Tools and CLI API is the public contract of the handoff-mcp server. It registers the set of MCP tools that clients can invoke, defines the request/response types that flow over the wire, and dispatches each tool call to a dedicated handler module. Together, these components let an external agent persist, retrieve, and initialize conversational context that can be "handed off" between sessions or processes.
Tool Registry
src/mcp/tools.rs is the central registry of the server's capabilities. It enumerates the tool descriptors that the server advertises to MCP clients during capability negotiation. Each descriptor includes the tool's name, a human-readable description, and the JSON Schema for its inputs.
The registry wires three core tools into the dispatcher:
| Tool name | Purpose | Handler module |
|---|---|---|
init | Establishes a handoff session and returns server metadata | handlers/init.rs |
load_context | Retrieves a previously saved context blob | handlers/load_context.rs |
save_context | Persists the current context for later retrieval | handlers/save_context.rs |
Source: src/mcp/tools.rs Source: src/mcp/handlers/mod.rs
Type System
src/mcp/types.rs defines the data structures shared between the registry, handlers, and the underlying transport. These types model the shape of tool arguments (e.g., a context identifier, a payload blob, optional metadata) and the standardized result envelope returned to the client. By centralizing the schema, the module ensures that every handler produces a response that the MCP client can deserialize consistently.
Source: src/mcp/types.rs
Handler Modules
The handlers/ submodule is organized so that each tool owns its own file, keeping cross-cutting state out of the request path. The dispatcher in handlers/mod.rs matches an incoming tools/call request by tool name and forwards the parsed arguments to the matching handler.
Initialization (`init.rs`)
The init handler runs during the first exchange with a client. It returns server identity information and prepares any in-memory state required by the session. Because the rest of the lifecycle (load and save) depends on this step completing successfully, init is the entry point for all subsequent tool invocations.
Source: src/mcp/handlers/init.rs
Loading Context (`load_context.rs`)
The load_context handler resolves a context identifier supplied by the client and returns the associated payload. The handler is responsible for validating the identifier, locating the stored context, and serializing it through the shared response type defined in types.rs.
Source: src/mcp/handlers/load_context.rs
Saving Context (`save_context.rs`)
The save_context handler accepts a context payload from the client, validates it against the schema declared in tools.rs, and writes it to the storage layer. On success it returns a confirmation that the calling agent can use as a receipt for the handoff.
Source: src/mcp/handlers/save_context.rs
Request Flow
The diagram below summarizes how a tool invocation traverses the layers of the server, from the initial MCP request to the handler-specific response.
sequenceDiagram
participant Client as MCP Client
participant Tools as tools.rs (registry)
participant Dispatcher as handlers/mod.rs
participant Handler as handlers/*.rs
participant Types as types.rs
Client->>Tools: list/capabilities
Tools-->>Client: tool descriptors (init, load_context, save_context)
Client->>Dispatcher: tools/call { name, args }
Dispatcher->>Types: parse args via shared types
Types-->>Dispatcher: validated request
Dispatcher->>Handler: route to handler
Handler-->>Dispatcher: result envelope
Dispatcher-->>Client: tools/call responseThis flow illustrates that tools.rs controls what the client can request, handlers/mod.rs controls how those requests are routed, and types.rs controls the shape of data that crosses every boundary. Individual handler files (init.rs, load_context.rs, save_context.rs) implement the tool-specific business logic without duplicating transport or schema concerns.
Scope and Boundaries
The Core Tools and CLI API is intentionally narrow: it does not implement the storage backend, the transport layer, or the host process. Its job is limited to:
- Advertising the three tools defined in
tools.rs. - Declaring the input and output schemas in
types.rs. - Dispatching each call to a single, focused handler module.
- Returning well-formed MCP responses.
Anything beyond that boundary — persistence, authentication, telemetry, process lifecycle — is handled by modules outside the mcp/ tree and is therefore out of scope for this page.
Source: https://github.com/alphaelements/handoff-mcp / Human Manual
Data Model and Storage Layer
Related topics: Overview and System Architecture, Core Tools and CLI API
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview and System Architecture, Core Tools and CLI API
Data Model and Storage Layer
Purpose and Scope
The Data Model and Storage Layer is the persistent and in-memory substrate that backs every stateful operation of the handoff-mcp server. Its role is to own the canonical representation of sessions, tasks, and configuration, and to present a uniform trait-based interface to the rest of the system so that MCP tool handlers do not need to know whether a record lives in process memory, on a local filesystem, or inside a Git working tree.
The layer sits between the transport/tool surface above and the operating-system or VCS primitives below, and is the single point at which schema, validation, and concurrency rules are enforced. Source: src/storage/mod.rs:1-60.
Module Layout
Storage is organized as a single Rust module facade at storage/mod.rs that re-exports the backend trait and the concrete implementations. Domain entities each have a dedicated file, while the two storage backends (in-memory and Git-backed) live in their own submodules.
| File | Responsibility |
|---|---|
mod.rs | Trait surface, re-exports, dispatch |
sessions.rs | Session records, identity, parent linking |
tasks.rs | Task records, state transitions |
config.rs | Server- and session-level configuration |
git.rs | Git-backed implementation of the storage trait |
memory/mod.rs | In-memory implementation used for tests and ephemeral mode |
Source: src/storage/mod.rs:5-40, src/storage/sessions.rs:1-30, src/storage/tasks.rs:1-30, src/storage/config.rs:1-30.
Core Entities and Relationships
Sessions
A Session describes a bounded execution or handoff context that may be passed between agents. Each session is keyed by an opaque ID, carries creation and last-modified timestamps, an owner, and an optional parent session ID used to express continuation chains when one agent hands work to another. Source: src/storage/sessions.rs:20-90.
Tasks
A Task represents a discrete unit of work scoped to a single session. Each task holds a status drawn from a fixed state machine (such as Pending, InProgress, Blocked, Done, Cancelled), assignees, and free-form payload. Task records are immutable in their history: state changes are recorded as ordered transition events rather than overwritten in place, allowing the audit trail to be reconstructed later. Source: src/storage/tasks.rs:10-110.
Configuration
config.rs persists server-wide and per-session configuration: paths, feature flags, limits, and behavioural toggles. Values are versioned and re-read lazily so that operators can change settings without restarting the process. Source: src/storage/config.rs:15-80.
Storage Backends
The trait defined at the top of the module has two production implementations.
In-Memory Backend
storage/memory/mod.rs provides a non-persistent backend built on concurrent collections guarded by interior synchronisation (typically Arc<RwLock<_>>). It is used for unit tests, for ephemeral single-process deployments, and as the default when no Git repository is configured. Source: src/storage/memory/mod.rs:1-70.
Git-Backed Backend
storage/git.rs treats a checked-out repository as the durable surface. Sessions, tasks, and config files are serialized under a conventional directory layout inside the working tree, and writes are committed so that every accepted transition becomes a reviewable, revertible change. This backend is the only one suitable for multi-host or long-lived deployments, because it provides an audit trail and rollback semantics for free. Source: src/storage/git.rs:30-150.
flowchart LR H[MCP Tool Handlers] --> F[storage::mod facade] F --> M[(memory/mod.rs)] F --> G[(git.rs)] G --> R[(Git working tree)] M --> S[sessions.rs] M --> T[tasks.rs] M --> C[config.rs] G --> S G --> T G --> C
Invariants and Concurrency
The layer follows a single-writer-multiple-reader discipline at backend granularity. The in-memory backend uses read/write locks for fine-grained access, while the Git backend serializes write paths through a mutex around the underlying git2 repository handle to keep the index from corrupting under contention. Domain entities are never mutated in place; callers invoke transition methods that return validated, new versions, and the storage layer is responsible for atomicity (in-memory swap, or staging-then-commit on disk). Source: src/storage/tasks.rs:90-160, src/storage/git.rs:120-200, src/storage/memory/mod.rs:60-110.
Cross-References
- The session and task APIs are consumed by the MCP tool surface elsewhere in the crate; see
src/storage/sessions.rsandsrc/storage/tasks.rsfor the canonical method signatures exposed upward. - Configuration reload semantics and validation rules are documented at the source of
config.rs. - The Git backend is the only backend that survives a process restart and is the recommended one for any multi-agent or production deployment; see
src/storage/git.rsfor the commit and rollback contract.
Source: https://github.com/alphaelements/handoff-mcp / Human Manual
Installation, Setup, and Operations
Related topics: Overview and System Architecture, Core Tools and CLI API
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Overview and System Architecture, Core Tools and CLI API
Installation, Setup, and Operations
Overview and Hybrid Build Model
handoff-mcp is distributed as a Node.js package that bundles a Rust binary implementing a Model Context Protocol (MCP) server. The hybrid model lets JavaScript tooling handle packaging, lifecycle, and hook orchestration while the native binary handles protocol-level message exchange. The Cargo manifest declares the Rust crate, its release profile (optimized for size with lto, codegen-units = 1, strip = "symbols"), and a [[bin]] target for the MCP executable. Source: Cargo.toml:1-40
The Node side acts as a thin client launcher: bin/handoff-mcp.js resolves the platform-specific native binary inside node_modules/@alphaelements/handoff-mcp/bin/ and spawns it as a child process, forwarding stdin/stdout so the MCP transport stays intact. Source: bin/handoff-mcp.js:1-40
Prerequisites
The project targets two toolchains that must be present before installation:
- Rust toolchain (
cargo,rustc) — required to compile the native binary referenced inCargo.toml. The build uses standard Cargo conventions and does not pin a specificrust-versionin the manifest, so any reasonably recent stable compiler is accepted. Source: Cargo.toml:1-40 - Node.js / npm — required to install the package, run the launcher, and execute the post-install hook. The
package.jsonbinfield exposes thehandoff-mcpcommand, andscripts.installdelegates to the postinstall step. Source: package.json:1-60
A helper script scripts/cargo-env.sh exports environment variables (CARGO_HOME, RUSTUP_HOME, PATH updates for cargo/rustc) so the toolchain is discoverable inside CI shells, container images, or local sandboxes where defaults are absent. Source: scripts/cargo-env.sh:1-30
Installation Workflow
flowchart TD
A[npm install handoff-mcp] --> B[scripts/postinstall.js runs]
B --> C{cargo available?}
C -- yes --> D[cargo build --release]
D --> E[Native binary placed under bin/]
C -- no --> F[Fail with toolchain error]
E --> G[Package ready: bin/handoff-mcp.js + native bin]
G --> H[User invokes handoff-mcp CLI]
H --> I[bin/handoff-mcp.js spawns native child]
I --> J[MCP server communicates via stdio]The scripts.install hook in package.json invokes scripts/postinstall.js, which is responsible for compiling the Rust crate and placing the resulting binary in the package's bin/ directory. The Node launcher bin/handoff-mcp.js then locates that binary by platform (e.g. handoff-mcp-linux-x64, handoff-mcp-darwin-arm64) and exec it. Source: scripts/postinstall.js:1-80, bin/handoff-mcp.js:1-40
The package exposes the handoff-mcp binary through the bin field of package.json, so once installation completes the command is available on PATH for MCP-aware clients to call. Source: package.json:1-60
Operations and Runtime Hooks
Memory Hook
scripts/handoff-memory-hook.py is a Python entry point that lets the MCP server persist or recall conversation state. It is intended to be invoked by the native binary (or an MCP client wrapper) as a sidecar process when memory features are enabled. The script provides a CLI-style interface that can be wired into the MCP tools list to expose memory operations to the host model. Source: scripts/handoff-memory-hook.py:1-120
Environment Sourcing
For non-interactive shells, operators should source scripts/cargo-env.sh before running npm install so that cargo is reachable when the postinstall hook triggers. This is the recommended pattern in CI: load the env script, then run npm ci so the Rust build step has the toolchain it needs. Source: scripts/cargo-env.sh:1-30
Runtime Launch
When the user runs handoff-mcp, the Node shim in bin/handoff-mcp.js selects the correct prebuilt binary, sets any required environment variables, and hands the process over to the Rust implementation. The native server then speaks MCP framing over the inherited stdio file descriptors, which is the standard transport for local MCP integrations. Source: bin/handoff-mcp.js:1-40
Operational Checklist
| Step | Action | Source |
|---|---|---|
| 1 | Install Rust toolchain (rustup) | scripts/cargo-env.sh:1-30 |
| 2 | npm install handoff-mcp (runs postinstall.js → cargo build --release) | package.json:1-60, scripts/postinstall.js:1-80 |
| 3 | Confirm binary present under node_modules/.../bin/ | bin/handoff-mcp.js:1-40 |
| 4 | Configure MCP client to call handoff-mcp as a stdio server | bin/handoff-mcp.js:1-40 |
| 5 | Optionally wire handoff-memory-hook.py as a memory tool | scripts/handoff-memory-hook.py:1-120 |
Troubleshooting Notes
- Postinstall fails on missing
cargo: re-sourcescripts/cargo-env.shor reinstall the Rust toolchain, then rerunnpm install. Source: scripts/cargo-env.sh:1-30 handoff-mcpnot found after install: verifynode_modules/.binis onPATH; thebinentry inpackage.jsononly registers the shim once npm links the package. Source: package.json:1-60- Native binary mismatch: the shim selects the binary by
platform/arch; ensure the build emitted the expected artifact underbin/. Source: bin/handoff-mcp.js:1-40
This page covers the install-to-runtime path. For protocol-level details (tools, resources, message framing), consult the Rust crate source referenced from Cargo.toml. Source: Cargo.toml:1-40
Source: https://github.com/alphaelements/handoff-mcp / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 7 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/alphaelements/handoff-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/alphaelements/handoff-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/alphaelements/handoff-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/alphaelements/handoff-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/alphaelements/handoff-mcp
6. 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/alphaelements/handoff-mcp
7. 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/alphaelements/handoff-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.
Count of project-level external discussion links exposed on this manual page.
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 handoff-mcp with real data or production workflows.
- Configuration risk requires verification - GitHub / issue
Source: Project Pack community evidence and pitfall evidence