Summary
Connect the Basic Memory memory provider through Hermes's native MCP runtime instead of maintaining a provider-owned MCP actor.
This is the implementation-specific follow-up to #1387 and replaces the transport approach in #1397. The user-facing goal remains the same: Hermes should support automatic Basic Memory recall and capture against an existing remote Streamable HTTP MCP endpoint.
Why this direction
Hermes v0.21.0 / v2026.8.31 and current upstream main provide PluginContext.call_mcp(server, tool, arguments, timeout=...). It is synchronous for plugin hooks and handlers, but executes through Hermes's existing MCP client and connection lifecycle:
- stdio and Streamable HTTP transports
- static headers and OAuth
- reconnect and session-expiry recovery
- circuit breaking and timeouts
- trust gates
- shared tool discovery and registration
Using that surface gives Hermes one owner for MCP connections. The Basic Memory provider remains responsible for memory policy—prefetch, automatic turn capture, session summaries, and commands—without duplicating transport state, retry rules, or an asyncio actor.
Relevant Hermes sources:
Proposed design
Configure Basic Memory once as a normal Hermes MCP server.
Remote:
memory:
provider: basic-memory
mcp_servers:
basic_memory:
url: "https://memory.example.com/mcp"
headers:
Authorization: "Bearer ${BASIC_MEMORY_API_KEY}"
plugins:
entries:
basic-memory:
mcp_allowlist:
- basic_memory
Local stdio uses the same path:
mcp_servers:
basic_memory:
command: "bm"
args: ["mcp"]
The provider receives a narrow callable backed by:
ctx.call_mcp("basic_memory", tool_name, arguments, timeout=timeout)
Provider lifecycle operations call the native MCP tools they need. The model receives the complete Basic Memory MCP tool surface through Hermes's normal discovery.
Expose the complete tool surface
Do not maintain a second, limited set of bm_* schemas.
- Return
[] from BasicMemoryProvider.get_tool_schemas().
- Do not configure
mcp_servers.basic_memory.tools.include or .exclude by default.
- Let Hermes register all Basic Memory tools, resources, and prompts directly.
- Retain the per-server
plugins.entries.basic-memory.mcp_allowlist; it authorizes provider-internal calls and is separate from model-facing tool filtering.
This also means newly added Basic Memory MCP tools become available without updating the Hermes provider.
Hermes prerequisite
There is one small upstream gap. The exclusive memory-provider _ProviderCollector delegates register_* methods to a real PluginContext, but currently hides non-registration capabilities such as call_mcp().
Submit an upstream Hermes change that explicitly forwards _ProviderCollector.call_mcp(...) to its lifecycle-owned PluginContext. Avoid reaching into Hermes's private MCP registries or calling _make_tool_handler from Basic Memory.
Set an explicit minimum Hermes version containing that forwarding API. Prefer a clear compatibility floor over keeping two independent MCP implementations indefinitely.
Acceptance criteria
- A supported Hermes release exposes
call_mcp() to exclusive memory-provider registration.
- Remote endpoint URL and authentication live in Hermes's canonical
mcp_servers.basic_memory configuration.
- Local stdio and remote HTTP use Hermes's native MCP lifecycle.
- The Basic Memory provider owns no MCP event loop, transport session, subprocess, reconnect logic, or actor.
- Automatic prefetch, turn capture, session summaries, and provider commands work through
ctx.call_mcp().
- All Basic Memory MCP tools are available through native Hermes discovery with no default include list.
- The limited duplicate
bm_* tool surface is removed.
- Clear integration tests start a real Basic Memory MCP endpoint and prove:
- Hermes discovers the complete Basic Memory tool surface.
- provider prefetch reads through the native connection.
- automatic turn capture writes through the same native connection.
- a transport reconnect does not create a second provider-owned session.
- Tests are scenario-focused integration tests rather than parameterized transport matrices.
- Hermes package documentation shows both local stdio and remote HTTP configuration.
Out of scope
- Reimplementing Hermes authentication, retry, reconnect, or circuit-breaker behavior.
- A second MCP SDK client owned by the Basic Memory provider.
- Restricting the model to a curated subset of Basic Memory tools by default.
Summary
Connect the Basic Memory memory provider through Hermes's native MCP runtime instead of maintaining a provider-owned MCP actor.
This is the implementation-specific follow-up to #1387 and replaces the transport approach in #1397. The user-facing goal remains the same: Hermes should support automatic Basic Memory recall and capture against an existing remote Streamable HTTP MCP endpoint.
Why this direction
Hermes v0.21.0 / v2026.8.31 and current upstream
mainprovidePluginContext.call_mcp(server, tool, arguments, timeout=...). It is synchronous for plugin hooks and handlers, but executes through Hermes's existing MCP client and connection lifecycle:Using that surface gives Hermes one owner for MCP connections. The Basic Memory provider remains responsible for memory policy—prefetch, automatic turn capture, session summaries, and commands—without duplicating transport state, retry rules, or an asyncio actor.
Relevant Hermes sources:
PluginContext.call_mcp: https://github.com/NousResearch/hermes-agent/blob/5a0b1ba766956a1a16bc2f17dc3b83eb63633402/hermes_cli/plugins.py#L502Proposed design
Configure Basic Memory once as a normal Hermes MCP server.
Remote:
Local stdio uses the same path:
The provider receives a narrow callable backed by:
Provider lifecycle operations call the native MCP tools they need. The model receives the complete Basic Memory MCP tool surface through Hermes's normal discovery.
Expose the complete tool surface
Do not maintain a second, limited set of
bm_*schemas.[]fromBasicMemoryProvider.get_tool_schemas().mcp_servers.basic_memory.tools.includeor.excludeby default.plugins.entries.basic-memory.mcp_allowlist; it authorizes provider-internal calls and is separate from model-facing tool filtering.This also means newly added Basic Memory MCP tools become available without updating the Hermes provider.
Hermes prerequisite
There is one small upstream gap. The exclusive memory-provider
_ProviderCollectordelegatesregister_*methods to a realPluginContext, but currently hides non-registration capabilities such ascall_mcp().Submit an upstream Hermes change that explicitly forwards
_ProviderCollector.call_mcp(...)to its lifecycle-ownedPluginContext. Avoid reaching into Hermes's private MCP registries or calling_make_tool_handlerfrom Basic Memory.Set an explicit minimum Hermes version containing that forwarding API. Prefer a clear compatibility floor over keeping two independent MCP implementations indefinitely.
Acceptance criteria
call_mcp()to exclusive memory-provider registration.mcp_servers.basic_memoryconfiguration.ctx.call_mcp().bm_*tool surface is removed.Out of scope