Install
$ agentstack add mcp-petal-labs-cortex ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Cortex
Cortex is a memory and knowledge service for AI agents. It provides persistent context, vector-backed knowledge retrieval, and conversation memory through the Model Context Protocol (MCP).
Features
Four Memory Primitives:
- Conversation Memory — Agent dialogue history with semantic search and auto-summarization
- Knowledge Store — Vector-indexed documents with hybrid search (semantic + full-text)
- Workflow Context — Key-value state that persists across tasks and runs
- Entity Memory — Auto-extracted knowledge graph of people, organizations, and concepts
Production Ready:
- SQLite + vec0 for single-node deployments (zero infrastructure)
- PostgreSQL + pgvector for production scale
- Prometheus metrics and structured logging
- Backup, export, and garbage collection
Developer Experience:
- MCP-native — works with any MCP-compatible client
- Web dashboard for browsing data
- Terminal UI for quick inspection
- Comprehensive CLI for all operations
Installation
Download Binary
Prebuilt binaries are published for Linux (amd64, arm64), macOS (amd64, arm64), and Windows (amd64) on the releases page.
On Linux and macOS, this resolves the current release and your platform automatically:
VERSION=$(curl -sI https://github.com/petal-labs/cortex/releases/latest | awk -F'/v' '/^[Ll]ocation:/ {print $2}' | tr -d '\r')
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
[ "$ARCH" = "x86_64" ] && ARCH=amd64
[ "$ARCH" = "aarch64" ] && ARCH=arm64
curl -LO "https://github.com/petal-labs/cortex/releases/latest/download/cortex_${VERSION}_${OS}_${ARCH}.tar.gz"
tar -xzf "cortex_${VERSION}_${OS}_${ARCH}.tar.gz"
sudo mv "cortex_${VERSION}_${OS}_${ARCH}/cortex" /usr/local/bin/
/releases/latest redirects to the current tag, so VERSION tracks whatever is newest without this page needing an edit each release.
Windows:
Download the cortex__windows_amd64.zip asset from the latest release, extract it, and add the extracted folder to your PATH.
Build from Source
Requires Go 1.24+ and CGO enabled.
git clone https://github.com/petal-labs/cortex.git
cd cortex
go build -o cortex ./cmd/cortex
Verify Installation
cortex --version
# cortex version 1.0.1 (a1b2c3d, 2026-08-16T22:00:00Z)
Release binaries report the version, commit, and build date. A binary built from source without ldflags reports cortex version dev.
Quick Start
Start the MCP Server
# Start with stdio transport (default)
cortex serve
# Start with SSE transport for web clients
cortex serve --transport sse --port 9810
# Restrict to a specific namespace
cortex serve --namespace my-project
Use the CLI
# Ingest a document (namespace defaults to "default")
cortex knowledge ingest --collection docs --title "README" --file README.md
# Search knowledge
cortex knowledge search "how to install"
# View conversation history
cortex conversation history --thread-id my-thread
# List entities
cortex entity list --namespace default
Launch the TUI
cortex tui
Navigate with 1-5 to switch sections, j/k to move, Enter to select, q to quit.
Configuration
Create ~/.cortex/config.yaml:
storage:
backend: sqlite # or "pgvector"
data_dir: ~/.cortex/data
embedding:
provider: openai # openai, voyageai, ollama
model: text-embedding-3-small
dimensions: 1536
cache_size: 10000
timeout: 120s # 0 disables the timeout
summarization:
provider: anthropic # anthropic, openai, gemini, ollama
model: claude-sonnet-4-6
timeout: 120s # 0 disables the timeout
conversation:
auto_summarize_threshold: 50
semantic_search_enabled: true
knowledge:
default_chunk_strategy: sentence # fixed, sentence, paragraph, semantic
default_chunk_max_tokens: 512
default_chunk_overlap: 50
entity:
extraction_mode: full # off, sampled, whitelist, full
extraction_max_attempts: 5
extraction_backoff: exponential # fixed, exponential
extraction_dead_letter_policy: retain # retain, drop
extraction_timeout: 120s # 0 disables the timeout
server:
metrics_enabled: true
metrics_port: 9811
structured_logging: true
shutdown_timeout: 30s
Provider API Keys
API keys are read from the environment. They are never read from config.yaml, so the config file stays safe to commit.
| Provider | Environment variable | Summarization / extraction | Embeddings | |----------|---------------------|:--------------------------:|:----------:| | openai | OPENAI_API_KEY | ✅ | ✅ | | anthropic | ANTHROPIC_API_KEY | ✅ | — | | gemini | GEMINI_API_KEY or GOOGLE_API_KEY | ✅ | — | | voyageai | VOYAGEAI_API_KEY | — | ✅ | | ollama | (none — runs locally) | ✅ | ✅ |
A missing key fails at startup, naming the variable:
Error: failed to create embedding client: failed to create embedding provider: OPENAI_API_KEY environment variable is required for openai provider
Not every provider does both. anthropic and gemini expose no embedding API through Iris; voyageai is embeddings-only and cannot summarize. Cortex checks this at startup and names the alternatives:
invalid config:
- embedding.provider "gemini" does not support embeddings (supported: ollama, openai, voyageai)
- summarization.provider "voyageai" does not support summarization (supported: anthropic, gemini, ollama, openai)
A typical setup mixes providers — Anthropic for summarization, OpenAI for embeddings:
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
embedding:
provider: openai
model: text-embedding-3-small
dimensions: 1536
summarization:
provider: anthropic
model: claude-sonnet-4-6
Entity extraction has no provider setting of its own. It reuses summarization.provider with entity.extraction_model, so that model must be one the summarization provider serves. If you switch summarization.provider, change entity.extraction_model to match — the default, claude-haiku-4-5, is an Anthropic model.
summarization:
provider: openai
model: gpt-4o
entity:
extraction_model: gpt-4o-mini # must be an OpenAI model too
Using Ollama
Ollama needs no API key. Pull the models you intend to use, then point both settings at them:
ollama pull nomic-embed-text
ollama pull llama3.1
embedding:
provider: ollama
model: nomic-embed-text
dimensions: 768 # must match the model — nomic-embed-text is 768
summarization:
provider: ollama
model: llama3.1
entity:
extraction_model: llama3.1 # reuses summarization.provider
Set dimensions to whatever your embedding model actually returns. A mismatch is caught on the first call rather than silently corrupting the index:
embedding 0 has 768 dimensions, expected 1536 (check embedding model and dimensions config)
On pgvector the dimension is baked into the schema at creation, so decide before first run — see [PostgreSQL Setup](#postgresql-setup).
Cortex talks to http://localhost:11434 by default. To reach Ollama elsewhere, set OLLAMA_BASE_URL (Cortex reads this first) or OLLAMA_HOST (Iris's fallback):
export OLLAMA_BASE_URL=http://gpu-box:11434
Config Validation
Cortex validates the configuration at startup and refuses to start on bad values, reporting every violation at once with its config key:
invalid config:
- storage.database_url is required when storage.backend is "pgvector"
- embedding.dimensions must be > 0 (got 0)
- entity.extraction_backoff "linear" is not supported (supported: "fixed", "exponential")
This replaces late, opaque runtime failures — a non-positive retention.gc_interval, for example, used to panic the background ticker after startup.
Timeouts
Provider calls are bounded so a hung upstream fails fast instead of blocking indefinitely:
| Option | Default | Bounds | |--------|---------|--------| | embedding.timeout | 120s | Embedding provider calls | | summarization.timeout | 120s | Conversation summarization calls | | entity.extraction_timeout | 120s | Entity extraction calls | | server.shutdown_timeout | 30s | Graceful drain of background workers |
Setting any of the provider timeouts to 0 disables it (unbounded). A timeout is only applied when the caller supplied no deadline of its own.
PostgreSQL Setup
For production deployments:
storage:
backend: pgvector
database_url: postgres://user:pass@localhost:5432/cortex
# Optional explicit pool sizing. 0 (the default) defers to the
# pool_max_conns/pool_min_conns query params on database_url, then to
# pgx's built-in defaults. Explicit values take precedence over the URL.
pool_max_conns: 0
pool_min_conns: 0
Ensure pgvector extension is installed:
CREATE EXTENSION IF NOT EXISTS vector;
Embedding dimensions. The pgvector schema is generated from embedding.dimensions, so a non-1536 model works without patching DDL. The dimension is baked into the vector(N) columns when the schema is first created. If you later change embedding.dimensions against an existing database, Cortex fails at startup rather than writing ragged vectors:
existing embedding columns are vector(1536) but embedding.dimensions is 768;
run an ALTER TABLE ... ALTER COLUMN embedding TYPE vector(768) migration
or start with a fresh database
Changing dimensions requires re-embedding your data — the stored vectors are not convertible.
Migrations. Both backends run versioned migrations at startup and record the applied version in cortex_metadata.schema_version. Upgrades apply only the pending migrations; no manual DDL step is needed.
MCP Tools
Cortex exposes 19 MCP tools across the four memory primitives:
Conversation
| Tool | Description | |------|-------------| | conversation_append | Add a message to a conversation thread | | conversation_history | Retrieve conversation history | | conversation_search | Semantic search across messages | | conversation_summarize | Summarize and compress history |
Knowledge
| Tool | Description | |------|-------------| | knowledge_ingest | Ingest a document with chunking | | knowledge_bulk_ingest | Batch ingest multiple documents | | knowledge_search | Hybrid search (vector + full-text) | | knowledge_collections | Create, list, delete collections |
Context
| Tool | Description | |------|-------------| | context_get | Retrieve a value by key | | context_set | Store a value with optional TTL | | context_merge | Merge values with strategy | | context_list | List keys with prefix filter | | context_history | View version history for a key |
Entity
| Tool | Description | |------|-------------| | entity_query | Look up entity by name or alias | | entity_search | Semantic search across entities | | entity_relationships | Get entity relationships | | entity_update | Modify entity attributes | | entity_merge | Combine duplicate entities | | entity_list | List entities with filters |
Entity types are person, organization, product, location, concept, event, and other. Any other value is rejected — an unrecognized type used to be silently remapped to an unrelated one.
Response Contract
Every tool response is a declared, versioned JSON shape. Each top-level response carries schema_version, so clients can feature-detect contract changes instead of guessing:
{
"schema_version": 1,
"results": [
{
"chunk": {
"id": "chunk-1",
"document_id": "doc-1",
"namespace": "ns",
"collection_id": "col-1",
"content": "chunk content",
"index": 0,
"token_count": 2
},
"score": 0.91,
"rank": 1,
"document_title": "Doc",
"source": "test://src"
}
],
"query": "chunk",
"total_found": 1
}
The contract guarantees:
schema_versionis bumped only on a breaking change to a response shape.- Empty collections serialize as
[]and{}, nevernull, so clients can
iterate without a nil check.
- Embedding vectors are stripped from search results. They were a large,
unusable payload for MCP clients; use the Go API if you need raw vectors.
- Zero-value timestamps are omitted rather than rendered as the misleading
0001-01-01T00:00:00Z.
Argument Handling
Tool arguments are validated rather than silently defaulted:
- An argument that is present but of the wrong type is rejected with a
message naming the parameter and the type it got — e.g. parameter "limit" must be a number, got string. Previously a wrong-typed argument fell back to the default, so a client bug looked like a working call.
- Metadata, filters, and attributes are string-valued. Non-string values are
rejected with an actionable message — parameter "metadata" values must be strings; key "count" has a number value (send "3" as a string). Cortex used to stringify them silently, which made filter matching ambiguous.
- Large integers keep their precision through the JSON argument path;
a value that would be corrupted by float64 decoding is rejected instead.
Errors
Tool errors are classified before they reach the client. Known client-facing conditions (not found, invalid input, version conflict, batch too large) return their own message. Anything else returns internal server error and is logged server-side with full detail, so SQL fragments, connection URLs, and other internals never leak to MCP clients.
Architecture
┌─────────────────────────────────────────────────────────┐
│ MCP Clients │
│ (AI Agents, IDEs, Tools) │
└─────────────────────┬───────────────────────────────────┘
│ MCP (stdio/SSE)
▼
┌─────────────────────────────────────────────────────────┐
│ Cortex │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │Conversation │ │ Knowledge │ │ Workflow Context│ │
│ │ Memory │ │ Store │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
│ │ │ │ │
│ ┌──────┴───────────────┴──────────────────┴──────┐ │
│ │ Entity Memory │ │
│ │ (Auto-extracted Knowledge Graph) │ │
│ └─────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌─────────────────────┴───────────────────────────┐ │
│ │ Storage Backend │ │
│ │ (SQLite+vec0 or PostgreSQL+pgvector) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Iris │
│ (Embedding Generation) │
└─────────────────────────────────────────────────────────┘
CLI Reference
Server
cortex serve [flags]
--transport string Transport mode: stdio or sse (default "stdio")
--port int Port for SSE transport (default 9810)
--namespace string Restrict to a single namespace
Knowledge Store
cortex knowledge ingest --collection --title --file
cortex knowledge ingest-dir --collection --dir --pattern "*.md"
cortex knowledge search [--collection ] [--mode hybrid]
cortex knowledge collections [--namespace ]
cortex knowledge create-collection --name [--description ]
cortex k
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [petal-labs](https://github.com/petal-labs)
- **Source:** [petal-labs/cortex](https://github.com/petal-labs/cortex)
- **License:** MIT
- **Homepage:** https://docs.petallabs.io/cortex/overview/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.