Skip to content

Conversation

@andrewleech
Copy link

Summary

Adds project isolation support to enable a single AutoMem backend to serve multiple projects with completely separate memory spaces.

Changes

  • AutoMemConfig interface: Add optional field
  • HTTP client: Send header when project is configured
  • CLI setup: Add flag with interactive prompting
  • Environment variables: Support for configuration
  • MCP server: Load project ID from environment in both main server and recall command

Benefits

  • Multiple projects can share one AutoMem deployment with isolated memories
  • Backward compatible - existing clients continue working without changes
  • Simple configuration via CLI flag or environment variable
  • Complements the backend project isolation feature

Usage

# Setup with project isolation
npx @verygoodplugins/mcp-automem setup --project-id my-project

# Or via environment variable
export AUTOMEM_PROJECT_ID=my-project
npx @verygoodplugins/mcp-automem setup

This works with the corresponding backend changes that add project_id scoping to Memory nodes and Qdrant collections.

- Add projectId to AutoMemConfig interface for project scoping
- Update HTTP client to send X-Project-ID header when project is configured
- Add --project-id CLI flag to setup command with interactive prompting
- Add AUTOMEM_PROJECT_ID environment variable support
- Update both main MCP server and recall command to load project ID from env

This enables multiple projects to use the same AutoMem backend with
isolated memory spaces via the project_id parameter.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

📝 Walkthrough

Walkthrough

This PR adds optional projectId configuration support throughout the AutoMem system. The projectId can be specified via environment variables, CLI arguments, or programmatic configuration, is validated and persisted through the setup workflow, and is conditionally injected as an X-Project-ID header in client requests.

Changes

Cohort / File(s) Change Summary
Type Definitions
src/types.ts
Added optional projectId?: string field to AutoMemConfig interface
Client Initialization
src/index.ts
Updated AutoMemConfig to accept projectId; passes projectId to AutoMemClient instantiation alongside existing endpoint and apiKey
HTTP Client
src/automem-client.ts
Added conditional header injection: includes X-Project-ID header in requests when config.projectId is set
CLI Setup Flow
src/cli/setup.ts
Extended SetupOptions interface with optional projectId field; added support for reading AUTOMEM_PROJECT_ID environment variable, parsing --project-id CLI argument, prompting user for projectId input in interactive mode, and persisting projectId to environment file

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI
    participant Config
    participant AutoMemClient
    participant HTTP

    User->>CLI: Run setup with --project-id
    CLI->>CLI: Read AUTOMEM_PROJECT_ID from env
    CLI->>CLI: Parse --project-id argument
    CLI->>User: Prompt for Project ID (if interactive)
    User->>CLI: Provide projectId
    CLI->>Config: Persist projectId to file
    
    Note over User,Config: Later: Using AutoMem with projectId
    User->>Config: Initialize with projectId in config
    Config->>AutoMemClient: Pass endpoint, apiKey, projectId
    User->>AutoMemClient: Make request
    AutoMemClient->>AutoMemClient: Check if projectId is set
    alt projectId set
        AutoMemClient->>HTTP: Add X-Project-ID header
    end
    AutoMemClient->>HTTP: Send request
    HTTP-->>AutoMemClient: Response
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Consistent pattern of adding an optional configuration field across multiple files
  • No complex business logic or destructive changes
  • Straightforward header injection in client layer
  • CLI setup follows existing patterns for environment/argument/persistence handling

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "Add project isolation support for multi-project deployments" clearly and concisely summarizes the main objective of the changeset. The raw_summary confirms that all modifications across four files (automem-client.ts, setup.ts, index.ts, and types.ts) work together to implement project isolation by adding a projectId field to the configuration, injecting an X-Project-ID header in requests, supporting a CLI flag with environment variable, and updating the MCP server to use this project ID. The title directly captures this primary change and would be immediately understood by a teammate reviewing the git history.
Description Check ✅ Passed The PR description is well-structured and directly related to the changeset. It explicitly documents each modified component: the AutoMemConfig interface extension, HTTP client header injection, CLI setup flag addition, environment variable support, and MCP server integration. Each item in the "Changes" section aligns with the file-level summaries provided in the raw_summary, and the description includes concrete usage examples and explains the backward compatibility aspect. The description provides meaningful context about the feature's purpose and benefits without being vague or off-topic.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0878b and e70d3d8.

