Relevant source files
The following files were used as context for generating this wiki page:
- integrations/openclaw/cli/commands.ts
- integrations/agent-plugin-core/python/hook_runner.py
- integrations/antigravity-plugin/core/hook_runner.py
- integrations/agent-plugin-core/conformance/run.py
- integrations/kimi-plugin/core/hook_runner.py
- integrations/claude-code-plugin/core/hook_runner.py
- integrations/codex-plugin/core/hook_runner.py
- integrations/cursor-plugin/core/hook_runner.py
- integrations/mem0-agent-plugin/core/memory_cli.py
- integrations/agent-plugin-core/python/memory_cli.py
- integrations/claude-code-plugin/core/memory_cli.py
- integrations/codex-plugin/core/memory_cli.py
- integrations/antigravity-plugin/core/memory_cli.py
- cli/python/src/mem0_cli/plugin_sync.py
- integrations/kimi-plugin/core/memory_cli.py
- integrations/cursor-plugin/core/memory_cli.py
- cli/node/src/plugin-sync.ts
- integrations/pi-agent-plugin/src/entry.ts
- integrations/codex-plugin/.mcp.json
- integrations/claude-code-plugin/.mcp.json
- integrations/openclaw/index.ts
- integrations/mem0-agent-plugin/mcp.json
- integrations/hermes-plugin-mem0/_setup.py
- integrations/pi-agent-plugin/src/memory/tools.ts
- integrations/antigravity-plugin/mcp_config.json
- integrations/mem0-agent-plugin/core/mcp_server.py
- integrations/antigravity-plugin/hooks.json
- integrations/antigravity-plugin/core/mcp_server.py
- integrations/codex-plugin/hooks/adapter.py
- integrations/agent-plugin-core/python/mcp_server.py
Overview
Plugin synchronization bridges canonical CLI authentication state with external ecosystem touchpoints cli/python/src/mem0_cli/plugin_sync.py:1-25, cli/node/src/plugin-sync.ts:1-22. By propagating active Mem0 API keys into runtime configuration files and shell environment export declarations, the synchronization subsystem prevents authentication mismatches during agent-mode bootstraps cli/python/src/mem0_cli/plugin_sync.py:1-15, cli/node/src/plugin-sync.ts:1-15.
Sources: cli/python/src/mem0_cli/plugin_sync.py:1-25, cli/node/src/plugin-sync.ts:1-22
The architecture enforces strict update constraints by modifying existing target entries without creating unrequested files, preserving document formatting and surrounding keys, and performing atomic file writes via temporary staging paths and renames cli/python/src/mem0_cli/plugin_sync.py:10-15, cli/node/src/plugin-sync.ts:10-15. It targets touchpoints such as Claude Code settings and shell resource configuration profiles cli/python/src/mem0_cli/plugin_sync.py:17-20, cli/node/src/plugin-sync.ts:16-19.
Sources: cli/python/src/mem0_cli/plugin_sync.py:10-20, cli/node/src/plugin-sync.ts:10-19
CLI Synchronization Mechanism
Propagation Targets and Rules
The Python and Node.js command-line interfaces implement identical credential synchronization logic to propagate active Mem0 API keys into external development environments cli/python/src/mem0_cli/plugin_sync.py:41-55, cli/node/src/plugin-sync.ts:40-50. When sync_api_key or syncApiKey executes with a valid string, it targets the Claude Code configuration file and three standard POSIX shell resource profiles cli/python/src/mem0_cli/plugin_sync.py:37-38, cli/node/src/plugin-sync.ts:28-33.
_CLAUDE_SETTINGS = Path.home() / ".claude" / "settings.json"
_SHELL_RCS = [Path.home() / ".zshrc", Path.home() / ".bashrc", Path.home() / ".bash_profile"]
Sources: cli/python/src/mem0_cli/plugin_sync.py:37-39
const CLAUDE_SETTINGS = path.join(os.homedir(), ".claude", "settings.json");
const SHELL_RCS = [
path.join(os.homedir(), ".zshrc"),
path.join(os.homedir(), ".bashrc"),
path.join(os.homedir(), ".bash_profile"),
];Sources: cli/node/src/plugin-sync.ts:28-33
| Target Path | Config Key / Pattern | Scope & Behavior |
|---|---|---|
~/.claude/settings.json | env.MEM0_API_KEY | Updated only if parent env object and key already exist cli/python/src/mem0_cli/plugin_sync.py:67-70, cli/node/src/plugin-sync.ts:66-69 |
~/.zshrc | export MEM0_API_KEY="..." | Replaces existing assignment value using regular expression matching cli/python/src/mem0_cli/plugin_sync.py:81-84, cli/node/src/plugin-sync.ts:37-38 |
~/.bashrc | export MEM0_API_KEY="..." | Replaces existing assignment value using regular expression matching cli/python/src/mem0_cli/plugin_sync.py:81-84, cli/node/src/plugin-sync.ts:37-38 |
~/.bash_profile | export MEM0_API_KEY="..." | Replaces existing assignment value using regular expression matching cli/python/src/mem0_cli/plugin_sync.py:81-84, cli/node/src/plugin-sync.ts:37-38 |
Sources: cli/python/src/mem0_cli/plugin_sync.py:37-84, cli/node/src/plugin-sync.ts:28-38
Important
The synchronization engine strictly enforces a non-creation policy for target keys. If MEM0_API_KEY is missing from settings.json or no export MEM0_API_KEY declaration exists in a shell resource file, the synchronizer skips that target without writing new keys cli/python/src/mem0_cli/plugin_sync.py:68-70, cli/node/src/plugin-sync.ts:67-69, cli/python/src/mem0_cli/plugin_sync.py:96-97, cli/node/src/plugin-sync.ts:87.
Sources: cli/python/src/mem0_cli/plugin_sync.py:68-70, cli/node/src/plugin-sync.ts:67-69, cli/python/src/mem0_cli/plugin_sync.py:96-97, cli/node/src/plugin-sync.ts:87
Parsing Patterns and Atomic Writes
Shell RC file matching relies on an anchored regular expression pattern that captures export prefixes, optional surrounding quotes, credential values, and trailing spaces while sparing newline characters cli/python/src/mem0_cli/plugin_sync.py:81-84, cli/node/src/plugin-sync.ts:37-38.
_RC_LINE = re.compile(
r'^([ \t]*export[ \t]+MEM0_API_KEY[ \t]*=[ \t]*)(["\']?)([^"\'\n]*)(["\']?)[ \t]*$',
re.MULTILINE,
)Sources: cli/python/src/mem0_cli/plugin_sync.py:81-84
const RC_LINE_RE =
/^([ \t]*export[ \t]+MEM0_API_KEY[ \t]*=[ \t]*)(["']?)([^"'\n]*)(["']?)[ \t]*$/m;Sources: cli/node/src/plugin-sync.ts:37-38
Tip
Both implementations use explicit horizontal whitespace character classes [ \t]* rather than generic whitespace selectors \s* in regex definitions. This ensures that trailing newlines at the end of shell configuration files remain intact when MEM0_API_KEY resides on the final line cli/python/src/mem0_cli/plugin_sync.py:79-80, cli/node/src/plugin-sync.ts:35-36.
Sources: cli/python/src/mem0_cli/plugin_sync.py:79-80, cli/node/src/plugin-sync.ts:35-36
File persistence utilizes an atomic write procedure that writes content to a temporary staging file in the target directory, copies POSIX file access permissions via bitwise masking against 0o777, and replaces the destination file atomically via OS system calls cli/python/src/mem0_cli/plugin_sync.py:105-118, cli/node/src/plugin-sync.ts:97-120.
def _atomic_write_text(path: Path, content: str) -> None:
"""Write content to path atomically (temp + rename)."""
dirname = path.parent
fd, tmp_path = tempfile.mkstemp(prefix=f".{path.name}.", suffix=".tmp", dir=dirname)
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
f.write(content)
# Preserve mode if the original existed.
if path.exists():
os.chmod(tmp_path, path.stat().st_mode & 0o777)
os.replace(tmp_path, path)Sources: cli/python/src/mem0_cli/plugin_sync.py:105-115
function atomicWriteText(filePath: string, content: string): void {
const dir = path.dirname(filePath);
const tmp = path.join(dir, `.${path.basename(filePath)}.${process.pid}.tmp`);
try {
fs.writeFileSync(tmp, content, "utf-8");
// Preserve permissions if original existed.
if (fs.existsSync(filePath)) {
try {
const mode = fs.statSync(filePath).mode & 0o777;
fs.chmodSync(tmp, mode);
} catch {
/* best-effort */
}
}
fs.renameSync(tmp, filePath);
} catch (err) {Sources: cli/node/src/plugin-sync.ts:97-112
IDE MCP Tool Manifests
Manifest Structure Across Targets
Standardized Model Context Protocol server declarations across IDE integration targets configure the execution parameters for the mem0 memory service tool. Each manifest registers a server entry point executing via Python, pointing to the local core/mcp_server.py module relative to the plugin root.
{
"mcpServers": {
"mem0": {
"command": "python3",
"args": ["${CLAUDE_PLUGIN_ROOT}/core/mcp_server.py"],
"env": {
"MEM0_CODE_DATA_DIR": "${CLAUDE_PLUGIN_DATA}"
}
}
}Sources: integrations/claude-code-plugin/.mcp.json:1-10
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"mem0": {
"type": "stdio",
"command": "python3",
"args": [
"${PLUGIN_ROOT}/core/mcp_server.py"
]
}
}Sources: integrations/mem0-agent-plugin/mcp.json:1-11
{
"mcpServers": {
"mem0": {
"command": "python3",
"args": ["./core/mcp_server.py"]
}
}Sources: integrations/antigravity-plugin/mcp_config.json:1-7
Target configurations differ in their schema references, environment variable scoping, and path variables used for runtime resolution.
| Target Plugin | Schema Reference | Command | Arguments | Environment Variables |
|---|---|---|---|---|
| Claude Code Plugin | None | python3 | ["${CLAUDE_PLUGIN_ROOT}/core/mcp_server.py"] | MEM0_CODE_DATA_DIR: "${CLAUDE_PLUGIN_DATA}" |
| Mem0 Agent Plugin | https://agent-plugins.org/schemas/1.0.0/mcp.schema.json | python3 | ["${PLUGIN_ROOT}/core/mcp_server.py"] | None |
| Antigravity Plugin | None | python3 | ["./core/mcp_server.py"] | None |
Sources: integrations/claude-code-plugin/.mcp.json:1-10, integrations/mem0-agent-plugin/mcp.json:1-11, integrations/antigravity-plugin/mcp_config.json:1-7
Note
The mem0-agent-plugin explicitly declares a JSON schema validator URI https://agent-plugins.org/schemas/1.0.0/mcp.schema.json and a transport type property ("type": "stdio"), whereas Claude Code and Antigravity omit these explicit schema and transport declarations integrations/mem0-agent-plugin/mcp.json:2-5, integrations/claude-code-plugin/.mcp.json:1-10, integrations/antigravity-plugin/mcp_config.json:1-7.
Sources: integrations/mem0-agent-plugin/mcp.json:2-5, integrations/claude-code-plugin/.mcp.json:1-10, integrations/antigravity-plugin/mcp_config.json:1-7
Standalone MCP Server Implementation
JSON-RPC Server Loop and Request Dispatch
The standalone Model Context Protocol server entry point is implemented in Python under integrations/mem0-agent-plugin/core/mcp_server.py and integrations/antigravity-plugin/core/mcp_server.py. It operates via standard input (sys.stdin) line reading, executing a JSON-RPC message processing loop that parses line-delimited payloads and flushes serialized responses to standard output (sys.stdout) with newline termination.
def main() -> int:
for raw_line in sys.stdin:
try:
message = json.loads(raw_line)
response = handle_request(message)
except json.JSONDecodeError:
response = {
"jsonrpc": "2.0",
"id": None,
"error": {"code": -32700, "message": "Parse error"},
}
except Exception:
response = {
"jsonrpc": "2.0",
"id": None,
"error": {"code": -32603, "message": "Internal error"},
}
if response is not None:
sys.stdout.write(json.dumps(response, separators=(",", ":")) + "\n")
sys.stdout.flush()
telemetry.spawn_flush()
return 0
Sources: integrations/mem0-agent-plugin/core/mcp_server.py:215-238, integrations/antigravity-plugin/core/mcp_server.py:215-238
The request router handles standard MCP JSON-RPC protocol methods. When an initialize request arrives, it echoes back the requested protocol version falling back to 2024-11-05, declares tool capabilities, and returns server metadata comprising name mem0 and the current PLUGIN_VERSION.
def handle_request(message: Any) -> dict[str, Any] | None:
if not isinstance(message, dict):
return None
request_id = message.get("id")
method = message.get("method")
if method == "notifications/initialized":
return None
if method == "initialize":
requested = (message.get("params") or {}).get("protocolVersion")
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"protocolVersion": requested or PROTOCOL_VERSION,
"capabilities": {"tools": {"listChanged": False}},
"serverInfo": {"name": "mem0", "version": PLUGIN_VERSION},
},
}
if method == "ping":
return {"jsonrpc": "2.0", "id": request_id, "result": {}}Sources: integrations/mem0-agent-plugin/core/mcp_server.py:152-172, integrations/antigravity-plugin/core/mcp_server.py:152-172
Warning
Incoming JSON-RPC lines failing JSON deserialization return a -32700 parse error, while unhandled internal exceptions return a -32603 internal error code with id: None. Requests carrying unrecognized methods return a -32601 method not found error integrations/mem0-agent-plugin/core/mcp_server.py:206-232, integrations/antigravity-plugin/core/mcp_server.py:206-232.
Sources: integrations/mem0-agent-plugin/core/mcp_server.py:206-232, integrations/antigravity-plugin/core/mcp_server.py:206-232
Memory Retrieval Tool and Argument Validation
The server exposes a single retrieval tool named search_memories. The tool definition includes input validation schemas, descriptive text, and execution annotations.
PROTOCOL_VERSION = "2024-11-05"
TOOL_NAME = "search_memories"
TOOL_DESCRIPTION = (
"Search memories from earlier work in this repository. Use it before "
"repeating investigation or when earlier decisions, fixes, commands, or "
"results may help."
)
TOOL_SCHEMA = {
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "A direct question about earlier work in this repository.",
},
"top_k": {
"type": "integer",
"minimum": 1,
"maximum": 20,
"description": "Maximum memories to return. Uses Mem0's configured default when omitted.",
},
"category": {
"type": "string",
"enum": list(CODING_MEMORY_CATEGORY_NAMES),
"description": "Optional memory category. Omit to search every category.",
},
"scope": {
"type": "string",
"enum": list(SEARCH_SCOPES),
"description": (
"Which memories to search. 'repo' (default) is the whole repository's "
"shared memory plus your own preferences, 'dir' narrows the shared "
"part to the current directory, 'mine' is your preferences alone."
),
},
"run_id": {
"type": "string",
"minLength": 1,
"description": (
"Optional coding-agent session ID. With any scope, restricts results to memories "
"saved in that session. Omit to recall memories across sessions."
),
},
},
"required": ["query"],
"additionalProperties": False,
}Sources: integrations/mem0-agent-plugin/core/mcp_server.py:21-68, integrations/antigravity-plugin/core/mcp_server.py:21-68
| Property | Type | Constraints / Enum | Purpose |
|---|---|---|---|
query | string | minLength: 1, maxLength: 2000, required | Direct question about earlier work in the repository |
top_k | integer | minimum: 1, maximum: 20, optional | Maximum number of memories to return |
category | string | CODING_MEMORY_CATEGORY_NAMES, optional | Optional memory category filter |
scope | string | SEARCH_SCOPES, optional | Search boundary (repo, dir, or mine) |
run_id | string | minLength: 1, optional | Restricts results to a specific coding-agent session ID |
Sources: integrations/mem0-agent-plugin/core/mcp_server.py:28-68, integrations/antigravity-plugin/core/mcp_server.py:28-68
The tools/list method announces search_memories with annotations configured with readOnlyHint: True, idempotentHint: True, and openWorldHint: True. Argument validation enforces strict type boundaries via _validate_arguments, raising ToolInputError if unknown arguments are present, strings exceed character limits, or integer bounds are violated.
def _validate_arguments(
arguments: Any,
) -> tuple[str, int | None, str | None, str | None, str | None]:
if not isinstance(arguments, dict):
raise ToolInputError("Search arguments must be an object.")
unknown = set(arguments) - {"query", "top_k", "category", "scope", "run_id"}
if unknown:
raise ToolInputError(f"Unknown search argument: {sorted(unknown)[0]}")
query = arguments.get("query")
if not isinstance(query, str) or not query.strip():
raise ToolInputError("query must be a non-empty string.")
query = query.strip()
if len(query) > 2000:
raise ToolInputError("query must be at most 2,000 characters.")
top_k = arguments.get("top_k")
if top_k is not None and (
isinstance(top_k, bool) or not isinstance(top_k, int) or not 1 <= top_k <= 20
):
raise ToolInputError("top_k must be an integer from 1 to 20.")
category = arguments.get("category")
if category is not None and category not in CODING_MEMORY_CATEGORY_NAMES:
raise ToolInputError("category must be one of Mem0's supported categories.")
scope = arguments.get("scope")
if scope is not None and scope not in SEARCH_SCOPES:
raise ToolInputError(f"scope must be one of {list(SEARCH_SCOPES)}.")
run_id = arguments.get("run_id")
if run_id is not None:
if not isinstance(run_id, str) or not run_id.strip():
raise ToolInputError("run_id must be a non-empty string.")
run_id = run_id.strip()
return query, top_k, category, scope, run_id
Sources: integrations/mem0-agent-plugin/core/mcp_server.py:75-113, integrations/antigravity-plugin/core/mcp_server.py:75-113
IDE Hook Event Dispatching
Hook Orchestration and Input Processing
Host IDE hooks are orchestrated through shared runner scripts that intercept environment events and route them into Mem0 background pipelines. Hook input is read directly from standard input as a JSON dictionary, defaulting to an empty structure on parse or I/O errors.
def read_hook_input() -> dict:
try:
value = json.load(sys.stdin)
return value if isinstance(value, dict) else {}
except (json.JSONDecodeError, OSError):
return {}
Sources: integrations/antigravity-plugin/core/hook_runner.py:44-50, integrations/kimi-plugin/core/hook_runner.py:44-50, integrations/claude-code-plugin/core/hook_runner.py:44-50, integrations/codex-plugin/core/hook_runner.py:44-50, integrations/cursor-plugin/core/hook_runner.py:44-50
Note
Tool use response hooks evaluate tool exit codes and error flags to detect failed executions. If a tool response indicates a failure via exit_code != 0, isError: true, or success: false, the runner injects error telemetry into the payload before recording integrations/codex-plugin/hooks/adapter.py:42-55.
Sources: integrations/codex-plugin/hooks/adapter.py:42-55
Configuration and Handoff Mechanics
Plugin hooks configure their respective harness environments and execute asynchronous background flush workers to persist capture data without blocking the IDE event loop.
configure_harness("codex", data_dir_name="codex-plugin", source_tag="codex_plugin")
telemetry.init(harness="codex", source_tag="CODEX_PLUGIN")Sources: integrations/codex-plugin/hooks/adapter.py:23-24
| Constant Name | Value / Default | Meaning / Constraint |
|---|---|---|
STALE_RUNNING_SECONDS | 300 | Threshold in seconds before a running handoff process is considered stale and reset |
PENDING_EXPIRY_SECONDS | 604800 (7 days) | Maximum age for pending handoff files before deletion |
PENDING_LAUNCH_LIMIT | 5 | Maximum number of pending handoff processes launched concurrently |
DEFAULT_IDLE_FLUSH_SECONDS | 300 | Default idle duration before triggering a flush |
Sources: integrations/antigravity-plugin/core/hook_runner.py:36-39, integrations/kimi-plugin/core/hook_runner.py:36-39, integrations/claude-code-plugin/core/hook_runner.py:36-39, integrations/codex-plugin/core/hook_runner.py:36-39, integrations/cursor-plugin/core/hook_runner.py:36-39
Warning
Handoff payloads are hashed using SHA-256 over the working directory, session ID, and reason, truncated to 24 hex characters, to prevent duplicate worker invocations for concurrent identical events integrations/antigravity-plugin/core/hook_runner.py:170-191, integrations/kimi-plugin/core/hook_runner.py:170-191, integrations/claude-code-plugin/core/hook_runner.py:170-191, integrations/codex-plugin/core/hook_runner.py:170-191, integrations/cursor-plugin/core/hook_runner.py:170-191.
Sources: integrations/antigravity-plugin/core/hook_runner.py:170-191, integrations/kimi-plugin/core/hook_runner.py:170-191, integrations/claude-code-plugin/core/hook_runner.py:170-191, integrations/codex-plugin/core/hook_runner.py:170-191, integrations/cursor-plugin/core/hook_runner.py:170-191
In-Plugin Diagnostic Utilities
Plugin distributions bundle a command-line interface script (memory_cli.py) that exposes diagnostic checks, telemetry controls, and repository memory management directly within agent environments and IDE extensions integrations/mem0-agent-plugin/core/memory_cli.py:1-20. The script configures harness environments via --harness, overrides local storage paths through --plugin-data-dir, and dispatches structured subcommands parsed with argparse integrations/mem0-agent-plugin/core/memory_cli.py:61-87.
| Subcommand | Arguments | Action Performed |
|---|---|---|
status | --json | Prints operational state, repository identity, local data paths, API key presence, and last operation metrics |
doctor | --json | Runs system diagnostics and integrity checks against the working environment |
pause | None | Disables local memory saving and searching by setting the paused setting to true |
resume | None | Re-enables local memory operations by setting the paused setting to false |
forget | --remote, --yes, --include-project-memory | Purges local repository memory scopes and optionally removes remote repository data from Mem0 |
Sources: integrations/mem0-agent-plugin/core/memory_cli.py:67-80, integrations/mem0-agent-plugin/core/memory_cli.py:92-146]
Warning
The forget subcommand enforces a safety check requiring the --yes flag; attempting to execute deletion without --yes aborts with exit code 2 to prevent accidental loss of user or project memory scopes integrations/mem0-agent-plugin/core/memory_cli.py:124-129.
Sources: integrations/mem0-agent-plugin/core/memory_cli.py:124-129]
The CLI records control telemetry events for every invoked command before executing the corresponding handler integrations/mem0-agent-plugin/core/memory_cli.py:91. Upon completion, the underlying EvidenceStore is safely closed within a finally block, and background telemetry flushes are spawned to transmit pending diagnostic records integrations/mem0-agent-plugin/core/memory_cli.py:147-150.
Sources: integrations/mem0-agent-plugin/core/memory_cli.py:91, integrations/mem0-agent-plugin/core/memory_cli.py:147-150]
Related
On This Page
OverviewCLI Synchronization MechanismPropagation Targets and RulesParsing Patterns and Atomic WritesIDE MCP Tool ManifestsManifest Structure Across TargetsStandalone MCP Server ImplementationJSON-RPC Server Loop and Request DispatchMemory Retrieval Tool and Argument ValidationIDE Hook Event DispatchingHook Orchestration and Input ProcessingConfiguration and Handoff MechanicsIn-Plugin Diagnostic UtilitiesRelated