AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Cortex

mcp-petal-labs-cortex · by petal-labs

Memory and knowledge service, MCP and TUI for AI agent workflows.

No reviews yet
0 installs
31 views
0.0% view→install

Install

$ agentstack add mcp-petal-labs-cortex

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-petal-labs-cortex)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Cortex? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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_version is bumped only on a breaking change to a response shape.
  • Empty collections serialize as [] and {}, never null, 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.

Versions

  • v0.1.0 Imported from the upstream source.