memgate

memgate

Access control, conflict resolution, and audit for shared agent memory. Policy-gated memory tools over Postgres + pgvector, exposed via MCP.

Category
Visit Server

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.: asciicast -->

asciicast

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:

  1. Policy — checks whether this agent's role may read or write this namespace. Default is deny.
  2. Conflict resolution — when a record already exists for an entity, applies the namespace's strategy (last-write-wins, versioned, or require-review) instead of silently clobbering it.
  3. 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 as pending_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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured