Skip to content

srinathsankara/contextmesh

Repository files navigation

🧠 ContextMesh

The missing memory layer for your team and your AI agents.

License: MIT TypeScript Node.js MCP SQLite Claude PRs Welcome


Every team loses knowledge constantly. Decisions get made in Slack threads, Zoom calls, and late-night emails — but only the outcome gets written down. The why disappears. When your AI agent starts a new task, it knows nothing about why you made past choices.

ContextMesh fixes this.



What is ContextMesh?

ContextMesh is an MCP (Model Context Protocol) server that gives your AI agents your team's full institutional memory. It captures team decisions with their complete reasoning, stores them in a SQLite knowledge base with full-text search, and exposes them to Claude Code, Cursor, Copilot, or any MCP-compatible AI agent.

Stop watching your AI agents make choices that contradict last quarter's hard-won decisions. Give them memory.

Slack thread / Meeting notes / Email / PR description
         │
         ▼  (Claude AI extraction)
   ContextMesh DB (SQLite + FTS5)
         │
         ▼  (MCP protocol)
  Claude Code · Cursor · Copilot · Your agents

✨ Features

Feature Description
🎯 Capture decisions with reasoning Save any decision with full context, rationale, alternatives rejected, and outcome — not just the final choice
🤖 AI-powered extraction Paste a raw Slack thread, meeting transcript, email, or PR — Claude automatically extracts and structures every decision
🔍 Full-text search SQLite FTS5 powers instant natural-language queries across all your organization's knowledge
🔌 MCP server Works with Claude Code, Cursor, GitHub Copilot, and any MCP-compatible AI agent out of the box
📊 7 MCP tools capture_decision, ingest_content, query_context, list_decisions, get_decision, update_outcome, memory_stats
🌐 Universal Engineering, healthcare, legal, finance, product, education — decisions are universal
💾 Zero-config storage SQLite database stored at ~/.contextmesh/contextmesh.db — no server, no Docker, no cloud required
⚡ Lightweight TypeScript, Node.js, better-sqlite3. Fast, local-first, and private

🚀 Quick Start

1. Clone & Install

git clone https://github.com/srinathsankara/contextmesh
cd contextmesh
npm install

2. Configure your API key

cp .env.example .env

Edit .env:

ANTHROPIC_API_KEY=sk-ant-your-key-here

Get your API key at console.anthropic.com.

3. Build

npm run build

4. Try the CLI

# Ingest a decision from raw text (Slack, email, meeting notes...)
npm run ingest -- --text "We chose Postgres over MongoDB for auth-service. ACID compliance was critical for our financial transactions. MongoDB was rejected because it lacks proper join support." --source slack --project auth-service

# Ingest from a file (meeting transcript, PR description, etc.)
npm run ingest -- --file ./meeting-notes.txt --source meeting --project backend

# Search your organizational memory
npm run query -- --q "why did we choose postgres"

# List all captured decisions
npm run query -- --list

# Filter by project
npm run query -- --list --project auth-service

# Get memory stats
npm run query -- --stats

Sample output:

$ npm run query -- --q "why did we choose postgres"

1 result(s) for: "why did we choose postgres"

════════════════════════════════════════════════════════════
📌 Database selection for auth-service
────────────────────────────────────────────────────────────
ID:        a3f2b1c4-...
Project:   auth-service
Tags:      postgres, database, architecture, acid
Source:    slack
Date:      2026-05-07

CONTEXT
Team debated database choice for the new auth service during Sprint planning.

DECISION
Use PostgreSQL as the primary database for auth-service.

REASONING
ACID compliance is non-negotiable for financial transactions. The team has 
deep Postgres expertise which reduces operational risk. Relational joins are 
critical for the user-role-permission model we need.

ALTERNATIVES REJECTED
MongoDB: No native join support, would require application-level joins which 
add complexity. MySQL: Weaker JSONB support, less mature full-text search.

🔌 Connect to Claude Code (MCP)

Add ContextMesh to your Claude Code MCP configuration so Claude automatically has access to your organizational memory before starting any task.

Edit ~/.claude/claude_desktop_config.json:

{
  "mcpServers": {
    "contextmesh": {
      "command": "node",
      "args": ["/absolute/path/to/contextmesh/dist/index.js"],
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-your-key-here"
      }
    }
  }
}

Or using npx (after building):

{
  "mcpServers": {
    "contextmesh": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/contextmesh/src/index.ts"],
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-your-key-here"
      }
    }
  }
}

After restarting Claude Code, it will automatically query your memory before working on tasks.


🖱️ Connect to Cursor

Open Cursor Settings → MCP → Add Server and paste:

