Skip to main content
Glama

aws-team-memory

Shared, centralized memory for a team of Claude agents. Claude Code, Agent SDK agents and claude.ai all connect to one remote MCP server, and they read and write the same set of markdown memory files stored in a versioned S3 bucket.

It's built for individuals on a Claude Pro or Max plan who want several agents to share memories without Claude's team features. claude.ai's built-in memory keeps working as before. This server runs alongside it as a custom connector; it doesn't replace it.

How it works

Claude Code / Agent SDK ──Bearer token──┐
                                        ├─> API Gateway ─> Lambda (MCP server) ─> S3 (versioned *.md files)
claude.ai custom connector ──OAuth──────┘                       │
                                                  Secrets Manager (agent tokens) · Cognito (claude.ai login)
  • Plain files are the source of truth. Each subject is one markdown file with YAML frontmatter, so memories are easy to read, diff and audit. S3 versioning keeps every overwrite, so any change can be undone.

  • No silent overwrites. Every read returns a version (the S3 ETag). Replacing a file requires that version, and S3 rejects the write if another agent changed the file in the meantime. The agent then gets the newest content back, merges its update into it, and retries against the new version. The retry is conditional too.

  • Every write is attributed. The server stamps updated_by (the agent's name) and updated_at into each file.

  • Shared knowledge is curated. Every agent can read everything, but only curator agents can write to shared/. Every agent has its own agents/<name>/ area.

Related MCP server: Hippocampus

Storage layout

shared/                       curated knowledge (curators only)
  clients/acme.md
  methods/sap-conventions.md
agents/<agent-name>/scratch/  each agent's own working notes
traces/digests/<agent>/<date>/<session>.json       session digests (kept indefinitely; not visible to memory_* tools)
traces/raw/<agent>/<date>/<session>.jsonl.gz       redacted raw transcripts, SSE-KMS (expire after TEAM_MEMORY_TRACE_RAW_DAYS)

An example file:

---
description: House conventions for statistical analysis plans
updated_by: claude-ai-alice
updated_at: 2026-11-03T21:40:00+00:00
---

# SAP conventions
...

Pass the summary as memory_write's description argument and the server writes valid YAML for you. If an agent writes the frontmatter itself, an unquoted : inside a flat key: value line is accepted and taken literally. Other invalid YAML is rejected with an error explaining how to quote the value.

Agents can't delete files. Experiment under agents/<you>/scratch/, and have an operator remove anything written by mistake:

uv run python -m infra.deploy rm shared/some/file.md [more paths...]   # versioned bucket: old versions stay recoverable

MCP tools

Tool

What it does

memory_list(prefix="")

Lists files under a prefix, with descriptions, authors, timestamps and versions.

memory_read(paths)

Reads one or more files. Each result includes the version you need to edit that file.

memory_write(path, content, if_version=None, description=None)

Creates a file (omit if_version), or replaces one (pass its current version). If the file already exists or has changed, nothing is written, and the result is status: "conflict" with current_content and current_version for the agent to merge into and retry.

memory_str_replace(path, old, new, if_version=None)

Replaces a single, unique occurrence of old in the newest version of a file. If the file changed but old is still unique, the edit is applied with rebased: true. Otherwise the result is status: "conflict" with the newest content.

memory_search(query, prefix="", max_results=50)

Searches file contents with a case-insensitive regex or plain text, and returns the matching lines.

| trace_summary(since_days=14, agent="", project="") | Aggregates recent session traces: recurring errors, tool error rates, token use, skills invoked, guidance loaded, and metrics per CLAUDE.md version. project is a repo's directory name, such as my-app. | | trace_get(session_id) | Returns one session's full digest. Raw transcripts are never served over MCP. |

Paths must end in .md and live under shared/ or agents/.

Prerequisites

  • An AWS account, and credentials for a profile that can manage S3, Lambda, API Gateway, IAM, Secrets Manager, KMS and Cognito.

  • uv and Python 3.11.

Configuration

Copy .env.example to .env (which is gitignored) and fill it in. All settings are defined in src/team_memory/settings.py, and can also be set as environment variables.

Variable

Default

Purpose

AWS_PROFILE

none

AWS CLI profile to deploy with

AWS_REGION

us-east-1

Region for every resource

TEAM_MEMORY_STACK_NAME

team-memory

Prefix for resource names, and the project tag

TEAM_MEMORY_BUCKET_NAME

(required)

S3 bucket name, which must be globally unique

TEAM_MEMORY_NONCURRENT_VERSION_DAYS

90

How long old file versions are kept

TEAM_MEMORY_TRACE_RAW_DAYS

90

How long redacted raw session transcripts are kept (digests are kept indefinitely)

TEAM_MEMORY_CURATOR_AGENTS

(empty)

Comma-separated agents allowed to write shared/

TEAM_MEMORY_COGNITO_DOMAIN_PREFIX

(empty)

Login domain prefix for claude.ai OAuth. Leave empty to skip Cognito.

TEAM_MEMORY_OAUTH_CALLBACK_URLS

https://claude.ai/api/mcp/auth_callback

Allowed OAuth redirect URLs (comma-separated)

TEAM_MEMORY_LWA_LAYER_VERSION

30

AWS Lambda Web Adapter layer version

TEAM_MEMORY_LAMBDA_MEMORY_MB

512

Lambda memory size

TEAM_MEMORY_LOG_LEVEL

INFO

Server log level

TEAM_MEMORY_TOKENS_SECRET_ARN, TEAM_MEMORY_TRACES_KMS_KEY_ARN, TEAM_MEMORY_COGNITO_USER_POOL_ID, TEAM_MEMORY_COGNITO_APP_CLIENT_ID, TEAM_MEMORY_PUBLIC_URL

(written by deploy)

Deploy outputs. Leave these blank.

TEAM_MEMORY_AGENT_TOKEN

(empty)

Client side only: the agent token the trace-upload hook sends. Leave it empty to disable uploads. TEAM_MEMORY_URL (env only) overrides TEAM_MEMORY_PUBLIC_URL for the hook.

Deploy

uv sync
uv run python -m infra.deploy up

up is idempotent, so run it again after any code or settings change. It does the following:

  1. Creates or updates the versioned, encrypted, private S3 bucket.

  2. Creates the KMS key for raw session transcripts, requires it for traces/raw/ with a bucket policy, and re-encrypts any raw transcripts stored before the key existed.

  3. Creates the agent-token secret.

  4. Creates the Cognito user pool, login domain and app client, if a domain prefix is set.

  5. Creates the Lambda's IAM role.

  6. Builds the Lambda package and deploys the function.

  7. Creates the HTTP API.

  8. Writes the outputs back into .env and prints the connection details.

To print the connection details again at any time:

uv run python -m infra.deploy outputs

Add agents and users

Each Claude Code or Agent SDK agent gets its own bearer token. The token is shown once, and only its hash is stored.

uv run python -m infra.deploy add-agent claude-code     # also rotates an existing token
uv run python -m infra.deploy list-agents
uv run python -m infra.deploy remove-agent claude-code

Agent names use lowercase letters, digits, - and _. To let an agent write shared/, add its name to TEAM_MEMORY_CURATOR_AGENTS and run up again.

claude.ai users sign in through Cognito. Invite yourself first, and Cognito emails a temporary password:

uv run python -m infra.deploy add-user alice you@example.com

That user's agent name becomes claude-ai-alice.

Connect clients

Claude Code

claude mcp add --transport http team-memory https://<api-id>.execute-api.<region>.amazonaws.com/mcp \
  --header "Authorization: Bearer <token>"

Agent SDK (Python):

options = ClaudeAgentOptions(
    mcp_servers={
        "team-memory": {
            "type": "http",
            "url": "https://<api-id>.execute-api.<region>.amazonaws.com/mcp",
            "headers": {"Authorization": f"Bearer {token}"},
        }
    }
)

claude.ai (Pro or Max):

  1. Go to Settings → Connectors → Add custom connector.

  2. Enter the MCP endpoint URL.

  3. Open Advanced settings and paste the Client ID and Client secret printed by infra.deploy outputs.

  4. Connect, and sign in with your Cognito user.

Session traces

To improve CLAUDE.md, rules and skills over time, each Claude Code session can upload its trace. The upload has two parts: a digest of about 2 KB (prompts, tool calls and errors, tokens, skills invoked, a hash of each guidance file loaded) and the raw transcript, with secrets redacted and internal request copies dropped, gzipped to about 15% of its size.

  1. Create a token for the machine's agent (add-agent claude-code) and put it in .env as TEAM_MEMORY_AGENT_TOKEN.

  2. The project's SessionEnd and PreCompact hooks in .claude/settings.json upload the session automatically. They never block or fail a session. They're committed, so they run for anyone who clones this repo, but they upload nothing unless TEAM_MEMORY_AGENT_TOKEN is set.

  3. To upload past sessions, or ones that didn't end cleanly, run python .claude/hooks/trace_upload.py --backfill. Add --dry-run --file PATH.jsonl to preview a digest without uploading.

  4. For other repos, add the same two hooks to that repo's gitignored .claude/settings.local.json, pointing at this checkout by absolute path, for example "command": "python \"C:/path/to/team-memory/.claude/hooks/trace_upload.py\"" under both SessionEnd and PreCompact. The repo needs no config of its own, because the uploader falls back to team-memory's .env. Backfill with python <team-memory>/.claude/hooks/trace_upload.py --backfill --project-dir <repo path>. Digests record project, so sessions stay distinguishable.

  5. For Agent SDK agents, run python .claude/hooks/trace_upload.py --file <transcript.jsonl> after a session, or register the same script as a SessionEnd hook.

Review the traces:

uv run python -m infra.deploy traces --days 14              # aggregate across sessions
uv run python -m infra.deploy traces --project my-app     # one repo only
uv run python -m infra.deploy trace SESSION_ID              # one session's digest
uv run python -m infra.deploy trace SESSION_ID --turn 3     # one turn of the raw transcript

In Claude Code, /trace-review runs these and turns recurring friction into guidance changes. From claude.ai, use the trace_summary tool. claude.ai conversations themselves aren't captured.

The claude.ai OAuth flow against Cognito is the least-tested part of this setup. If sign-in fails, check the Lambda's CloudWatch logs, and confirm that the callback URL in TEAM_MEMORY_OAUTH_CALLBACK_URLS matches the one claude.ai uses.

Run locally

uv run team-memory          # serves http://localhost:8000/mcp using the AWS resources named in .env
uv run pytest               # unit + end-to-end tests against moto; no AWS needed

The local server uses the same Secrets Manager tokens and S3 bucket as the deployed one.

Security and data handling

  • Every connected agent can read everything. Keep identifiable client or trial data out of the store. If you must store it, deploy a separate stack (with its own TEAM_MEMORY_STACK_NAME and bucket) for each client.

  • The bucket blocks all public access and is encrypted (SSE-S3). The Lambda role can only read and write shared/*, agents/* and traces/digests/*, and sign uploads to traces/raw/*.

  • Raw transcripts are encrypted with a customer-managed KMS key (alias/<stack>-traces, rotated yearly). The bucket policy rejects any raw upload that doesn't use it. Reading a raw transcript needs kms:Decrypt on the key as well as s3:GetObject, and every decrypt is logged in CloudTrail. The Lambda can only encrypt (kms:GenerateDataKey), never read. Digests and memory files use SSE-S3. down keeps the key unless you pass --delete-bucket, because raw transcripts can't be read without it.

  • Session traces contain whatever the session saw: file contents, command output and prompts. The uploader masks agent tokens, AWS keys, JWTs, bearer tokens and *SECRET*=/password:-style values, but that's pattern matching, not a guarantee. Don't enable trace upload on machines whose sessions handle client or trial data.

  • Tokens are stored as SHA-256 hashes. Rotate a token by running add-agent again with the same name. Running servers pick up the change within 5 minutes.

Cost

At personal or small-team scale this costs roughly $1.50/month:

  • Secrets Manager is $0.40 per secret, and the KMS key is $1/month (S3 Bucket Keys keep request costs negligible).

  • Lambda, API Gateway and S3 cost pennies, or fall within the free tier. Traces add about 200–300 KB per session in S3.

  • Cognito is free under its monthly active user allowance.

Tear down

uv run python -m infra.deploy down                   # keeps the bucket and all memories
uv run python -m infra.deploy down --delete-bucket   # deletes everything, irreversibly

Contributing

CLAUDE.md describes the code layout and conventions for Claude Code sessions. The project skills /update-claude-md and /update-readme (triggered by the rules in .claude/rules/) keep both documents current.

License

MIT © 2026 Paul Stevenson

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Cross-machine memory system for Claude Code that records sessions as searchable markdown, syncs across machines via Git, and exposes full-text search, semantic search, session summarization, and a knowledge graph through an MCP server.
    40 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables Claude Code to automatically recall and write shared long-term memories stored as plain Markdown, combining BM25, vector, and link-graph hybrid search so relevant notes are injected on every prompt. Memories persist across sessions, projects, and machines, with status tracking for pending and resolved items plus optional end-of-session curation.
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude, ChatGPT, and other AI apps to share one MCP-accessible hub of Markdown-based memories and skills, with per-app adapters, versioned writes, git history, saving policies, Google OAuth, and a web UI.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables persistent cross-session memory for Claude and other AI agents by storing and automatically retrieving decisions, patterns, and knowledge across conversations and workspace contexts, surviving restarts and context compaction.
    24 npm
    MIT