⛔ Files ignored due to path filters (11)
  • dist/automem-client.d.ts.map is excluded by !**/dist/**, !**/*.map
  • dist/automem-client.js is excluded by !**/dist/**
  • dist/automem-client.js.map is excluded by !**/dist/**, !**/*.map
  • dist/cli/setup.d.ts.map is excluded by !**/dist/**, !**/*.map
  • dist/cli/setup.js is excluded by !**/dist/**
  • dist/cli/setup.js.map is excluded by !**/dist/**, !**/*.map
  • dist/index.js is excluded by !**/dist/**
  • dist/index.js.map is excluded by !**/dist/**, !**/*.map
  • dist/types.d.ts is excluded by !**/dist/**
  • dist/types.d.ts.map is excluded by !**/dist/**, !**/*.map
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • src/automem-client.ts (2 hunks)
  • src/cli/setup.ts (6 hunks)
  • src/index.ts (3 hunks)
  • src/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/automem-client.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/automem-client.ts: Add a corresponding AutoMemClient method for any new tool that needs an API call
Normalize AutoMem API responses: accept memory_id, id, or response.memory_id and map to a single internal field
Normalize timestamps from timestamp, created_at, or updated_at in service responses
When recall is called with tags, merge results from /recall and /memory/by-tag for better coverage

Files:

  • src/automem-client.ts
src/types.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Update src/types.ts with new argument/result types when adding a tool

Files:

  • src/types.ts
src/index.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/index.ts: Define new MCP tool schemas in the tools array in src/index.ts (with inputSchema) when adding a tool
Add a handler for each new tool in the CallToolRequestSchema switch in src/index.ts
Import and register new CLI commands in src/index.ts command routing
Do not expose the removed search_by_tag tool; use recall_memory with tags instead

Files:

  • src/index.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-10-01T01:12:18.800Z
Learning: Include a <project-name> tag in all memories (auto-detected)
📚 Learning: 2025-10-01T01:11:42.805Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-01T01:11:42.805Z
Learning: Applies to src/automem-client.ts : Add a corresponding AutoMemClient method for any new tool that needs an API call

Applied to files:

  • src/automem-client.ts
  • src/types.ts
  • src/index.ts
📚 Learning: 2025-10-01T01:11:42.805Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-01T01:11:42.805Z
Learning: Applies to src/automem-client.ts : Normalize AutoMem API responses: accept memory_id, id, or response.memory_id and map to a single internal field

Applied to files:

  • src/automem-client.ts
  • src/types.ts
  • src/index.ts
📚 Learning: 2025-10-01T01:11:42.805Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-01T01:11:42.805Z
Learning: Applies to .env : Provide AUTOMEM_ENDPOINT in environment or .env; AUTOMEM_API_KEY is optional

Applied to files:

  • src/cli/setup.ts
  • src/index.ts
📚 Learning: 2025-10-01T01:13:48.061Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: .cursor/rules/project-assistant.md:0-0
Timestamp: 2025-10-01T01:13:48.061Z
Learning: Automatically detect the current project from, in order: package.json name, Git remote repository name, then current directory name

Applied to files:

  • src/cli/setup.ts
📚 Learning: 2025-10-01T01:11:42.805Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-01T01:11:42.805Z
Learning: Applies to src/automem-client.ts : When recall is called with tags, merge results from /recall and /memory/by-tag for better coverage

Applied to files:

  • src/index.ts
📚 Learning: 2025-10-01T01:12:18.800Z
Learnt from: CR
Repo: verygoodplugins/mcp-automem PR: 0
File: .cursor/rules/AGENTS.md:0-0
Timestamp: 2025-10-01T01:12:18.800Z
Learning: Include a <project-name> tag in all memories (auto-detected)

Applied to files:

  • src/index.ts
