Ask Hekkos & MCP
For anyone in the org.
Ask a question about your codebase in plain language — “how does auth work here?”, “which repos are missing a CONTRIBUTING.md?” — and get an answer with clickable sources, in the web chat or straight from your IDE and coding agents. Under the hood, every answer is grounded in your repos’ committed documentation, cross-checked against the extracted real state of the code, and the same answers are exposed to MCP-capable tools.
Ask Hekkos (the web chat)
Open Chat and ask a question in plain language, for example:
- “What is the authentication flow in this org?”
- “Which repos are missing a CONTRIBUTING.md?”
- “How does the scan engine work?”
In a brand-new org, those example questions appear once the first repos have been indexed. Before that, Chat shows guidance instead: if no GitHub source is connected yet, admins see a Connect GitHub button and members see a note to ask an admin to connect one; once a source is connected but nothing is indexed yet, Chat says it’s scanning your repositories and that questions will work once the first repos are indexed.
Hekkos retrieves the most relevant documentation chunks across your connected repos and answers from them. Above an AI-written answer, a compact grounding bar leads with the claim that matters — “Answered from N sources in your repos” — with the retrieval mode (semantic) kept as a de-emphasized detail. Below the answer, those sources are listed as a numbered rail — [1], [2], … — each linking to its file on GitHub (or, for a wiki source, its Confluence page). Where a statement in the answer draws on a source, a small superscript citation like [1] appears inline, pointing to that numbered entry, so you can trace any claim back to where it came from. (The rail always lists the sources; inline citations appear when the answer includes them.) If it can’t ground an answer in your repos, it tells you rather than guessing.
Answers stream in live. The chat respects your org’s monthly usage limits and is rate-limited per org, so a burst of questions may briefly be throttled.
Your conversations are kept in a Conversations sidebar, grouped by date (Today / Yesterday / Last 7 days / Older). Each conversation is stored separately in your browser, so several coexist and starting a New chat never discards an earlier one — click any past conversation to reopen it exactly as it was, drift flags, limit notices, and truncation notes included. History is client-side only (this browser), scoped to the current org, and never leaves your device.
Grounded in the real code, not just the docs
Hekkos also extracts your code’s real state — the actual routes, env vars, functions, types, and CLI flags — and grounds answers on it. When the docs and the code disagree, the answer shows both sides, says which one matches the current code, and flags the drift instead of quietly trusting the doc. If a cited doc section has known drift, the answer carries a severity-colored annotation linking to that finding; if the underlying scan is stale, it says so. These drift flags come straight from the database (no extra model call), so they appear on the Free plan too.
Assess a pasted document (“how would we build this?”)
Hekkos can take a whole ticket, RFC, or spec — not just a question — and tell
you how it could be built with what your code already has. In the web chat,
use the Attach a document control under the composer to paste the text, then
ask your question; the same capability is available over MCP and the API via
the ask_real_state tool (see the
MCP section below), which takes
the pasted text as its optional document argument. Hekkos
drives retrieval from both your question and the document,
then answers by separating what already exists in your real code (cited) from
what you’d need to add (reasoned) — it never invents functions or routes that
aren’t in the extracted real state. A very long document is bounded and the
answer tells you if part of it was dropped.
Retrieval modes — keyword vs semantic
How the chat finds relevant docs — the retrieval mode — depends on your plan (see plans & usage):
| Free — keyword | Team — semantic | |
|---|---|---|
| How it matches | Same words as your question (Postgres full-text) | Same meaning (vector search — synonyms & paraphrases too) |
| What you get | The matching passages, with source links | An AI-written, cited answer |
| Needs an embedder | No | Yes |
On the Free plan, keyword search returns a “Keyword matches from your docs” block — labeled clearly so it’s never mistaken for an AI answer — with an upgrade nudge. When keyword search finds nothing, you get a distinct “no matches — try different words” state. Semantic search is the paid upgrade because it finds the right material even when your wording differs from the docs.
This plan-based split is on by default for SaaS (TIERED_RETRIEVAL_ENABLED).
The MCP surface below always uses semantic search regardless of plan.
Access & privacy
The chat only ever sees your org’s indexed docs — never another tenant’s.
A repo can be excluded from the index entirely with exclude_from_knowledge: true in its .hekkos.yml.
MCP (drive Hekkos from your IDE or an agent)
Hekkos exposes a Model Context Protocol server, so an MCP-capable client (an IDE assistant, an agent) can query and author against your org programmatically. Point your client at the MCP endpoint and authenticate with your Hekkos user token.
Representative tools:
| Tool | What it does |
|---|---|
query_knowledge | Ask a question; get a cited answer (the chat, as a tool — always semantic). Carries the same drift flags and docs-only caveat as ask_real_state, so a cited doc the code has since moved past is flagged — and a plan-limit refusal comes back as a tool error, never as prose you’d read as the answer. |
ask_real_state | Ask a question grounded in the code’s real state; optionally pass a document to assess how it could be built with what exists. Surfaces drift on cited docs. When no live code-state fact backed the answer, it says so — the answer is flagged as documented intent, not verified real state, so you can tell a code-verified answer from a docs-only one. |
get_real_state | List the real-state entities (routes, env vars, funcs, types, flags) extracted from a repo, with file:line provenance. Filter by domain / kind. Paginated — a large repo returns one capped page plus a cursor to fetch the next. |
risk_ranking | Rank a repo’s undocumented surface by call-graph centrality — the highest-leverage code to document first. Each item carries its file:line, live caller count (in-degree), and whether a route targets it. Pass repo and an optional limit. |
impact_of | Compute the deterministic blast radius of a code entity over your org’s dependency graph — who calls it and which routes, types, tables, and dependencies it reaches, at what depth. Pass the entity fingerprint (from get_real_state provenance) and hops (1–3). |
check_change | Before you commit: run your org’s structural principle rules on a proposed change and get the same verdict the merge gate would emit — plus surface collisions (existing code you’d be re-creating) and the real-state drift the change would introduce between its code and the docs it carries in the same changeset (a companion doc still describing the old signature). Drift is checked against the changeset’s own docs only — whole-repo drift stays the PR-open path. Pass repo and the proposed files ([{path, content}]). Returns the verdict both as human-readable Markdown and as a typed structured verdict (blocks_merge, blocks_agent_merge, would_block_merge, blocking_count, advisory_count, attested, attestation_note, violations[], collisions[], introduced_drift[]) declared via the tool’s OutputSchema. Agent-authored PRs must branch on would_block_merge (= blocks_merge OR blocks_agent_merge): blocks_agent_merge is the hard, non-dismissible hekkos/agent-drift gate that fails an agent PR carrying would-flag drift when your org enabled it — so a change with blocks_merge:false can still be blocked, and the pre-commit self-check now matches the gate instead of green-lighting a change the gate will stop. On a repo with no baseline scan yet, or one that is frozen (paused), the verdict returns attested:false (with a reason) and is labeled NOT ATTESTED — an empty result there is the absence of a baseline to compare against, not a clean “docs match code” pass, so don’t read it as an all-clear. Deterministic; writes nothing, opens no PR. |
list_drift | List a repo’s active documentation-vs-code drift, each with an id, effective severity, and location. Filter by domain / min_severity. On a repo with no baseline scan yet, or one that is frozen (paused), an empty result is reported as NOT an all-clear (with the reason) rather than “the docs match the code” — no findings there means nothing was measured, not that it is clean. |
get_fix | Return the deterministic, surgical fix for a drift finding (from list_drift) — closing the write loop. Pass finding_id and doc_content (the current text of the finding’s doc file); get back the exact replace "<stale>" with "<correct>" plus the fixed file to apply verbatim. Only high-confidence signature mismatches with a known-correct value and an unambiguous locus are auto-fixable; anything else comes back as not auto-fixable with the reason. Strictly the computed fix — never free-form edits; writes nothing. |
list_violations | List a repo’s policy violations — the principle lens (code breaking a declared rule) and the advisory lens (known-bad practice, e.g. weak crypto). Filter by lens / category. Read-only. |
ack_drift | Acknowledge a drift finding by id (from list_drift) so it stops surfacing until the code changes again. |
get_doc_section | Fetch a specific section of a specific doc, by doc type + heading. |
get_doc_status | A repo’s documentation-coverage status. |
list_repos | List repositories you can access. |
get_org_standards | Read your org’s current doc-standards configuration. |
dismiss_suggestion | Dismiss a pending suggestion with a reason. |
refresh_knowledge | Re-index a repo (admin only). |
Tools are org-scoped and permission-checked the same way the web app is — e.g.
refresh_knowledge requires you to be an admin of the org.
Every tool accepts an optional org argument (an org id or name) to target a
specific org for callers who belong to more than one connected org; without it,
the oldest connected org is used deterministically. The selector never widens
access — it can only pick among orgs you are already a current member of.
See the API reference for the full tool list and the REST endpoints behind the web app.