Skip to main content
Glama

Tacit

Your team's memory, wired into every AI tool.

Tacit syncs a team's Slack, GitHub and Notion into a permission-aware knowledge graph, so you can ask "why did we do X, who decided, and where's the evidence?" from the web app, or from Claude and Cursor over MCP.

Status: early development. Auth, workspaces, the GitHub connector, hybrid search with citations, the MCP server and the knowledge graph (Graphiti, opt-in) work. Slack/Notion connectors and the public benchmark are next.

Architecture (so far)

Browser ──► Next.js (apps/web) ── Better Auth ──► Postgres (auth tables, as tacit_auth)
                │  short-lived JWT (EdDSA)
                ▼
            FastAPI (apps/api) ── verifies JWT via /api/auth/jwks
                │  SET LOCAL app.user_id / app.workspace_id
                ▼
            Postgres with row-level security (as tacit_api)
  • Workspaces are Better Auth organizations (members, roles, email invites).

  • Isolation is enforced twice: every query filters by workspace in code, and Postgres RLS blocks anything a filter misses. The API's database role can't read sessions, OAuth tokens or signing keys at all.

  • Four DB roles: tacit_migrator owns tables (Alembic), tacit_auth is used by Better Auth, tacit_api by FastAPI and MCP (read-only on synced content), and tacit_worker by Celery jobs (scoped to one workspace per transaction).

  • Source permissions are enforced in Postgres: a restrictive RLS policy shows a synced document only if it's public or your linked GitHub account can access the repo, based on access data less than 6 hours old. Otherwise access is denied.

Related MCP server: Rememberizer MCP Server

Synced documents are split into ~400-token chunks and indexed two ways: embeddings (pgvector, HNSW) and Postgres full-text (tsvector). A query runs both and fuses them with Reciprocal Rank Fusion. Each result is the best chunk per document, with a highlighted snippet and a link to the exact PR, issue, comment or doc. Documents are only re-embedded when their content hash changes.

Embeddings default to a local model (fastembed bge-small-en-v1.5, 384 dims): no API key, no per-document cost, reproducible. Set EMBEDDING_PROVIDER=openai (plus OPENAI_API_KEY) to use text-embedding-3-small at 384 dims instead. Ranking weights and re-ranking are deliberately untuned until the benchmark (build step 7) measures them.

Knowledge graph (opt-in)

Merged PRs with their reviews, discussed issues and docs become Graphiti episodes on Neo4j: people, components, technologies and decisions, with facts that know when they became true and when they were replaced. Answers can say what the current decision is and what it superseded.

  • Never leaks: one graph group per repo. A search only covers repos you can read right now (from Postgres), never calls Graphiti with an empty group list, and drops any fact Postgres can't tie to a visible source, which is also where its citation comes from.

  • Costs money, so it's off by default. It needs GRAPH_ENABLED=true, an LLM key (claude-haiku-5-5 by default), and a per-workspace opt-in by an admin. Private repos need a second opt-in, because their text goes to the LLM provider. Every call is recorded in llm_usage, and a monthly budget per workspace is a hard stop.

  • Run docker compose --profile graph up -d neo4j. See docs/design/graph-layer.md.

Benchmark

On the fictional Larkspur dataset (52 "why" questions, local embeddings, $0), hybrid search beats vector-only RAG (recall@10 0.865 vs 0.750, MRR 0.545 vs 0.386). Keyword-only scored highest (0.904), probably because the questions reuse the corpus's wording. The graph arm hasn't run yet. Numbers, caveats and how to reproduce: benchmark/README.md.

Use it from Claude or Cursor (MCP)

Tacit is a remote MCP server at http://localhost:8000/mcp with OAuth 2.1. The web app is the authorization server (dynamic client registration, PKCE, consent screen), and tokens are bound to the MCP resource. Every tool call runs with your permissions, so the assistant sees exactly what you can see.

# Claude Code
claude mcp add --transport http tacit http://localhost:8000/mcp

For Claude Desktop or Cursor, add a remote MCP server with that URL. The client opens a browser to sign in and approve access.

Tools: list_workspaces, search (hybrid, cited), get_document (a source plus its review/comment thread) and search_facts (time-aware graph facts with citations, when the graph is enabled).

Local development

Needs Docker, uv, Node 22+ and pnpm.

pnpm bootstrap    # .env + dependencies
pnpm infra:up     # Postgres (pgvector), Redis, Mailpit
pnpm db:migrate   # create tables, grants, RLS policies
pnpm dev:api      # http://localhost:8000  (in one terminal)
pnpm dev:web      # http://localhost:3000  (in another)

Emails (verification, invites) land in Mailpit at http://localhost:8025.

To sync GitHub, create the dev GitHub App with pnpm github:create-app and run pnpm dev:worker and pnpm dev:webhooks. See infra/github/README.md.

pnpm test         # API tests (uses a throwaway tacit_test database)
pnpm lint && pnpm typecheck

Repo layout

Path

What

apps/web

Next.js 16, Better Auth, shadcn/ui

apps/api

FastAPI, SQLAlchemy (async), Alembic migrations, Celery workers

apps/api/src/tacit_api/connectors/github

GitHub connector (githubkit)

docs/design

Design docs

infra/postgres

Role setup (pnpm db:roles re-applies it)

infra/github

GitHub App manifest and setup guide

docker-compose.yml

Local infrastructure

License

Apache 2.0

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Connects Claude to a personal knowledge base with hybrid search over code, documents, and images. Allows the AI assistant to retrieve and answer from your own files during conversations.
    1
    MIT
  • A
    license
    Not graded
    quality
    F
    maintenance
    Connects AI assistants like Claude Code and Codex to a team's shared knowledge graph for searching, storing, and managing documents.
    7 npm
    MIT