🧬 Code graph analysis (2)
src/cli/setup.ts (1)
dist/cli/setup.js (20)
  • ENV_PROJECT_ID_KEY (10-10)
  • options (12-12)
  • options (54-54)
  • options (143-143)
  • options (230-230)
  • i (13-13)
  • i (55-55)
  • defaultProjectId (154-157)
  • existingValues (145-145)
  • projectId (175-175)
  • rl (132-132)
  • rl (162-162)
  • rl (177-177)
  • rl (191-191)
  • promptSuffix (164-164)
  • promptSuffix (179-179)
  • answer (134-134)
  • answer (165-165)
  • answer (180-180)
  • updates (204-206)
src/index.ts (2)
dist/cli/queue.js (1)
  • client (63-66)
src/automem-client.ts (1)
  • AutoMemClient (15-251)
🔇 Additional comments (12)
src/types.ts (1)

4-4: LGTM!

The optional projectId field is properly typed and aligns well with the existing optional apiKey field.

src/cli/setup.ts (6)

13-13: LGTM!

The projectId field is appropriately added to SetupOptions as optional, maintaining consistency with other optional fields.


26-26: LGTM!

The environment variable key follows the existing naming convention (AUTOMEM_ prefix).


46-49: LGTM!

The --project-id argument parsing is correctly implemented and follows the same pattern as --endpoint and --api-key.


181-184: LGTM!

The default value resolution logic correctly prioritizes CLI options, then existing values from the env file, then process environment, and finally defaults to an empty string. This matches the pattern used for endpoint and API key.


204-217: LGTM!

The interactive prompt for projectId is well-implemented. The prompt suffix clearly indicates that the field is optional and explains its purpose ("for project isolation"), which improves user experience.


239-241: LGTM!

The persistence logic correctly filters out sentinel values and only writes valid projectId values to the environment file, consistent with the apiKey handling.

src/index.ts (4)

171-171: LGTM!

The AUTOMEM_PROJECT_ID environment variable is correctly read in the recall command flow, maintaining consistency with AUTOMEM_ENDPOINT and AUTOMEM_API_KEY.


178-178: LGTM!

The projectId is properly passed to the AutoMemClient constructor in the recall command, ensuring project isolation is applied when configured.


208-208: LGTM!

The AUTOMEM_PROJECT_ID environment variable is correctly read for the main MCP server configuration.


214-218: LGTM!

The projectId is properly included in the clientConfig object, completing the configuration flow for project isolation support.

src/automem-client.ts (1)

37-39: Header name is correct per commit specifications.

The actual commit message for "Add project isolation support" explicitly states: "Update HTTP client to send X-Project-ID header when project is configured." The code at line 38 correctly implements this with headers['X-Project-ID']. The review comment's claim that the PR description specifies X-AutoMem-Project cannot be verified, and there are no references to that header name anywhere in the codebase. The implementation matches the documented intent of the commit.

Likely an incorrect or invalid review comment.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@andrewleech andrewleech marked this pull request as draft November 3, 2025 00:05
@danieliser
Copy link

Clarification on X-Project-ID Intent

@andrewleech Nice addition! Before this gets merged, I was hoping to clarify the intended purpose of X-Project-ID - it affects how backend support should be implemented.

Option A: Organizational Tagging

If the goal is to automatically tag/categorize memories by project for better filtering and recall (all data still in the same database), then the backend would:

  • Auto-tag memories with project:
  • Enable filtering by project in recall queries
  • Single database, logical separation only

Option B: True Multi-Tenant Isolation

If the goal is actual data isolation between projects (separate databases, no cross-project data leakage), the backend needs to route requests to different FalkorDB graphs and Qdrant collections per project.

There's a PR on the AutoMem backend (verygoodplugins/automem#29) that adds isolation header support via X-Graph-Name and X-Collection-Name. If Option B is the intent, that approach might be worth considering because:

  1. Physical separation - No risk of query bugs leaking data between projects
  2. Independent scaling - Heavy projects don't impact others
  3. Granular control - Different graph vs collection names if needed
  4. Simpler queries - No WHERE project_id = $id on every query

If Option A is what your after I have a backend PR already prepped too.

The linked PR addresses requirements for a true multi-tennant architecture (which I have working), along with needed changes to allow federated memories to each based on context of the memory.

Happy to help coordinate MCP and backend alignment. I already had working branches heading for PR when I saw this.

Which use case is this targeting?

@danieliser
Copy link

