Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
# AGENTMEMORY_DEBUG=1 # Trace MCP shim probe + standalone fallback decisions to stderr
# AGENTMEMORY_FORCE_PROXY=1 # Skip the MCP shim livez probe and trust AGENTMEMORY_URL (for sandboxed MCP clients that can't reach localhost)
# AGENTMEMORY_REQUIRE_SERVER=1 # Make the MCP shim fail instead of using local fallback when AGENTMEMORY_URL is unreachable
# AGENTMEMORY_NO_FALLBACK=1 # Alias for AGENTMEMORY_REQUIRE_SERVER=1
# AGENTMEMORY_REMOTE_REQUIRED=1 # Alias for AGENTMEMORY_REQUIRE_SERVER=1
# AGENTMEMORY_LIVEZ_TIMEOUT_MS=2000 # MCP shim livez probe timeout; takes precedence over AGENTMEMORY_PROBE_TIMEOUT_MS
# AGENTMEMORY_PROBE_TIMEOUT_MS=2000 # Older MCP shim livez probe timeout name
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ agentmemory connect claude-code --with-hooks
This merges the same hook commands into `~/.claude/settings.json` with absolute paths resolved to the bundled `plugin/` directory of the currently installed `@agentmemory/agentmemory` package. Re-run the command after upgrading agentmemory to refresh the paths. User entries in the same file are preserved; only previous agentmemory entries are replaced. Using the `/plugin install` path remains the recommended approach.
For remote or protected deployments, launch Claude Code with `AGENTMEMORY_URL` and `AGENTMEMORY_SECRET` set. The plugin passes both values through to its bundled MCP server; when `AGENTMEMORY_URL` is empty, the MCP shim uses `http://localhost:3111`.

If agentmemory is your central cross-agent memory instance, add `AGENTMEMORY_REQUIRE_SERVER=1` to the MCP server env block. This makes the shim fail hard when `/agentmemory/livez` or a proxied tool call fails instead of silently switching to the local `~/.agentmemory/standalone.json` fallback. The error tells the host to start `npx @agentmemory/agentmemory`. `AGENTMEMORY_DISABLE_LOCAL_FALLBACK=1` and `AGENTMEMORY_REMOTE_REQUIRED=1` are accepted as aliases. `AGENTMEMORY_LIVEZ_TIMEOUT_MS` overrides the livez probe timeout and takes precedence over the older `AGENTMEMORY_PROBE_TIMEOUT_MS`.
If agentmemory is your central cross-agent memory instance, add `AGENTMEMORY_REQUIRE_SERVER=1` to the MCP server env block. This makes the shim fail hard when `/agentmemory/livez` or a proxied tool call fails instead of silently switching to the local `~/.agentmemory/standalone.json` fallback. The error tells the host to start `npx @agentmemory/agentmemory`. `AGENTMEMORY_DISABLE_LOCAL_FALLBACK=1`, `AGENTMEMORY_NO_FALLBACK=1`, and `AGENTMEMORY_REMOTE_REQUIRED=1` are accepted as aliases. When fallback-capable MCP tool calls succeed, their JSON text payload includes `storage_mode: "local"` or `storage_mode: "remote"` so hosts can tell which store answered. `AGENTMEMORY_LIVEZ_TIMEOUT_MS` overrides the livez probe timeout and takes precedence over the older `AGENTMEMORY_PROBE_TIMEOUT_MS`.

### Codex CLI (Codex plugin platform)

Expand All @@ -551,7 +551,7 @@ codex plugin add agentmemory@agentmemory

The Codex plugin ships from the same `plugin/` directory as the Claude Code plugin. It registers:

- `@agentmemory/mcp` as an MCP server (proxies the server-advertised 8 core tools by default when `AGENTMEMORY_URL` points at a running agentmemory server; start the server with `--tools all` for all 61 tools; falls back to 7 tools locally when no server is reachable unless `AGENTMEMORY_REQUIRE_SERVER=1` or `AGENTMEMORY_REMOTE_REQUIRED=1` is set)
- `@agentmemory/mcp` as an MCP server (proxies the server-advertised 8 core tools by default when `AGENTMEMORY_URL` points at a running agentmemory server; start the server with `--tools all` for all 61 tools; falls back to 7 tools locally when no server is reachable unless `AGENTMEMORY_REQUIRE_SERVER=1`, `AGENTMEMORY_NO_FALLBACK=1`, or `AGENTMEMORY_REMOTE_REQUIRED=1` is set)
- 6 lifecycle hooks: `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `PreCompact`, `Stop`
- 8 invocable skills: `/recall`, `/remember`, `/session-history`, `/forget`, `/recap`, `/handoff`, `/commit-context`, `/commit-history`, plus 7 reference skills the agent loads on demand (MCP tools, REST API, config, agents, hooks, architecture, and the skill-authoring guide)

Expand Down Expand Up @@ -696,7 +696,7 @@ Kilo Code uses `mcp` instead of `mcpServers`:
}
```

