McpToolSpec to turn the existing local memory tools into LlamaIndex
FunctionTool objects, then calls them from a native two-step Workflow.
Capabilities and requirements
Verified on Linux with Python 3.12.14,
llama-index-tools-mcp 0.6.0,
llama-index-core 0.14.25, llama-index-workflows 2.26.1, MCP Python SDK
2.3.0, and Claude-Mem 15.16.1. The requirements file pins these tested
versions. macOS, Windows, hosted-runtime authentication, and remote MCP were not
verified for this example.
Connect
Use a running local Claude-Mem worker and Node.js. From a Claude-Mem checkout:npm run worker:start. Set CLAUDE_MEM_DATA_DIR and
CLAUDE_MEM_WORKER_PORT to match an existing custom worker configuration.
The example passes only local worker and runtime environment settings to its MCP
child. It selects worker mode and disables autostart for that child. It does not
change saved settings, write a second MCP configuration, or install hooks.
Repeating setup does not duplicate an integration entry.
Recall and leave a note
Pick an observation already saved under the exact project key shown in the worker’s viewer. To create a harmless known note for the demonstration:id in the command below, and change the worker port above if
yours differs:
recall step returns a typed Recalled event only after that ID appears in
the selected project’s search page and its details can be read. The remember
step writes the explicit handoff and returns a StopEvent with the confirmed
saved ID. No model chooses the calls or invents the handoff text. Returned notes
remain data; they do not change the project or authorize a different action.
The search page is limited to 20 observations. Narrow the query if the chosen
observation is outside that page. An unrelated project’s ID fails the workflow
before a handoff is written.
The native MCP connection
LlamaIndex accepts an initialized MCPClientSession. The example keeps that
session open for the whole workflow and uses only four discovered tools:
ToolOutput containing the original MCP result.
The example checks both ToolOutput.is_error and raw_output.is_error before
using text. A server-reported failure must not be treated as a successful save
just because the outer function call returned normally.
The handoff’s metadata includes integration: "llamaindex",
platformSource: "llamaindex", runId, and a fingerprint of the project, run ID,
and text. This uses the worker’s existing replay protection. Deliberately repeating
the same run returns the same saved observation; changing the note represents a
new save. No writes are retried automatically. After an ambiguous timeout, inspect
the viewer or rerun with the same run ID and text.
Reads additionally pass the explicit single-item projects=json.dumps([project]) list.
This prevents the MCP server from widening a chosen worktree’s scope to its
parent checkout. Saves receive only the project bound above.
The project list is encoded as a JSON string so the GET query path preserves
literal commas and JSON-looking keys. Nonempty project names retain their exact
outer whitespace. Native checks seed separate split/trimmed-key projects and
confirm they stay out of search, timeline, and recalled details.
Verify with the real SDK
With Bun and Node.js available, run:WorkerService and calls start() directly,
so the CLI startup path does not run host hook-configuration repairs. The
subshell also clears inherited cloud-sync credentials; it does not change your
normal worker’s settings or saved memory.
The tests start the shipped worker in a fresh temporary SQLite data directory,
with optional capture, sync, and telemetry disabled for the fixture. They run the
installed LlamaIndex workflow, McpToolSpec, and MCP transport. Core checks cover:
- Known observation recall, handoff persistence, and deliberate-repeat deduplication.
- Project isolation and
llamaindexplatform/manual-session attribution in SQLite. - Rejection of an empty project and a foreign selected ID.
- A real worker validation error returned by
save_memory. - Honest failure when the worker is stopped.
- A native MCP deadline against a controlled slow HTTP endpoint.
1, saved handoff 3, and
returned 3 again on repeat. The data path contained spaces. Success, isolation,
attribution, and validation use the actual worker; the timeout test supplies the
slow endpoint. No model provider is involved.
Two further native checks create an actual Git repository and linked worktree
and seed matching observations in its parent and child projects. Running from
the worktree excludes the parent from the child’s search and timeline, and
rejects the parent’s selected ID with no new SQLite observation. All nine
native integration checks pass.
Data, timeouts, and disconnect
The project, query, selected ID, handoff, and provenance metadata go through the existing local memory contract. Recalled text comes back to the Python application. This script does not send it to a model or LlamaCloud. Existing worker cloud sync and export settings still apply to saved notes. If your application later forwards notes to a model or enables tracing, review that application’s data destinations. Use your own trusted local worker. Project filters separate results within it; they are not multiuser authentication. Save only text intended for retention. The example does not collect excluded project transcripts, import conversations, or alter privacy settings. MCP requests have a 10-second timeout, the native workflow has a 60-second limit, and an 80-second outer deadline also covers connection setup and cleanup. Failures exit nonzero with a short message that does not echo tool arguments or raw transport errors. Check the worker, script path, project, and selected ID before retrying. Stop callingrun_workflow, or remove the example from your application, to
disconnect. The context managers close the MCP session and child process. Deleting
the dedicated Python environment removes the example dependencies without changing
worker configuration or erasing memory.