Should clarify I have a PR for this repo (the MCP) to handle those new headers as well, both at MCP definition, but also on the fly via headers.

@andrewleech
Copy link
Author

My goal was closest to A, I want one installation of the service to be used by multiple projects I'm working on; many of them are worktrees of the same codebase but very different development activities.

I'm installing this and using this on a single development server that might have up to 10 different Claude code tmux's running in separate worktrees so I didn't want their individual dev memories to get all mixed together.

@danieliser
Copy link

@andrewleech have you tested it much? Not quite the use case I had in my head from your initial description, though same solution works I guess.

I do question though the veracity of separating their concerns so much with a memory solution like this.

Follow up

  • Do you have different developer preferences for each project that compete? IE 2 typescript projects that use different syntax flavors or such?

As this is was originally built for long term, full scale memory across many projects/activities all at once from its inception by @jack-arturo , I'm genuinely curious how a per project folder variant would work in real world.

That is to say do you still get the full benefits? Are you having some global and some per project memories mixed for each agent, or is each truly siloed with no idea the others exist and no top-down memories they all share?


In any case I have a second PR I haven't submitted yet for the main core that handled automated tagging based on an MCP config, similar to yours. I like your header though better than what I had.

I'd be interested if the simple solution I implemented would be sufficient for what you were already testing. or if your actual usage of this concept found more tweaks were required.

Look forward to hearing @jack-arturo weigh in too.

I overall think its genuinely useful header to offer.

@andrewleech
Copy link
Author

I used it heavily on one development activity that went for a few weeks before needing to be paused and tried to use it on a few others with mixed degrees of success. It was hard to gauge how well it was working to be honest.

For context I'm working on embedded system designs based on micropython, so most of the coding is in C and python, but hardware in the loop so there's a mixture of PC tooling, compilers, gdb debugging etc.

I already have a shared CLAUDE.md for all related projects which is used in the typical way for overall/shared guidance.

The first big project I tried automem with was deeply complex work building a new threading engine for embedded platforms; lots of trial and error work on memory layout and timing debugging.

I was hoping automem would be able to work as the long term memory to keep Claude more focused over literally weeks of development on this; most of this time was on finding and fixing bugs in the underlying integration running in hardware. I needed to be able to keep track of what had been theorized, trialed and failed to avoid repeating the same things.
This didn't work out for me, sonnet 4.5 kept going around in circles for a week or more.

At some point during this time automem dropped out though, the docker service had been accidentally killed, so the test pretty much fell apart.

I'd also been trying to replace the mcp with a cli tool & hooks to make it get called deterministically. So... lots of variables... It wasn't a very good test.

I had automem configured in some other development branches briefly but not enough to know how well it was working really.

I started this project separation as I couldn't tell from the documentation if it was safe/supported to use one instance of automem on multiple development efforts or if the memories would all be mixed in together.

My primary goal is to find a memory system like this that can maintain an efficient trial and error development log for long running development investigations and help maintain focus across compact cycles.

@danieliser
Copy link

@andrewleech - I noticed in the recent MCP updates that the hooked automatic memories were removed, not sure how long you used it but prior to that mine created lots of memories in every chat on its own via the queue.

Lost a bunch of memories myself in similar fashion, reboot of my machine caused docker lost volumes etc. However if you run it on Railway via the 1 click button, that shouldn't occur as it uses a true persistent volume.

Losing them sucks for sure, I lost a lot when I ran backups to move to cloud, but the backup script didn't account for 10k row hard coded query limits in FalkorDB, causing me to only get 10k of 15k memories/connections. Submitted a PR shortly after to fix that.

Honestly its meant to just run without switching/segmentation. The auto-hooked-memory is something I've already pointed out to @jack-arturo needs brought back, but in general once you get Claude correctly utilizing it, its quite good at keeping things on track.

@jack-arturo
Copy link
Member

Thank you for this contribution @andrewleech! Project isolation is a valuable feature for multi-tenant deployments.

Unfortunately, this PR has become significantly out of date (3+ months, many changes to main) and would require substantial rebasing to merge cleanly.

I'm opening a new issue to track this feature request. If you're interested in updating this, feel free to rebase on main and reopen, or we can implement it fresh in a future release.

Thanks for your contribution to the project!

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.

4 participants