For central memory deployments where an empty local fallback would be misleading, also pass `"AGENTMEMORY_REQUIRE_SERVER": "1"`. With this flag, livez failures and proxy-call failures return a clear MCP error instead of answering from `~/.agentmemory/standalone.json`. `AGENTMEMORY_DISABLE_LOCAL_FALLBACK=1` and `AGENTMEMORY_REMOTE_REQUIRED=1` are accepted as aliases. `AGENTMEMORY_FORCE_PROXY=1` only skips the livez probe; it does not by itself disable local fallback after a proxy call fails. Use `AGENTMEMORY_LIVEZ_TIMEOUT_MS` to tune the livez probe timeout; it takes precedence over `AGENTMEMORY_PROBE_TIMEOUT_MS`.
For central memory deployments where an empty local fallback would be misleading, also pass `"AGENTMEMORY_REQUIRE_SERVER": "1"`. With this flag, livez failures and proxy-call failures return a clear MCP error instead of answering from `~/.agentmemory/standalone.json`. `AGENTMEMORY_DISABLE_LOCAL_FALLBACK=1`, `AGENTMEMORY_NO_FALLBACK=1`, and `AGENTMEMORY_REMOTE_REQUIRED=1` are accepted as aliases. Successful fallback-capable tool responses include `storage_mode: "local"` or `storage_mode: "remote"` in their JSON text payload. `AGENTMEMORY_FORCE_PROXY=1` only skips the livez probe; it does not by itself disable local fallback after a proxy call fails. Use `AGENTMEMORY_LIVEZ_TIMEOUT_MS` to tune the livez probe timeout; it takes precedence over `AGENTMEMORY_PROBE_TIMEOUT_MS`.

| Agent | Config file | Notes |
|---|---|---|
Expand Down Expand Up @@ -748,9 +748,9 @@ GitHub Copilot in VS Code uses `servers` instead of `mcpServers`. Put this in `.
}
```

Start `npx @agentmemory/agentmemory` in another terminal first when you want the persistent memory server. By default the server advertises the 8 core MCP tools; start it with `npx @agentmemory/agentmemory --tools all` or `AGENTMEMORY_TOOLS=all npx @agentmemory/agentmemory` when you want the full 61-tool surface. If the shim cannot reach that server, it falls back to the local 7-tool standalone surface unless you also set `"AGENTMEMORY_REQUIRE_SERVER": "1"` or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` in `env`.
Start `npx @agentmemory/agentmemory` in another terminal first when you want the persistent memory server. By default the server advertises the 8 core MCP tools; start it with `npx @agentmemory/agentmemory --tools all` or `AGENTMEMORY_TOOLS=all npx @agentmemory/agentmemory` when you want the full 61-tool surface. If the shim cannot reach that server, it falls back to the local 7-tool standalone surface unless you also set `"AGENTMEMORY_REQUIRE_SERVER": "1"`, `"AGENTMEMORY_NO_FALLBACK": "1"`, or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` in `env`.

