memgate

memgate

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

Category
访问服务器

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.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选