memgate
Access control, conflict resolution, and audit for shared agent memory. Policy-gated memory tools over Postgres + pgvector, exposed via MCP.
README
Memgate
Access control, conflict resolution, and audit for shared agent memory.
Memgate sits in front of the memory your AI agents share. It decides who can read and write what, resolves conflicting writes, and records every operation — so a multi-agent system's memory stays trustworthy as it grows.
It speaks MCP, so agents connect with one config entry and no code changes.
Status: early but working. The core (policy, conflict handling, audit, MCP tools) runs and is tested end-to-end with real agents. Adapters for external memory backends and a hosted dashboard are on the roadmap, not built yet. Feedback and issues welcome.
Demo
<!-- Record a short terminal session showing: agent creation, an agent writing and reading, a denied write, and the audit log. Then replace the line below.
brew install asciinema # or: pipx install asciinema
asciinema rec memgate-demo.cast
# run the flow, then Ctrl+D
asciinema upload memgate-demo.cast
Paste the badge asciinema gives you here, e.g.:
-->
The problem
A single agent's memory is easy: keep the conversation in context, done. But when several agents share one memory pool — one handling support, one writing code, one doing billing — that pool degrades:
- Conflicting writes. One agent records "customer is happy," another records "customer is angry." Nobody knows which is current.
- No access boundaries. The billing agent can read customer PII; the support agent can overwrite financial records. Nothing stops it.
- No accountability. When something goes wrong, there's no record of which agent wrote what, or when.
Memory stores like pgvector, Mem0, or Zep hold memory well. They don't govern it. Memgate is the governance layer that sits on top.
The idea
Think of the shared memory as a ledger, and Memgate as the gatekeeper standing in front of it. Agents never touch the ledger directly — every request goes through the gate, which does three things:
- Policy — checks whether this agent's role may read or write this namespace. Default is deny.
- Conflict resolution — when a record already exists for an entity, applies the namespace's strategy (
last-write-wins,versioned, orrequire-review) instead of silently clobbering it. - Audit — appends every operation, allowed or denied, to an append-only log.
Identity is bound to the API key, not to anything the agent says. An agent cannot escalate its own privileges by claiming a different role.
How it works
Agent A ─┐
Agent B ─┼── MCP ──▶ [ Memgate ] ──▶ Postgres + pgvector
Agent C ─┘ policy · conflict · audit
Agents call three tools through MCP:
| Tool | What it does |
|---|---|
memory_write(namespace, entity_key, content) |
Policy check → conflict resolution → write → audit |
memory_read(namespace, entity_key) |
Policy check → return the active record → audit |
memory_search(namespace, query) |
Policy check → semantic search over authorized namespaces → audit |
Quickstart
Requires Docker.
git clone https://github.com/denizayhan04/memgate
cd memgate
docker compose up --build
This starts Postgres (with pgvector), runs migrations, and serves the MCP endpoint on :8088.
Create an agent and get its API key:
docker compose exec memgate memgate agent create --name support-bot --role support
# → API key (shown once): mg_live_...
Connect an MCP client (Claude Code, Cursor, or anything that speaks MCP). Add to your project's .mcp.json:
{
"mcpServers": {
"memgate": {
"type": "http",
"url": "http://localhost:8088/mcp",
"headers": { "Authorization": "Bearer mg_live_YOUR_KEY" }
}
}
}
Now the agent has memory_write, memory_read, and memory_search tools, scoped to whatever its role allows.
Inspect what happened:
docker compose exec memgate memgate audit --entity "customer:acme"
ID AT AGENT ACTION NAMESPACE ENTITY_KEY RESULT
14 2026-07-08T15:43:30Z test-eng write customer-data customer:acme denied
13 2026-07-08T15:43:14Z test-eng read customer-data customer:acme allowed
12 2026-07-08T15:41:05Z test-support read customer-data customer:acme allowed
11 2026-07-08T15:41:02Z test-support write customer-data customer:acme allowed
Two agents, one shared record, different permissions — the support agent writes and reads; the engineer reads but cannot write. Every attempt, allowed or denied, is on record.
Policies
Policies live in a YAML file (config/policies.example.yaml by default), not in the database — so they're versioned in git and reviewed like any other config. The rule is default deny: anything not explicitly granted is closed.
namespaces:
customer-data:
conflict_strategy: versioned # old record superseded, new active; history queryable
tech-context:
conflict_strategy: last-write-wins # new record overwrites old
billing:
conflict_strategy: require-review # write parked as pending until a human approves
roles:
support:
customer-data: [read, write]
tech-context: [read]
engineer:
tech-context: [read, write]
customer-data: [read]
finance-bot:
billing: [read, write]
customer-data: [read]
auditor:
"*": [read]
The running server reloads the policy file without a restart, on SIGHUP or via memgate reload.
Conflict strategies
When a write targets an entity that already has an active record:
last-write-wins— the new record becomes active, the old one is marked superseded.versioned— same, but history is preserved and queryable (what did we know, and when).require-review— the new write is parked aspending_review; the existing record stays active until a human approves it.
Reviewing parked writes:
memgate review list # list memories awaiting review
memgate review approve <id> # make a pending memory active
memgate review reject <id> # reject it
CLI
memgate serve Start the MCP (Streamable HTTP) server
memgate migrate Apply SQL migrations
memgate agent create --name N --role R Create an agent and print its API key
memgate review list List memories awaiting review
memgate review approve <id> Approve a pending memory
memgate review reject <id> Reject a pending memory
memgate reload Reload the policy YAML in a running server
memgate audit [--entity K] [--namespace N] [--agent A] [--limit N]
Show audit log, most recent first
Environment
| Variable | Purpose |
|---|---|
MEMGATE_DATABASE_URL |
Postgres DSN (required) |
MEMGATE_POLICY_FILE |
Policy YAML path (default config/policies.example.yaml) |
MEMGATE_LISTEN_ADDR |
Listen address for serve (default :8080) |
MEMGATE_MIGRATIONS_DIR |
Migrations directory (default migrations) |
MEMGATE_PID_FILE |
PID file written by serve, read by reload |
MEMGATE_OPENAI_API_KEY |
Optional. Set for real embeddings; unset falls back to a deterministic offline embedder, so search works without a key. |
Local development
make build # compile to bin/memgate
make test # run tests
make migrate # apply migrations (needs MEMGATE_DATABASE_URL)
make run # run the MCP server locally
make up # docker compose up --build
make down # stop and remove services
Running from source without Docker:
export MEMGATE_DATABASE_URL="postgres://memgate:memgate@localhost:5432/memgate?sslmode=disable"
go run ./cmd/memgate agent create --name support-bot --role support
Design notes
- Backend-agnostic by design. The memory store is behind an interface. Today the only implementation is Postgres + pgvector; adapters for external stores (Mem0, Zep) can be added without touching the policy, conflict, or audit layers.
- Identity is the key, not the claim. An agent's role is resolved from its API key on every request. What the agent says about its role is irrelevant — there is no way to self-escalate.
- Audit is append-only. The audit log rejects updates and deletes at the database level, not just in application code.
Roadmap
- Backend adapters (Mem0, Zep)
- REST endpoints alongside MCP, for clients that don't speak MCP
- A read-only audit dashboard
- Team policy management and SSO (hosted)
Tech
Go · Postgres + pgvector · mark3labs/mcp-go · MCP Streamable HTTP transport.
License
Apache 2.0. See LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.