**Sandboxed MCP clients** (Flatpak / Snap / restrictive containers) that can't reach the host's `localhost`: also set `"AGENTMEMORY_FORCE_PROXY": "1"` in the `env` block, and point `AGENTMEMORY_URL` at a route the sandbox can actually reach. Add `"AGENTMEMORY_REQUIRE_SERVER": "1"` or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` when the client should fail rather than use the local fallback if that route is still broken. If `AGENTMEMORY_SECRET` is set, that route must be HTTPS or a loopback tunnel; the MCP shim refuses to send bearer auth over plaintext HTTP to non-loopback hosts. See [#234](https://github.com/rohitg00/agentmemory/issues/234) for the diagnostic walkthrough.
**Sandboxed MCP clients** (Flatpak / Snap / restrictive containers) that can't reach the host's `localhost`: also set `"AGENTMEMORY_FORCE_PROXY": "1"` in the `env` block, and point `AGENTMEMORY_URL` at a route the sandbox can actually reach. Add `"AGENTMEMORY_REQUIRE_SERVER": "1"`, `"AGENTMEMORY_NO_FALLBACK": "1"`, or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` when the client should fail rather than use the local fallback if that route is still broken. If `AGENTMEMORY_SECRET` is set, that route must be HTTPS or a loopback tunnel; the MCP shim refuses to send bearer auth over plaintext HTTP to non-loopback hosts. See [#234](https://github.com/rohitg00/agentmemory/issues/234) for the diagnostic walkthrough.

### Programmatic access (Python / Rust / Node)

Expand Down Expand Up @@ -1053,7 +1053,7 @@ For native Ollama embeddings, run Ollama locally and set `EMBEDDING_PROVIDER=oll

61 tools, 6 resources, 3 prompts, and 15 skills, the most comprehensive MCP memory toolkit for any agent.

> **MCP shim vs full server:** the published `@agentmemory/mcp` package is a thin shim. It exposes the server's MCP surface **only when it can reach a running agentmemory server** via `AGENTMEMORY_URL` (proxy mode). The server advertises the 8 core tools by default; set `AGENTMEMORY_TOOLS=all` on the server to expose the full 61-tool surface. With no server reachable, the shim falls back to a 7-tool local set (`memory_save`, `memory_recall`, `memory_smart_search`, `memory_sessions`, `memory_export`, `memory_audit`, `memory_governance_delete`). Lesson lifecycle tools such as `memory_lesson_save` require the full server/proxy surface. Set `AGENTMEMORY_REQUIRE_SERVER=1` or `AGENTMEMORY_REMOTE_REQUIRED=1` in the shim's env when that fallback would hide an outage; then livez failures and proxy-call failures return an MCP error instead. `AGENTMEMORY_LIVEZ_TIMEOUT_MS` tunes the livez probe timeout and wins over `AGENTMEMORY_PROBE_TIMEOUT_MS`. The `AGENTMEMORY_TOOLS=core|all` env var is a *server-side* flag — setting it in the shim's `env` block has no effect. If you see only 7 tools in Cursor / OpenCode / Gemini CLI, start `npx @agentmemory/agentmemory` (or the Docker stack) and set `AGENTMEMORY_URL=http://localhost:3111`.
> **MCP shim vs full server:** the published `@agentmemory/mcp` package is a thin shim. It exposes the server's MCP surface **only when it can reach a running agentmemory server** via `AGENTMEMORY_URL` (proxy mode). The server advertises the 8 core tools by default; set `AGENTMEMORY_TOOLS=all` on the server to expose the full 61-tool surface. With no server reachable, the shim falls back to a 7-tool local set (`memory_save`, `memory_recall`, `memory_smart_search`, `memory_sessions`, `memory_export`, `memory_audit`, `memory_governance_delete`). Successful calls to those fallback-capable tools include `storage_mode: "local"` or `storage_mode: "remote"` in the JSON text payload. Lesson lifecycle tools such as `memory_lesson_save` require the full server/proxy surface. Set `AGENTMEMORY_REQUIRE_SERVER=1`, `AGENTMEMORY_NO_FALLBACK=1`, or `AGENTMEMORY_REMOTE_REQUIRED=1` in the shim's env when that fallback would hide an outage; then livez failures and proxy-call failures return an MCP error instead. `AGENTMEMORY_LIVEZ_TIMEOUT_MS` tunes the livez probe timeout and wins over `AGENTMEMORY_PROBE_TIMEOUT_MS`. The `AGENTMEMORY_TOOLS=core|all` env var is a *server-side* flag — setting it in the shim's `env` block has no effect. If you see only 7 tools in Cursor / OpenCode / Gemini CLI, start `npx @agentmemory/agentmemory` (or the Docker stack) and set `AGENTMEMORY_URL=http://localhost:3111`.

### 61 Tools

Expand Down Expand Up @@ -1207,7 +1207,7 @@ Most agents (Cursor, Claude Desktop, Cline, Roo Code, Windsurf, Gemini CLI):
}
```

Merge the `agentmemory` entry into your host's existing `mcpServers` object rather than replacing the file. For sandboxed clients that can't reach the host's `localhost`, add `"AGENTMEMORY_FORCE_PROXY": "1"` to the env block and set `AGENTMEMORY_URL` to a route the sandbox can reach. For central cross-agent memory, add `"AGENTMEMORY_REQUIRE_SERVER": "1"` or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` so the shim errors instead of falling back to its local standalone store when the server route breaks. If `AGENTMEMORY_SECRET` is set, use HTTPS or a loopback tunnel; plaintext HTTP to non-loopback hosts is refused before bearer auth is sent.
Merge the `agentmemory` entry into your host's existing `mcpServers` object rather than replacing the file. For sandboxed clients that can't reach the host's `localhost`, add `"AGENTMEMORY_FORCE_PROXY": "1"` to the env block and set `AGENTMEMORY_URL` to a route the sandbox can reach. For central cross-agent memory, add `"AGENTMEMORY_REQUIRE_SERVER": "1"`, `"AGENTMEMORY_NO_FALLBACK": "1"`, or `"AGENTMEMORY_REMOTE_REQUIRED": "1"` so the shim errors instead of falling back to its local standalone store when the server route breaks. Successful fallback-capable tool responses include `storage_mode: "local"` or `storage_mode: "remote"` in their JSON text payload. If `AGENTMEMORY_SECRET` is set, use HTTPS or a loopback tunnel; plaintext HTTP to non-loopback hosts is refused before bearer auth is sent.

