You do not need to write code to contribute. Testing MARM with your client setup, reporting what broke, sharing your workflow in Discussions, or jumping into Discord to help someone get unstuck are all real contributions.
If you do want to go deeper, MARM is focused on the MCP server, local memory workflows, the code and concept knowledge graphs, Docker/STDIO transports, IDE and client integrations, and marm-console for inspecting local memory data. This guide covers that practical development workflow. For project history and community recognition, see ACKNOWLEDGMENTS.md.
Drop a message in MARM Discord or reach out directly at support@marmemory.com.
git clone https://github.com/Lyellr88/marm-memory.git
cd marm-memoryInstall the MCP server in editable mode:
cd marm-mcp-server
pip install -e ".[dev]"For source development, fetch the bundled extraction model into package data:
python scripts/bundle-concept-model.pyRun the HTTP server:
python -m marm_mcp_serverRun the STDIO server:
python -m marm_mcp_server.server_stdioGenerate an API key when using exposed HTTP mode or Docker HTTP:
python -m marm_mcp_server --generate-keymarm-mcp-server/
marm_mcp_server/
__main__.py # `python -m marm_mcp_server` entry, delegates to cli
cli.py # HTTP CLI, dependency checks, and server factory
server.py # FastAPI HTTP composition root
server_stdio.py # STDIO bootstrap and core-tool registration
config/settings.py # Paths, host/port, auth, feature flags
core/
memory.py # MARMMemory facade and public memory object wiring
memory_utils.py # Shared memory helpers, chunking, and encoding utilities
memory_db.py # SQLite schema, connection pool, and DB maintenance routines
memory_scoring.py # Semantic, FTS, temporal, and chunk-aware recall scoring
memory_ops.py # Store/update/recall/delete/list memory operations
memory_recall.py # Recall orchestration across the scoring lanes
memory_delete.py # Delete paths and their cascade handling
write_queue.py # Serialized write queue for SQLite writer stability
consolidation.py # Content-hash and semantic write-time consolidation
compaction.py # Background compaction candidate detection and nudges
compaction_scheduler.py # Optional compaction maintenance scheduler
docs_db.py # Indexed copy of the shipped docs served to agents
concept_db.py # Concept graph schema and isolated SQLite pool
concept_extraction.py # spaCy entity/relationship extraction (bundled model)
concept_queue.py # Durable outbox: one indexing task per stored memory
concept_worker.py # Background worker draining that queue into the graph
concept_build_lock.py # Concept-graph binding of the cross-process lease
lease_lock.py # Leased-row mutual exclusion, shared by both graphs
graph_supervisor.py # Lazy singleton supervisor for the embedded graph engine
graph_client.py # Concept graph's in-process link into the code graph
graph_index_lock.py # The one gate every code-graph store mutation takes
graph_index_worker.py # Git-signature poller that keeps code graphs current
runtime_flags.py # Persisted on/off switches and watch suppressions
runtime_manager.py # Local runtime discovery and background start/stop
protocol_delivery_state.py # Bounded HTTP protocol-delivery state
models.py # Shared Pydantic request/response models
events.py # Internal event hooks
rate_limiter.py # Rate limiting primitives
response_limiter.py # MCP response size controls
shutdown_manager.py # Graceful shutdown handling
stdio_logging.py # STDERR-only STDIO logger setup
stdio_tool_lifecycle.py # STDIO protocol, logging, and compaction wrapper
endpoints/
session.py # Session tools
logging.py # Log tools
reasoning.py # Reasoning/deep-dive tools
notebook.py # Notebook tools
memory.py # Recall/search tools
compaction.py # Unified compaction tool and hidden helper routes
graph.py # 5 bundled code-graph tools (routed through marm_graph)
concepts.py # 2 concept-graph tools (build + recall)
system.py # Health/system tools
middleware/
auth.py # Bearer auth for HTTP mode
protocol_injection.py # HTTP MCP protocol/compaction response injection
rate_limiting.py # HTTP rate limiting middleware
services/
analytics.py # Best-effort local usage analytics
documentation.py # Startup documentation loading
automation.py # Event handler registration
notebook.py # Notebook dispatch service
recall.py # Shared smart-recall response logic
summary.py # Shared session summary formatting
graph_context.py # Bounded read-only concept context for recall
log_entry.py # Shared log-entry/notebook data ops, both transports
compaction_apply.py # Atomic compaction apply transaction
compaction_summarize.py # Compaction cluster summarization helpers
stdio_entry_tools.py # STDIO log entry/show/delete workflow bodies
stdio_graph_tools.py # STDIO graph/concept bodies and registration helper
cli_parser.py # Argument parsers for the product and legacy CLIs
cli_output.py # Human-readable status/doctor/maintenance rendering
product_help.py # Terminal-aware root help rendering
product_workflows.py # High-level local workflows (start, upgrade, uninstall)
product_logs.py # Bounded managed-runtime log display
runtime_status.py # Read-only status aggregation for diagnostics
projects_cli.py # `projects` code-index commands
graph_auto_cli.py # `projects auto` / `knowledge auto` on-off switches
key_management.py # Persistent local API-key operations
package_management.py # Installer detection and registry checks
skill_install.py # Installs the bundled marm-init skill into agent folders
docker_cli.py # Docker parser registration and dispatch
docker_commands.py # Safe Docker command planning and execution
utils/
dependency_check.py # Runtime dependency validation
helpers.py # Shared helpers
logging_filters.py # Process logging noise filters
multiprocess_guard.py # Unsupported multi-worker runtime warning
security.py # API key generation
embedding_state.py # Inspect persisted embedding compatibility, no runtime init
embedding_migration.py # Resumable stopped-server embedding vector migration
chunk_backfill.py # Stopped-server backfill of memory_chunks after config change
marm_graph/ # Embedded marm-graph wrapper: subprocess JSON-RPC client,
# tool router, and backend verification for the pinned
# codebase-memory-mcp binary
tests/ # MCP server test suite
Dockerfile # One image, HTTP default, STDIO override
pyproject.toml # Package metadata and console scripts
docs/ # User-facing docs and project docs
scripts/ # Local validation, release, and maintenance helpers
marm-console/ # Standalone local Console app in active development (:8002)
HTTP and STDIO are separate transports
HTTP mode lives in marm_mcp_server/server.py and is mounted through FastAPI/FastApiMCP at /mcp.
STDIO mode lives in marm_mcp_server/server_stdio.py and uses the official MCP Python SDK over standard input/output. It owns the FastMCP app and registers the seven core tools first; services/stdio_graph_tools.py supplies the graph/concept tool bodies through explicit registration so tools/list order remains stable. STDIO must keep stdout clean for JSON-RPC messages; logs and incidental print() output belong on stderr.
If a tool behavior changes, check whether the HTTP endpoint and STDIO tool both need the same update.
Separate transports means separate processes. Both run the same background indexers (concept extraction and code re-indexing) against the same databases, so anything they touch needs mutual exclusion that reaches across processes: a leased row in the memory database, not an asyncio.Lock or a module-level threading.Lock. core/lease_lock.py is that primitive, and a run of the test suite is not enough to catch a mistake here, since one interpreter never exercises the boundary. The two-process tests in tests/test_concept_two_process.py and tests/test_graph_auto_index.py spawn a real second interpreter for exactly that reason.
Docker HTTP requires an API key
Docker HTTP binds inside the container with SERVER_HOST=0.0.0.0, and host requests arrive through Docker bridge networking rather than 127.0.0.1. Always pass MARM_API_KEY for Docker HTTP.
docker run -d --name marm-mcp-server `
-p 127.0.0.1:8001:8001 `
-e SERVER_HOST=0.0.0.0 `
-e MARM_API_KEY=your-generated-key `
-v ${HOME}\.marm:/home/marm/.marm `
lyellr88/marm-mcp-server:latestDocker STDIO does not use an HTTP key
Docker STDIO launches a one-client process and does not expose an HTTP listener.
docker run -i --rm `
-v ${HOME}\.marm:/home/marm/.marm `
lyellr88/marm-mcp-server:latest `
python -m marm_mcp_server.server_stdioUse Docker HTTP for shared or multi-agent workflows. Use STDIO for private single-client local workflows. Multiple STDIO containers can point at the same mounted SQLite database, but heavy concurrent writes may hit normal SQLite lock contention.
Local HTTP defaults to loopback
SERVER_HOST defaults to 127.0.0.1. Local loopback HTTP is intended for same-machine use and does not require a key unless MARM_API_KEY is set.
If SERVER_HOST=0.0.0.0, MARM requires a key. When no key is provided, the settings layer auto-generates one and stores it in ~/.marm/.env.
SQLite schema changes need extra care
MARM uses a local SQLite database under ~/.marm/ by default. Tool behavior depends on specific tables for sessions, log entries, notebook entries, memories, compaction staging, and analytics.
Memory, log, and notebook rows can carry nullable project and platform attribution columns. When changing write paths, recall filters, consolidation, or schema migrations, keep these fields aligned across HTTP, STDIO, tests, and docs.
Do not rename fields, move data between tables, or change date/session parsing behavior without updating HTTP tools, STDIO tools, tests, smoke scripts, and docs together.
Retired features stay retired unless re-scoped
Current supported connection paths are HTTP and STDIO. Do not reintroduce retired transports or auth shims unless there is a new spec and implementation plan for them.
- Find the current HTTP behavior in
marm_mcp_server/endpoints/. - Find the matching STDIO behavior in
marm_mcp_server/server_stdio.py. - Keep request/response field names aligned where possible.
- Prefer parameterized actions for closely related operations, following existing tools such as
marm_notebook(action=...),marm_delete(type=...), andmarm_compaction(action=...). - Update or add focused tests in
marm-mcp-server/tests/. - Update docs if the command shape, transport setup, auth behavior, or user-facing workflow changes.
- Run the local test runner before submitting changes.
Run the known-good local test checks from the repo root:
python scripts/run-tests.pyThis runs:
- Python compile check for
marm_mcp_serverandtests - Pytest suite with a controlled temp directory
For targeted ad hoc pytest runs, use --basetemp C:\tmp\... or clean repo-local pytest artifacts afterward:
powershell -ExecutionPolicy Bypass -File scripts\clean-pytest-artifacts.ps1Current expectations:
Failed: 0required before submitting a PR- Docker tests may skip automatically when Docker or the smoke image is unavailable
- Warnings should be reviewed, but a known dependency warning may not block a PR
Run release preflight before a push or release:
python scripts/release-preflight.pyThis runs the version scan, stale docs scan, known-good test runner, optional Docker smoke test, and a git status summary.
Run Docker smoke directly when changing Docker, transport setup, auth, or startup behavior:
python scripts/test-scripts/docker-smoke.pyFor changes to Docker bind mounts, container users, HOME, cache paths, or data persistence, also run the Linux-only smoke test. It verifies that a host-owned mounted database can be written through HTTP and survives a container restart.
Run it from a native Linux host or WSL2 with Docker Desktop WSL integration enabled. The script creates its temporary mounted data directory under Linux /tmp; do not change that location to /mnt/c, or the UID/GID assertion is no longer meaningful:
bash scripts/test-scripts/docker-linux-bind-mount-smoke.shThe script uses the latest official image by default. To test a locally built image instead:
MARM_DOCKER_SMOKE_IMAGE=marm-mcp-server:smoke bash scripts/test-scripts/docker-linux-bind-mount-smoke.shUpdate docs when changing:
- Install commands
- Docker behavior
- Client transport commands
- API key behavior
- Tool request/response fields
- Database behavior
- Version numbers
- Roadmap or support status
Useful maintenance scripts:
python scripts/find-versions.py
python scripts/find-dead-code.pyfind-versions.py is interactive and can update active version references. It intentionally avoids changing CHANGELOG.md because that file contains historical versions. find-dead-code.py looks for unused functions and classes in the MCP server codebase. Review its findings carefully before removing any code, as some utilities may be used in dynamic ways or reserved for future features.
MARM uses a PR-first workflow for normal development. Do not push feature, fix, or release-prep work directly to MARM-main.
- Create a focused branch from
MARM-main. - Keep the change scoped to one feature, fix, or doc cleanup.
- Follow existing file patterns before adding new abstractions.
- Run
python scripts/run-tests.py. - Run Docker smoke if the change touches Docker, HTTP/STDIO startup, auth, or transports.
- Update docs and changelog when user-facing behavior changes.
- Push the branch and open a PR into
MARM-main. - Wait for CodeRabbit and GitHub checks, then address review findings before merge.
No formal style guide beyond this: keep code readable, preserve current behavior unless the PR is explicitly changing it, and avoid broad refactors mixed into feature work.
Use short, descriptive branch names:
feature/notebook-polish
fix/dependency-range
docs/install-cleanup
release/v2.6.3
Publishing is tag-driven. Merging a PR into MARM-main does not publish PyPI, Docker, or the MCP Registry by itself.
Release sequence:
branch → PR → CodeRabbit review → merge to MARM-main → tag vX.Y.Z → publish workflow
After the PR is merged and MARM-main is clean:
git checkout MARM-main
git pull
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.ZThe v* tag triggers the publish workflow for:
- PyPI package publish
- MCP server Docker image
- MCP Registry publish
Use normal branch pushes for review. Use tag pushes only for intentional releases.
- README.md - Complete MCP server usage guide with commands, workflows, and examples
- PROTOCOL.md - Quick start commands and protocol reference
- FAQ.md - Answers to common questions about using MARM
- INSTALL-DOCKER.md - Docker deployment (recommended)
- INSTALL-WINDOWS.md - Windows installation guide
- INSTALL-LINUX.md - Linux installation guide
- INSTALL-PLATFORMS.md - Platform installation guide
- CONTRIBUTING.md - This file - how to contribute to MARM
- CHANGELOG.md - Version history and updates
- ACKNOWLEDGMENTS.md - Contributors and acknowledgments
- ROADMAP.md - Planned features and development roadmap
- LICENSE - Apache 2.0 license terms