Skip to content

Local Setup

Before setting up the development environment, ensure the following tools are installed:

ToolMinimum VersionPurpose
Python3.10+Core runtime
pipLatestPackage management
DockerLatestLocal service dependencies (optional)
Docker ComposeLatestMulti-container orchestration (optional)
gitAny recent versionSource control

After cloning the repository, the structure relevant to development:

PathDescription
app.pyMain Flask API application
consolidation.pyBackground consolidation engine
requirements.txtProduction dependencies
requirements-dev.txtDevelopment dependencies
DockerfileContainer image definition
docker-compose.ymlLocal service orchestration
tests/Test suite
scripts/Utility scripts

Create an isolated Python environment to avoid dependency conflicts:

Terminal window
python3 -m venv venv
source venv/bin/activate # macOS/Linux
# or: venv\Scripts\activate # Windows

The virtual environment isolates all installed packages from system Python, ensuring reproducible builds.

Terminal window
pip install -r requirements-dev.txt

This installs:

  • Production dependencies via -r requirements.txt
  • Testing tools: pytest==8.3.4
  • HTTP client: requests==2.31.0 (for integration tests)
  • Configuration: python-dotenv==1.0.1
  • Code quality: black==24.8.0, flake8==7.1.1
Terminal window
pip install -r requirements.txt

Use this for minimal installations without testing/development tools.

Optional: spaCy for Enhanced Entity Extraction

Section titled “Optional: spaCy for Enhanced Entity Extraction”
Terminal window
pip install spacy
python -m spacy download en_core_web_sm

The en_core_web_sm model enables Named Entity Recognition (NER) in the enrichment pipeline for extracting persons, organizations, locations, and temporal entities from memory content. AutoMem degrades gracefully if spaCy is unavailable — entity extraction simply won’t run.


graph TB
    subgraph "Developer Machine"
        subgraph "Virtual Environment (venv)"
            Flask["app.py\nFlask API\nPort 8001"]
            Consol["consolidation.py\nBackground Engine"]
        end

        subgraph "Docker Compose Stack (make dev)"
            DC["docker-compose.yml"]
            Falkor["falkordb/falkordb:latest\nPort 6379\nVolume: ./data/falkordb"]
            Qdrant["qdrant/qdrant:latest\nPort 6333\nVolume: ./data/qdrant"]
            APIContainer["memory-service\nPort 8001\nOptional"]
        end

        subgraph "External Services (Optional)"
            ExtFalkor["External FalkorDB\nlocalhost:6379"]
            ExtQdrant["External Qdrant\nlocalhost:6333"]
        end
    end

    Flask -->|"FALKORDB_HOST=localhost\nFALKORDB_PORT=6379"| Falkor
    Flask -->|"QDRANT_URL=http://localhost:6333"| Qdrant
    Flask -.->|"Alternative"| ExtFalkor
    Flask -.->|"Alternative"| ExtQdrant

    DC --> Falkor
    DC --> Qdrant
    DC -.->|"Optional"| APIContainer

Two primary approaches exist for running the database dependencies.

Terminal window
make dev # equivalent to: docker-compose up -d

This starts:

  • FalkorDB on port 6379 with volume mount at ./data/falkordb
  • Qdrant on port 6333 with volume mount at ./data/qdrant

The docker-compose.yml defines these services with persistent storage, ensuring data survives container restarts.

Terminal window
# Stop services
docker-compose down
# Check service status
docker-compose ps
# View logs
docker-compose logs -f falkordb

Run FalkorDB and Qdrant independently (bare metal, separate Docker containers, or cloud) and configure connection via environment variables (see Development Configuration below).


With dependencies running, start the Flask API:

Terminal window
python app.py

The Flask application binds to 0.0.0.0:8001 by default. The PORT environment variable controls the listening port.

Verify startup:

Terminal window
curl http://localhost:8001/health

Expected response:

{
"status": "healthy",
"falkordb": "connected",
"qdrant": "connected"
}
sequenceDiagram
    participant Dev as "Developer"
    participant Flask as "app.py (Flask)"
    participant Falkor as "FalkorDB :6379"
    participant Qdrant as "Qdrant :6333"
    participant Enrich as "EnrichmentWorker"
    participant Embed as "EmbeddingWorker"
    participant Sched as "ConsolidationScheduler"

    Dev->>Flask: "python app.py"
    Flask->>Flask: "Load env vars\n(PORT, FALKORDB_HOST, etc.)"
    Flask->>Falkor: "Connect to localhost:6379"

    alt Qdrant configured
        Flask->>Qdrant: "Connect to localhost:6333"
        Qdrant-->>Flask: "Connection OK"
    else No Qdrant
        Flask->>Flask: "Graceful degradation\n(FalkorDB-only mode)"
    end

    Flask->>Enrich: "Start worker thread"
    Enrich->>Enrich: "Begin polling queue"

    Flask->>Embed: "Start worker thread"
    Embed->>Embed: "Begin batch accumulator"

    Flask->>Sched: "Initialize scheduler"
    Sched->>Sched: "Schedule decay (1h)\ncreative (1h)\ncluster (6h)\nforget (1d)"

    Flask->>Flask: "Bind to 0.0.0.0:8001"
    Flask-->>Dev: "Server ready"

    Dev->>Flask: "GET /health"
    Flask->>Falkor: "Ping"
    Falkor-->>Flask: "PONG"
    Flask->>Qdrant: "Collection info"
    Qdrant-->>Flask: "Collection exists"
    Flask-->>Dev: '{"status": "healthy"}'

AutoMem loads configuration from three sources in order of precedence:

  1. Process environment (highest priority)
  2. .env file in project root
  3. ~/.config/automem/.env (user-wide config)

Minimal development configuration — create .env in the project root:

Terminal window
PORT=8001
FALKORDB_HOST=localhost
FALKORDB_PORT=6379
QDRANT_URL=http://localhost:6333
OPENAI_API_KEY=sk-...
AUTOMEM_API_TOKEN=your-dev-token
VariableDefaultDescription
PORT8001Flask API port
FALKORDB_HOSTlocalhostFalkorDB hostname
FALKORDB_PORT6379FalkorDB port
FALKORDB_PASSWORDunsetFalkorDB auth password
FALKORDB_GRAPHmemoriesGraph database name
QDRANT_URLunsetQdrant endpoint URL
QDRANT_API_KEYunsetQdrant API key
QDRANT_COLLECTIONmemoriesQdrant collection name
VECTOR_SIZE768Embedding dimension
OPENAI_API_KEYunsetOpenAI API key
ENRICHMENT_MAX_ATTEMPTS3Enrichment retry limit
ENRICHMENT_SIMILARITY_LIMIT5Semantic neighbors count
ENRICHMENT_SIMILARITY_THRESHOLD0.8SIMILAR_TO edge threshold
FLASK_ENVproductionFlask mode (development enables debug)
LOG_LEVELINFOLogging verbosity

Enable development mode for verbose logging and auto-reload:

Terminal window
FLASK_ENV=development
LOG_LEVEL=DEBUG

The FLASK_ENV=development setting enables: detailed error pages with stack traces, auto-reload on file changes, and more verbose console output.


Code formatting with Black:

Terminal window
black app.py consolidation.py tests/

Code linting with Flake8:

Terminal window
flake8 app.py consolidation.py

Running tests:

Terminal window
pytest tests/ -v

Manual API testing:

Terminal window
# Store a test memory
curl -X POST http://localhost:8001/memory \
-H "Authorization: Bearer your-dev-token" \
-H "Content-Type: application/json" \
-d '{"content": "Test memory", "tags": ["test"], "importance": 0.5}'
# Recall memories
curl "http://localhost:8001/recall?query=test&limit=5" \
-H "Authorization: Bearer your-dev-token"

Symptom: OSError: [Errno 48] Address already in use

Terminal window
lsof -i :8001 # Find process using port
kill -9 <PID> # Kill it

Or change the port: PORT=8002 python app.py

Symptom: 503 Service Unavailable or FalkorDB is unavailable

Terminal window
docker-compose ps # Check if FalkorDB container is running
docker-compose up -d falkordb # Start it if not
docker-compose logs falkordb # Check for errors

Symptom: ModuleNotFoundError: No module named 'flask'

Terminal window
source venv/bin/activate # Activate virtualenv
pip install -r requirements-dev.txt

Symptom: Qdrant errors in logs but API still works

Behavior: AutoMem operates in graceful degradation mode, using FalkorDB-only functionality. Vector search is replaced by keyword search. This is acceptable for development but impacts recall quality.

Terminal window
docker-compose up -d qdrant
curl http://localhost:6333/health # Verify Qdrant is accessible

Symptom: Memories stored but enrichment: queued never completes

Debug steps: Check logs for enrichment_worker thread exceptions. Look for metadata.enriched_at field to confirm enrichment ran.

Common causes:

  • Worker thread crashed (check logs for exceptions)
  • spaCy model not installed (pip install spacy && python -m spacy download en_core_web_sm)
  • Memory already enriched (check metadata.enriched_at field)

Symptom: Permission denied errors when writing to ./data/falkordb or ./data/qdrant

Terminal window
sudo chown -R $(whoami) ./data/

  • Node.js: Version 20.0.0 or higher
  • npm: Comes with Node.js
  • git: For version control
  • AutoMem Service: Running instance for integration testing (local or Railway-hosted)
Terminal window
git clone https://github.com/verygoodplugins/mcp-automem
cd mcp-automem
npm install # Also installs Husky git hooks via "prepare" lifecycle script
ScriptCommandPurpose
buildtsc && npm run postbuildCompile TypeScript to dist/, make executable
postbuildchmod +x dist/index.jsEnsure binary is executable
devtsx watch src/index.tsHot-reload development server
linteslint .Run ESLint static analysis
preparehuskyInstall git hooks (runs on npm install)
startnode dist/index.jsRun compiled server
testvitest runExecute unit tests
test:watchvitestRun tests in watch mode
test:coveragevitest run --coverageGenerate coverage report
test:integrationvitest run --config vitest.integration.config.tsRun integration tests
test:allvitest run && vitest run --config vitest.integration.config.tsRun all test suites
typechecktsc --noEmitType-check without compilation
prepublishOnlynpm run build && npm run testPre-publish validation
build:extensionnpm run build && npx @anthropic-ai/mcpb packBuild .mcpb Claude Desktop extension

Create a .env file in the project root:

Terminal window
AUTOMEM_ENDPOINT=http://localhost:8001
AUTOMEM_API_KEY=your-api-key

Configuration is read in priority order:

  1. Constructor arguments (programmatic usage)
  2. Process environment variables (process.env)
  3. .env file in current directory
  4. .env file in home directory

The dev script uses tsx for hot-reload development — TypeScript runs directly without a compilation step:

Terminal window
npm run dev # Watch mode, restarts on file changes

This is the recommended mode when actively developing. For testing the compiled output:

Terminal window
npm run build && node dist/index.js

Method 1: Direct invocation — test CLI commands without MCP client:

Terminal window
node dist/index.js setup # Test setup wizard
node dist/index.js --help # Show available commands

Method 2: Hot-reload in server mode — run without arguments to enter server mode, then send JSON-RPC messages via stdin.

Debugging tips:

  • Add console.error() statements (goes to stderr, doesn’t corrupt stdio protocol)
  • Use DEBUG=* environment variable if using the debug library
  • Check AutoMem service logs for backend errors
  • Validate JSON payloads with jq or online validators

Before committing changes to mcp-automem:

  • Run npm run lint (no errors)
  • Run npm run typecheck (no type errors)
  • Run npm test (all tests pass)
  • Ensure commit message follows Conventional Commits format
  • Update documentation if adding new features
  • Add tests for new functionality