{
  "name": "contextmesh",
  "command": "node",
  "args": ["/absolute/path/to/contextmesh/dist/index.js"],
  "env": {
    "ANTHROPIC_API_KEY": "sk-ant-your-key-here"
  }
}

🤖 Connect to any MCP Client

ContextMesh speaks standard MCP over stdio. Any client that supports the Model Context Protocol can connect:

{
  "command": "node",
  "args": ["/path/to/contextmesh/dist/index.js"],
  "env": {
    "ANTHROPIC_API_KEY": "sk-ant-your-key-here"
  }
}

🛠️ MCP Tools Reference

Once connected, your AI agent has access to 7 tools:

capture_decision

Manually capture a decision with its full reasoning context.

Parameter Type Required Description
title string Short label for the decision (max 10 words)
context string What situation or problem led to this decision?
decision string What was actually decided?
reasoning string Why was this choice made?
alternatives string What other options were considered and why rejected?
tags string Comma-separated keywords (e.g. architecture,database)
project string Which project, team, or area does this apply to?
decided_by string Who made this decision?
source string Where does this come from? (slack, meeting, email, manual)

Example:

capture_decision(
  title: "Switch auth to JWT tokens",
  context: "Session-based auth was causing scaling issues with horizontal pod scaling.",
  decision: "Move to stateless JWT authentication for all services.",
  reasoning: "JWTs are stateless so any pod can validate without shared session store. Team has JWT expertise. Industry standard for microservices.",
  alternatives: "Redis sessions: adds operational complexity and single point of failure. Sticky sessions: limits autoscaling ability.",
  tags: "auth,jwt,security,architecture",
  project: "platform",
  decided_by: "engineering lead"
)

ingest_content

Paste raw text from any source — Claude AI automatically extracts all decisions.

Parameter Type Required Description
content string Raw text: Slack thread, meeting notes, email, PR, document
source string Where is this from? (slack, meeting, email, pr, document)
project string Which project or team does this relate to?

Example:

ingest_content(
  content: "...[paste full Slack thread or meeting notes here]...",
  source: "slack",
  project: "backend"
)

Claude (claude-opus-4-5) reads the raw text and extracts every decision with its full context, reasoning, and alternatives — automatically.


query_context

Search your organization's memory using natural language.

Parameter Type Required Description
query string Natural language query — e.g. "why did we pick PostgreSQL"
limit number Max results (default: 5)

Example:

query_context(query: "authentication approach", limit: 3)
query_context(query: "why did we reject Redis")
query_context(query: "API versioning strategy")

Uses SQLite FTS5 full-text search with fallback to LIKE search for robustness.


list_decisions

List recent decisions with optional filters.

Parameter Type Required Description
limit number How many to return (default: 10)
project string Filter by project name
tag string Filter by tag
source string Filter by source

get_decision

Get the full details of a specific decision by ID.

Parameter Type Required Description
id string Full UUID or first 8 characters

update_outcome

Close the feedback loop — record what actually happened as a result of a past decision.

Parameter Type Required Description
id string The decision ID to update
outcome string What happened? Was it the right call?

Example:

update_outcome(
  id: "a3f2b1c4",
  outcome: "Postgres was the right call. Zero issues after 6 months in production. The ACID compliance proved critical when we added payment processing."
)

memory_stats

Get statistics about your organizational memory.

memory_stats()

Returns total decisions, breakdown by source and project.


💡 Real-World Use Cases

Engineering Teams

# Before starting a refactor, check what decisions were made:
query_context("why did we choose this auth approach")
query_context("API versioning decisions")

# After a sprint retro, ingest the meeting notes:
ingest_content("[paste full meeting transcript]", source="meeting", project="platform")

# Capture an architecture decision record (ADR):
capture_decision(
  title: "Use event sourcing for order service",
  context: "Order history needed for audit, refunds, and analytics. Mutable records made this complex.",
  decision: "Implement event sourcing with an append-only event store for the order service.",
  reasoning: "Perfect audit trail. Enables time-travel debugging. Decouples downstream consumers via event bus. Team studied Martin Fowler's CQRS patterns.",
  alternatives: "Mutable DB + audit log table: fragile, often incomplete. Snapshot-only: loses fine-grained history needed for dispute resolution.",
  tags: "architecture,event-sourcing,orders,cqrs",
  project: "order-service"
)

Product Teams

# After a planning meeting:
ingest_content("Today we decided to delay v2 launch by 2 weeks because QA found 3 P0 bugs in the checkout flow. We considered shipping with known bugs but rejected this due to chargeback risk.", source="meeting", project="v2-launch")

# Before a prioritization session:
query_context("why did we de-prioritize mobile app")

Healthcare Teams

