Skip to content

feat(integrations): use Hermes native MCP runtime for Basic Memory #1475

Description

@phernandez

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions