Quorum
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., "@QuorumWhat was the root cause of INC-4471?"
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.
Quorum — Agentic Meeting Intelligence
Ask an archive of recorded meetings a question in plain language, and get an answer where every claim points back at a speaker and a timestamp in an actual recording — or an explicit refusal when the archive does not support one.
Exposed as an MCP server speaking protocol revision 2026-07-28, and as a
FastAPI service. Runs offline on a fresh clone: no API key, no model download.
pip install -e . && quorum ingest && quorum ask "What was the root cause of INC-4471?"What it looks like
Verbatim output from quorum ask against the five-meeting demo archive in
data/meetings/. Nothing here is edited.
A question the archive answers.
$ quorum ask "What was the root cause of INC-4471?"
"Ada Okonjo: Root cause was a connection pool exhaustion in the shipment-tracking
service." [1] "Ada Okonjo: INC-4471 was the two-hour partial outage on the
twenty-eighth of February." [1]
Sources
[1] Platform Sync (2026-03-04) - Ada Okonjo, Ben Sørensen, Priya Raman @ 00:02:13
retrieval: accept@0.82
grounded: True (1.00) | abstained: False | 11 ms
cost: 3 model call(s), 27 tokens, $0.0000
trace: 39e563cfe873c8fb81059ba3db556f69A question it does not. No hedged paragraph assembled from whatever matched:
$ quorum ask "How many warehouses do we operate in Brazil?"
The archive does not contain enough to answer that. The closest passages
retrieved did not cover the question.
retrieval: abstain@0.21
grounded: True (1.00) | abstained: True | 24 ms
cost: 2 model call(s), 22 tokens, $0.0000A question where the first retrieval is too weak, and the corrective loop
rescues it. Watch the retrieval: line — two re-queries, then an answer:
$ quorum ask "Which team owns the legacy customs work?"
"Ada Okonjo: The eleventh is the legacy customs-declaration service, which nobody
wants to touch, and honestly that one might be a rewrite rather than a patch." [1]
"Tomás Lindqvist: They don't use customs declarations at all, they're
domestic-only." [1] "Tomás Lindqvist: The customs service also isn't in Halden's
path." [1]
Sources
[1] Halden Escalation Review (2026-03-25) - Mei Watanabe, Ada Okonjo, Tomás Lindqvist @ 00:02:33
retrieval: requery@0.34 -> requery@0.34 -> accept@0.34
grounded: True (1.00) | abstained: False | 21 ms
cost: 7 model call(s), 70 tokens, $0.0000The question never says "customs-declaration service" or "Halden". The first two retrievals score below the accept threshold, the agent folds the archive's own vocabulary into the query, and the third round finds it.
Related MCP server: tero-mcp-lite
The MCP surface
Five typed tools over the archive, on MCP Python SDK v2 speaking revision
2026-07-28. Three parts of that revision are used deliberately rather than
incidentally.
Typed tools. Every tool returns a Pydantic model, so each advertises a JSON
outputSchema and every result carries structuredContent. Clients deserialize
an object; they never parse prose.
Trace context crosses the protocol boundary. The revision documents W3C trace
context propagation through _meta — traceparent, tracestate, baggage
(SEP-414). Quorum reads it, so a span opened in the calling client is the parent
of every span the agent produces:
result = await client.call_tool(
"ask_meetings",
{"question": "What was the root cause of INC-4471?"},
meta={"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"},
)
result.structured_content["trace_id"] # '4bf92f3577b34da6a3ce929d0e0e4736'One trace covers the client call, planning, each retrieval round, each model
call, synthesis and citation verification — instead of two disconnected ones.
Asserted in tests/test_mcp.py and again over a real subprocess in
scripts/smoke_mcp.py.
Stateless by construction. The revision removed protocol sessions and the
initialize handshake. Nothing here holds per-connection state: chunk_id is a
server-minted handle passed as an ordinary tool argument, which is the pattern
the revision prescribes.
Tool | Returns |
| archive inventory + speaker roster |
| cited answer, retrieval rounds, cost, trace id |
| ranked passages with speaker + timestamp |
| the passages either side of a citation |
| cited summary by decisions / actions / risks |
Wiring instructions for stdio and streamable HTTP: docs/mcp.md.
How it works
plan ──▶ retrieve ──▶ grade ──┬── accept ───▶ synthesise ──▶ verify ──▶ answer
▲ │
│ ├── requery ──▶ rewrite ──┘
└───────────────┘
└── abstain ──▶ refusalA LangGraph state machine. The interesting part is what stops it from answering.
Three gates, cheapest first.
Corpus coverage. Do the question's content words appear anywhere in any transcript? If a question asks about an acquisition and no transcript contains the word, no re-query can find it. One set intersection, and it catches the largest class of unanswerable question before any model call.
Relevance grading — the corrective-RAG step. Each passage is scored; the accept/re-query decision uses the mean of the best three, not the whole candidate list, so weak tail hits cannot veto a strong head. Below threshold, the query is rewritten from the archive's own vocabulary and retrieval runs again, bounded at three rounds.
Citation verification. Every
[n]marker must resolve to a passage that was actually retrieved; unresolvable markers are stripped and recorded. Each sentence's content must appear in what it cites. An answer that ends up citing nothing is withdrawn and becomes a refusal.
Gate 3 is deterministic on purpose. Asking a model whether its own answer is grounded fails in precisely the case that matters — a model that hallucinated a claim will also attest that the claim is supported.
Retrieval is hybrid because meeting questions come in two shapes: "what did we decide about the vendor contract" is a paraphrase (dense wins); "who mentioned INC-4471" is an exact token with no semantics (BM25 wins). Fusion is a weighted sum of min-max normalised scores rather than RRF, because RRF discards score magnitude and gate 2 thresholds on magnitude.
Chunking never splits a segment. Segments are what diarization produced, so
they are the smallest span whose speaker and time range can be trusted. Cut
inside one and every citation built from it starts misattributing who said what.
tests/test_ingest.py asserts this and the properties that follow from it.
More detail: docs/architecture.md.
Results
Measured on the 29-case golden set in evals/golden_set.jsonl, offline backends,
regenerated by python evals/run_eval.py. Full report:
docs/results.md.
Metric | Value | What it means |
False answer rate | 0% | never answered a question the archive cannot support |
Abstention rate on unanswerable | 100% | declined all 6 unanswerable questions |
Answer rate on answerable | 100% | never abstained out of excessive caution |
Citation accuracy | 100% | cited the meeting the answer is actually in |
Speaker accuracy | 100% | attributed to the right speaker |
Content accuracy | 96% | 22/23 — the answer contains the expected fact |
Mean retrieval rounds | 1.21 | the corrective loop fires on 3 of 29 questions |
p50 / p95 latency | 4.2 / 9.4 ms | offline backends, 27 chunks, one local machine* |
* Latency is the one machine-dependent number here, so it is deliberately kept
out of the committed docs/results.md — that report is diffed by CI as a
regression gate, and a file that changes on every runner cannot serve as one.
Both directions of the abstention trade-off are reported, because a system that reports only one is hiding half its errors: refusing everything scores 100% on abstention, and answering everything scores 100% on answer rate.
The one failure is real and is in the table. fact-12 ("How long would
migrating away from Meridian take?") retrieves and cites the correct passage but
extracts the wrong sentence from it: the deliberately conservative stemmer does
not merge migrating with migration, so the sentence that echoes the question
outranks the sentence that answers it. Merging derivational pairs would fix this
case and risk wrong citations elsewhere, which is the worse failure for this
system. It is left failing and documented rather than tuned away.
Quickstart
git clone https://github.com/AnjanaSuresh01/agentic-meeting-intelligence
cd agentic-meeting-intelligence
pip install -e ".[dev]"
quorum ingest # build the index (~1s)
quorum ask "Why was the notification-dispatch migration deferred?"
quorum search "INC-4471" -k 3 # raw retrieval hits
quorum summarise 2026-03-18-security-review --focus risks
quorum doctor # config + readiness
pytest -q # 103 tests, offline
python evals/run_eval.py # the numbers above
python scripts/smoke_mcp.py # MCP over a real subprocessServing:
quorum serve-mcp # MCP over stdio (how desktop MCP clients attach)
quorum serve-mcp --http # MCP over streamable HTTP, :8765
quorum serve-api # FastAPI, :8080 (docs at /docs)Using real models
Everything above runs with no key. To use a hosted or local model:
pip install -e ".[anthropic]"
export QUORUM_LLM_BACKEND=anthropic ANTHROPIC_API_KEY=sk-ant-...
# or, fully local:
export QUORUM_LLM_BACKEND=ollama QUORUM_LLM_MODEL=llama3.1And for semantic rather than lexical embeddings:
pip install -e ".[embeddings]"
export QUORUM_EMBEDDER=sentence-transformers
quorum ingest # required: vectors from different embedders are not comparableAll settings and their defaults: .env.example.
What is and is not verified
Claims in this README are things the repository actually does. This table says which ones a machine checked.
Component | Status |
Ingest, chunking, retrieval, agent, citations | ✅ 103 tests, every run |
MCP tools, schemas, | ✅ in-memory transport (tests) and real subprocess over stdio ( |
FastAPI endpoints, | ✅ tests |
Golden-set metrics | ✅ regenerated by CI; |
| ✅ default, every run |
| ✅ tested — asserted to rank identically to numpy |
| ⚠️ code path exercised, not run in CI (model download) |
Anthropic / Ollama backends | ⚠️ written and reviewed, not run in CI (needs a key / a daemon) |
ASR ingest ( | ⚠️ error paths tested only; transcription never executed — see the module docstring |
Dockerfile, docker-compose | ⚠️ written and reviewed, never built or run |
OTLP export to a collector | ⚠️ spans are produced and asserted; export to Jaeger not run |
Known limitations
The demo corpus is synthetic. Five fictional meetings about a fictional freight company, written for this repo. They are realistic in shape — decisions reversed, numbers corrected mid-discussion, one participant catching another's error — but no real meeting, person or customer is depicted. There is no public benchmark of speaker-attributed meeting transcripts with citation ground truth, so the alternative was no evaluation at all.
Groundedness is uninformative for the offline backend. It answers by quoting transcript sentences verbatim, so groundedness is 1.00 by construction. The metric only discriminates once a generative backend paraphrases.
The offline embedder is lexical, not semantic. The hashing embedder will not connect budget to spend. It exists so a clone runs and CI is byte-reproducible;
sentence-transformersis one env var away.The offline grader has no word sense. Content-term coverage cannot tell lift (a freeze lifting) from lift (raising something).
Stemming is inflectional only. starts/start and credits/credit merge; migrating/migration deliberately do not. See
fact-12above.Single-archive scope. No multi-tenancy, no access control. Every tool can read every meeting.
Repository layout
quorum/
text.py tokenisation, stopwords, the conservative stemmer
config.py env-driven settings; every default works offline
llm.py deterministic / anthropic / ollama backends
costs.py per-query token and money ledger
telemetry.py OTel spans, GenAI semconv, MCP _meta trace propagation
ingest/ VTT + JSON loaders, speaker-turn chunking, optional ASR
index/ hashing + sentence-transformers embedders, BM25,
numpy/faiss/chroma stores, hybrid retriever
agent/ LangGraph graph, reasoner (LLM + algorithmic paths),
citation verification
mcp_app/ MCP server, five typed tools
api/ FastAPI service
cli.py the `quorum` command
data/meetings/ the synthetic corpus (4 × .vtt, 1 × .json)
evals/ golden set + harness that generates docs/results.md
scripts/smoke_mcp.py MCP stdio smoke test, run in CI
tests/ 103 tests, all offlineLicence
MIT. The transcripts in data/meetings/ are synthetic and MIT-licensed with the
rest of the repository.
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
- Flicense-qualityCmaintenanceMCP server that acts as a research intelligence agent, converting natural language queries into SQL or full-text search against Hacker News and arXiv data, and returning answers with supporting evidence.
- AlicenseBqualityAmaintenanceA lightweight MCP server that enables querying a project's corpus (docs, decisions, issues, skills) with cited answers and typed refusals via stdio JSON-RPC 2.0.9MIT
- Flicense-qualityBmaintenanceA read-only MCP server that provides conversational querying of quotations data (counts, values, lookups) via tools like quotation_stats, search_quotations, and find_by_number.
- FlicenseAqualityBmaintenanceMCP server providing governed access to board meeting data, with tools to query meetings, motions, and documents, automatically applying anonymity policies before returning answers.6
Related MCP Connectors
GibsonAI MCP server: manage your databases with natural language
Query any docs site via MCP. Submit a URL, ask questions, get cited answers.
Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.
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/AnjanaSuresh01/agentic-meeting-intelligence'
If you have feedback or need assistance with the MCP directory API, please join our Discord server