Files
cortex/docs/architecture.md

3.7 KiB

Architecture

Cortex is a small domain-specific MCP server.

flowchart LR
    Client["MCP client"] -->|Streamable HTTP| App["Cortex .NET 10 app"]
    Browser["Browser"] --> Web["Cortex Blazor web UI"]
    Web --> Db
    Web --> Embed
    App --> Db["PostgreSQL + pgvector"]
    App --> Embed["Text Embeddings Inference"]
    Embed --> Model["BAAI/bge-small-en-v1.5"]

Runtime

The app is an ASP.NET Core service hosted by Kestrel. MCP is exposed over Streamable HTTP at:

/mcp

Health is exposed at:

/health

Optional Web UI

The web UI is a separate Blazor Server project and Docker container. It is optional and not needed for MCP clients.

The UI talks to the same PostgreSQL database and embedding service through the existing Cortex service layer. It is intended for manual browsing, adding memories, searching, editing, and soft-deleting during local development.

Dev URL:

http://localhost:5118

Test URL:

http://localhost:5218

Data Model

Project

Projects are mandatory and explicit. There is no default project.

Fields:

  • id
  • name
  • slug
  • created_at
  • updated_at

Memory Item

Memory items belong to exactly one project. EF Core maps them with table-per-type inheritance: shared fields live in memory_items, and each category has a subtype table with required category-specific columns.

Base fields:

  • id
  • project_id
  • category
  • title
  • content
  • tags
  • status
  • created_at
  • updated_at
  • deleted_at

Memory Item Embedding

Embeddings are stored separately from items so a large item can expose additional targeted discoverability text without changing its canonical description.

Fields:

  • id
  • memory_item_id
  • position
  • label
  • text
  • embedding
  • embedding_model
  • created_at
  • updated_at

The embedding column is a vector(384) pgvector column. Position 0 is the generated default embedding. Additional embeddings use position 1 and above.

Categories

Category Table Required fields
requirement requirement_memory_items statement, context
location location_memory_items item_name, place
todo todo_memory_items task, priority
note note_memory_items subject, body

Search is hybrid:

  • PostgreSQL full-text ranking over title and content
  • pgvector cosine similarity over all embeddings linked to each item
  • Project and category filters
  • Recency as a secondary sort

FindItems accepts one to four query texts. Cortex embeds each query, scores every query against every item embedding, and returns each item once using its best matching query/embedding pair.

Normal search requires a project. Global search requires searchAllProjects = true.

Embeddings

The embedding model is:

BAAI/bge-small-en-v1.5

The model produces 384-dimensional vectors. That dimension is part of the embedding table schema, so changing models later requires a planned re-embedding migration or a parallel embedding table/column strategy.

Embeddings are generated for:

  • new items
  • category-specific field changes
  • tag changes

Additional embeddings are generated when they are added or when their text changes. Additional embedding text is only for discoverability; the item still has one canonical title/content description.

Status changes do not regenerate embeddings.

Deletes

Deletes are soft deletes. DeleteItem sets:

  • deleted_at
  • status = "deleted"

Search excludes deleted items.

Migrations

EF Core migrations are applied by running the app in migration mode:

.\scripts\migrate-db.ps1

In Docker, deploy-all.ps1 runs migrations before starting the app.