Files
pallas/docs/mnemosyne_integration.md
2026-05-04 15:34:51 -04:00

5.9 KiB

Mnemosyne Integration — Pallas Reference

This document describes how Pallas-hosted agents connect to Mnemosyne for workspace-scoped knowledge search. The full integration specification lives in daedalus/docs/mnemosyne_integration.md.


Overview

Mnemosyne is a downstream MCP server like any other from Pallas's perspective. Agents declare "mnemosyne" in their servers list; the server URL and bearer-forward opt-in live in the project's fastagent.config.yaml.

What makes Mnemosyne different from other downstream servers:

  • Workspace-scoped search. Daedalus mints a per-turn HS256 JWT carrying the workspace UUID and sends it as Authorization: Bearer on the send_message call to Pallas. Pallas captures it in request_bearer_token, and the fast-agent patch (pallas._fastagent_patch) forwards it on outgoing calls to Mnemosyne when forward_inbound_auth: true is set. Mnemosyne validates the JWT and scopes all Cypher searches to that workspace.
  • The LLM never sees workspace_id. The scoping is claim-driven: Mnemosyne reads the JWT claims, overwrites any workspace_id the model may have produced in tool arguments, and enforces containment server-side. Pallas is transparent transport.

Configuration

fastagent.config.yaml

Add the mnemosyne stanza to mcp.servers. The only Mnemosyne-specific flag is forward_inbound_auth: true:

mcp:
  servers:
    mnemosyne:
      transport: http
      url: "https://mnemosyne.ouranos.helu.ca/mcp/"
      forward_inbound_auth: true

This is already deployed in iolaus/fastagent.config.yaml, kottos/fastagent.config.yaml, and mentor/fastagent.config.yaml and their Ansible templates in virgo/ansible/.

Agent Definitions

Add "mnemosyne" to the servers list of any agent that should be able to search workspace content. Sub-agents (e.g. research, tech_research) that are orchestrated by primary agents do not need it unless they independently issue search calls.

iolaus — all primary agents have Mnemosyne access: shawn, david, hypatia, watson, nate, garth, bourdain, cousteau, marcus, cristiano, mikael.

kottosharper, scotty.

mentoralan, ann, jeffrey, jarvis, aws_sa.

Example (from iolaus/agents/shawn.py):

@fast.agent(
    name="shawn",
    instruction=_INSTRUCTION,
    servers=["argos", "mnemosyne", "neo4j_cypher", "kernos", "time"],
    default=True,
)
async def _shawn():
    pass

How Bearer Forwarding Works

  1. Daedalus mints a per-turn JWT:

    {
      "iss": "daedalus",
      "sub": "chat",
      "ws": "<workspace_uuid>",
      "libs": [],
      "iat": <now>,
      "exp": <now + 600>,
      "jti": "<uuid4>"
    }
    
  2. Daedalus calls Pallas's send_message tool with Authorization: Bearer <token> in the HTTP request headers.

  3. Pallas's MultimodalAgentMCPServer captures the token via FastMCP's get_access_token() into the request_bearer_token context variable (see pallas/multimodal_server.py).

  4. The fast-agent patch in pallas/_fastagent_patch.py (installed at import time in pallas/__init__.py) wraps _prepare_headers_and_auth. When a server config has forward_inbound_auth: true, the patch reads request_bearer_token.get() and injects Authorization: Bearer <token> into the outgoing HTTP headers for that MCP call.

  5. Mnemosyne receives the same token, validates the HMAC signature against its MCPSigningKey table, and scopes all search Cypher queries to ws from the claims.

The forward_inbound_auth flag is per-server — other servers in the same agent (argos, neo4j_cypher, time, etc.) never receive the bearer.


Available Mnemosyne MCP Tools

These tools become available to agents with "mnemosyne" in their servers list:

Tool Purpose
search_knowledge Hybrid vector + full-text + graph search with re-ranking, scoped to the current workspace
search_by_category Search within a specific library type (technical, fiction, business, etc.)
list_libraries List accessible libraries
list_collections List collections within a library
get_item Retrieve item metadata, chunk previews, and concept links
get_concepts Traverse the concept graph

All tools are transparently scoped to the workspace by JWT claims. An agent in workspace A cannot retrieve content from workspace B regardless of what arguments it produces.


Downstream MCP Servers

Server URL forward_inbound_auth
mnemosyne https://mnemosyne.ouranos.helu.ca/mcp/ true
argos http://miranda.incus:25534/mcp
neo4j_cypher http://circe.helu.ca:22034/mcp
kernos http://caliban.incus:22021/mcp
gitea http://miranda.incus:25535/mcp
rommie http://caliban.incus:22031/mcp
grafana http://miranda.incus:25533/mcp

Provisioning (one-time, server-side)

  1. On the Mnemosyne host, generate the signing key:

    docker compose exec app python manage.py seed_signing_key --kid daedalus-1
    # Copy the printed hex secret
    
  2. Set on Daedalus (.env or Ansible vault):

    DAEDALUS_MNEMOSYNE_MCP_URL=https://mnemosyne.ouranos.helu.ca/mcp/
    DAEDALUS_MNEMOSYNE_SIGNING_KID=daedalus-1
    DAEDALUS_MNEMOSYNE_SIGNING_SECRET=<hex from step 1>
    DAEDALUS_MNEMOSYNE_TOKEN_TTL_SECONDS=600
    
  3. Restart Daedalus and the three agent deployments (iolaus, kottos, mentor).

The OCI vault secret is virgo-mnemosyne-signing-secret; Ansible injects it via mnemosyne_signing_secret.


Degraded Mode

If Daedalus's MNEMOSYNE_SIGNING_SECRET is blank or MNEMOSYNE_MCP_URL is empty, mint_chat_token returns None. Pallas calls proceed without a bearer; Mnemosyne search is unavailable but all other agent tools continue normally. No error is surfaced to the user.