Skip to main content
Glama

jog-mcp

An MCP server that gives Claude, or any MCP client, the full text of Romanian surveying and cadastre law: the cadastre and land-registry law, the ANCPI registration regulation, the new urbanism code, the land-fund law, ANCPI fees and the relevant books of the Civil and Fiscal codes. It has 18 acts and about 2,400 articles, taken verbatim from legislatie.just.ro.

Python 3.10+, read-only, no API key needed. 124 tests, pytest, all passing.

Jog is Hungarian for "law". The server is built for people who ask questions in Hungarian or Romanian and must quote Romanian law at a land-registry counter, so its rules are strict:

  • It cites everything. Every result names its act and article, links the official source, and gives the Monitorul Oficial consolidation and the date it was fetched.

  • It never presents repealed law as current. A repealed act, or one repealed article of an act that is otherwise in force, is flagged on every result together with what replaced it. Example: Legea 10/1995 lost art. 1–9, 11–40 and 42–44 on 2026-08-25, while art. 10, 41 and 45 onward remain in force.

  • It says when the corpus doesn't cover a question. The server instructions and prompts tell the model to say so rather than answer from memory. For nonsense queries, search returns nothing rather than plausible-looking hits.

Tools, prompts, resource

Tool

What it does

search_law

Ranked keyword search across every act, or within one act. Romanian or Hungarian; diacritics optional.

get_article

One article by number: art. 24, Articolul 24, 24^1. Exact lookup, so a citation never depends on ranking.

find_exact

Every article that contains a phrase literally: 15%, 30 de zile, servitute de trecere. Catches the numbers and fixed wording that ranked search can't see.

outline

The article headings of one act, chapter by chapter, so a 584-article code can be navigated without loading it into context.

list_acts

What the corpus holds: each act, its consolidation, its fetch date and its repeal status.

Every tool is annotated read-only and non-destructive.

Prompts: jogi_kerdes (a legal question, answered with a citation) and dosszie_lista (the documents a cadastral procedure needs, each traced to its article). Both are in Hungarian.

Resource: acts://list, the same act list as list_acts, as JSON.

Related MCP server: Romanian Law MCP Server

Example

Q: Care este termenul de valabilitate al certificatului de urbanism?

search_law returns the Codul urbanismului article first:

Articolul 257 — CODUL AMENAJĂRII TERITORIULUI, URBANISMULUI ȘI CONSTRUCȚIILOR din 5 august 2026
…
(15) Emitentul certificatului de urbanism stabilește termenul de valabilitate
pentru un interval de timp cuprins între 12 și 36 de luni de la data emiterii, …

Forrás / sursa: https://legislatie.just.ro/Public/DetaliiDocumentAfis/313329
verzió: MONITORUL OFICIAL nr. 661 din 10 august 2026
korpuszba került: 2026-10-16

Results from the old law say so before anything else:

Articolul 7 — LEGE nr. 50 din 29 iulie 1991 (**republicată**)
!! ⚠️ HATÁLYON KÍVÜL 2026-08-25 óta — Legea 169/2026 (Codul urbanismului), art. 576 alin. (3); helyette: codul-urbanism-169-2026

An answer that follows the server's citation rules reads like this (written by hand from the excerpt above, not model output): "A certificate of urbanism is valid for 12 to 36 months from issue, as set by the issuer (Codul urbanismului, Legea 169/2026, art. 257 alin. (15))." Legea 50/1991, which used to govern this, has been repealed since 2026-08-25.

Install

Requires Python 3.10 or newer.

git clone https://github.com/zbencz3/jog-mcp && cd jog-mcp
uv venv && uv pip install -e .        # or: python -m venv .venv && .venv/bin/pip install -e .
.venv/bin/jog-mcp --stats             # what the corpus holds

Claude Code

claude mcp add jog -- "$PWD/.venv/bin/jog-mcp" --glossary "$PWD/glossary.sample.md"

Claude Desktop

In claude_desktop_config.json:

{
  "mcpServers": {
    "jog": {
      "command": "/path/to/jog-mcp/.venv/bin/jog-mcp",
      "args": ["--glossary", "/path/to/jog-mcp/glossary.sample.md"]
    }
  }
}

Over HTTP

JOG_MCP_TOKEN=$(openssl rand -hex 32) .venv/bin/jog-mcp --http --host 127.0.0.1 --port 8787

HTTP mode won't start without a token, and it checks the token as a bearer token on every request. Read SECURITY.md before exposing it beyond localhost.

Hungarian queries and the glossary

The corpus is Romanian and stays Romanian, because a translation can't be cited. Hungarian questions reach it through a glossary, which expands the query: "telekkönyv" is searched as "telekkönyv carte funciară". Each translation counts for less than a word the user actually typed.

The glossary is a two-column markdown table, passed with --glossary. The repository ships glossary.sample.md, five generic rows that show the format. Supply your own for real use. Without a glossary, Romanian questions work unchanged; purely Hungarian ones reach less. The test suite measures both cases. A test also checks every Romanian term in the glossary against the corpus, because the statute is the authority on its own vocabulary.

How search works

It's pure Python with no embeddings, no vector database and no API key. search.py is a BM25-style keyword index with diacritic folding and a 5-character prefix stem. The stem handles Hungarian agglutination and the dropped diacritics of fast typing. The ranking also does the following:

  • Length normalisation. Without it, a 25k-character fee annex outranked the short article that actually answered the question.

  • Long-section splitting. Long sections are split at paragraph breaks when indexed, never in the stored text, so get_article still returns the whole article.

  • Focused excerpts. A long table returns its header row plus the matching rows. A price without its column headings can't be quoted.

  • Friendly act names. acts.yaml gives each act a friendly name that queries can match. The official title "ORDIN nr. 16 din 7 ianuarie 2019" contains none of the words people search for.

  • N-gram fallback. A character-n-gram similarity search tops up thin results. Its score floor was measured on this corpus: useful matches score 0.20–0.35 and noise scores 0.06–0.12.

Refreshing the corpus

uv pip install -e '.[fetch]'
.venv/bin/jog-mcp-fetch --check --deep   # is each doc_id the right document, and is there a newer consolidation?
.venv/bin/jog-mcp-fetch                  # fetch, rewrite only the acts whose text changed
git diff --stat acts/                    # every amendment is a reviewable diff

The fetcher handles two quirks of the portal, both of which fail silently:

  • An order is not the regulation it approves. Ordin 700/2014 is three articles; the regulation itself is a separate document. --check flags an act that parses to suspiciously few articles.

  • Every consolidation gets a new document ID. The portal has no link from the old ID to the new one. --check --deep compares the configured alt_ids.

A running server picks up re-fetched files on the next query, with no restart.

Development

uv pip install -e '.[dev]'
.venv/bin/pytest

The 124 tests cover the parser against real portal markup, exact citation, act-reference resolution, every repeal case (whole act, partial, agreement with the portal's own "Abrogat." stamps) and the security properties. They also run a question benchmark against the real corpus that checks each question lands in the right act.

Licence

The code is MIT; see LICENSE. The texts in acts/ are Romanian legislation as published on the Portal Legislativ of the Ministry of Justice, included for convenience. Check the official source before relying on any of them.

Available Tools

5 tools
find_exactA
Read-onlyIdempotent

Find every article that contains a phrase LITERALLY (case and diacritics ignored). Use it for numbers and fixed wording that ranked search cannot see: '15%', '30 de zile', 'servitute de trecere', 'art. 41 alin. (10)'. Returns each match with the text around it; pull the whole article with get_article.

Inputs: phrase (required), act. Returns: result

get_articleA
Read-onlyIdempotent

Return one article of one act verbatim, by number. Use this whenever an article is cited by number ('art. 24 din Regulament'); it is exact and does not depend on search ranking.

Inputs: act (required), article (required). Returns: result

list_actsA
Read-onlyIdempotent

What the law corpus holds: each act, its size, the consolidation it came from and the date it was last fetched. Check this when an answer needs to state how current the law text is.

Inputs: no named parameters. Returns: result

outlineA
Read-onlyIdempotent

List the article headings of one act, with its chapters. Use this to find the right article in a long regulation before pulling its text.

Inputs: act (required). Returns: result

search_lawA
Read-onlyIdempotent

Search the Romanian surveying-law corpus (cadastre, land registry, construction permits, land fund) and return the matching articles verbatim. Use this for a question about what the law requires. Queries may be in Romanian or Hungarian; diacritics are optional. Returns the article text, its act and its chapter, so the answer can be cited.

Inputs: query (required), act, limit. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 5 tools

    Disambiguation5/5

    Each tool occupies a distinct retrieval mode: ranked search, exact fetch by article number, literal phrase match, structural outline, and corpus metadata. The descriptions explicitly state when to prefer one over another (e.g. get_article 'does not depend on search ranking', find_exact for 'fixed wording that ranked search cannot see'), leaving almost no room for misselection.

    Naming Consistency4/5

    Four of five names follow a clear verb_noun pattern (search_law, get_article, find_exact, list_acts). 'outline' is a bare noun that breaks the pattern, though its meaning is still unambiguous.

    Tool Count5/5

    Five tools is tightly scoped to a read-only legal-corpus server, and each one covers a genuinely different retrieval need. Nothing feels redundant or missing at the count level.

    Completeness4/5

    The read-only surface covers ranked search, ID lookup, literal search, structural navigation and freshness metadata — the full lifecycle for answering citable legal questions. Minor gaps remain: no way to restrict search to a specific act, and no explicit pagination or result-limit control for large result sets.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers