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.

NameRequiredDescriptionDefault
actNoOptional: restrict to one act
phraseYesThe exact words or number to find

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, so the description only needs to add context — and it does: case and diacritic insensitivity and the fact that each match is returned with surrounding text. Nothing contradicts the annotations; the only omission is any note on result limits or pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core behavior, then when to use it, then what it returns and the follow-up call. The example phrases earn their space by showing the exact query shapes ranked search would miss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering the safety profile, full schema coverage, and an output schema handling return structure, the description supplies everything else an agent needs: matching semantics, targeting guidance, and the follow-up to get_article. There is no meaningful gap for a two-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuinely useful meaning for the required parameter: the phrase is matched literally with case and diacritics ignored, which changes how an agent constructs the query. The optional 'act' scoping parameter is left entirely to the schema, which already documents it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ("Find every article that contains a phrase LITERALLY") plus the precise matching rule (case and diacritics ignored). It is clearly distinguishable from ranked search (search_law) because it declares literal matching rather than ranking.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says when to use it — numbers and fixed wording that ranked search cannot see — with concrete example phrases ('15%', 'art. 41 alin. (10)'). It also gives a next step ("pull the whole article with get_article"), though it never explicitly states when not to use it or names search_law as the alternative to choose instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

NameRequiredDescriptionDefault
actYesAct id, number or a word from its name
articleYesArticle number: '24', 'art. 24' or 'Articolul 24'

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered elsewhere. The description still contributes real behavioral context: the result is verbatim and exact, independent of search ranking, which tells the agent the output is authoritative text rather than a ranked snippet. It says nothing about behavior when the act or article does not resolve, which is the main remaining gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with the core action and the key differentiator (verbatim, ranking-independent) front-loaded. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the tool is a simple two-required-parameter read. What an agent still might want — behavior on ambiguous act names or a missing article number — is absent, but the definition is otherwise sufficient to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (act, article) are already documented with accepted forms including '24', 'art. 24' and 'Articolul 24'. The description's mention of citation-by-number largely restates that, adding little syntax or constraint information beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Return one article of one act verbatim, by number') and scope ('one article of one act'), which is unambiguous. It implicitly separates itself from ranking-based search siblings ('does not depend on search ranking') but never distinguishes itself from find_exact or outline, which are the most plausible confusions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states an explicit trigger condition: use this whenever an article is cited by number, with a concrete citation example ('art. 24 din Regulament'). It does not state when-not to use it or name an alternative sibling for the non-citation case, so the routing guidance is clear but incomplete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and closed-world behavior, so the safety profile is covered. The description adds a genuinely useful behavioral signal, that results carry provenance (consolidation) and freshness (last fetched), enabling currency judgments. It says nothing about result volume or whether the whole corpus is returned in one call, which is the remaining behavioral unknown for a zero-parameter enumeration.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, both load-bearing: the first defines the payload, the second defines the decision it supports. The content is front-loaded and there is no filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters, full annotation coverage, and an output schema that documents the returned fields, the description carries only the burden of stating purpose and trigger, which it does. The one gap is scale: an agent cannot tell whether this returns the entire corpus at once or a truncated listing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no parameter meaning for the description to supply. Baseline for a no-parameter tool applies, and the description correctly avoids inventing filtering options that do not exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description enumerates exactly what the call returns per act: size, source consolidation, and last-fetched date, which combined with the name makes the resource and operation unambiguous. It does not explicitly contrast itself with search_law or outline, so sibling differentiation is left to inference from the noun 'each act'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Check this when an answer needs to state how current the law text is' gives a concrete triggering condition tied to a user-facing need, which is stronger than generic 'use this to list' guidance. It stops short of naming when-not to use it or pointing to search_law/find_exact as the alternative for content lookup.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

NameRequiredDescriptionDefault
actYesAct id, number or a word from its name

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as a read-only, idempotent, closed-world operation, so the safety profile needs no restating. The description adds structural context (headings are grouped by chapter), which helps the agent interpret the result, but says nothing about ordering, depth, or size of the outline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero redundancy, with the capability stated first and the usage rationale second. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read tool with annotations and an output schema, the description plus structured fields cover everything an agent needs to invoke it correctly. Only the shape of the outline output is left unaddressed, and the output schema supplies that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single act parameter is already documented as accepting an id, number, or a word from the name. The description adds no further meaning about the parameter, so the schema carries the full burden and baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"List the article headings of one act, with its chapters" gives a specific verb (list), resource (article headings) and scope (one act, grouped by chapter). It is distinguishable from get_article, which is implied by "before pulling its text," though no sibling is named outright.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states a concrete use case: orient yourself in a long regulation before retrieving text. That gives the agent a clear when-to-use signal and implicitly points to get_article for the follow-up step, but no explicit exclusion or named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

NameRequiredDescriptionDefault
actNoOptional: restrict to one act. Accepts an id ('regulament-700-2014'), a number ('7/1996') or a word from its name ('urbanism')
limitNoHow many articles (max 12)
queryYesThe question or the key terms

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered elsewhere. The description adds genuinely new behavioral context on top: multilingual query tolerance (Romanian or Hungarian), diacritic insensitivity, and the shape of each hit (article text plus act and chapter, presented for citation).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each doing distinct work: corpus scope, selection condition, language/encoding tolerance plus result shape. Front-loaded, no filler, and the language note is placed where it will be read before the agent types a query.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With four annotations, a fully documented 3-parameter schema, and a present output schema, the description only needs to supply corpus scope, retrieval semantics and language handling — and it does all three. Nothing an agent needs in order to issue a correct query is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns above baseline by adding meaning to the query parameter — it accepts a question or key terms, in Romanian or Hungarian, with optional diacritics. The act filter and limit cap are left entirely to their schema descriptions, which is acceptable given full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (search) and a precisely scoped resource (the Romanian surveying-law corpus, enumerated as cadastre, land registry, construction permits, land fund) and says what comes back (matching articles verbatim). It does not name the siblings it is meant to be distinguished from (find_exact, get_article, outline, list_acts), so the boundary is inferable but not declared.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use this for a question about what the law requires" gives a clear positive trigger, and the corpus enumeration implicitly scopes out non-surveying-law questions. However, no alternatives are named and no exclusions are given, so an agent cannot tell from this text when find_exact or get_article would be the better call.

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.

  1. 5 tool updatesv0.1.0
    • First observedfind_exact
    • First observedget_article
    • First observedlist_acts
    • First observedoutline
    • First observedsearch_law

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