RecallMCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@RecallMCPremember that the client prefers weekly status updates"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
RecallMCP
Persistent semantic memory as an MCP tool for AI agents.
CI badge: Once pushed to GitHub, replace the
CIbadge above with:https://github.com/<owner>/<repo>/actions/workflows/ci.yml/badge.svg
RecallMCP gives AI agents a persistent, searchable memory they can write to and query at any time — across sessions, across conversations, across namespaces. It is an MCP server that exposes five tools (remember, recall, list_memories, update_memory, forget) backed by Postgres + pgvector for semantic similarity search.
Memories are partitioned per user, isolated by row-level security, and stored as content + embedding + optional structured metadata. Deduplication happens automatically on identical content within the same namespace.
Tools
remember
Store a memory with semantic embedding.
Input:
Field | Type | Required | Description |
| string | Yes | Content to remember (1–50,000 characters) |
| string | No | Namespace grouping (default: |
| object | No | Arbitrary key/value metadata |
Output:
{ "id": "550e8400-e29b-41d4-a716-446655440000" }Returns an error with deduped: true if identical content already exists in the same namespace (or you can check the returned id — it matches the existing memory's id).
Example:
{
"content": "The user prefers Python for data analysis and prefers FastAPI over Flask for web services.",
"namespace": "preferences",
"metadata": { "source": "conversation", "confidence": 0.95 }
}Response:
{ "id": "550e8400-e29b-41d4-a716-446655440000" }Calling remember again with identical content in the same namespace returns the existing memory's id without creating a duplicate.
recall
Retrieve memories semantically similar to a query, ranked by cosine similarity.
Input:
Field | Type | Required | Description |
| string | Yes | Search query (1–10,000 characters) |
| string | No | Filter by namespace (default: |
| number | No | Max results (1–50, default: 10) |
| number | No | Minimum similarity 0.0–1.0 (default: 0.7) |
| object | No | Key/value filter on metadata (AND semantics, max 8 keys, primitive values only) |
Output:
Array of matching memories, ordered by decreasing similarity. Each result includes <memory> tag wrapping with HTML-escaped content for prompt-injection defense.
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"content": "The user prefers Python for data analysis and prefers FastAPI over Flask for web services.",
"similarity": 0.92,
"metadata": { "source": "conversation", "confidence": 0.95 },
"namespace": "preferences",
"created_at": "2026-04-29T12:00:00.000Z"
}
]Example — recall with namespace and metadata filter:
{
"query": "What are the user's web framework preferences?",
"namespace": "preferences",
"threshold": 0.8,
"metadata_filter": { "source": "conversation" }
}Results are formatted as <memory> tags internally so the calling agent receives escaped, structured output that can't be broken by injected content (e.g., a memory containing </memory> is safely escaped).
list_memories
List stored memories for a user, with pagination and namespace filtering.
Input:
Field | Type | Required | Description |
| string | No | Filter by namespace (default: |
| number | No | Max results (1–100, default: 20) |
| number | No | Pagination offset (default: 0) |
| string | No | Sort column — |
Output:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"content": "The user prefers Python for data analysis.",
"namespace": "preferences",
"created_at": "2026-04-29T12:00:00.000Z",
"updated_at": "2026-04-29T12:00:00.000Z"
}
]update_memory
Update a memory's content and/or metadata. Changes trigger re-embedding of new content.
Input:
Field | Type | Required | Description |
| string (UUID) | Yes | Memory ID to update |
| string | No | New content (re-embedded) |
| object | No | New metadata (replaces existing) |
At least one of content or metadata must be provided.
Output:
{ "success": true }forget
Delete memories. Supports two modes:
Mode by_id — delete a single memory by ID
{ "mode": "by_id", "id": "550e8400-e29b-41d4-a716-446655440000" }Output:
{ "success": true }Mode by_query — two-step semantic deletion
This mode requires two calls to prevent accidental bulk deletion:
Step 1 — Preview: Call forget with mode: "by_query" and a search query. Returns matching memories and a confirmation_token.
{
"mode": "by_query",
"query": "web framework preferences",
"namespace": "preferences",
"threshold": 0.85,
"limit": 10
}Response:
{
"preview": true,
"matches": [
{ "id": "550e8400-e29b-41d4-a716-446655440000", "content": "The user prefers...", "similarity": 0.91 }
],
"total_matches": 1,
"confirmation_token": "a1b2c3d4e5f6...",
"expires_at": "2026-04-29T12:05:00.000Z"
}Step 2 — Confirm: Call forget again with the same mode: "by_query" and the confirmation_token.
{
"mode": "by_query",
"confirmation_token": "a1b2c3d4e5f6..."
}Response:
{ "success": true, "deleted_count": 1 }Confirmation tokens expire after 5 minutes and are scoped to the requesting user (cross-user token reuse is rejected).
Related MCP server: aimemory
Authentication & API Keys
RecallMCP uses bearer-token authentication. API keys follow a recall_live_ prefix followed by a 32-character random suffix (URL-safe base64).
Authorization: Bearer recall_live_<32-char-suffix>Keys map to a user account and a tier that governs rate limits:
Tier | Rate Limit | Max Memories |
Free | 10 requests/min | 100 |
Starter | 60 requests/min | Unlimited |
Pro | 60 requests/min | Unlimited |
Team | 60 requests/min | Unlimited |
Rate limits are enforced per API key using a token-bucket algorithm. Paid tier quotas are currently uniform pending billing-granularity tuning.
Note: API key self-service issuance and management endpoints are in development (planned for a future release). Keys are currently provisioned manually.
Rate Limiting
Every API call is rate-limited by token-bucket per API key. The bucket is lazily refilled — idle keys don't accumulate beyond capacity. When a key exceeds its rate:
HTTP 429 with a
Retry-Afterheader (seconds until the bucket refills enough for another request)A
rate_limitedusage event is recorded withtokens_consumed: 0Denied requests never reach the tool handler
The rate limiter uses an InMemoryRateLimiter by default. The RateLimiter interface supports swapping to a distributed implementation (e.g., Redis) for multi-instance deployments.
Usage Tracking
Every tool invocation that passes authentication produces exactly one row in usage_events:
Column | Description |
| Owner of the API key that made the call |
| Specific API key used |
| Correlates with structured logs |
| Which tool was called |
| 1 for normal calls, 0 for rate-limited |
| Wall-clock time of the handler |
| Whether the tool call completed without error |
| String identifier on failure ( |
The insert is fire-and-forget — failures are logged as warnings but never surfaced to the client. Usage events are RLS-protected: users can only see their own events.
Self-Hosting Guide
A more complete deployment guide ships in a later release — this section covers the basics for local and small-scale self-hosting.
Prerequisites
Node.js 20.x (exact version required — see
.nvmrc)PostgreSQL 15+ with pgvector extension
An OpenAI API key (for embeddings; the server refuses to start without one in production)
Environment Variables
Variable | Required | Description |
| Yes | Postgres connection string with pgvector support |
| Yes | OpenAI API key for text embeddings |
| No | HTTP port (default: 8080) |
| No |
|
| No | Log level: |
| No | HMAC secret for MCPize billing webhook |
| No | Stripe secret key (webhooks disabled if absent) |
| No | Stripe webhook signing secret |
| No | JSON mapping: price IDs → tiers, e.g. |
Run Migrations
Apply migrations in order — each is a standalone SQL file under supabase/migrations/:
# Using Supabase CLI (recommended for managed Postgres):
supabase db push --db-url "$DATABASE_URL"
# Or apply manually with psql:
for f in supabase/migrations/*.sql; do
psql "$DATABASE_URL" -f "$f"
doneMigration history:
File | Description |
| Base schema: users, api_keys, memories (with pgvector), usage_events, RLS policies, update trigger |
| Forces RLS on all tables, creates the |
| Adds GIN index on |
| Adds |
| Replaces the initial usage_events table with a richer schema (request_id, tool_name, latency, tokens_consumed, error_code) |
Start the Server
# Install dependencies
npm install
# Build TypeScript
npm run build
# Start (HTTP mode on port 8080)
npm startFor development with hot reload:
npm run devThe server exposes two HTTP endpoints:
GET /health— health checkGET /ready— readiness check (DB connected)POST /mcp— MCP endpoint (Streamable HTTP transport)
Local Development
git clone https://github.com/<your-org>/recall-mcp
cd recall-mcp
npm install
# Set up local Postgres with pgvector, then:
cp .env.example .env
# Edit .env with your DATABASE_URL and OPENAI_API_KEY
# Run migrations
for f in supabase/migrations/*.sql; do
psql "$DATABASE_URL" -f "$f"
done
# Start in dev mode
npm run dev
# Run tests (requires Docker for testcontainers-based Postgres):
npm testThe test suite spins up isolated Postgres + pgvector containers via Testcontainers, applies all migrations, and runs 255 integration and unit tests covering every tool, RLS isolation, rate limiting, usage events, and cross-user security boundaries.
Architecture Overview
┌──────────────┐ POST /mcp ┌──────────────────────────────────────┐
│ MCP Client │ ──────────────────> │ Fastify Server │
│ (AI Agent) │ <────────────────── │ (Streamable HTTP Transport) │
└──────────────┘ JSON-RPC 2.0 └──────┬───────────────────────────────┘
│
▼
┌─────────────────────────┐
│ Auth Middleware │
│ (Bearer API Key → │
│ userId + tier) │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ Rate Limiter │
│ (token-bucket per key) │
└───────────┬─────────────┘
│
▼
┌─────────────────────────┐
│ Usage Event Recorder │
│ (fire-and-forget) │
└───────────┬─────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Tool Dispatcher │
│ ┌───────┬──────┬────────┬──────┬────────┐ │
│ │remember│recall│list_mem│update│forget │ │
│ └───┬────┴──┬───┴───┬────┴──┬───┴───┬────┘ │
└──────┼──────┼───────┼───────┼───────┼────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌──────────────────────────────────────┐
│ Database Client (pg pool) │
│ with RLS user context │
└──────────┬───────────────────────────┘
│
▼
┌──────────────────────┐
│ PostgreSQL + pgvector│
│ ┌──────────────────┐ │
│ │ users │ │
│ │ api_keys │ │
│ │ memories (vec) │ │
│ │ usage_events │ │
│ └──────────────────┘ │
│ Row-Level Security │
└──────────────────────┘Key design points:
Auth is HTTP-only — API keys are sent as Bearer tokens, never exposed in MCP tool arguments
Auth context flows via AsyncLocalStorage — middleware stores
{ userId, tier, apiKeyId }in a request-scoped context; tools read it transparently without explicit parameter passingRLS is the security boundary — every database query is wrapped in
SET LOCAL app.current_user_id; Postgres enforces isolation at the row level. Even the database owner cannot bypass policies (FORCE ROW LEVEL SECURITY)Rate limiter uses a pivot-resistant interface — swap from in-memory to Redis by implementing two methods (
check()andlastDecisionMeta())Usage events are fire-and-forget — never blocks the response; failures are logged but never surfaced
Logging & Observability
RecallMCP uses pino for structured JSON logging:
Production: JSON output (pipe through
pino-prettyfor local readability withNODE_ENV=development)Request correlation: Every request has a
request_idthat appears in both structured logs and theusage_events.request_idcolumn, enabling cross-system joinabilitySensitive data redaction: Memory content, query strings, and embedding vectors are SHA-256 hashed (8-char truncated) or replaced with
[redacted]in logsTool-level wrapping: All five tools are wrapped by
handleToolWithLogging, which logs entry, exit (withelapsed_ms), and errors (witherror_codeand redacted details)
Migration History
# | File | What it does |
1 |
| Base schema: users, api_keys, memories (with |
2 |
| Forces RLS on memories and api_keys (table owner cannot bypass), creates |
3 |
| GIN index ( |
4 |
| Adds |
5 |
| Replaces the initial usage_events table with a richer schema: adds |
Status & Roadmap
Done — production hardening complete:
✅ All five MCP tools with Zod validation
✅ Row-level security with FORCE (Zero-trust multi-tenancy)
✅ Semantic search with metadata filtering
✅ Content normalization & deduplication
✅ Two-step semantic deletion (preview → confirm)
✅ Auth middleware (API key → user + tier, 1-hour LRU cache)
✅ Per-API-key token-bucket rate limiting
✅ Structured logging with request correlation and redaction
✅ Usage event tracking (foundation for billing)
✅ 255-test integration+unit suite (Testcontainers)
✅ API key self-service issuance and management endpoints (R12)
✅ Stripe webhook integration for tier sync (R13)
✅ Docker and deployment guide (R14–15)
✅ MCP Registry manifest & npm publish prep (R16)
In development:
🔄 Public user dashboard (usage stats, key management)
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenancePersistent memory for AI agents. Store, recall, and share knowledge across sessions with five MCP tools: remember, recall, context, forget, and share. Includes semantic search and agent/user/org scoping.52Apache 2.0
- Alicense-qualityDmaintenanceGives AI agents persistent memory with semantic search, automatic extraction, and memory decay, accessible via MCP protocol.7MIT
- Alicense-qualityAmaintenanceProvides persistent, searchable memory for MCP-compatible agents, enabling recall by meaning, automatic decay, trust scoring, and cross-agent handoffs.4MIT
- AlicenseAqualityDmaintenanceProvides persistent memory with semantic search for MCP-based AI agents, enabling them to store and recall information across sessions using vector embeddings.41MIT
Related MCP Connectors
User-owned memory for AI agents, Copilot, Claude, IDEs, CLIs, and chat apps over remote MCP.
Cross-vendor AI memory over MCP. One semantic store, readable and writeable from every MCP client.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/omniologynow-rgb/recall-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server