capture_decision(
  title: "Switch ICU patients to Protocol B",
  context: "Rising antibiotic resistance rates observed over 6 months of data. Protocol A success rate dropped from 94% to 71%.",
  decision: "Adopt Protocol B as first-line treatment for ICU patients effective next quarter.",
  reasoning: "Internal data shows 40% better outcomes. Lower resistance profile confirmed by three peer-reviewed studies. Hospital formulary already stocks required antibiotics.",
  alternatives: "Protocol C: effective but 3x cost, rejected for budget reasons. Continuing Protocol A: too high failure rate given resistance trends.",
  tags: "clinical-protocol,icu,antibiotics",
  project: "critical-care"
)

Legal Teams

ingest_content(
  "We removed the arbitration clause from the consumer contract. Client's jurisdiction (California) restricts mandatory arbitration for consumer agreements under the CA Arbitration Act. Alternative of voluntary arbitration with opt-in was considered but rejected — client preferred clean contract. We retained arbitration for B2B contracts.",
  source: "contract-review",
  project: "consumer-terms-2026"
)

📁 Project Structure

contextmesh/
├── src/
│   ├── index.ts                     # MCP server entry point (stdio transport)
│   ├── server.ts                    # 7 MCP tools: capture, ingest, query, list, get, update, stats
│   ├── types.ts                     # Decision, DecisionInsert, QueryResult, IngestResult interfaces
│   ├── db/
│   │   ├── schema.ts                # SQLite setup, WAL mode, FTS5 virtual table, triggers
│   │   └── queries.ts               # insertDecision, searchDecisions, filterDecisions, listDecisions, getStats...
│   ├── extractors/
│   │   └── claude-extractor.ts      # Claude claude-opus-4-5 extraction + claude-haiku-4-5 enrichment
│   └── cli/
│       ├── ingest.ts                # CLI: npm run ingest -- --file / --text / stdin
│       └── query.ts                 # CLI: npm run query -- --q / --list / --stats / --id
├── .env.example                     # Environment variable template
├── package.json
└── tsconfig.json

🗄️ How the Database Works

ContextMesh stores all decisions in a local SQLite database at ~/.contextmesh/contextmesh.db (configurable via CONTEXTMESH_DB_DIR environment variable).

Schema:

  • decisions table — stores all fields: id, title, context, decision, reasoning, alternatives, outcome, tags, source, project, decided_by, created_at, updated_at
  • decisions_fts — SQLite FTS5 virtual table for full-text search across all text fields
  • Three triggers keep the FTS index synchronized automatically: decisions_ai (insert), decisions_au (update), decisions_ad (delete)
  • WAL journal mode for safe concurrent reads

Search: FTS5 search tokenizes queries and uses SQLite's built-in BM25 ranking. Multi-word queries are expanded as OR conditions. Falls back to LIKE search if FTS fails.


⚙️ Configuration

Environment Variable Default Description
ANTHROPIC_API_KEY Required. Anthropic API key for Claude AI extraction
CONTEXTMESH_DB_DIR ~/.contextmesh Directory for the SQLite database

🗺️ Roadmap

  • Web UI — Browse, edit, and visualize decisions in a browser dashboard
  • Slack bot — Auto-ingest decisions from Slack channels in real time
  • GitHub integration — Auto-capture decisions from PR descriptions and ADR files
  • Vector embeddings — Semantic similarity search beyond keyword matching
  • Team sharing — Multi-user support with a shared remote memory server
  • Notion / Confluence sync — Two-way sync with existing knowledge bases
  • Decision templates — Domain-specific templates (ADR, clinical protocol, legal memo, post-mortem)
  • VS Code extension — Capture decisions inline from your editor
  • Export to Markdown — Generate formatted ADR documents from captured decisions

🤝 Contributing

Contributions are welcome! ContextMesh is designed to be the foundation for a richer organizational memory ecosystem.

  1. Fork the repo
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Make your changes, ensuring TypeScript compiles: npm run build
  4. Open a PR with a clear description

Good first issues:

  • Add support for importing Notion pages
  • Add a --format json flag to the CLI query output
  • Write tests for the FTS5 query builder
  • Add a search alias for query_context in the MCP server

📦 Scripts Reference

Script Command Description
build npm run build Compile TypeScript to dist/
start npm run start Run the compiled MCP server
dev npm run dev Run MCP server with tsx (no compile step)
ingest npm run ingest -- [options] CLI: extract and save decisions from text/file
query npm run query -- [options] CLI: search and list decisions

📄 License

MIT — see LICENSE for details.


Built with TypeScript · Claude AI · SQLite FTS5 · MCP Protocol

GitHub · Report a Bug · Request a Feature

About

MCP server that gives AI agents your team's institutional memory — capture decisions with reasoning, not just outcomes

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors