codecite
Click on "Deploy 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., "@codeciteWhat's the occupancy load factor for business areas in the 2026 code?"
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.
codecite
Bring-your-own-corpus retrieval for building codes: section-faithful chunking, hybrid search in Postgres, and an MCP server so Claude Code or Codex can answer with §1004.5-style citations from your licensed copy of a code. The repo ships code, schema, tests, an eval harness, and an original synthetic code. It never ships, fetches, or redistributes ICC text.
flowchart LR
A[PDF / HTML / DOCX / MD] --> B[parse blocks]
B --> C[profile grammar<br/>ibc · oac · generic]
C --> D[section tree]
D --> E[chunks<br/>body · exception · table · definition]
E --> F[(Postgres 17<br/>pgvector + FTS)]
F --> G[hybrid search<br/>RRF + amendment overlay]
G --> H[MCP server<br/>stdio / http]
H --> I[Claude Code · Codex]Quickstart (no API key)
docker compose up -d
uv sync --extra local # local nomic-embed-text-v1.5; or set CODECITE_EMBED_PROVIDER=fake for CI-style runs
uv run codecite init
uv run codecite ingest samples/sample-building-code/model-building-code-2026.md --corpus sample-bc-2026 --layer base --title "Model Building Code" --version 2026 --corpus-title "Model Building Code 2026"
uv run codecite ingest samples/sample-building-code/local-amendments-2026.md --corpus sample-bc-2026 --layer amendment --title "Local Amendments" --version 2026
uv run codecite search "occupant load factor for business areas"Then wire it into a client. The repo ships a .mcp.json, so Claude Code picks the server up automatically when run inside the folder (project scope, nothing global, nothing loaded in other sessions). For a global registration instead:
claude mcp add codecite --scope user -- uv run --directory /path/to/codecite codecite serve# ~/.codex/config.toml
[mcp_servers.codecite]
command = "uv"
args = ["run", "--directory", "/path/to/codecite", "codecite", "serve"]
env = { CODECITE_DATABASE_URL = "postgresql://codecite:codecite@127.0.0.1:5432/codecite" }Related MCP server: MCP Context Manager
What the MCP server exposes
Tool | Use |
| hybrid search; returns governing sections with full text, matched chunk kinds, amendment overlay, cross-refs, and a ready-to-paste citation |
| exact lookup ( |
| parent chain, siblings, children, referenced-by |
| which section/table/chapter references in a piece of text actually exist |
| what is indexed |
| off unless |
Resources: codecite://{corpus}/toc, codecite://{corpus}/section/{number}, codecite://{corpus}/document/{id}.
Prompts: code_question, compare_to_standard (cite-or-abstain rules baked in).
Verified in both clients (2026-09-07):
$ claude mcp get codecite
codecite:
Scope: User config (available in all your projects)
Status: ✔ Connected
Type: stdio
Command: uv
Args: run --directory <path-to-repo> codecite serve
$ codex mcp list
codecite uv run --directory <path-to-repo> codecite serve enabled
How retrieval works
Chunk by section, not by window. Each chunk is one section body, prefixed with its breadcrumb (
Model Building Code 2026 > 10 Means Of Egress > 1004 Occupant Load > 1004.5 …) so the vocabulary the body omits is still embedded. Exceptions, tables, and definitions are separate chunks because that is where the answer usually is.Hybrid. pgvector HNSW cosine candidates plus Postgres full-text (strict AND pass, then OR pass), fused with Reciprocal Rank Fusion (k = 60), collapsed to sections.
Amendment overlay. A same-numbered section on the
amendmentlayer is surfaced directly above its base section and named inamended_byand in the citation.One embedding model per database.
initrecords it; mixing models is refused.
Eval
uv run codecite eval evals/sample-bc.yaml --modes naive,vector,lexical,hybrid --report docs/EVALS.md runs 64 questions (lookup, paraphrase, exception, table, definition, cross-reference, not-in-corpus) against the synthetic corpus. Results with the default local model (nomic-embed-text-v1.5, CPU), 2026-09-07:
mode | hit@1 | hit@3 | hit@5 | MRR | kind@5 | abstain | false abstain |
naive (512-token windows, no sections) | 0.275 | 0.442 | 0.442 | 0.353 | 0.000 | 1.000 | 0.033 |
vector only | 0.817 | 0.950 | 0.983 | 0.888 | 0.957 | 1.000 | 0.017 |
lexical only | 0.717 | 0.883 | 0.917 | 0.808 | 0.957 | 0.000 | 0.000 |
hybrid (default) | 0.817 | 0.950 | 0.983 | 0.880 | 0.957 | 1.000 | 0.000 |
hit@k: the expected section (or a descendant, half credit) is in the top k. kind@5: the matched chunk was the expected kind (table, exception, definition). abstain: the four not-in-corpus questions were flagged low-confidence; false abstain: in-corpus questions wrongly flagged. Full per-tag breakdown in docs/EVALS.md. CI runs the same gate with a dependency-free hashed-bag-of-words embedder (hybrid hit@5 0.95).
Ohio profile
codecite fetch-oac 4101:1 downloads the Ohio Administrative Code rule PDFs (state law, free) from codes.ohio.gov, politely (robots.txt, 1 req/s, identifies itself). Ingest them with --profile oac --layer amendment over your own licensed IBC 2021 PDF on the base layer. The tool never touches any ICC domain.
uv run codecite fetch-oac 4101:1 --out corpus/oac
uv run codecite ingest corpus/oac --corpus ohio-bc --layer amendment --profile oac --corpus-title "Ohio Building Code (OAC 4101:1)"
uv run codecite ingest /path/to/your/IBC-2021.pdf --corpus ohio-bc --layer base --profile ibc --title "IBC 2021" --version 2021
uv run codecite eval evals/ohio-bc.yaml --modes hybridevals/ohio-bc.yaml ships questions and expected rule numbers only; it contains no code text.
Run locally on 2026-09-07 against the 35 OAC 4101:1 rules alone (amendment layer, 291 sections, no IBC base layer indexed), 30 questions, nomic-embed-text-v1.5:
mode | hit@1 | hit@3 | hit@5 | MRR |
hybrid | 0.679 | 0.893 | 0.893 | 0.749 |
vector only | 0.696 | 0.929 | 0.929 | 0.796 |
lexical only | 0.625 | 0.786 | 0.804 | 0.694 |
The misses are mostly one-line "modify exception #1" instructions with almost no text of their own, which a base-layer IBC index would give context to. Report in docs/EVALS-ohio.md.
Full-pipeline test on a real code: New York City
The IBC itself is sold by ICC, but New York City publishes its own IBC-derived Building Code as free chapter PDFs (2014 edition based on IBC 2009; 2022 edition based on IBC 2015), and city law is a government edict. That makes it the cleanest way to exercise the whole pipeline on genuine ICC-layout PDFs. The chapter files are linked from the 2022 Construction Codes page and served from /assets/buildings/codes-pdf/cons_codes_2022/.
uv run codecite ingest corpus/nyc2022 --corpus nyc-bc-2022 --layer base --profile ibc --version 2022 --corpus-title "New York City Building Code 2022"
uv run codecite eval evals/nyc-bc-2022.yaml --modes hybrid,vector,lexicalIndexed 2026-09-07: 33 chapters, about 5,700 sections and 6,600 chunks (400+ tables, 500+ exceptions). Egress golden set (24 questions), nomic-embed-text-v1.5 on CPU:
mode | hit@1 | hit@3 | hit@5 | MRR |
hybrid | 0.705 | 0.977 | 0.977 | 0.803 |
vector only | 0.818 | 0.886 | 0.886 | 0.841 |
lexical only | 0.614 | 0.750 | 0.750 | 0.676 |
Known parser limits on these PDFs: NYC prints chapter and section titles as running page headers, which the parser strips, so those two levels of the breadcrumb lose their titles (subsections keep theirs). Report in docs/EVALS-nyc.md.
Legal posture
Operators index documents they already have the right to use. Nothing indexed leaves the machine unless a remote embedding provider is explicitly enabled. See docs/LEGAL.md for the cases and the reasoning, docs/ARCHITECTURE.md for the design, and docs/WRITEUP.md for the short version.
Layout
src/codecite/ config · db (migrations, queries) · parse · profiles · tree · chunk · extract · embed · retrieve · evaluate · mcp_server · cli · fetch
samples/ synthetic Model Building Code 2026 (+ local amendments) · Acme design standards (generic profile)
evals/ golden question set
tests/ grammar, tree, chunker, extractors, retrieval (real Postgres), MCP over stdioMIT.
Available Tools
6 toolsget_contextA
What surrounds a section: parent chain up to the chapter, previous/next siblings, children, and the sections that reference it. Use for 'where does this sit' or 'what else applies' questions.
| Name | Required | Description | Default |
|---|---|---|---|
| corpus | No | ||
| number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explains what kind of information is surfaced and implies a read-only lookup, but with no annotations it does not explicitly state side effects, permissions, or that no modifications are made.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single focused sentence followed by a short use-case clause, with no redundant or extraneous content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple context lookup with no output schema, the description enumerates the returned context categories and typical use cases. It could be more complete by defining the parameters, but the core behavior is understandable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides no parameter descriptions, and the description does not clarify what 'number' refers to or how 'corpus' is used. The words 'section' and 'corpus' offer only weak inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what the tool does: it returns surrounding context for a section, including parent chain, siblings, children, and referencing sections. It also names concrete question types it supports.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells when to use the tool ('where does this sit' or 'what else applies' questions), giving an agent clear selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sectionD
| Name | Required | Description | Default |
|---|---|---|---|
| corpus | No | ||
| number | Yes | ||
| include_tables | No | ||
| include_children | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Tool has no description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Tool has no description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has no description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Tool has no description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Tool has no description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tool has no description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_chaptersC
Table of contents: chapter numbers and titles for one corpus.
| Name | Required | Description | Default |
|---|---|---|---|
| corpus | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations to indicate side effects or safety, the description carries the full burden. It does not state that the operation is read-only, nor does it describe any potential errors or limitations. The brief mention of output content ('chapter numbers and titles') is helpful but insufficient for full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, using a single sentence that conveys the essential purpose without any redundant or extraneous information. It is well-structured for a simple listing tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the lack of return-format details is acceptable. However, the description omits usage context, edge cases, and any relationship to sibling tools, making it only partially complete for an agent deciding when and how to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, 'corpus', is not described in the schema. The description's phrase 'for one corpus' hints that it is a corpus identifier, but it does not clarify expected format, allowed values, or how to obtain such an identifier. Since schema coverage is 0%, the description does not sufficiently compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource (chapters) and the scope (one corpus), and the noun phrase 'Table of contents' effectively conveys the listing intent. However, it lacks an explicit verb and does not directly contrast with sibling tools like get_section or list_corpora, so it falls short of a perfect score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as get_section or search_code. It does not mention any preconditions or typical use cases, leaving the agent to infer the appropriate context from the name and parameters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_corporaA
List indexed corpora with their documents (layer, version), section/chunk counts, and the embedding model. Call this to tell the user what is actually indexed before answering.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description reveals what the tool returns (documents, counts, embedding model) and implies a non-mutating read operation. While it doesn't explicitly state side effects, listing is inherently safe.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, concise, and to the point, with no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of parameters and presence of an output schema, the description sufficiently explains the tool's function and output. It provides enough context for an agent to call it appropriately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so the description fully covers them. No additional explanation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (list indexed corpora) and the resource (corpora), distinguishing it from sibling tools like get_context and search_code.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly advises calling this tool before answering to tell the user what is indexed, giving clear guidance on when to use it. It doesn't mention when not to use it, but the context is straightforward.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_referenceA
Parse free text for section/table/chapter references and report which ones exist in the index.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| corpus | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It communicates a read-only parse-and-report behavior, but does not mention side effects, required index/corpus state, or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, direct sentence that front-loads the action and avoids redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and an output schema exists, so return values need not be described. However, the 'corpus' parameter is unexplained and the relationship between 'index' and 'corpus' is ambiguous.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%. The 'text' parameter is loosely tied to 'free text', but the optional 'corpus' parameter is never mentioned or explained, leaving a significant parameter-semantics gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('parse'), a specific resource ('section/table/chapter references'), and the outcome ('report which ones exist'), making it clearly distinct from sibling tools like search_code or get_context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the use case—validating references in free text—but it does not explicitly state when to prefer this tool over alternatives or give exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_codeD
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | ||
| kinds | No | ||
| layer | No | ||
| query | Yes | ||
| chapter | No | ||
| corpora | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Tool has no description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Tool has no description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has no description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Tool has no description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Tool has no description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tool has no description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
get_context - First observed
get_section - First observed
list_chapters - First observed
list_corpora - First observed
resolve_reference - First observed
search_code
TDQS
Scored across 6 tools
Tool names are distinct and suggest different purposes (context, reference resolution, corpus listing, code search, section retrieval, chapter listing). However, two tools (search_code, get_section) have empty descriptions, which slightly reduces clarity and could cause ambiguity in edge cases.
All tool names follow a consistent verb_noun pattern (get_context, resolve_reference, list_corpora, search_code, get_section, list_chapters). The verbs are varied but the structure is uniform and predictable.
With 6 tools, the set is well-scoped for a code citation/reference server. It covers lookups, searches, and structural navigation without being overly granular or excessive.
The tool set appears to cover core operations: searching code, retrieving sections and chapters, resolving references, and listing corpora. Missing operations like creating or updating references are likely outside the server's purpose, but the empty descriptions for two tools leave some uncertainty about full coverage.
Maintenance
Related MCP Connectors
No-data MCP handoff for local Claude Code to Codex harness moves. $49 lifetime.
Your office's procedures inside Claude or ChatGPT - verified citations or an honest refusal.
Live SEO workflow tools for Claude Code, Codex, and AI agents.
Source-checked CLI guides and model-aware planning for Claude Code, Codex, and Grok Build.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides semantic code intelligence to help users search, navigate, and analyze entire codebases using plain English. It enables Claude to perform architectural overviews, bug detection, and refactor suggestions through local semantic search and keyword indexing.MIT
- AlicenseAqualityDmaintenanceEnables efficient code navigation and retrieval through natural language search, BM25 ranking, and fuzzy matching across multiple programming languages. It drastically reduces token usage by allowing Claude to query specific code symbols and logic instead of reading entire files.1370 npm13MIT
- AlicenseAqualityDmaintenanceEnables semantic search over codebases using natural language queries, returning relevant code snippets with source locations. Integrates with Claude Code for automatic codebase exploration.11MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code to index and semantically search through PDFs, code, and documents with exact citations and zero hallucinations.MIT