Skip to content

feat(memory): env-aware backend + memory in default plugin set - #44

Merged
rrader26 merged 1 commit into
mainfrom
feat/memory-default-plugin-env-aware
May 15, 2026
Merged

feat(memory): env-aware backend + memory in default plugin set#44
rrader26 merged 1 commit into
mainfrom
feat/memory-default-plugin-env-aware

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

Summary

PR α of the ThinkFleet Memory Bridge slice. Makes the Memory Pack a zero-config default — the MCP server now picks the right backend based on what's in the environment, and exposes agentmark_memory_* tools whether or not SaaS creds are present.

This is the foundation for: install ThinkFleet Desktop → log in → every AI tool (Claude Code, Cursor, Codex, Copilot, Windsurf) gets persistent hierarchical memory automatically.

What's in

detectMemoryBackend() — env-aware cascade

Env state Backend Behavior
All of THINKFLEET_BASE_URL + THINKFLEET_PROJECT_ID + THINKFLEET_API_KEY set ActivepiecesMemoryBackend Memory flows to SaaS, available across machines
None set LocalFileMemoryBackend Legacy default, on-disk, offline-safe
Some-but-not-all set Throws MemoryBackendConfigError Refuses to silently fall back
API key missing sk- prefix Throws Truncated to first 4 chars in error — no leak

Refusing to silently fall back to local on partial creds matters: a typo in one variable shouldn't quietly demote a user from "memory syncs to my team" to "memory only on my disk."

Dispatcher integration

  • createDispatcherState() always builds a memory plugin alongside web + pdf + desktop.
  • On misconfiguration: memory disabled, reason logged to stderr (which MCP clients surface to the user), rest of the server stays alive.
  • Selected backend logged at startup via describeMemoryBackend() — credential-free description, safe for any log sink.

Threat model (codified in the docstrings)

  • API key only ever lives in process env. Upcoming desktop installer (PR γ) reads it from the OS keychain at install time and passes it via the MCP install CLI (PR β).
  • Error messages never echo back the supplied API key.
  • Backend description never embeds credentials.

Tests

  • test/memory/detect-backend.test.ts16 cases covering each branch of the cascade, error-message sanitization, whitespace handling.
  • test/mcp/default-memory-plugin.test.ts5 cases covering dispatcher integration: tools register, partial creds disable cleanly, malformed keys don't leak to logs.

Full suite: 540 passed, 10 pre-existing skips. Typecheck clean.

Backwards compatibility

Strictly additive:

  • Callers passing an explicit plugins array to createMcpServer() see no change.
  • Default callers (most consumers) now get the memory tools registered.
  • Existing LocalFileMemoryBackend behavior unchanged when env is unset.

Next PRs

  • βagentmark-mcp install --env KEY=VAL so the install CLI can write env into client config blocks safely.
  • γ — ThinkFleet Desktop installer reads OS-keychain-stored creds and passes them via β.
  • δ — Canonical thinkfleet-memory.skill.yaml + per-tool skill installer (Claude Code skills, Cursor rules, etc.) so agents are taught the protocol, not just given the tools.

🤖 Generated with Claude Code

Makes the Memory Pack a zero-config default. The MCP server now picks
the right backend based on what's in the environment, and exposes the
agentmark_memory_* tools whether or not SaaS creds are present.

Detection cascade in detectMemoryBackend():
  - All three of THINKFLEET_BASE_URL + THINKFLEET_PROJECT_ID +
    THINKFLEET_API_KEY present → ActivepiecesMemoryBackend (memory
    flows to SaaS; available across machines + AI tools).
  - None present → LocalFileMemoryBackend (legacy default, on-disk,
    offline-safe).
  - Some-but-not-all present → throw MemoryBackendConfigError.
    Refusing to silently fall back to local matters: a typo in one
    variable shouldn't quietly demote a user from "memory syncs to my
    team" to "memory only on my disk".
  - Malformed API key (no sk- prefix) → throw; truncated to first 4
    chars in the error so secrets don't leak into logs.

Dispatcher integration:
  - createDispatcherState() now always builds a memory plugin and
    adds it to the default plugin set alongside web + pdf + desktop.
  - On misconfiguration, memory is disabled and the reason logged
    to stderr; the rest of the server stays alive. MCP clients
    (Claude Code, Cursor, …) surface stderr so users see the
    misconfiguration.
  - Selected backend is logged at startup via describeMemoryBackend()
    — credential-free description, safe for any log sink.

Threat model:
  - API key only ever lives in process env. Callers (ThinkFleet
    Desktop installer in upcoming PRs) should pass it from an OS
    keychain, not persist it in a plain settings file.
  - The MCP install CLI's --env support (PR β) is the supported
    transport into a client's MCP config.

Tests:
  - test/memory/detect-backend.test.ts — 16 cases covering each
    branch of the detection cascade, error-message sanitization,
    whitespace handling.
  - test/mcp/default-memory-plugin.test.ts — 5 cases covering
    dispatcher integration: tools register, partial creds disable
    cleanly, malformed keys don't leak to logs.

540 tests pass. Typecheck clean. Backwards-compat: callers passing
an explicit `plugins` array to createMcpServer() see no change;
default callers get the memory tools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants