ENGRAM Developer Guide
The README gets you running in one command. This guide is the in-repo reference for everything underneath it: prerequisites, the deployment profiles, manual setup, the command surface, connecting an MCP client, and the MCP Inspector.
The full documentation site lives at engram.events/docs.
The one-command installer
Section titled “The one-command installer”From a fresh clone, scripts/install.sh does the whole
setup — copies .env, installs dependencies, starts PostgreSQL, runs migrations,
and builds:
./scripts/install.sh # lite profile (default), then prints the start command./scripts/install.sh --start # same, then launches the server on :3000./scripts/install.sh --standard # multi-tenant profile (auth, API keys, rate limits)It is idempotent — re-run it any time. If you don’t have Docker, point
DATABASE_URL at your own PostgreSQL (with the pgvector extension) and the
installer skips the bundled container.
Prerequisites
Section titled “Prerequisites”- Node.js 22.13.0 or newer with npm
- Git
- Optional:
pnpm@11.5.0on yourPATH - Optional: Docker and Docker Compose v2 — to run the bundled PostgreSQL
container (image
pgvector/pgvector:pg17)
ENGRAM pins pnpm@11.5.0 in package.json. Every command below
uses pnpm; when pnpm is not on your PATH, replace the leading pnpm with
npm exec --yes pnpm@11.5.0 --. For example, pnpm install becomes
npm exec --yes pnpm@11.5.0 -- install.
Deployment profiles
Section titled “Deployment profiles”ENGRAM ships two profiles. Both run on PostgreSQL alone — the same storage,
vectors (pgvector), and durability — and both expose the full MCP tool set,
including the queued reindex / cancel / retry maintenance tools. The server reads
DEPLOYMENT_PROFILE; when it is unset, standard is the default.
| Profile | DEPLOYMENT_PROFILE |
Tenancy | Backing services |
|---|---|---|---|
| Lite | lite |
Single user — auth/organization stack not wired | PostgreSQL (pgvector) |
| Standard (default) | standard |
Multi-tenant — auth, API keys, organizations, rate limits | PostgreSQL (pgvector) |
The legacy value enterprise is accepted as an alias for standard. The old
memory profile was removed — every profile now runs on Postgres, so the server
rejects DEPLOYMENT_PROFILE=memory with guidance to pick lite or standard.
- Lite — best for a personal machine running a local memory server. Same
durable Postgres storage as
standard, minus the multi-tenant auth/organization stack, so there is no login or API-key surface to configure. - Standard — best for shared or production deployments. Adds JWT sessions, per-agent API keys, organizations, and Postgres-backed rate limiting on top of the same storage.
Manual setup
Section titled “Manual setup”If you’d rather not use the installer, run the steps yourself. Both profiles use
the same flow; only the profile passed to build (and to the server at runtime)
differs.
Lite (single-user)
Section titled “Lite (single-user)”pnpm installtest -f .env || cp .env.example .envpnpm docker:uppnpm db:generatepnpm db:migrate:deployDEPLOYMENT_PROFILE=lite pnpm buildDEPLOYMENT_PROFILE=lite pnpm --filter mcp-server devStandard (multi-tenant, default)
Section titled “Standard (multi-tenant, default)”pnpm installtest -f .env || cp .env.example .envpnpm docker:uppnpm db:generatepnpm db:migrate:deploypnpm buildpnpm --filter mcp-server devThe MCP server starts on http://localhost:3000. Verify it in a second terminal:
curl http://localhost:3000/healthStop the database without deleting data with pnpm docker:down; remove the
containers and local volumes with pnpm docker:clean.
Common commands
Section titled “Common commands”| Task | Command |
|---|---|
| Start PostgreSQL (pgvector), then wait | pnpm docker:up |
| Stop the database, keep data | pnpm docker:down |
| Stop the database, delete data | pnpm docker:clean |
| Start the MCP server | pnpm --filter mcp-server dev |
| Start the web app | pnpm --filter web dev |
| Start the docs app | pnpm --filter docs dev |
| Generate Prisma client | pnpm db:generate |
| Deploy migrations (unattended) | pnpm db:migrate:deploy |
| Create a dev migration | pnpm db:migrate |
| Open Prisma Studio | pnpm db:studio |
| Build all workspaces | pnpm build |
| Lint all workspaces | pnpm lint |
| Type-check all workspaces | pnpm typecheck |
| Test all workspaces | pnpm test |
| Check documentation links | pnpm docs:check |
| Format source files | pnpm format |
Environment
Section titled “Environment”Local defaults live in .env.example. Docker Compose uses these host ports by default:
| Service | Host port setting | Purpose |
|---|---|---|
| PostgreSQL | POSTGRES_PORT, defaults to 5432 |
Primary datastore (memories, vectors, auth state) |
| Ollama (optional) | OLLAMA_PORT, defaults to 11434 |
Local embeddings (--profile ollama compose flag) |
When a host port is already in use, update the matching port value and URL in
.env before starting Docker. For PostgreSQL, change both POSTGRES_PORT and the
port inside DATABASE_URL.
Embeddings
Section titled “Embeddings”The embedding provider is selected by EMBEDDING_PROVIDER:
ollama(default) — a local Ollama server, no API key. Install Ollama (ollama.com/download) and runollama pull nomic-embed-text, or start the bundled container withdocker compose --profile ollama up -d.openai— requiresOPENAI_API_KEY.local— a deterministic hash provider, for testing.disabled— no embeddings.
When no provider is reachable, writes still succeed: memories are stored without a vector and can be backfilled later with a reindex. See .env.example for the full list of embedding variables.
MCP client setup
Section titled “MCP client setup”Build the server before connecting a client:
pnpm buildClaude Desktop (stdio)
Section titled “Claude Desktop (stdio)”Claude Desktop spawns the server as a subprocess. Copy the example config from the repository root:
cp claude_desktop_config.json.example claude_desktop_config.jsonEdit the args path to the absolute location of
apps/mcp-server/dist/main.js in your checkout:
{ "mcpServers": { "engram": { "command": "node", "args": ["/absolute/path/to/your/engram/apps/mcp-server/dist/main.js"], "env": { "DATABASE_URL": "postgresql://engram:dev_password@localhost:5432/engram", "DEPLOYMENT_PROFILE": "lite", "NODE_ENV": "production" } } }}Copy the file into Claude Desktop’s config location and restart the client:
| Operating system | Config path |
|---|---|
| Linux | ~/.config/Claude/claude_desktop_config.json |
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
Then ask the client to call the ping tool to confirm connectivity.
Claude Code (Streamable HTTP)
Section titled “Claude Code (Streamable HTTP)”To share one persistent server across sessions and agents, run it with
MCP_TRANSPORT=streamable-http and register it in the repository’s .mcp.json:
{ "mcpServers": { "engram": { "type": "http", "url": "http://127.0.0.1:3000/mcp", "headers": { "Authorization": "Bearer ${ENGRAM_API_KEY:-}" } } }}The ${ENGRAM_API_KEY:-} default keeps the file parseable when the key is unset.
Authentication (read before sharing a server)
Section titled “Authentication (read before sharing a server)”AUTH_REQUIREDdefaults tofalse. A single-user stdio server spawned by your own client needs no key, and theliteprofile is single-user, so the auth gate does not apply to it.- On the multi-tenant
standardprofile, a Streamable HTTP server refuses to start withoutAUTH_REQUIRED=truein everyNODE_ENV, unless the operator explicitly setsALLOW_UNAUTHENTICATED_HTTP=true— an acknowledged trusted-network escape hatch (for example a loopback-bound, single-operator host). Without a gate, the tenantuserIdis read from the request body and is spoofable by any process that can reach the port. - Recommended posture for any shared server:
AUTH_REQUIRED=true, one least-privilege API key per agent, and a loopback (127.0.0.1) bind. SettingAUTH_REQUIRED=truealso requires aJWT_SECRETof at least 32 characters.
For an HTTP server, the repository’s verification script checks the full MCP handshake and the auth gate:
AUTH_REQUIRED=true ./scripts/verify-engram-server.shMCP Inspector
Section titled “MCP Inspector”The MCP Inspector has no official Docker image on GHCR — running
docker run ghcr.io/modelcontextprotocol/inspector:latest will fail with a
registry error. Use one of the two approaches below instead.
Option A — host-run (simplest)
Section titled “Option A — host-run (simplest)”With the MCP server already running on http://localhost:3000, start the
Inspector in a separate terminal:
pnpm inspectorThen open:
http://localhost:6274/?transport=streamable-http&serverUrl=http%3A%2F%2Flocalhost%3A3000%2FmcpPort 6274 is the Inspector UI and port 6277 is the proxy. If either port is already in use (for example from a previous run), kill the stale process before restarting.
Option B — Docker (Inspector in a container)
Section titled “Option B — Docker (Inspector in a container)”First ensure the base infrastructure is up (pnpm docker:up) and the MCP server
is running on the host. Then start the Inspector container:
pnpm docker:inspector:upThe container reaches the host-side MCP server via host.docker.internal. Open
the Inspector UI at:
http://localhost:6274/?transport=streamable-http&serverUrl=http%3A%2F%2Fhost.docker.internal%3A3000%2FmcpStop the container with pnpm docker:inspector:down.
Reindex and backfill
Section titled “Reindex and backfill”After changing the embedding model or its dimensionality, rebuild the vector
index from Postgres (the source of truth). The admin MCP tools
(reindex_memories, queue_reindex_memories, and friends) require an
adminToken matching MCP_ADMIN_TOKEN; there is also a CLI:
pnpm --filter mcp-server reindex --recreate --regenerate--recreate drops the old index and rebuilds it at the new dimensionality;
--regenerate recomputes embeddings and writes them back to Postgres. The CLI is
cursor-resumable (--cursor <id>).
Project layout
Section titled “Project layout”| Path | Purpose |
|---|---|
| apps/mcp-server | Main NestJS MCP server |
| apps/web | Web application workspace |
| apps/docs | Documentation site workspace |
| packages/core | Core MCP types, registry, and tools |
| packages/config | Environment validation and profile taxonomy |
| packages/database | Prisma database module |
| packages/vector-store | pgvector vector store module |
| packages/embeddings | Embedding generation |
| packages/memory-stm | Short-term memory package |
| packages/memory-ltm | Long-term memory package |
| prisma | Prisma schema and migrations |
| docker | Local infrastructure initialization |
More information
Section titled “More information”| Topic | Link |
|---|---|
| Full documentation site | engram.events/docs |
| Agent and contributor instructions | AGENTS.md |
| Shared memory contract for agent fleets | agent-memory-contract.md |
| Release SLOs and quality gates | RELEASE_GATES.md |
| Current roadmap | roadmap.md |
| MCP server details | apps/mcp-server/README.md |
| MCP tool development | packages/core/src/mcp/tools/README.md |