MCP clients that support Streamable HTTP can connect directly to the running server without the stdio shim:

Expand Down
86 changes: 86 additions & 0 deletions docs/todos/2026-06-19-issue-273-storage-mode/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Plan: Issue #273 Transparent Fallback Mode

## TDD Steps

1. Add RED tests in `test/mcp-standalone.test.ts`.
- Assert local `memory_save` includes `storage_mode: "local"` and still includes `saved`.
- Assert the stored memory record does not include `storage_mode`.
- Assert local `memory_recall` includes `storage_mode: "local"` for existing formats.
- Assert local `memory_smart_search` includes `storage_mode: "local"` while preserving `mode`.
- Assert local `memory_sessions`, `memory_export`, `memory_audit`, and `memory_governance_delete` include `storage_mode: "local"`.

2. Add RED tests in `test/mcp-standalone-proxy.test.ts`.
- Assert successful dedicated proxy responses for the seven fallback-capable tools include `storage_mode: "remote"`.
- Assert proxy-call fallback and `AGENTMEMORY_FORCE_PROXY=1` failure fallback report `storage_mode: "local"`.
- Assert generic proxy-only tools remain unannotated.
- Add `AGENTMEMORY_NO_FALLBACK` cleanup in `afterEach`.
- Assert `AGENTMEMORY_NO_FALLBACK=1` rejects livez fallback, proxy-call fallback, and tools/list fallback.

3. Run targeted tests and confirm they fail for the intended missing assertions.

```sh
corepack pnpm exec vitest run test/mcp-standalone.test.ts test/mcp-standalone-proxy.test.ts --exclude test/integration.test.ts --reporter verbose
```

## Implementation Steps

1. Update `src/mcp/standalone.ts`.
- Add a small response helper that shallow-copies object payloads and adds `storage_mode`.
- Use `"remote"` in `handleProxy` for the seven fallback-capable tools.
- Use `"local"` in `handleLocal` for those same tools.
- Leave `handleProxyGeneric`, `tools/list`, and error responses unchanged.

2. Update `src/mcp/rest-proxy.ts`.
- Add `envFlag("AGENTMEMORY_NO_FALLBACK")` to `requireServerMode()`.
- Add the alias to `requireServerModeFlag()` while preserving existing flag priority where possible.
- Update fallback stderr hints to mention the new alias.

3. Update docs/config references.
- `.env.example`
- `README.md`
- `packages/mcp/README.md`
- `plugin/skills/agentmemory-config/SKILL.md`
- Regenerate `plugin/skills/agentmemory-config/REFERENCE.md` with `corepack pnpm run skills:gen`.

## Verification Plan

1. Targeted MCP tests:

```sh
corepack pnpm exec vitest run test/mcp-standalone.test.ts test/mcp-standalone-proxy.test.ts --exclude test/integration.test.ts --reporter verbose
```

2. Generated skill reference:

```sh
corepack pnpm run skills:gen
corepack pnpm run skills:check
git diff -- plugin/skills/agentmemory-config/REFERENCE.md
```

3. Repo checks:

```sh
corepack pnpm run lint
corepack pnpm run build
corepack pnpm test
git diff --check
semgrep scan --config p/default --error --metrics=off .
```

4. Before commit:

```sh
git add ...
gitleaks protect --staged --redact
git status -sb --untracked-files=all
```

OSV is not required unless dependency, lockfile, container, vendored, or package-manager files change.

## Review Focus

- Verify the response helper does not mutate remote payload objects in-place.
- Verify `memory_export` adds only a top-level response field and does not inject `storage_mode` into exported records.
- Verify strict mode does not change default fallback behavior.
- Verify docs do not imply sync-on-reconnect was implemented.
Loading
Loading