Repository navigation
feat(integrations): use Hermes native MCP runtime for Basic Memory #1475
Description
Activity
Claude finished @phernandez's task in 33s —— View job
Triage
Type: Enhancement — architectural change to how the Hermes memory-provider integration reaches Basic Memory's MCP surface (routes through Hermes's native
PluginContext.call_mcpinstead of a provider-owned MCP actor/transport).Component:
integrations/hermes(Hermes plugin package). Not a Cloud-specific issue — applies to both local stdio (bm mcp) and remote Streamable HTTP configurations.Priority: Medium. This is a design/maintainability improvement (removing duplicated transport/retry/reconnect logic from the provider) rather than a fix for broken user-facing functionality today.
Complexity: Complex. It depends on an upstream Hermes change (
_ProviderCollector.call_mcpforwarding) that doesn't exist yet, requires pinning a minimum Hermes version once that lands, removing the currentbm_*tool-schema surface (get_tool_schemas()→[]), and new integration tests against a real Basic Memory MCP endpoint covering discovery, prefetch, turn capture, and reconnect behavior without a second session. Sequencing (upstream PR first, then this repo's changes) is a key risk to plan around.Relationship to other issues: Not a duplicate. This is the stated "implementation-specific follow-up" to #1387 (remote-projects support in the Hermes plugin, still open) and explicitly replaces the transport approach from #1397 (closed). No other open issue covers this native-MCP-runtime approach.
Note on scope: The issue itself is thorough (design, acceptance criteria, out-of-scope list) — no clarifying questions needed before implementation planning. Per triage process, no code changes were made here.
The upstream prerequisite is now submitted: NousResearch/hermes-agent#105558. It explicitly forwards memory-provider ctx.call_mcp through the existing PluginContext, retaining native MCP lifecycle and per-plugin allowlists. A real discovery/config regression fails on upstream main and passes with the fix; 24 targeted tests pass. Current Hermes main still lacks this forwarding, so the downstream migration remains gated on an upstream release containing it. No second MCP client or private-registry workaround is being added.
Rechecked for v0.24.0 on 2026-09-14: blocked on a released Hermes prerequisite; downstream reimplementation stopped before coding.
Concrete upstream evidence:
- Latest published release is v2026.9.11, published 2026-09-11, commit
939e45c91d751fadd94dcd1b873ac3cb44846213. - That release has
PluginContext.call_mcp, including native MCP dispatch and per-plugin allowlist enforcement. However, its_ProviderCollectorhas nocall_mcpmethod, and__getattr__explicitly raises for every non-register_*attribute. - Current upstream main
5eb99eb2844b22ebb723711b8e6a0bbb80bb5f04has the same missing forwarding. - Upstream prerequisite PR #105558 is still OPEN, with
mergedAt: nulland no merge commit. Its proposed implementation forwards through the collector's existing lifecycle-owned context.
Verification: downloaded the release and main source through the GitHub API and executed each unchanged
_ProviderCollectorclass in isolation, extracted with Python AST (no replacement collector or transport mock). Both produce:release: _ProviderCollector("basic-memory").call_mcp -> AttributeError: call_mcp main: _ProviderCollector("basic-memory").call_mcp -> AttributeError: call_mcpThis is a narrow capability probe, not a full Hermes discovery or live MCP integration test. It directly confirms that the required binding in provider registration remains unavailable.
Also inspected the current Basic Memory integration and abandoned PR #1397: current code still owns
_BmMcpActor, a stdioClientSession, and ten curatedbm_*schemas; #1397 was closed unmerged in favor of this issue's host-owned transport design. Reviving that actor/HTTP design or accessing private Hermes registries would bypass the agreed prerequisite rather than complete #1475.Prepared fresh branch
codex/1475-hermes-native-mcpfrom fetchedorigin/mainat756f183617a8aae0ce7c503b88e9fb5c8180b1dein the existing reusablebasic-memory-pr1524worktree. No implementation changes, commits, new downstream PR, or merge. Main checkout and worktree topology preserved. Package checks and live host contract tests were not run because implementation is gated before coding.Adding
needs review. Resume when a supported Hermes release contains the forwarding API (or an equivalent public memory-provider capability), then establish that release as the compatibility floor and implement/test the native-runtime design. Issue remains open; it is not complete for v0.24.0.- Latest published release is v2026.9.11, published 2026-09-11, commit
- addedneeds reviewA human maintainer needs to look at this issueA human maintainer needs to look at this issue
on Sep 14, 2026 Milestone status (2026-09-14): blocked on a released Hermes prerequisite; no downstream code should be written yet.
Fresh read-back is unchanged: the latest Hermes release remains v2026.9.11, and NousResearch/hermes-agent#105558 is still open. Both the release and current upstream collector lack the
call_mcpforwarding required for a memory provider to use Hermes's lifecycle-owned native MCP runtime.Next step: when a supported Hermes release contains that forwarding API, set it as the compatibility floor, replace the provider-owned MCP actor with native
ctx.call_mcp, and run discovery/prefetch/capture/reconnect tests against a real Basic Memory MCP endpoint. Do not revive the second-client design or depend on private registries.Milestone decision: removing this from v0.24.0. Pi's integration model is intentionally CLI-first rather than MCP-native, and the Hermes-native MCP migration remains independently blocked on an unreleased upstream forwarding API. Keep this issue open as a future Hermes integration improvement; it is not a v0.24 release requirement.
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