Groundtruth
Allows review and approval of canon entry drafts through Slack, using a bot token and signing secret to manage approvals in a designated Slack channel.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Groundtruthquery the canon for our refund policy"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Groundtruth
The governed knowledge layer for companies deploying AI. Full product and system specification in specs/company-brain-full-spec.md.
Layout
Path | What | Stack |
| Web app surfaces | Next.js App Router, TypeScript, Tailwind |
| Serving API and MCP interface | NestJS |
| Connector runtime, normalizer, event writer | Go |
| Embedding pipeline workers | Go |
| Shared domain types and enums | TypeScript |
| Migrations, RLS policies, isolation tests, seed | Postgres, pgvector |
Related MCP server: governance-mcp-server
Local development
Requires Node 22+, pnpm, Go 1.25+, Docker, Supabase CLI.
pnpm install
bin/dev.shbin/dev.sh starts the Supabase stack, applies migrations, and runs all four services: ingestion and embedding daemons (Go), the serving API with the scheduler on port 3001, and the web app on port 3000. supabase status prints local URLs and keys. Seed data lives in supabase/seed.sql and loads on a fresh stack. Each service also ships a Dockerfile for the promote-the-artifact deploy flow in spec section 9.
Verification: supabase test db (pgTAP suites), go test -race ./... per Go service with TEST_DATABASE_URL, pnpm -r lint && pnpm -r typecheck && pnpm -r test, and pnpm --filter @company-brain/serving test:e2e for the HTTP suites.
Key environment variables: DATABASE_URL and PAYLOAD_ROOT everywhere; ANTHROPIC_API_KEY, DRIFT_TIER2_MODEL, DRIFT_TIER3_MODEL, and SCHEDULER_ENABLED=1 for the drift engine and synthesis; SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, SLACK_APPROVAL_CHANNEL, and SLACK_TENANT_ID for the Slack approval app; DEV_TENANT_ID and DEV_PERSON_ID for the web dev-auth shim. Every LLM-dependent feature reports itself disabled rather than failing when its key is absent.
Database access model
Application services connect as the brain_app role and set app.tenant_id per session. Row level security enforces tenant isolation on every table; events and audit_log are append-only because brain_app holds no update or delete grants on them. Cross-tenant isolation is asserted by the pgTAP suite in supabase/tests, which blocks merge in CI.
Cold start (ColdStartService.runOnce) mines backfilled history into a draft canon: a full-text prefilter finds decision, pricing, and policy language in new chunks (own watermark in cold_start_state, capped tier 3 calls per run), the model drafts candidate entries in batches, word-overlap dedup skips facts the canon already covers, and each accepted draft lands through canon_create_entry_draft (budget enforced, provenance to source events) with a linked origin=cold_start proposal so the standard approve and reject transactions are the review flow. reviewQueue returns pending drafts ordered bedrock first, then pricing, then confidence. Org inference (ColdStartService.inferOrg) and gap clustering (GapService.runOnce) are built; wiki import is not.
The drift engine runs inside the serving service as DriftService.runOnce(tenantId). Tier 1 is SQL: each new chunk (per-tenant watermark over event_chunks) is compared against active canon statement embeddings written by the Go embedding pipeline, with per-source-type threshold discounts from drift_tuning and bot-authored chunks excluded. Tier 2 classifies survivors with claude-haiku-4-5 (structured outputs, zod-validated, three bounded attempts); confirms bump last_referenced_at, unrelated drops. Tier 3 drafts corrections with claude-opus-4-8 using thread context and corroborating chunks. Hygiene runs dedup and cooldown checks before tier 3 spend: one open proposal per entry and conflicting field with evidence attaching in drift_evidence, a 14-day cooldown after rejection unless evidence doubles (then flagged recurring), per-owner weekly budgets that queue overflow, and bedrock contradictions escalated to the admin as strategic. Without ANTHROPIC_API_KEY the engine reports itself disabled instead of failing. The tier 2 eval lives in services/serving/eval and runs with pnpm eval:tier2 when a key is present.
The serving API (NestJS, services/serving) exposes the four spec tools as REST under /tools: query (canon-first answers with trust labels, receipts, conflicts, and freshness), entries/:id, conflicts, and proposals. Agents authenticate with hashed API keys resolved by a security-definer lookup, carry per-key domain scopes and token-bucket rate tiers, and every call writes an audit row with the tool, entry ids touched, and trust level served. Every request runs in a brain_app transaction with app.tenant_id set, so RLS holds end to end. When canon coverage is empty and the caller asks for it, query falls back to stream_search and labels the answer stream_only; an LLM synthesises the final sentence from the cited statements, degrading to the top cited statement when no key is configured or the call fails.
Rate limiting and metering are one database call. meter_and_take refills a per-key token bucket in api_key_buckets from rate_tiers, decrements it, and writes the metering_events row only when the call is allowed, so limits and usage counts survive multiple serving replicas. A refused call returns retry_after and never bills. Calls that fail after authorisation still meter; deriving billing from audit_log, which records every served call inside the request transaction, is the follow-up when the billing loop lands.
Metering bills by principal, not by surface. Third-party agents on the MCP and REST paths meter once per authenticated call (category = 'tool_call'). The web chat surface is a first-party agent run by a human, so it follows the same rule the answer contract implies: reading the canon is free, running an agent that acts is billable. Every chat turn writes one metering_events row tagged category = 'agent_run' with the run's token usage, and billable is true only when the turn invoked an action tool (propose_update, create_document, create_deck); a pure question-and-answer turn is recorded billable = false so its inference cost is visible as telemetry without taxing human engagement. metering_cost_daily aggregates the billable rows by tenant, day, and category with summed tokens, so billing charges by cost rather than by a flat query count. Token usage is captured because a chat run fans out to as many as nine model calls, and a per-turn count would undercharge exactly the heaviest runs.
Canon governance also lives in the database: canon_create_entry_draft, canon_submit_version, canon_approve, canon_reject, canon_decay_sweep, and canon_health are security-invoker functions executed by brain_app, so the approval transaction (version, approvals, pointer flip, proposal resolution, audit row) is atomic for every surface that calls it. Version attributes are validated against per-domain JSON Schemas in domain_schemas by a trigger using pg_jsonschema; platform defaults ship for the six spec domains and tenants can override. Approval requirements resolve from approval_policies by tier and domain, most specific wins, with role ranking and distinct-approver counting for multi-approver policies.
Stream retrieval is the stream_search database function, security invoker so tenant RLS applies inside it. It fuses a vector arm and a full-text arm with reciprocal rank fusion, checks the caller's principal set against chunk ACLs inside the query, over-fetches with doubled ef_search up to three iterations when filtering starves recall, and weights scores by per-source-type freshness decay from retrieval_half_life.
Evidence visibility
Drift evidence follows one rule: the fact crosses, the excerpt does not. Tier 3 drafts from every chunk in the tenant, so a contradiction raised in a private channel still reaches the entry owner. What that owner sees is filtered. Every human read of drift_evidence joins through acl_admits(chunk.acl, principals) and renders only chunks the viewer could have opened in the source tool; the rest collapse to a count and a list of source types, never channel names or thread subjects. The admin role does not bypass this, per spec section 3.1, which forbids admin override on raw content.
Excerpts are attributable by construction. Tier 3 receives evidence as <evidence id="eN"> blocks and must return each supporting_excerpt tagged with the block it quoted, so every excerpt resolves to a chunk id before it is stored in the audit detail. An excerpt naming an unknown block is dropped rather than stored unattributable. Prompt versions tier3-v2 and gap-tier3-v2 mark the change.
The residual risk is deliberate and worth stating: a drafted statement is derived from evidence the owner may not be able to see. Tier 3 is instructed to state the corrected fact in its own words and never to quote evidence into drafted_statement, and the queue tells the owner how many sources were withheld so they know their view is partial.
acl_admits is the single predicate for new call sites. stream_search keeps its inlined literal copy on purpose: its vector arm depends on (acl->>'scope') = 'tenant' matching the partial HNSW index event_chunks_tenant_visible_hnsw_idx, and replacing it with a function call risks losing that index.
Ingestion
The ingestion worker connects as brain_worker, a separate role that owns the operational queue: full access to ingestion_queue, ingestion_dlq, and connector_state across tenants, read access to connectors plus a column grant to flip status, insert-only on events with the tenant checked by RLS per item, and no read access to anything else. brain_app has no grants on the queue tables, so serving code can never see raw queue payloads. Duplicate delivery is absorbed by the idempotency unique constraint; the worker treats a unique violation as a counted no-op rather than using ON CONFLICT, which under RLS would require select privileges the worker should not hold.
Schema deviations from the spec
Three corrections to Part II section 4.1, each preserving the spec's invariants:
Postgres requires the partition key inside primary key and unique constraints, so
eventskeys are(id, occurred_at)and idempotency isunique (tenant_id, connector_id, external_id, occurred_at).occurred_atis source-stable per item, so duplicate delivery still collapses.event_chunksandaudit_logcarry composite keys for the same reason.event_chunkspartitions bycreated_at, which the spec references but never defines. The column is added. Rows referencingeventscarryevent_occurred_atso the foreign key can target the composite key.canon_versions,canon_provenance,canon_relations, andapprovalscarry a denormalizedtenant_idbecause section 4.2 mandates RLS on every table and a one-line policy needs the column. Consistent with the spec's own ACL denormalization rationale.
event_chunks.embedding_model is also stored per row so re-embedding stays traceable when the module 02 provider changes.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityBmaintenanceAn MCP server that provides a self-improving knowledge graph with per-triple provenance and deterministic reasoning, enabling auditable, reproducible, and contradiction-aware answers for AI agents.Last updated64,384MIT
- Alicense-qualityDmaintenanceMCP server for querying the DodaOne governance framework, enabling users to retrieve governance information and evaluate proposed actions.Last updated2MIT
- AlicenseAqualityAmaintenanceProvides a single-writer MCP server for a governance-grade knowledge base of markdown documents with version control and query capabilities.Last updated12918Apache 2.0
- Alicense-qualityAmaintenanceGoverned knowledge base for AI agents via the Model Context Protocol (MCP), enabling agents to search, read, and contribute persisted knowledge with versioning, audit trails, and approval workflows.Last updated22MIT
Related MCP Connectors
MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.
Knowledge coverage map and health score. Ingest docs into a governed knowledge graph via MCP.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ElijahSLimaj/groundtruth'
If you have feedback or need assistance with the MCP directory API, please join our Discord server