Skip to main content
Glama

estonian-mcp

Claude is quite bad at Estonian, so this MCP is here to fix that. Give it a shot.

CI Smithery License: Apache 2.0 Python 3.11-3.13 MCP

A small Model Context Protocol server that exposes EstNLTK, the Estonian NLP toolkit, as tools any LLM client can call in real time, backed by EKI's orthography rules (Reeglid) and public-domain Riigi Teataja legislation. Hand it Estonian text, get back correct lemmas, morphology, POS tags, spell-check + suggestions, syllables, named entities, WordNet synonyms, fastText-based related words, a register hint, orthography/grammar checks, kantseliit and terminology-consistency checks for reports and academic prose, and, for legal texts, legalese simplification and canonical legal-usage lookups.

One-click install from Anthropic's official Connectors Directory, or self-host. See below.

If your AI agent has to draft, edit, or proofread Estonian, this wires in ground truth so it stops guessing on the mechanical layer (spelling, case forms, conjugation) and gives it real Estonian synonyms instead of inventing them.

It also covers the editorial layer, where a word can be correctly spelled, morphologically valid and still wrong: check_translationese for Estonian that keeps English sentence structure, check_officialese for bureaucratic Estonian in reports and academic prose, check_term_consistency for a document that names one thing three ways, and synonyms read as a word-fit check: its glosses carry domain constraints (korpus is specifically "kirjaliku või suulise teksti elektrooniline kogu", so a set of images is not one, however natural it sounds in ML jargon).

Benchmark: on TalTech's inflection_et gold dataset (a noun-phrase inflection benchmark; Lillepalu & Alumäe, arXiv:2510.21193), our morphology engine scores 99.1% first-candidate / 99.1% any-candidate over 1,400 items (first-candidate is 96.6% without the optional fastText model, which is what ranks a lemma's inflection types; any-candidate is 99.1% either way). The 13 answers it gets "wrong" are all ones where the benchmark itself contradicts EKI, so once those 13 are corrected the score is 100% / 100%; the 13 are listed with their EKI citations in data/inflection_et_eki_disputes.json. uv run python scripts/apply_eki_corrections.py rebuilds the dataset locally with those 13 rows corrected. The corrections live here; the data does not, because the dataset carries no licence and re-hosting it is not ours to do. Reproduce: uv run python scripts/eval_inflection.py. (We're a tool server, not a rankable LLM, so this scores our tools against published gold data.)

Second benchmark, wider and from real text: inflection_et covers four cases, so ten were never measured. Against Pert Lomp's käänamiskorpus (11,011 single-word rows over all fourteen cases, drawn from Riigikogu stenographs and ERR news and frequency-weighted, CC-BY-SA-4.0), the engine scores 99.3% first-candidate / 99.9% any-candidate. The gap between those two is the interesting part: Estonian forms most plural oblique cases two ways, and leading with the wrong one cost 11 points until 0.5.10 ordered a slot's variants by the paradigm's own genitive stem (raamatutele before the literary raamatuile). Reproduce: uv run python scripts/eval_kaanamiskorpus.py. The data is downloaded at run time, never vendored here, and the server never touches it.

Three ways to use it:

  1. 👉 One-click from Anthropic's Connectors Directory, the easiest path, no terminal, no install, no URL to paste. See Get started in 30 seconds below.

  2. One-click on Smithery, install from the estonian-mcp listing.

  3. Self-host, clone, run locally as stdio, or deploy your own container to Fly.io / any host. See Self-host (advanced).

What it does

Tool

What it does

tokenize(text)

Split text into sentences and words

analyze_morphology(text)

Lemma, POS, form, root and ending per word (punctuation left out), plus, where they apply, the form's Estonian name, clitic, compound parts, ambiguity count, usage flags (archaic / foreign / interjection / abbreviation / proper-noun) and an indeclinable flag

paradigm(word)

Full Vabamorf-generated inflection paradigm, 14 cases × 2 numbers for nominals (including ordinals, comparatives, superlatives and proper nouns, the last from Vabamorf's lexicon only), plus the short illative where a word has one (majja beside majasse), ~39 verb forms including the umbisikuline tegumood (kasutatakse, kasutati), with Estonian labels per form. A lemma with several inflection types (kott → koti or kota, two different words) returns one consistent table per type, corpus-ranked, rather than a merged one; pass an inflected form (koti) to select the type you mean. Proper nouns inflect from Vabamorf's lexicon (Tallinn → Tallinnasse); a name it lacks gets an empty table rather than invented forms, and a capitalised common word it has no name for (Pikk at the start of a sentence) gets the lowercase word's table

lemmatize(text)

Just the dictionary form per word (punctuation left out)

pos_tag(text)

Just the part-of-speech tag per word (punctuation left out)

spell_check(text)

Misspelled words with correction suggestions; an empty list means every word passed

syllabify(word)

Syllables with quantity + accent

named_entities(text)

People / places / organisations

synonyms(word)

Synsets from Estonian WordNet: synonymous lemmas and a definition per word sense, plus examples where WordNet has them

find_related_words(word)

Top-N semantically nearby words via fastText embeddings (semantically related, not always synonymous)

classify_register(text)

Coarse formal/colloquial register hint with matched markers, consistency flag for register-mixed text, plus structural signals (umbisikuline tegumood ratio, noun density) so dense officialese no longer scores "neutral"

check_style(text)

Style metrics, lemma-aware repetition, umbisikuline-tegumood ratio, sentence-length variance, hedging-word density

check_officialese(text)

Kantseliit check for non-legal prose (reports, academic, business), where check_legalese stays silent. Nominalisation density (hindamine → hindama), impersonal-voice ratio, clause stacking (mille käigus … ning …), Estonian-calibrated sentence length, admin filler (omab → on, mudeli poolt loodud → mudeli loodud), läbi viima in every form (viis läbi uuringu → korraldas / tegi, läbiviimine) with routes (Rada viib läbi metsa) left alone, translated stock phrases of letters (Palun leidke manuses, ärge kõhelge ühendust võtmast, sealhulgas, kuid mitte ainult) and the request Küsin täpsemalt, kas … (→ Palun täpsustage, …). A -mine noun's verb is a real one: läbivaatamine → läbi vaatama, riskihindamine → hindama

check_translationese(text)

English structure in Estonian, the patterns that make a text read as translated, each one EKI or an EKI-published author rewrites: teie andmed where the subject's own thing is oma andmed, lähtume me → lähtume, Kui ..., me saadame → saadame (the verb comes first after a fronted clause), saab olema → on, ettepanek võtmaks → võtta, Tagamaks → et tagada, Mitte leides → Leidmata, tänu with a bad cause → tõttu, minu arvamusel, a third of the sentences opening with Ma, and English habits of form: Hea Mari, → Hea Mari!, Tere Mari → Tere, Mari, Lugupidamisega, → Lugupidamisega, the serial comma (teed, ja), title case in headings. Accepted Estonian such as aset leidma, rolli mängima or Eile ma läksin is left alone

check_term_consistency(text, glossary?)

One referent, one term. Flags a document that calls the same thing andmestik on page 1 and teadusandmestik on page 2, via shared compound head or shared Estonian WordNet synset, with per-variant counts so you can standardise on the dominant one. With a domain glossary (the server's, or a per-call glossary), a variant that is the only one listed in its group is named the group's preferred form

check_redundancy(text)

Pleonasm check, flags semantic doubling like samuti ka (also+also), kõige optimaalsem (most+optimal), and fixed redundant phrases

check_object_case(text)

Käändeõpetus, flags direct-object case errors under negation and after partitive-only verbs (armastama, vihkama, vajama, …), and verb government: teavitama takes the person in the partitive, teatama in the allative (teavitas politseile → teavitas politseid or teatas politseile; kahtlasest tegevusest teavitamine Rahapesu Andmebüroole → teatamine)

check_abbreviation_hyphenation(text)

Lühendiortograafia, flags an ending that starts with l written straight onto an all-capital abbreviation (OÜle → OÜ-le, THIl → THI-l), where EKI finds the hyphen clearer; a letter whose name ends in a consonant also gets the stem vowel (ASle → AS-ile). Other hyphenless forms (ELi, APIga, MCPst) are as correct as the hyphenated ones and are not flagged, and chloride formulas (HCl) are not abbreviations

check_compound_familiarity(text)

Attestation check, for each compound noun, reports whether the lemma is in the corpus vocabulary, Estonian WordNet or the legal terms list, and returns the top fastText neighbours of each unattested one. Unattested is ordinary for specialist vocabulary and is not a rewrite signal; the narrow is_suspect flag needs an unattested lemma whose nearest real neighbour is still under 0.55 (mõtteliin-style translationese, literal English "train of thought" → real Estonian is mõttekäik). With a server glossary, each compound also carries in_domain_glossary

check_domain_terms(text, glossary?, suggest_cutoff?)

Domain-glossary check, for Estonian written about an organisation's own systems, where a compound should be the organisation's term or the thing's identifier. Reports compounds that are unattested AND not on the operator's glossary or identifier list (see Domain glossary): not the organisation's word, though not necessarily coined, since much ordinary Estonian is unattested, each with up to three glossary terms spelled alike (look-alikes, not synonyms) and the glossary term it is built on, if any (vagunireisitabel on vagunireis). The hosted server has no glossary of its own: pass your terms in glossary (up to 1,000), used for that call only

check_capitalization(text)

Algustäheortograafia check, flags wrongly capitalized weekdays, months, nationalities, and language/culture adjectives per EKI's Reeglid

check_compounds(text)

Liitsõnaõigekiri, flags common AI-generated splits of words that should be a single compound (kooli maja → koolimaja)

check_punctuation(text)

Kirjavahemärgid, flags missing commas before subordinating conjunctions (et, sest, kuna, kuid, vaid, nagu, …); a comma before a two-part connective (nii et, ilma et) passes, and nagu is flagged only before a clause with a verb. Also flags the comma that closes an embedded clause (Mees, kes seal seisis oli minu isa → seisis, oli), which EKI keeps even before ja when the main clause continues (Juhtisin projekti, mis kestis kaks aastat, ja koolitasin …)

check_hyphenation(word)

Poolitamine, line-break positions for an Estonian word at syllable boundaries, never fewer than 2 characters from either end. Compound seams are among them but not singled out

check_numbers(text)

Numbrite õigekirjutus, flags decimal separators (3.14 → 3,14) and thousands separators (1,250 → 1250, 1,000,000 → 1 000 000; keep 1,250 if the decimal 1,25 is meant). Skips times after kell, time ranges, dates, clause, section and version numbers (4.13., punkt 3.2, Python 3.12); a time without kell mid-sentence (väljub 8.47 ja) is still flagged. Also flags a tilde used as "about" before a number (~50 → u 50; EKI keeps the tilde for variants such as mina ~ ma), a month and year in digits (09.2016 → sept 2016, where it used to be called a decimal), a spaced range dash (2020 - 2024 → 2020-2024) and a suffix on the per cent sign (20%-line → 20% or 20-protsendiline)

check_legalese(text)

Legal plain-language aid, flags archaic kantseliit filler (käesolev → see, juhul kui → kui) and over-long sentences to simplify, while listing the terms of art that must be preserved so simplification doesn't change legal meaning

check_defined_terms(text)

Long-document structure, maps terms defined with (edaspidi „X“) or , edaspidi „X“, in any common quote style (an adverbial edaspidi before a quotation defines nothing), counts their exact-form uses (case-sensitive, so a term used only in inflected forms shows as defined-but-unused), lists § / lõige / punkt / artikkel cross-references, and flags defined-but-unused or doubly-defined terms (cap raised to 500k chars)

common_legal_usage(word)

Canonical legal collocations from an offline corpus index, how often a term occurs in legislation and the commonest lemmas of the nearest content word on each side (hagi → esitama hagi, kohustus → kohustuse täitmine), so the model uses real legalese instead of inventing it (bundled index: 5 core Riigi Teataja codes, obligations, civil procedure, property, penal, general; expandable, see Notes)

POS tag set: S=noun, H=proper noun, V=verb, A=adj (C=comparative, U=superlative, G=indeclinable), P=pron, D=adv, K=adp, J=conj, N=cardinal, O=ordinal, I=interj, Y=abbreviation or symbol (§, €), X=verb-bound word (plehku). Punctuation (Z) is left out of per-word output; tokenize keeps it.


Related MCP server: Võro MCP Server

✨ Get started in 30 seconds (no install)

This section is for everyone, including if you've never opened a terminal in your life. You'll be done before your tea is steeped.

estonian-mcp is in Anthropic's official Connectors Directory, so on most Claude apps you can add it with one click, no URL to paste, no config, no auth.

One-click from the Connectors Directory (Cowork, claude.ai, Claude Desktop)

  1. In your Claude app, open Settings → Connectors.

  2. Browse connectors (the directory) and search estonian, it shows up as the Estonian connector.

  3. Click Add / Connect. That's it, the server is public, so there's no authentication step.

  4. Start a new chat and write in Estonian, proofread an email, study a paragraph, draft a legal clause. Claude reaches for the tools whenever it needs to verify spelling, lemmas, morphology, or legal phrasing rather than guessing.

(On older Claude Desktop without a Connectors menu, use the stdio path in Self-host (advanced).)

Prefer to paste the URL? (or don't see it in the directory yet)

Any MCP-over-HTTPS client can also connect directly to the hosted server: we run it for you at https://estonian-mcp.fly.dev/mcp. In Settings → Connectors → Add custom connector, paste:

https://estonian-mcp.fly.dev/mcp

Leave every "Authentication" / "API key" / "Bearer token" field empty (the server is public, no token needed), then Save.

In Claude Code (CLI)

One command, no clone, no Python, no uv. Point Claude Code at the hosted server over HTTP:

claude mcp add --transport http estnltk https://estonian-mcp.fly.dev/mcp

Then run /mcp inside a session to confirm estnltk shows as connected. The tools are live immediately, ask Claude to proofread or lemmatize Estonian text and it'll reach for them.

Want a fully local, zero-network setup instead? See the stdio path in Self-host (advanced).

In Codex (CLI)

One command, the same hosted server over streamable HTTP:

codex mcp add estonian --url https://estonian-mcp.fly.dev/mcp

codex mcp list should then show it as enabled. Auth reads as "Unsupported", which is correct here: the server is public and wants no token. Ask Codex to proofread or lemmatize Estonian and it calls the tools directly.

In ChatGPT

ChatGPT reaches MCP servers through a custom connector, which lives behind developer mode. Turn that on in ChatGPT's settings, add a connector pointing at https://estonian-mcp.fly.dev/mcp with no authentication, then switch it on inside the chat that should use it. A saved connector is not active until it is selected in the conversation.

OpenAI has moved that toggle between Settings sections more than once, so follow their current developer mode article for the exact path rather than a menu name written down here.

One limit worth knowing: ChatGPT's deep research connectors expect a server to expose search and fetch tools. This server exposes 27 Estonian NLP tools and neither of those, so it belongs in the ordinary connector slot, not the deep research one.

Don't see your client here?

Any tool that supports MCP over HTTPS can connect, just point it at https://estonian-mcp.fly.dev/mcp with no auth. If your client only speaks stdio (Cursor, VS Code MCP, Continue, Zed), jump to the local-install path in Self-host.


💡 Pro tip, teach Claude your Estonian alongside the MCP

This MCP gives Claude correct linguistics: real lemmas, real case forms, real spelling. What it can't do is teach Claude your voice: the register, idioms, and tone you actually want when writing.

You handle the voice; the MCP handles the correctness. Layer them.

A few things to add to your Claude project / custom instructions / system prompt to get this right:

  • Set the register. "Always reply in formal officialese Estonian for legal and government topics, and in conversational Tallinn speech for chat replies. Never mix the two in one message."

  • Pin the dialect / region. "I'm from Tartu, prefer southern Estonian phrasings where there's a choice (e.g. 'kus sa lähed' rather than 'kuhu sa lähed' for casual speech)."

  • Show your tone with examples. Paste 3-4 short paragraphs of your own writing into the project instructions and ask Claude to match that voice. Real examples beat any abstract description.

  • Anchor common mistakes. "You always confuse kasutama (to use) with käsitlema (to handle / to deal with). Double-check those with the lemmatize tool before sending."

  • Direct the MCP explicitly when it matters. "Before sending any Estonian email, run spell_check on every word. Show me misspelled words with suggestions before drafting."

  • Use classify_register as a sanity check. "After drafting, run classify_register on the final text and warn me if it lands in 'formal' or 'colloquial' when I asked for the opposite." The classifier is coarse but reliably catches drift into officialese (käesolev, vastavalt, sätestama) or slang (mõnus, vinge, kuule).

  • Use synonyms to break repetition. "This newsletter uses kasutama four times. Look up synonyms via the MCP and suggest natural-sounding swaps." You'll get real Estonian alternatives with definitions, not invented ones.

  • Use find_related_words for richer rewrites. "What words pattern with kohv in Estonian? Use that to suggest three alternative phrasings for our café-launch ad copy." This is fastText-based, so it surfaces near-neighbours that aren't strict synonyms, useful when you want adjacent concepts, not just same-meaning swaps. (Quick rule of thumb: synonyms for "say the same thing differently"; find_related_words for "what else belongs in this conceptual space.")

The MCP catches misspelled words and invented case forms; your prompt drives the style. Together they make Claude actually useful for writing in Estonian, not just plausible-looking.


How to prompt it once it's connected

Most prompts don't need to mention the tools by name, Claude picks the right one. A few patterns that work especially well:

Proofread this Estonian email and use spell_check on any words
you're unsure about: <text>
Lemmatize this Estonian paragraph, then translate the lemmas to
English so I can study vocabulary: <text>
Analyze the morphology of this sentence and explain the case
markings: "Tallinnas elavad eestlased räägivad eesti keelt."
Extract the people and places from this Estonian news article,
then summarise in one paragraph.
This Estonian draft uses "kasutama" three times, look up synonyms
via the MCP and rewrite each occurrence with a natural-sounding
alternative that preserves the meaning.
Write this reply in Estonian, short, the way a native speaker would,
then run check_translationese on it and fix what holds: <text>
Classify the register of this draft. If it scores formal, soften
it for a casual newsletter audience. If it scores colloquial,
tighten it for a B2B email.

The model calls the tool, gets authoritative output, and bases its response on that, no more hallucinated lemmas or invented case forms.


All clients at a glance

Client

No-install path

Local-install path

Claude Cowork

✅ One click (directory)

✅ stdio via JSON

Claude Desktop

✅ One click (newer)

✅ stdio via JSON

claude.ai web

✅ One click (directory)

n/a

Claude Code (CLI)

✅ claude mcp add --transport http

✅ claude mcp add ... (stdio)

Codex (CLI)

✅ codex mcp add --url

✅ codex mcp add -- <command> (stdio)

ChatGPT

✅ Custom connector (developer mode)

n/a

Cursor

✅ Paste URL

✅ stdio via JSON

VS Code MCP / Continue / Zed

n/a

✅ stdio via JSON

For Claude apps the no-install path is one click from the Connectors Directory (search "estonian"). Codex takes the URL as a command, ChatGPT takes it as a custom connector once developer mode is on, and other MCP clients paste https://estonian-mcp.fly.dev/mcp in their Connectors UI. The local-install path clones the repo and points the client at python server.py.

Reducing permission prompts

Claude clients ask for confirmation before calling a tool from a custom/third-party connector, that's the client's security default, not something the server controls (there's no MCP field a server can send to suppress it). You'll especially see it right after adding or updating the connector, since the client re-checks tools it hasn't seen before.

Good news: all 28 tools are marked readOnlyHint: true (they only read text, never write or call out), so any well-behaved client can safely let you allow them once and stop asking:

  • Claude Desktop / Cowork / claude.ai, when the prompt appears, choose "Always allow" for the connector (or toggle it in the connector's settings). One time, then it's quiet.

  • Claude Code, run /permissions and allow the estonian-mcp tools, or allow the whole server at once.

Re-releasing or updating the connector can reset that "always allow" state (the client sees changed tools and re-asks), just allow it again. A verified listing in the Anthropic Connectors Directory also gets smoother permission UX than an unverified custom connector.


Self-host (advanced)

The hosted instance is convenient, but if you'd rather run your own (privacy, latency, custom auth, offline use), the same one-file server works locally and as a container.

Run locally as stdio (zero network)

Python 3.11-3.13. EstNLTK stops at 3.13, and the Pillow it pulls in needs 3.11 for its security fixes.

git clone https://github.com/silly-geese/estonian-mcp.git
cd estonian-mcp
uv sync
uv run python scripts/fetch_resources.py   # required, see below
uv run python tests/test_smoke.py          # verify

Don't skip the fetch_resources.py step. uv sync installs Python packages, but three of the things the server needs are data, not Python distributions, so they can't live in uv.lock: NLTK's punkt_tab tokenizer, Estonian WordNet (~26 MB), and the fastText embeddings (~33 MB). Without them check_compounds and check_term_consistency raise, synonyms refuses to run, and check_term_consistency reports degraded: true. The script is idempotent, so re-running it is free.

The server never downloads anything itself: not at import, not on a tool call. That's the privacy promise: no outbound HTTP from the running process. Fetching is a separate step you run knowingly, and the Docker image does the equivalent at build time.

Then wire it into your client.

Claude Code:

claude mcp add estnltk -- /absolute/path/to/uv \
  --directory /absolute/path/to/estonian-mcp \
  run python server.py

Claude Desktop / Cowork (local mode), edit ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "estnltk": {
      "command": "/absolute/path/to/uv",
      "args": [
        "--directory", "/absolute/path/to/estonian-mcp",
        "run", "python", "server.py"
      ]
    }
  }
}

Cursor, same JSON shape in ~/.cursor/mcp.json.

Run as a remote server (HTTP)

The same server.py speaks streamable-http over the network. Two auth postures:

  • Public mode (ESTNLTK_MCP_PUBLIC_MODE=1), no bearer token, per-IP rate limit (default 300/min). This is how the silly-geese hosted instance runs.

  • Bearer mode (default), every request must carry Authorization: Bearer <token> (or Smithery's ?config=<base64>); per-token rate limit. Refuses to start without ESTNLTK_MCP_AUTH_TOKEN ≥16 chars.

Fly.io public deployment (matches silly-geese):

fly auth login
fly apps create my-estonian-mcp
# one-time: persistent volume for /metrics counters (~$0.15/month)
fly volumes create estonian_mcp_data --size 1 --region ams -a my-estonian-mcp
fly deploy

fly.toml already sets ESTNLTK_MCP_PUBLIC_MODE=1 and mounts the volume at /data, so no token needed and /metrics counters survive machine restarts. Endpoint: https://my-estonian-mcp.fly.dev/mcp.

Fly.io with bearer auth, remove ESTNLTK_MCP_PUBLIC_MODE from fly.toml's [env] block, then:

fly secrets set ESTNLTK_MCP_AUTH_TOKEN="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')"
fly deploy

Generic Docker (any container host):

docker build -t estonian-mcp .   # no image is published

# Public
docker run -p 8081:8081 -e ESTNLTK_MCP_PUBLIC_MODE=1 estonian-mcp

# Bearer
docker run -p 8081:8081 \
  -e ESTNLTK_MCP_AUTH_TOKEN="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')" \
  estonian-mcp

Behind nginx, with TLS and a token per client: deploy/ is a Docker Compose stack (app + nginx + certbot) for running this on your own host. nginx terminates TLS with Let's Encrypt certificates, holds one bearer token per client with per-client rate limits and one-line revocation, meters the requests it refuses as well as the ones it serves, and answers OAuth discovery for connectors that cannot send a static Authorization header. It writes no access log unless you turn one on. See deploy/README.md.

cp .env.example .env         # set DOMAIN, LETSENCRYPT_EMAIL, INTERNAL_TOKEN
./deploy/new-token.sh my-laptop
./deploy/init-letsencrypt.sh

Smithery auto-builds from smithery.yaml and hosts the image for you. Fork, connect on Smithery, deploy. The shipped configSchema is empty (one-click install) because the deployment runs in public mode; flip it back if you fork to a bearer-mode setup.

Domain glossary (optional)

An organisation writing about its own systems has words no general corpus contains, and an agent writing for it tends to coin a compound where the organisation already has a word. Give the server that vocabulary and check_domain_terms can tell the two apart.

Variable

Contents

ESTNLTK_MCP_DOMAIN_GLOSSARY

Path to the organisation's terms: UTF-8, one lemma (base form) per line, # starts a comment. Matched case-insensitively, and offered as suggestions

ESTNLTK_MCP_DOMAIN_IDENTIFIERS

Path to names check_domain_terms never reports and never suggests: table, column or function names written as words. Same format; matched as written as well as by lemma. Only check_domain_terms reads this list

ESTNLTK_MCP_DOMAIN_SUGGEST_CUTOFF

Spelling similarity, 0.4 to 1, that a glossary term needs to be suggested. Default 0.6

The server reads the files once, at startup, so restart it after editing them. A file it cannot read, or a cutoff outside 0.4 to 1, stops it with exit status 2. With a glossary set, check_compound_familiarity marks each compound in_domain_glossary and check_term_consistency names a variant as its group's preferred form when it is the only one listed. Unset, every other tool answers exactly as before.

For stdio, add "env": {"ESTNLTK_MCP_DOMAIN_GLOSSARY": "/absolute/path/to/terms.txt"} to the server's entry in the client config, or with Claude Code:

claude mcp add estnltk -e ESTNLTK_MCP_DOMAIN_GLOSSARY=/absolute/path/to/terms.txt \
  -- /absolute/path/to/uv --directory /absolute/path/to/estonian-mcp \
  run python server.py

In a container, mount the file read-only. It must be readable by uid 1000, the user the image runs as. Bearer mode, so the glossary is not handed to anyone who finds the port:

docker build -t estonian-mcp .
docker run -p 8081:8081 \
  -e ESTNLTK_MCP_AUTH_TOKEN="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')" \
  -v "$PWD/terms.txt:/etc/estonian-mcp/glossary/terms.txt:ro" \
  -e ESTNLTK_MCP_DOMAIN_GLOSSARY=/etc/estonian-mcp/glossary/terms.txt \
  estonian-mcp

The deploy/ stack reads them from deploy/glossary/.

Anyone who can call the server can read the glossary, because the suggestions quote it, and can probe the identifier list by what it stops reporting. On a public instance, list nothing confidential. The server logs a warning at startup when the two are combined.


Security

  • stdio mode: pure local subprocess. No network egress, no shell exec, no fs writes, no telemetry.

  • HTTP / public mode: no auth required (intentional for the free public service). Per-IP rate limit (300/min default). Same hardening as bearer mode: no shell exec, no fs writes, no telemetry, size-bounded inputs.

  • HTTP / bearer mode: ESTNLTK_MCP_AUTH_TOKEN (≥16 chars) required, server refuses to start without it. Bearer auth on every request, constant-time comparison, per-token rate limit (120/min).

  • Common to all HTTP: /health is the only path without a rate limit. The landing page, favicons, server card and /metrics share a separate per-IP limit (60/min default). No request or token logging. proxy_headers is off: the server reads X-Forwarded-For itself, counting ESTNLTK_MCP_TRUSTED_PROXY_HOPS entries from the RIGHT (default 1, for Fly's single edge proxy), because the leftmost entry is caller-controlled and letting uvicorn trust it defeated the per-IP rate limit (0.5.4).

  • Inputs: 100 KB cap per text tool, 200 chars for syllabify, 1,000 terms of up to 200 chars for a per-call glossary. Oversized inputs return a structured error rather than hanging.

  • Supply chain: deps pinned + hashed in uv.lock. Dependabot watches pip + GitHub Actions weekly. CI runs smoke + HTTP tests + Docker build/boot on Python 3.11 and 3.13 on every push.

Full threat model and disclosure path: SECURITY.md. Privacy policy (what we receive, what we don't store): PRIVACY.md. Terms of service for the hosted endpoint: TERMS.md.


Notes

  • The server never downloads anything at runtime. Not on import, not on a tool call, not to fill a gap it notices. That's the privacy promise. Resources are fetched at Docker build time, or by you running scripts/fetch_resources.py on a source install. If a resource is missing, tools say so: synonyms raises an actionable error, and check_term_consistency returns degraded: true with the reason in its Estonian summary rather than a confident-looking partial answer.

  • Most EstNLTK models (morph, NER, spell-check) ship inside the wheel. Three things don't, because they're data, not Python distributions, so uv.lock can't carry them: NLTK's punkt_tab tokenizer, WordNet, and the fastText model.

  • WordNet is a separate ~26 MB resource (used by synonyms and one of check_term_consistency's two rules).

  • The fastText model used by find_related_words, check_compound_familiarity and check_domain_terms is a ~33 MB compressed resource with a 100K-word vocabulary (built locally from Facebook's cc.et.300 via compress-fasttext, CC-BY-SA-3.0; see NOTICE).

  • common_legal_usage reads a bundled index of five Riigi Teataja codes (data/legal_collocations.json.gz). To cover more acts, build one with scripts/build_legal_collocations.py (see scripts/README.md) and set ESTNLTK_MCP_LEGAL_INDEX to its path; the server reads it on the first call.

  • Results are lean, because every caller pays for them in tokens. Each answer is one compact JSON block holding only the fields that apply. No tool echoes your input or repeats a fixed note, and the rules every tool shares are said once in the server instructions. 0.8.0 cut the tool list by 42% and a typical result by about half.

  • Heavy neural taggers (estnltk_neural, BERT-based NER) are intentionally not pulled in; this server stays lean and fast.

  • First call after server start incurs a one-time tag-layer load (~1-2 s). Subsequent calls are millisecond-scale.

  • The hosted Fly instance scales to zero when idle; the first request after a quiet period takes ~5 s, then everything is fast again.

🤝 Contributing

Contributions are welcome, especially from Estonian speakers who can sharpen the linguistic rules. Here's how to get started:

  1. Fork the repo and clone your fork.

  2. Set up the environment (Python 3.11-3.13):

    uv sync
    # punkt_tab + WordNet + fastText (none can come from uv.lock):
    uv run python scripts/fetch_resources.py
    export ESTNLTK_MCP_FASTTEXT_PATH=~/.cache/estnltk-mcp/fasttext-et-medium
  3. Create a feature branch (git checkout -b feature/my-feature).

  4. Run the tests, both must pass:

    uv run python tests/test_smoke.py       # tool behaviour
    uv run python tests/test_http.py        # transport, auth, /metrics
    uv run python tests/test_resources.py   # resource-availability handling
  5. Commit and open a pull request against master. CI (smoke on Python 3.11 + 3.13, plus a Docker build/boot check) must be green before merge.

Please open an issue first for major changes so we can discuss the approach before you invest the work.

Especially wanted: linguistic corrections

The heuristic tools lean on small hand-curated lexicons in server.py, marked/archaic words, register markers, compound-split pairs, partitive-governing verbs, and the EKI orthography rule sets. These are deliberately conservative and incomplete. If you're a fluent Estonian speaker and spot a gap or a wrong entry, that's the highest-value contribution you can make:

  • A missing calque AI agents produce, with the idiomatic native form

  • A verb that governs the partitive but isn't in the list

  • A compound that should (or shouldn't) be flagged

  • A register marker that's miscategorised

Open an issue with the English source (if it's a calque), the bad Estonian, and the better Estonian, or send a PR adding the entry to the relevant lexicon with a one-line test case.

License

Apache-2.0 for the source. Bundled data + models keep their own (copyleft) licenses, these apply to those files only, not to the Apache-2.0 code:

  • EstNLTK, dual-licensed GPL-2.0 OR Apache-2.0 (we use Apache-2.0).

  • Vabamorf analyzer, LGPL-2.1 with a separate commercial-use license.

  • Estonian fastText model (find_related_words, check_compound_familiarity, check_domain_terms), CC-BY-SA-3.0.

  • Estonian Wordnet (synonyms), CC-BY-SA-4.0.

The CC-BY-SA model + Wordnet data carry share-alike obligations on those files when you redistribute them (the Docker image includes both). See NOTICE for full attribution and redistribution terms.

Available Tools

28 tools
analyze_morphologyB
Read-onlyIdempotent

Morphological analysis of each word (punctuation omitted): word, lemma, partofspeech (pos_tag's tags), form (Vabamorf code, "" if uninflected), root (_ joins compound parts), ending ("0" = none).

Present only when they apply: form_estonian (the form's Estonian name), clitic, root_tokens (compound parts), analyses_count (>1: still ambiguous in context), usage_note (archaic, foreign, abbreviation, interjection, proper-noun) and the more precise usage_note_estonian (often names the neutral word), indeclinable: true (keeps its base form before a noun: täis, tuntud, täitmata; check it before declining a noun phrase).

NameRequiredDescriptionDefault
textYesEstonian text.
all_analysesNoReturn every reading left after in-context disambiguation, in an `analyses` list, instead of only the most likely one.

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent/closed-world, and the description adds real semantic context: what 'form' codes mean ("" if uninflected, "0" = none), that `_` joins compound parts, that `analyses_count` >1 signals residual ambiguity, and practical guidance that `indeclinable` should be checked before declining a noun phrase. This is genuine behavioral value rather than a restatement of annotations.

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

Conciseness3/5

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

Front-loaded with the purpose sentence, which is good, but the bulk is a dense catalogue of output fields that largely duplicates the existing output schema. Every sentence is informative in isolation, yet the overall proportion of redundant return-value detail is high.

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

Completeness3/5

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

An agent can tell what the tool returns in detail, but with an output schema already present that detail is partly wasted, and nothing addresses input behavior, output size, or how this differs from the many sibling analysis tools. Adequate but with clear gaps for a tool in a 27-sibling family.

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% and both parameters (text, all_analyses) are documented in the schema. The description mentions ambiguity and analyses_count but never explains the `text` input or the `all_analyses` toggle, so it adds nothing beyond the schema baseline.

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+resource ('morphological analysis of each word') and enumerates the per-word fields produced, so an agent knows this is a full morphological parse rather than a tokenizer or tagger. It does not name or distinguish itself from close siblings like pos_tag, lemmatize, or paradigm, leaving the superset relationship to inference.

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

Usage Guidelines2/5

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

There is no explicit statement of when to call this instead of pos_tag, lemmatize, or paradigm, and no prerequisites or exclusions. The only implicit cue is that the field list overlaps those narrower tools, which the agent must infer on its own.

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

check_abbreviation_hyphenationA
Read-onlyIdempotent

Flags an ending that starts with l written straight onto an all-capital abbreviation: OÜle → OÜ-le, ÜROlt → ÜRO-lt, THIl → THI-l. EKI finds the hyphen clearer there. Every other hyphenless form (ELi, ELis, APIga, MCPst, ASile) is as correct as the hyphenated one and is not flagged: keep the text's own choice.

A stem read with a final consonant also needs the stem vowel i (ASle → AS-ile, ELlt → EL-ilt); a Roman ordinal up to XXXIX before a noun or adjective in the same case drops the ending (XIIl sajandil → XII).

Any all-capital stem counts, known or not; mixed-case ones (SaaS, PhD, iOS) and chloride formulas (HCl, NH4Cl) are not checked.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and a closed world, and an output schema exists, so the safety and return-surface burden is largely pre-carried. The description adds genuine behavioral context by enumerating the non-flagging cases and the extra stem-vowel and Roman-ordinal rules, which no structured field conveys.

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

Conciseness4/5

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

Three sentences, front-loaded with the flagging rule and its examples, then exceptions, then scope boundaries — each block earns its place. It is dense with examples and secondary rules but no sentence is filler.

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 checker with an output schema and full annotation coverage, the description supplies the rule semantics an agent needs to interpret and trust the results. The only gap is that it never clarifies its division of labour with the sibling check_hyphenation, which matters given both exist.

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?

There is a single parameter, 'text', with 100% schema description coverage, so the schema already tells the agent what to pass. The description adds no constraint on language, length, or expected input form beyond noting the examples are Estonian, leaving this at the baseline.

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 states a specific rule-based check with three worked examples (OÜle → OÜ-le, ÜROlt → ÜRO-lt, THIl → THI-l), so an agent knows exactly what pattern is being flagged. It does not, however, distinguish itself from the sibling check_hyphenation, which an agent could reasonably assume covers the same ground.

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 gives strong positive and negative scoping: hyphenless forms like ELi, APIga, MCPst are explicitly declared correct and not flagged, and mixed-case stems and chloride formulas are excluded. What it lacks is any routing guidance against the alternative hyphenation/compounds checks that sit among the siblings.

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

check_capitalizationA
Read-onlyIdempotent

Flags words wrongly capitalized mid-sentence (algustäheortograafia):

  • weekday, month, nationality: lowercase except at sentence start (esmaspäeval, jaanuaris, eestlane).

  • language-adjective: a country name before a language or culture noun is lowercase (eesti keel, vene kultuur). On its own it is the country (Eesti, Eestis) and is not flagged.

Sentence-initial words and all-caps acronyms are skipped. A hit that opens a line, list item or quotation, or sits in a proper name (Eesti Keele Instituut), is usually false. English title case in headings is check_translationese's title-case.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already cover safety (readOnlyHint=true, idempotentHint=true, openWorldHint=false), so the bar is lower, yet the description adds real behavioral detail the annotations can't: which categories are suppressed (sentence-initial, all-caps acronyms) and which hits are likely false positives (line/list/quotation openers, proper names like Eesti Keele Instituut). That false-positive guidance is exactly what prevents an agent from over-reporting.

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?

Front-loaded with the core action, then bulleted category rules with parenthetical examples, then a compact caveat block. Every sentence carries information (category definition, exception, or false-positive warning); no filler or restatement of the name.

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?

An output schema exists, so return-value explanation is unnecessary; the description instead supplies the decision logic an agent needs — what counts as a hit, what is skipped, and when a hit should be ignored. Combined with the readOnly/idempotent annotations, nothing material is missing for correct invocation and interpretation.

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?

One parameter with 100% schema description coverage ('Estonian text.'), so the schema carries the parameter burden and baseline 3 applies. The description adds only implicit confirmation that input is Estonian prose subject to capitalization rules; it says nothing about handling markdown, HTML, mixed-language spans, or multi-paragraph input.

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?

States a specific verb and resource ('Flags words wrongly capitalized mid-sentence') plus the Estonian orthography term, and immediately enumerates the exact categories it covers (weekday, month, nationality, language-adjective). It also explicitly excludes the sibling's territory ('English title case in headings is check_translationese's `title-case`'), so an agent can distinguish it from the 28 siblings without opening schemas.

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?

Gives clear inclusion rules with examples (esmaspäeval, jaanuaris, eestlane) and explicit exclusions: sentence-initial words and all-caps acronyms are skipped, and line/list/quotation openers or proper names are 'usually false'. It routes one adjacent case to check_translationese. It doesn't state input-language prerequisites beyond the schema's 'Estonian text', but the when-to-use boundary is essentially complete.

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

check_compound_familiarityA
Read-onlyIdempotent

Attestation check for Estonian compound nouns; use it on compounds you coined.

A compound is attested when its lemma is in the fastText 100K-word corpus vocabulary (in_vocab), Estonian WordNet (in_wordnet) or the legal terms list (neighbour_quality.legal_term). Read attested first: false is normal for correct specialist words, not evidence of invention, and never on its own a reason to rewrite.

is_suspect is narrow: unattested, and the nearest neighbour is a real word scoring under 0.55 (mõtteliin). Judge a flag from neighbours (unattested entries only): coherent related words mean the word is real. neighbour_quality.signal: "none": the nearest neighbour is scrape junk, so there is no verdict. Recall is low on purpose: some coinages pass, and so does any stilted compound (check register with check_officialese).

in_domain_glossary: true (only with a server glossary): the organisation's own word, so treat it as real. For your own glossary use check_domain_terms. Proper nouns are skipped.

NameRequiredDescriptionDefault
textYesEstonian text to check.

Output Schema

NameRequiredDescription
noteNo
all_compoundsNo
wordnet_checkedNo
summary_estonianNo
suspect_compoundsNo
compounds_analysedNo
unattested_compoundsNo

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, it discloses the three attestation sources, the deliberate low recall, the narrow definition of `is_suspect` with the 0.55 threshold, the `signal: "none"` junk-neighbour case, and the crucial false-positive caveat that unattested is normal for specialist words. This is exactly the context annotations cannot carry.

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

Conciseness4/5

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

Front-loads the purpose, then the core result interpretation, then edge cases — good ordering with no filler prose. It is dense and somewhat long for one parameter, but nearly every sentence carries decision-relevant information (thresholds, field names, fallbacks).

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 an output schema present, the description needn't enumerate return values, yet it explains the key result fields (`attested`, `is_suspect`, `neighbours`, `neighbour_quality.signal`, `in_domain_glossary`) and their interpretation. Nothing an agent needs in order to call and interpret this correctly is missing.

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?

Single parameter with 100% schema description coverage, so the schema already documents `text`. The description adds no syntax, format or length guidance for the input, so it neither helps nor hurts — baseline 3.

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?

Opens with a specific verb+resource: an attestation check for Estonian compound nouns, and immediately narrows scope ('use it on compounds you coined'), which separates it from sibling check_compounds and check_domain_terms. An agent can distinguish it from every listed sibling without opening a schema.

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

Usage Guidelines5/5

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

Explicitly states when to use it (coined compounds), how to read the result ('Read `attested` first', 'Judge a flag from `neighbours`'), and names alternatives with their conditions (check_domain_terms for your own glossary, check_officialese for register). Also states exclusions: proper nouns are skipped.

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

check_compoundsA
Read-onlyIdempotent

Flags compounds wrongly written as two words (liitsõnaõigekiri): kooli maja → koolimaja.

Matches a curated list of about 30 common splits, so a hit is reliable but most compounds are not covered.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already establish readOnly, idempotent, and closed-world behavior, so the bar is lower. The description still adds genuinely useful behavioral context the annotations cannot convey: an approximate 30-item curated list, high precision on hits, and likely false negatives otherwise.

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, zero filler: the purpose and example come first, and the coverage caveat follows where it is needed. Every sentence earns its place.

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?

For a one-parameter, read-only checker with an output schema and rich annotations, the description covers what the tool does, what it returns conceptually, and its main limitation. Nothing an agent needs to call it correctly or interpret a null result is missing.

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

Parameters5/5

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

Schema coverage is 100% for the single required parameter and it is already documented as 'Estonian text.' A bonus is that the description's worked example clarifies the expected unit of input (word/compound pair in context) rather than just a language tag, reinforcing the schema without contradicting it.

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 states a specific verb and resource ('Flags compounds wrongly written as two words'), gives the Estonian term, and shows a concrete input→output example (`kooli maja` → `koolimaja`). It does not explicitly contrast itself with the nearby `check_compound_familiarity` sibling, so it stops just short of full sibling differentiation.

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 second sentence sets expectations for when results are trustworthy: a hit is reliable, but 'most compounds are not covered', which tells the agent how to interpret and when not to rely on a clean pass. There is no explicit routing to an alternative tool for broader coverage, so it is clear context rather than full when/when-not guidance.

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

check_defined_termsA
Read-onlyIdempotent

Maps defined terms and cross-references in a long Estonian legal document.

defined_terms: each (edaspidi «X») term. total_occurrences counts exact-form, case-sensitive matches, the definition included, so it misses inflected uses: verify a defined-but-unused issue before acting. cross_references: §, lõige, punkt and artikkel mentions, not validated. issues: terms defined twice or unused.

NameRequiredDescriptionDefault
textYesWhole Estonian legal document.

Output Schema

NameRequiredDescription
issuesNo
defined_termsNo
cross_referencesNo
summary_estonianNo

TDQS

A4.2/5.0
Behavior5/5

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

Goes well beyond the readOnly/idempotent annotations: it warns that total_occurrences is exact-form and case-sensitive, includes the definition itself, and therefore misses inflected uses, and that cross-references are unvalidated. These are exactly the false-positive traps an agent needs to know before reporting results.

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?

One front-loaded sentence states the purpose, then each output field gets a tight clause explaining its semantics and caveat. No filler, and the caveats sit next to the fields they qualify.

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?

For a one-input read-only analyzer with an output schema, the definition covers input expectations, each returned field, the counting semantics, and the reliability limit on issues and cross-references. Nothing an agent needs to call or interpret it 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?

Single required parameter with 100% schema description coverage, so the baseline is 4. The description adds the meaningful constraint that the text must be a whole Estonian legal document, which the schema's one-line description also conveys.

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 and resource: mapping defined terms and cross-references in a long Estonian legal document, plus an issues check. That is concrete and distinguishable from morphological siblings like lemmatize or pos_tag, though it never contrasts with check_term_consistency, the closest neighbor.

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

Usage Guidelines3/5

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

Usage is implied by the domain (Estonian legal documents) and by the caution to 'verify a defined-but-unused issue before acting'. There is no explicit statement of when to pick this over check_term_consistency or check_domain_terms, leaving the agent to infer the boundary from names alone.

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

check_domain_termsA
Read-onlyIdempotent

Reports compounds no lexicon or domain glossary vouches for, in Estonian you wrote about an organisation's own systems.

A compound is reported when it is unattested (see check_compound_familiarity) and absent from the server's glossary and identifier list and your glossary. A reported compound is not necessarily coined: it is only not the organisation's word, and may be ordinary Estonian (vagunisõit is). Where it names something the organisation has a term or identifier for, use theirs; otherwise leave it.

suggestions are glossary terms SPELLED alike, not synonyms: use one only if it names the same thing. contains_glossary_term is the term the compound is built on (vagunireisitabel on vagunireis): ordinary Estonian, not to be shortened to the term; ask only whether the thing it names has its own term.

The hosted server has no glossary: pass yours in glossary. Without one this is the unattested list, never on its own a reason to rewrite. Proper nouns are skipped.

NameRequiredDescriptionDefault
textYesEstonian text to check.
glossaryNoDomain lemmas (base forms), added to the server's glossary for this call only. Not stored.
suggest_cutoffNoMinimum spelling similarity for a glossary term to be suggested. Default: the server's setting, else 0.6.

Output Schema

NameRequiredDescription
noteNo
glossary_sizeNo
suggest_cutoffNo
wordnet_checkedNo
identifiers_sizeNo
summary_estonianNo
compounds_analysedNo
suggestions_cappedNo
unlisted_compoundsNo

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/closed-world, so safety is covered; the description goes well beyond them. It discloses the crucial caveat that a reported compound is not necessarily coined and may be ordinary Estonian (with a concrete example), that suggestions are spelling-similar rather than synonymous, what contains_glossary_term means, that proper nouns are skipped, and that the hosted server holds no glossary.

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

Conciseness4/5

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

Purpose is front-loaded and nearly every sentence adds distinct information: definitions, caveats, the suggestions warning, the glossary requirement, and the proper-noun exception. It is dense and the opening sentence's clause order makes it harder to parse than necessary, but there is no filler to cut.

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 an output schema present, return values need no explanation, and the description still covers the interpretive burden: what a hit means, what it does not mean, how to act on it, and the configuration dependency on a supplied glossary. Nothing an agent needs in order to call this correctly and interpret results 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, but the description adds operational meaning the schema does not: the server has no glossary, so the caller must supply one via `glossary`, and absent it the result degrades to a pure unattested list. It also clarifies how `suggestions` (driven by suggest_cutoff) should be read — spelled alike, not synonymous — which changes how the agent interprets that parameter's effect.

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 first sentence names a specific verb and resource: it reports Estonian compounds that no lexicon or domain glossary vouches for, in text about an organisation's own systems. It also points at the related sibling check_compound_familiarity, so the agent can separate attestation checking from glossary comparison. The phrasing is convoluted ('compounds no lexicon or domain glossary vouches for, in Estonian you wrote about...'), which slows first-pass comprehension, but the substance is specific rather than tautological.

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

Usage Guidelines5/5

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

It states when to act and when not to: where the compound names something the organisation has a term or identifier for, use theirs; otherwise leave it. It also explicitly warns that without a glossary this is only the unattested list and 'never on its own a reason to rewrite', which is a clear negative condition. Alternatives are named (check_compound_familiarity) and the glossary-passing requirement is spelled out.

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

check_hyphenationA
Read-onlyIdempotent

Line-break positions in one Estonian word (poolitamine); use only when line breaks matter. breaks: character offsets at syllable boundaries, at least 2 characters from either end; preferred: the word with each break marked ·. Compound seams, which Estonian prefers, are among the breaks but not singled out: choose the seam yourself (kooli·maja). A break can also split one vowel off a compound part (maao-manik in maa·o·ma·nik); skip those.

NameRequiredDescriptionDefault
wordYesOne Estonian word, no whitespace.

Output Schema

NameRequiredDescription
breaksNo
preferredNo
syllable_countNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already cover safety (readOnly, idempotent, closed-world), and the description goes further by disclosing the shape and constraints of the result: offsets kept at least 2 characters from either end, compound seams present but not flagged, and a caution about breaks that split a vowel residue. The maao-manik example is garbled enough that the exclusion rule is harder to apply than intended, keeping this from a 5.

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

Conciseness4/5

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

The scope statement and both return fields are front-loaded, and every sentence carries information. The nested parenthetical examples make the middle dense, but nothing is plainly padding.

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 safety and an output schema covering return shape, the description still supplies the interpretive guidance an agent needs to decide which breaks matter and to not expect a flagged compound seam. Nothing essential is missing.

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?

There is a single parameter with 100% schema coverage ('One Estonian word, no whitespace'), so the schema already carries the semantics. The description adds nothing new about the parameter itself, so the baseline 3 applies.

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?

States a specific verb+resource ('line-break positions in one Estonian word') and names the native term poolitamine, which makes it unambiguous against siblings like syllabify or check_abbreviation_hyphenation. An agent can tell what this returns without opening the schema.

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?

Explicitly scopes usage ('use only when line breaks matter'), which effectively excludes general-purpose calls. It does not name a sibling alternative (e.g., syllabify) the way a 5 would, so the routing is clear but not fully disambiguated.

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

check_legaleseA
Read-onlyIdempotent

Plain-language aid for Estonian statutes and contracts; rewrites must keep the legal meaning.

issues: archaic filler and stock phrases with a plainer suggestion, and over-long or comma-heavy sentences to split. terms_of_art: legal terms (first use per lemma) to keep verbatim, never swapped for a general synonym. Starter lexicons: an empty or short issues list does not mean the text is plain, and an unlisted word can still be a term of art. For reports and business prose use check_officialese.

NameRequiredDescriptionDefault
textYesEstonian statute or contract text.

Output Schema

NameRequiredDescription
issuesNo
terms_of_artNo
summary_estonianNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already carry readOnly/idempotent/closed-world, and the description adds genuinely useful recall caveats beyond them: the lexicons are starters, an empty or short issues list does not mean the text is plain, and an unlisted word can still be a term of art. That false-negative warning is exactly the kind of behavioral context an agent needs before trusting a clean result. The one ambiguity is whether the tool returns rewrites or merely flags them — "rewrites must keep the legal meaning" could be read either way.

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

Conciseness4/5

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

Very dense and front-loaded: domain, output categories, caveats, then the sibling pointer, in four compact clauses. The telegraphic "issues:" / "terms_of_art:" fragment style is efficient but slightly harder to parse than full sentences.

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?

With an output schema present, the description needn't document return values, and it still summarizes both result lists plus their reliability limits. Combined with 100% parameter coverage and full annotations, an agent has nearly everything needed; only the flag-vs-rewrite question remains open.

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?

Single parameter with 100% schema description coverage that already says "Estonian statute or contract text." The description restates the same domain constraint but adds no syntax, length, or formatting detail beyond the schema, so the baseline 3 applies.

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?

States the specific resource (Estonian statutes and contracts), the function (plain-language aid / legalese detection), and enumerates the two result categories: issues (archaic filler, stock phrases, over-long or comma-heavy sentences) and terms_of_art to keep verbatim. It also names the sibling it is not (check_officialese), so an agent can route without opening either schema.

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?

"For reports and business prose use check_officialese" gives an explicit alternative with the selecting condition, and "rewrites must keep the legal meaning" frames the constraint under which results should be applied. It stops short of stating exclusions such as non-Estonian input, but the domain scoping largely covers that.

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

check_numbersA
Read-onlyIdempotent

Flags number-writing slips (numbrite õigekirjutus):

  • decimal-separator: 3.14 → 3,14; skips kell 10.30, 14.05, punkt 3.2, Python 3.12, but flags a bare 10.30.

  • thousands-separator: 1,250 → 1250, 1,500,000 → 1 500 000 (EKI groups from five digits; ideally non-breaking spaces, suggestion has plain ones). If 1,250 was meant as the decimal 1,25, keep it.

  • approximate-tilde: 50 → u 50 (Umbes 50 at a sentence start; umbes and ligikaudu also fit). A style hint for general prose: EKI keeps the tilde for variants (mina ~ ma), so a spaced tilde after a word, ≈, code (inline, fenced or indented), paths, versions and ranges (510) are not flagged.

  • month-year-digits: 09.2016 → sept 2016, a date rather than a decimal; EKI finds the month in words clearer. A one-digit month (1.2019) is left alone, as it may be a rate, and 10 to 12 after a rate word or currency pair in the clause (kurss 11.2050, EUR/SEK, keskmine, koefitsient) is a decimal. Inflect a full month name to fit the sentence (alates märtsist 2019); abbreviations need no ending.

  • range-spacing: 2020 - 2024 → 2020-2024, 5 - 10 päeva → 5-10. Only a spaced keyboard hyphen between plain numbers; typeset EKI text uses the mõttekriips, also unspaced. Skips sums and expressions after =, scores, code, phone numbers, a label and its value (ülesanne 1 - 10 punkti), ends containing a space (9000 - 10 000), ordinal and season ranges (2015.-2019. aastal, 2019/2020), and month.year ends.

  • percent-sign-suffix: 20%-line → 20% or 20-protsendiline; case endings (10%-st, 5%-ni) are fine.

Spelling out small numbers is not checked.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already establish readOnly/idempotent/closed-world, and the description goes well beyond them: per-rule false-positive exclusions, the note that typeset mõttekriips is out of scope, and the disclosure that `suggestion` returns plain spaces where non-breaking spaces are ideal. That last point is genuinely useful output nuance; only the overall response shape is left to the output schema.

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

Conciseness4/5

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

Front-loaded with a one-line purpose, then a scannable bullet per rule with arrow examples — dense but each line carries rule, conversion, and exceptions. The bullets are long and exception-heavy (the range-spacing bullet alone carries five skip categories), which is justified for a linter but borders on spec-dumping.

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?

For a single-parameter read-only linter with an output schema, the description supplies everything an agent needs: what counts as a violation per category, what is deliberately not flagged, and that suggestions may be imperfect on whitespace. Nothing material is missing.

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?

One required parameter with 100% schema coverage ('Estonian text'). The description reinforces the input domain through its Estonian-language examples but adds no syntax, length, or formatting constraints for `text`, so the schema carries the semantics here.

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?

States a specific verb and resource: flags number-writing slips (numbrite õigekirjutus) in Estonian text, then enumerates the six exact rule categories with before/after examples. This is clearly distinguishable from sibling linters like check_punctuation or check_hyphenation, which cover other orthographic domains.

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?

Each bullet defines the triggering condition plus explicit skips (code, paths, versions, scores, phone numbers, sums after =), and the closing line 'Spelling out small numbers is not checked' marks a real boundary. It never names an alternative sibling tool or says when to prefer this over, say, spell_check, so it stops short of full routing guidance.

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

check_object_caseA
Read-onlyIdempotent

Flags a direct object in the wrong case (käändeõpetus): a common noun in nominative or genitive (form) after

  • negation-requires-partitive: negation (ei söönud leib → leiba), or

  • partitive-only-verb: verb, one of nine verbs such as armastama, vajama and ootama that always take a partitive object.

The negation rule skips any sentence containing olema (pole, ei ole, pole näinud). The fix is the partitive of lemma in the number form shows; take it from paradigm. With no parser, a hit may be a subject or an adverbial, so treat it as worth a second look.

Two more rules check the government of teavitama (keda + millest) and teatama (kellele + millest), and add a suggestion:

  • teavitama-allative-recipient: teavitama or informeerima, or their noun teavitamine or informeerimine (verb), with the person or body in the allative (teavitas politseile; word is the allative phrase).

  • teatama-partitive-person: teatama with a partitive personal pronoun (Teatame Teid, et ...).

The fix is either teavitama + partitive (teavitas politseid) or teatama + allative (teatas politseile); for the noun, Rahapesu Andmebüroo teavitamine or teatamine Rahapesu Andmebüroole. Recall is low by design: a clause that already has a partitive object (teavitab õpilastele hindeid), an allative before the verb, an allative that a participle, adjective or action noun governs (teavitada isikut talle seatud piirangust), one whose head noun is not a person or body (kolimisest teisele korrusele), the experiencer of an adverb or a translative (meile teadaolevalt, kõigile üllatuseks) and an allative after a heading line are not flagged, and neither is a partitive pronoun that a following participle governs (Teatame Teid puudutavatest muudatustest: grammatical, but Teatame Teile ... reads better).

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A3.9/5.0
Behavior5/5

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

The description goes well beyond the annotations by disclosing the exact rules, known exclusions, low recall by design, and the important caveat that a hit may be a subject or adverbial without a parser, so it should be treated as worth a second look. These are substantive behavioral details that annotations (readOnlyHint, idempotentHint, openWorldHint) do not cover.

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

Conciseness3/5

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

The purpose is front-loaded, and the rule structure is clear, but the description is very long and dense for a single-parameter checker. Many examples and exclusions earn their place for behavioral transparency, yet the text could be tightened and made easier to scan.

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?

Given the complexity of the grammar rules and the presence of an output schema, the description is complete enough for an agent to invoke and interpret the tool correctly. It covers the core rules, exceptions, false-positive behavior, and recall limitations without needing to explain return values.

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%, and the single `text` parameter is already documented as 'Estonian text.' The description does not add further parameter-level semantics such as input length limits, language constraints, or formatting expectations beyond what the schema provides.

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 clearly states a specific verb and resource: it flags a direct object in the wrong case and names the exact rule families (negation-requires-partitive, partitive-only-verb, teavitama-allative-recipient, teatama-partitive-person). It is highly specific, but it does not explicitly differentiate itself from sibling tools such as check_style, analyze_morphology, or paradigm.

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

Usage Guidelines3/5

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

Usage is implied by the rule descriptions and by the note that recall is low by design, but the description never explicitly says when to use this tool versus alternatives or when not to call it. An agent must infer that it is for Estonian object-case proofreading from the purpose statement alone.

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

check_officialeseA
Read-onlyIdempotent

Flag Estonian kantseliit in reports, academic and business prose; statutes and contracts go to check_legalese, which protects terms of art.

Issue rules: impersonal-voice (ratio 0.4+, 4+ verbs), nominalisation (4+ -mine nouns per 100 words, positioned at the first), noun-density (noun/verb 2.5+, weakest: weigh it last), clause-stacking (3+ subordinate-clause openers in a sentence), long-sentence (25+ words), officialese-filler, officialese-phrase, poolt-calque, kusin-tapsemalt, calque-phrase. impersonal-voice and noun-density are document-wide (position 0). 'läbi viima' in the conduct sense is an officialese-phrase in any form (viidi läbi, on läbi viinud, viis uuringu läbi), and läbiviimine, läbiviija, läbiviidud, läbiviidav, läbi viimine an officialese-filler, suggesting korraldama / tegema (pidama for a meeting) in the same form, with the words between kept (viis uuringu läbi → korraldas uuringu); routes and threaded objects (Rada viib läbi metsa, Kaabel tuleb läbi viia seinast, kaabli läbiviimine), time spans (päev läbi), postpositions, the numeral viis and the fugue term are skipped, and the 'läbi suruma' sense is not told apart. A thing carried through with no route word (Kohver viidi läbi) is still flagged. kusin-tapsemalt is a sentence-initial 'Küsin/Küsime täpsemalt, kas …' in a letter; a plan to ask someone else matches too unless a reporting-back verb follows (…, ja annan teada; …, ja võtan teiega ühendust), and quoted speech, a dialogue-dash line and a quoted e-mail line ('>') are skipped. Both are style hints, not errors. calque-phrase is a translated stock phrase of letters: sealhulgas, kuid mitte ainult (and eelkõige, kuid mitte ainult, where only the tail goes); antud juhul / hetkel / olukorras, not the participle (on antud olukorras, kus ...); adresseerima a problem, not a mail item; ärge kõhelge ... võtmast, rewritten with its own verb; kiri leiab teid hästi; tänan teid teie ... eest; vaatan edasi koostööle, with an awaited event (not vaatas edasi merele); Palun leidke manuses, not a search instruction (Palun leidke manusest oma nimi). Leiate manusest and läbi e-posti are accepted Estonian and not flagged. metrics.nominalisations gives each -mine noun's verb, a particle verb written apart (läbivaatamine → läbi vaatama, tagaajamine → taga ajama), a noun + verb compound by its head (riskihindamine → hindama, sisuloomine → looma), and no verb when none is known. The split 'läbi viimine' counts as läbiviimine. Nouns lexicalised as things (teadmised, pakkumine, kohtumine, ettevõtmine and their compounds) and -misi adverbs (vaikimisi) are not counted.

Precision-first starter lexicons: no issues is not proof the text is plain.

NameRequiredDescriptionDefault
textYesEstonian non-legal prose (report, academic, business).

Output Schema

NameRequiredDescription
issuesNo
metricsNo
summary_estonianNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/openWorld, so the description is free to disclose genuine behavior — and it does: per-rule thresholds, which rules are document-wide (position 0), which senses are skipped, and precise false-positive carve-outs. The one gap is that the `metrics.nominalisations` explanation is a return-value detail rather than invocation behavior, and the description never states the output shape at a high level (though an output schema exists).

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

Conciseness3/5

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

Purpose and rule inventory are front-loaded and machine-scannable via backticked rule names, but the second half collapses into a dense run-on paragraph of micro edge cases (the numeral viis, the fugue term, "Kohver viidi läbi", quote-line skipping). These are real precision aids but are unstructured and would read far better as bullets; the agent must parse a wall of prose to extract the exclusion rules.

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?

Since an output schema exists, return values needn't be explained — yet the description still clarifies the one ambiguous field (`metrics.nominalisations`, its verb resolution, split-particle handling, and lexicalised exclusions). For a rule-engine style checker with 10+ rules and many carve-outs, this is materially complete.

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?

Single parameter with 100% schema coverage, so the baseline is 4. The description reinforces the expected input domain (Estonian non-legal prose; kantseliit-bearing reports/academic/business text) which adds a small amount of guidance beyond the schema's own "Estonian non-legal prose (report, academic, business)."

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?

Opens with a specific verb+resource+scope: "Flag Estonian kantseliit in reports, academic and business prose" and immediately names the boundary case ("statutes and contracts go to check_legalese"). An agent can distinguish this from check_legalese, check_style, and classify_register without opening a schema.

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

Usage Guidelines5/5

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

Explicitly routes the alternative: legal texts go to check_legalese; this tool is for non-legal prose. It also states the tool's epistemic posture ("Both are style hints, not errors" and "no issues is not proof the text is plain"), which tells the agent how to interpret results rather than just when to call.

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

check_punctuationA
Read-onlyIdempotent

Flags a missing comma:

  • comma-before-clause-conjunction: before et, kuna, sest, kuigi, kuid, vaid, nagu, mistõttu, millepärast or kuhu. A comma before a pair (nii et, ilma et) passes, as does et after ja, ning, ega or ehk; nagu is flagged only before a clause with a verb.

  • comma-after-subordinate-clause: closing a clause opened after a comma by a relative word (kes, mis, kus) or a subordinator (et, kui, kas), before the main clause's verb: Mees, kes seal seisis oli minu isa → , oli; before its subject instead when that stands right before the verb and cannot be the clause's own (Hommikul, kui ärkasin päike juba paistis → , päike). Otherwise that is where the comma goes at the latest; it may belong earlier, before a longer fronted subject or inside a split phrase.

  • comma-before-ja-after-subordinate-clause: before ja or ning when the main clause goes on after a kes or mis clause, told by the verbs' person: Juhtisin projekti, mis kestis kaks aastat ja koolitasin → , ja.

The last two read only words that cannot be anything but a verb, so a verb that is also a noun (tuli, sai, lõppes) is missed; ei in ei ... ega and in ei tea kus, a -vad participle after olema (kes olid sobivad) and on in an English name (video on demand) are not counted. A line break, a table cell edge (| or a tab), an HTML tag, an arrow or a quotation mark ends the clause. Not checked: the comma before kui, mis or kes (it depends on meaning), apposition commas, dashes, colons. A comma before ja in a list and a letter's greeting and closing commas are check_translationese's.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4.2/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, closed-world), and the description goes well beyond them by disclosing concrete false negatives (verb/noun homographs like tuli, sai, lõppes; ei in ei ... ega; -vad participles after olema; "on" inside English names) and the token boundaries that terminate a clause (line break, table cell edge, HTML tag, arrow, quotation mark). That is exactly the accuracy context an agent needs before trusting the output.

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

Conciseness3/5

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

The lead is front-loaded and each bullet is information-bearing, but the second bullet sprawls into a long, hard-to-parse sentence ("Otherwise that is where the comma goes at the latest; it may belong earlier, before a longer fronted subject or inside a split phrase"). Much of the rule-level detail is more useful for interpreting results than for deciding to call the tool, which is heavy for a one-parameter checker.

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?

With an output schema present, return values need no explanation, and the description fully covers scope, exclusions and known blind spots. The only residual gap is that it never states in its own text that the input must be Estonian or whether all issues in a passage are reported at once.

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?

There is a single parameter with 100% schema description coverage ("Estonian text."), so the schema carries the load and the baseline is 3. The description adds only indirect input hints — that line breaks, tabs and HTML tags act as clause boundaries — but never states the language requirement or input expectations itself.

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 opens with a specific verb and outcome ("Flags a missing comma") and enumerates the three exact rule IDs it emits, so an agent knows precisely what class of problem is detected. It also names the sibling that owns the excluded cases ("check_translationese's"), making it distinguishable from check_style, check_capitalization and the rest.

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?

Scope boundaries are unusually explicit: the "Not checked" sentence lists kui/mis/kes commas, apposition commas, dashes and colons, and the final sentence routes list/greeting commas to check_translationese. There is no explicit "use this when" framing or statement that it should be combined with the other checks, so it stops short of a 5.

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

check_redundancyA
Read-onlyIdempotent

Flags redundant doubling (liiasus, pleonasm):

  • doubled-also: two "also" particles together (samuti ka, ka samuti, ühtlasi ka); keep one.

  • double-superlative: kõige before an absolute adjective (kõige optimaalsem, "most optimal"); drop kõige.

  • fixed-pleonasm: a short curated list (ajaline periood, väike nüanss, üldine konsensus).

Each issue's explanation gives the reason in Estonian. Conservative: it misses much redundancy a native speaker would hear.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent and closed-world behavior, and the description adds real value beyond them: the exact detection taxonomy, the fact that each issue's `explanation` is in Estonian, and an honest recall limitation ('misses much redundancy a native speaker would hear'). It does not state severity levels or whether output is per-occurrence, but the conservativeness disclosure is substantive.

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?

Front-loaded purpose statement followed by a tight bulleted taxonomy where each bullet earns its place by pairing a category code with concrete examples. The final sentence on conservativeness is short and load-bearing, with no filler.

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 structure need not be explained, and the description covers categories, explanation language, and known recall gaps. Minor gaps remain: nothing on input size limits or what happens with non-Estonian text. For a single-parameter checker this is close to complete.

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?

One parameter with 100% schema description coverage, so the schema already documents `text` as Estonian text. The description adds nothing about the parameter itself (no length limits, no handling of mixed-language input). Baseline 3 applies when the schema does the heavy lifting.

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?

Names a specific verb (flags) and a precise linguistic resource (redundant doubling / liiasus / pleonasm), then enumerates the exact three categories it detects with Estonian examples. Among the many check_* siblings this is unmistakably the redundancy checker, distinguishable without opening the schema.

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

Usage Guidelines3/5

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

Usage is implied: pass Estonian text and it reports doubling/pleonasm issues. There is no explicit when-to-use versus check_style, check_officialese, or check_compounds, nor any when-not guidance. The closing note about being conservative hints at when to distrust results, which is useful but not full routing guidance.

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

check_styleA
Read-onlyIdempotent

Heuristic Estonian style metrics; no cliche detection.

  • repetition: content lemmas used threshold+ times (scales with length), with character offsets.

  • passive_voice: umbisikuline tegumood share of verbs (attributive -tud participles go to attributive_excluded). Marketing copy: aim under 15%; under 5% may read forceful. Reports: over 40% is the clearest kantseliit sign (see check_officialese).

  • sentence_length: words per sentence; a stddev under 30% of the mean reads monotonous. News and web text: at most 10 to 15 words a sentence (the state's web-writing guide). Measured averages: e-mail about 9, news about 14, statutes about 25.

  • hedging: share of words on a short fixed list (vist, pigem, ehk); over 5% reads wishy-washy, 0% does not rule hedging out.

NameRequiredDescriptionDefault
textYesEstonian text to measure.

Output Schema

NameRequiredDescription
hedgingNo
repetitionNo
passive_voiceNo
sentence_lengthNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/closedWorld, so the description earns credit for what it adds: repetition counts scale with text length and return character offsets; attributive -tud participles are excluded from passive_voice into a named `attributive_excluded` bucket; hedging is a short fixed list (vist, pigem, ehk). This tells the agent exactly how numbers are computed, including the exclusion rule that would otherwise cause confusion. It stops short of describing anything else about the returned result shape.

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

Conciseness4/5

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

Front-loaded one-line summary, then one bullet per metric with thresholds and measured baselines — no filler, and the offsets/exclusion caveats sit next to the metric they qualify. Slightly long for a one-parameter tool, but every bullet carries actionable interpretation.

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 an output schema present, the description need only convey what each metric means and how to read its value, which it does for all four families including the minimum/maximum danger thresholds. Nothing an agent needs in order to call it or interpret the results is missing.

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?

Single parameter with 100% schema coverage ('Estonian text to measure.'). The description adds no syntax, format, length, or preprocessing guidance for the input beyond the existing 'Estonian' constraint, so 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?

States a specific verb+resource: heuristic Estonian style metrics, and enumerates the four metric families (repetition, passive_voice, sentence_length, hedging). The explicit 'no cliche detection' boundary and the pointer to check_officialese for kantseliit separate it from at least one noisy sibling. It doesn't cleanly distinguish itself from classify_register or check_redundancy, which also touch style, keeping it below a 5.

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?

Gives concrete application context via interpretation thresholds (marketing copy passive under 15%, news sentences 10–15 words, hedging over 5% reads wishy-washy) rather than a bare 'measures style'. It also routes the kantseliit question to check_officialese, an explicit alternative. What's missing is a plain when-to-use statement for the sibling style tools.

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

check_term_consistencyA
Read-onlyIdempotent

Flag a document that names one thing several ways (andmestik, teadusandmestik, pildiandmestik).

Rules: shared-compound-head (a bare noun plus a compound on it, or 3+ lemmas sharing a head) and shared-wordnet-synset (two of the 40 most frequent nouns share a WordNet synset). Each group gives variants with counts and dominant, the most used. Some groups are distinct concepts and the tool does not pick the right term: read each first.

degraded: true means WordNet is missing and the synset rule did not run: no groups is then no proof of consistency.

With a domain glossary (the server's or glossary), variants carry in_domain_glossary, and a group's only listed variant is its preferred term, whatever dominant says (several listed suggest distinct concepts).

Misses synonyms sharing neither head nor synset (korpus / andmestik): compare their synonyms definitions.

NameRequiredDescriptionDefault
textYesThe whole Estonian document, not one paragraph at a time.
glossaryNoOptional domain lemmas (base forms) for this call only, added to any server glossary. Not stored.

Output Schema

NameRequiredDescription
groupsNo
degradedNo
terms_analysedNo
summary_estonianNo

TDQS

A4/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, the description discloses the two detection heuristics by name, the output fields (variants, counts, dominant, preferred, in_domain_glossary), the meaning of degraded: true and its consequence that empty output proves nothing, and an explicit known miss (synonyms sharing neither head nor synset). This is unusually rich behavioral context for a checker.

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

Conciseness4/5

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

Purpose is front-loaded in sentence one and no sentence is filler; the rules, degraded mode, and glossary effects each appear once. The prose is telegraphic in places ('no groups is then no proof of consistency'), which costs some readability but not content.

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?

With an output schema present, the description need not detail return values, yet it usefully does. It covers limitations, degraded behavior, and glossary interaction; the main remaining gap is guidance on choosing this tool over the domain-terms and defined-terms siblings.

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 goes further by explaining that supplying a glossary changes the returned data (in_domain_glossary flags, and a sole listed variant becoming preferred regardless of dominant). The glossary's per-call, non-stored nature is already in the schema, so no credit there.

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 first sentence states a specific verb and outcome ('Flag a document that names one thing several ways') with a concrete Estonian example, so the agent knows exactly what class of problem it detects. It does not, however, distinguish itself from near-siblings such as check_domain_terms or check_defined_terms, leaving the agent to guess which check to run.

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

Usage Guidelines3/5

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

The description explains the two triggering rules and warns that 'some groups are distinct concepts and the tool does not pick the right term: read each first', which governs how to interpret hits. But it never says when to call this versus check_domain_terms, check_defined_terms, or check_redundancy, and gives no prerequisite about document language or size beyond the schema.

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

check_translationeseA
Read-onlyIdempotent

Flag English structure that makes Estonian read as translated. Run it on Estonian you wrote or translated.

Rules: oma-possessive (saatke meile teie andmed → oma andmed), pronoun-after-verb (lähtume me → lähtume), subject-pronoun (a third of the sentences open with Ma or Me; once), verb-second (Kui ..., me saadame → saadame), saama-future (saab olema → on), maks-infinitive (ettepanek võtmaks → võtta), maks-purpose (Tagamaks → et tagada), mitte-des (Mitte leides → Leidmata), tanu-negative (tänu + a bad cause → tõttu), english-phrase (minu arvamusel), greeting-punctuation (Hea Mari, → Hea Mari!; Tere Mari → Tere, Mari), closing-comma (Lugupidamisega,), serial-comma (teed, ja küpsiseid), title-case (Meie Teenused Ja Hinnad).

maks-purpose and subject-pronoun are style hints. Third-person possessives, negated verbs and questions are not checked. Accepted Estonian is never flagged (aset leidma, rolli mängima, Eile ma läksin, a capital Teie to one reader). Letter formulas such as Palun leidke manuses are check_officialese's.

NameRequiredDescriptionDefault
textYesEstonian text you wrote, translated or are editing.

Output Schema

NameRequiredDescription
issuesNo
summary_estonianNo

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/closed-world, and the description adds substantial context beyond them: the exact rule inventory, which two rules are only style hints, which constructs are deliberately NOT checked (third-person possessives, negated verbs, questions), and a false-positive guard that accepted Estonian is never flagged. That is unusually rich behavioral disclosure for a checker.

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

Conciseness4/5

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

Purpose and usage are front-loaded in the first two sentences, then the rule list. The rule block is long but each item carries distinct information (rule name plus example), so it earns its space; it is dense rather than padded.

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?

With an output schema present, the description needn't explain return values, and it covers scope, rules, exclusions, and sibling routing. Minor gaps remain: no statement about behavior on non-Estonian or mixed input, and no mention of input size limits.

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?

Only one parameter and schema coverage is 100%, so the schema already fully documents `text`. The description's guidance (Estonian you wrote or translated) largely duplicates the schema description and adds no syntax, size, or format constraints for the input.

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 first sentence names a specific verb (flag), a specific target (English structure in Estonian), and frames it as translationese detection. It also names the sibling it defers to for a related-but-different concern (check_officialese handles letter formulas), so an agent can separate it from check_style and check_officialese without opening schemas.

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?

"Run it on Estonian you wrote or translated" gives a clear usage condition, and the closing line explicitly routes letter formulas to check_officialese. It lacks a full when-not-to-use statement (e.g. versus check_style or check_legalese for register/rhetoric), so the alternative map is clear but not exhaustive.

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

classify_registerA
Read-onlyIdempotent

Heuristic Estonian register score: a directional hint, not a verdict. Most everyday prose scores neutral, and address forms (sina/teie) are not scored.

score runs from -1 (colloquial) to 1 (formal); tier_estonian is the correct Estonian label to quote (formaalne, never *formalne). consistency.is_mixed: formal and colloquial markers both occur, which jars even when the tier is neutral. structure adds up to 0.4 (applied) for umbisikuline tegumood and noun density, from 25 words up and never on net-colloquial text. For a per-issue kantseliit breakdown use check_officialese.

NameRequiredDescriptionDefault
textYesEstonian text to classify by register (formal vs colloquial).

Output Schema

NameRequiredDescription
tierNo
scoreNo
structureNo
word_countNo
consistencyNo
tier_estonianNo
formal_markersNo
colloquial_markersNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already mark it read-only/idempotent/closed-world, and the description adds substantial beyond-schema behavior: the -1 to 1 score range, the correct label to quote (formaalne, not *formalne), what consistency.is_mixed means, and the exact conditions under which structure contributes (up to 0.4, from 25 words, never on net-colloquial text). This is unusually rich disclosure for a heuristic scorer.

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

Conciseness4/5

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

Front-loads the core caveat ('directional hint, not a verdict') before the detail, and every sentence carries information about output fields or applicability. The backtick-fragment style is dense and slightly telegraphic, but nothing is padding.

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?

Complete for a single-input scorer. The output schema exists, yet the description goes further by explaining how to read score, tier_estonian, consistency.is_mixed and structure, which is exactly what an agent needs to interpret the result.

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?

Only one parameter and schema coverage is 100%, so the baseline is 3. The description still adds input-relevant meaning: address forms are unscored and the structure component only applies from 25 words up, which tells an agent how input length and content affect the result.

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?

States a specific verb and resource ('Heuristic Estonian register score') plus the scope limit ('a directional hint, not a verdict'). It explicitly disambiguates from the nearest sibling, check_officialese, so an agent can choose without opening either schema.

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?

Gives real usage context: everyday prose scores neutral, address forms (sina/teie) are excluded, and per-issue kantseliit work should go to check_officialese instead. It lacks an explicit 'call this when...' trigger sentence, but the alternative routing is clear.

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

lemmatizeA
Read-onlyIdempotent

Lemma (dictionary form) of each word, from its most likely analysis. Punctuation is omitted.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, and closed-world behavior, so the safety profile is covered. The description adds genuinely behavioral detail beyond that: lemmas come from the single most likely analysis (a disambiguation policy) and punctuation is omitted from output, both of which affect how the agent interprets results.

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 filler, with the core output definition front-loaded ahead of the punctuation caveat. Nothing could be removed without losing information.

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?

With an output schema present, the description need not explain return values, and annotations cover the safety profile. What it supplies — per-word lemmas, most-likely-analysis selection, punctuation omission — is sufficient to call the tool correctly, though behavior on unknown or out-of-vocabulary words is unstated.

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% for the single `text` parameter ('Estonian text.'), so the baseline is 3. The description's 'of each word' hints that input may be multi-word text, but it adds no format or language guidance beyond what the schema already says.

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 names the concrete resource produced (the lemma/dictionary form) on a per-word basis and specifies the disambiguation rule ('most likely analysis'). It is clear what the tool returns, but it never names its siblings (analyze_morphology, tokenize, pos_tag), so the agent gets no in-description help distinguishing lemmatization from full morphological analysis.

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

Usage Guidelines2/5

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

There is no statement of when to use this versus analyze_morphology, pos_tag, or tokenize, and no mention of prerequisites or excluded inputs. The agent must infer the use case from the noun phrase alone.

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

named_entitiesA
Read-onlyIdempotent

People, places and organisations (type PER, LOC, ORG) with character offsets start and end. text is the span as written, often inflected (Tallinnas).

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false. The description adds useful behavioral detail beyond those annotations by clarifying the returned fields (type, start, end, text) and warning that text is the span as written and often inflected, which matters for interpreting results.

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?

The description is two compact sentences, front-loaded with the entity categories and offsets. Every phrase contributes useful information without repetition or filler.

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 simple, read-only named-entity extraction tool with complete annotations, a complete input schema, and an output schema, the description is largely sufficient. It provides the entity types, offsets, and an inflection caveat; only explicit usage guidance is notably absent.

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?

There is only one input parameter, and schema description coverage is 100%, so the schema already documents the input adequately. The description mentions `text`, `type`, `start`, and `end`, but these appear to describe output fields rather than adding input-parameter semantics beyond what the schema provides.

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 clearly identifies the resource as named entities by naming the categories (people, places, organisations) and corresponding types (PER, LOC, ORG). It does not state an explicit action verb or explicitly differentiate from siblings, but the tool name and unique entity-recognition focus make its purpose clear.

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

Usage Guidelines2/5

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

The description provides no guidance about when to use this tool versus alternatives such as tokenize or pos_tag. It implies usage through the entity categories but does not state conditions, exclusions, or alternatives.

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

paradigmA
Read-onlyIdempotent

Inflection paradigm of one Estonian word from Vabamorf, which generates what is possible, not necessarily idiomatic.

Nominals: up to 28 forms, 14 cases in singular and plural (iga has no plural), plus the short illative adt (majja beside majasse) where it exists. Verbs: about 39 common forms, impersonal included, not all Vabamorf can make. A word that does not inflect gets empty forms and a summary_estonian saying why.

forms entries: form (Vabamorf code), form_estonian (its Estonian name), surface. A list surface holds correct variants, any built on this paradigm's own stem first (raamatutele before the literary raamatuile).

Both illatives are correct and the short illative is often the commoner: never "correct" one into the other. adt is usually spelled like the singular partitive sg p (vend: venda), so a surface in this table does not confirm its case in a sentence.

paradigm_count > 1 means several inflection types (kott: koti or kota): forms is the first-ranked, named by paradigm_key (its singular genitive), and the rest are in other_paradigms, which give form_estonian only for a code forms lacks. Read ambiguity_estonian before quoting a form. Pass an inflected form (koti) to select the type you mean.

NameRequiredDescriptionDefault
wordYesOne Estonian word, lemma or inflected form.

Output Schema

NameRequiredDescription
formsNo
lemmaNo
invariantNo
word_classNo
paradigm_keyNo
partofspeechNo
paradigm_countNo
other_paradigmsNo
reading_estonianNo
summary_estonianNo
ambiguity_estonianNo
invariant_estonianNo
word_class_estonianNo
partofspeech_estonianNo
ranked_by_corpus_frequencyNo

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, idempotent, closed-world), and the description still goes well beyond them: it discloses that output is generative not normative, that non-inflecting words yield empty `forms` with an explanatory `summary_estonian`, and the crucial caveat that `adt` surfaces often coincide with singular partitives and do not confirm case. That is exactly the kind of trap-flagging an agent cannot infer from structured fields.

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

Conciseness4/5

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

It is front-loaded with purpose and output shape, then the caveats, and every sentence carries substantive information about return structure or pitfalls. It is dense and jargon-heavy (form codes, `adt`, `sg p`) but not padded.

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?

Despite an output schema existing, the description explains the return contract in detail: per-entry `form`/`form_estonian`/`surface`, list-valued surfaces with ordering rationale, `paradigm_key` naming the ranked type, `other_paradigms` coverage rules, and `ambiguity_estonian`. Nothing an agent needs to interpret or safely quote results 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?

The single parameter is fully described in the schema, so the baseline is already high. The description earns extra credit by explaining a non-obvious behavior the schema does not: passing an inflected form rather than the lemma selects which paradigm type is returned when `paradigm_count` > 1.

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 opens with a precise verb+resource: 'Inflection paradigm of one Estonian word from Vabamorf,' and immediately scopes the output ('generates what is possible, not necessarily idiomatic'). That is enough to separate it from morphological siblings like analyze_morphology or lemmatize, though it never names those alternatives explicitly.

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

Usage Guidelines3/5

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

It gives real operational guidance – 'Read `ambiguity_estonian` before quoting a form' and 'Pass an inflected form (koti) to select the type you mean' – which tells the agent how to steer the tool. But it never states when to reach for this tool rather than the sibling morphology tools, so the when-to-use decision is left implicit.

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

pos_tagA
Read-onlyIdempotent

Part-of-speech tag of each word (most likely reading); punctuation omitted.

S noun, H proper noun, V verb, A adjective (C comparative, U superlative, G indeclinable), P pronoun, D adverb, K adposition, J conjunction, N cardinal, O ordinal, I interjection, Y abbreviation or symbol (§, €), X verb-bound word (plehku), Z a word of 40+ characters, too long for Vabamorf to analyse.

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent, closed-world behavior, so the description is free to add real semantics: a single most-likely reading is returned per word, punctuation is dropped, and edge cases (X verb-bound words, Z words of 40+ characters too long for Vabamorf) are disclosed. This goes meaningfully beyond the annotation set without contradicting it.

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

Conciseness4/5

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

The operational sentence is front-loaded and short, followed by an enum-key legend that is dense but earns its place since those tag codes would otherwise be opaque. No filler sentences.

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 structure need not be explained; the description supplies exactly the missing piece, the meaning of each tag code including the two special cases. The only gap is routing guidance against near-duplicate siblings.

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?

Only one parameter, fully described in the schema as 'Estonian text.' The description adds no detail about input format, length limits, or whether multi-sentence input is allowed, so baseline 3 applies with schema coverage at 100%.

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 opens with a specific verb+resource: 'Part-of-speech tag of each word', and qualifies it with 'most likely reading'. It does not name or contrast with the closest sibling, analyze_morphology, so an agent cannot tell from the text alone which of the two to reach for.

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

Usage Guidelines2/5

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

There is no statement of when to use this tool versus analyze_morphology, tokenize, or lemmatize, and no exclusions or prerequisites. Usage must be inferred entirely from the tool name and the tag legend.

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

spell_checkA
Read-onlyIdempotent

Spell-check Estonian text. Lists only the misspelled tokens, each occurrence in text order: text, spelling: false, and suggestions when Vabamorf has any. An empty list means every word passed.

Passing proves only that a word is well-formed: Vabamorf accepts any valid compound, even an invented one (toortõlkeoht). Check a compound you coined with check_compound_familiarity.

NameRequiredDescriptionDefault
textYesEstonian text.
suggestionsNoInclude correction suggestions for misspelled words.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent, but the description adds the crucial semantic caveat that a pass only proves well-formedness, not lexical reality, because Vabamorf accepts invented compounds. It also defines what an empty list means and when suggestions appear — behavior an agent could not derive from the annotations.

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

Conciseness4/5

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

Two short paragraphs, front-loaded with the core action and the key caveat, with no filler. Minor waste in enumerating output field names (`text`, `spelling: false`) that an existing output schema already covers, though the ordering and conditional-presence notes do earn some of that space.

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 an output schema present, the description needs only to explain semantics and caveats, and it does exactly that — what a hit looks like, what empty means, and the false-positive risk on compounds. Nothing an agent needs to call this correctly is missing.

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 `text` and `suggestions` are already documented with a default. The description mentions `suggestions` only as an output field ("`suggestions` when Vabamorf has any"), which adds little to the parameter's own schema text; baseline 3 applies.

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?

States a specific verb and resource ("Spell-check Estonian text") and immediately characterizes the output ("Lists only the misspelled tokens"). It also distinguishes itself from the compound-oriented siblings by naming check_compound_familiarity as the tool for coined compounds.

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?

Gives a clear condition for escalating to check_compound_familiarity when a compound is newly coined, which is real routing guidance against a large sibling set. It does not, however, explain how it relates to check_punctuation, check_capitalization, or check_style, so an agent must infer the boundaries of the other check_* family members.

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

syllabifyA
Read-onlyIdempotent

Lowercased syllables of one Estonian word; quantity is the välde (1-3), accent 1 marks stress. Vabamorf's guesser syllabifier: it can err even on common words.

NameRequiredDescriptionDefault
wordYesOne Estonian word, no whitespace.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/closed-world, and the description adds genuinely new behavioral context: the underlying engine is Vabamorf's guesser syllabifier and it can err even on common words, so the agent knows to treat results as approximate. It also decodes output semantics (välde 1-3, accent=stress) that annotations cannot convey.

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 dense sentences, front-loaded with what is returned, then output-field semantics, then the reliability caveat. No filler and nothing repeated from the schema or annotations.

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?

With an output schema present and a fully documented single parameter, the description only needs to add output semantics and caveats, which it does. The remaining gap is routing guidance against sibling tools, but that is minor for such a narrow utility.

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?

There is one parameter with 100% schema description coverage, so the schema already documents it fully ('One Estonian word, no whitespace'). The description's 'one Estonian word' reinforces but does not extend that, so the 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?

The description states a specific resource and transformation: lowercased syllables of exactly one Estonian word, plus what the returned `quantity` and `accent` fields mean. It is clearly distinct in substance from siblings like tokenize or analyze_morphology, though it never names or contrasts them explicitly.

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

Usage Guidelines3/5

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

Usage is only implied: if you need syllables, call this. The scope constraint 'one Estonian word' hints at the boundary (not phrases, not multiple words), but there is no explicit when-to-use, when-not, or pointer to alternatives such as tokenize.

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

synonymsA
Read-onlyIdempotent

Estonian WordNet synsets for a word, one per sense, each with lemmas (the synonyms), any definition and any examples. synset_count is the total before max_synsets cuts the list.

For "is this the right word here?", read each definition against the context, not just lemmas. A gloss naming a medium, field or material limits where the word fits: korpus is "kirjaliku või suulise teksti elektrooniline kogu", so a set of images is not a korpus, while andmestik has no such limit. Register is a different question: check_officialese, classify_register.

NameRequiredDescriptionDefault
wordYesOne Estonian word in dictionary form, spelled as the dictionary spells it (kohv, not kohvi or Kohv).
max_synsetsNoMaximum number of word-sense synsets to return.

Output Schema

NameRequiredDescription
synsetsNo
synset_countNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, closed-world behavior, so safety is covered; the description adds the truncation contract (synset_count is the total before max_synsets cuts the list), which is genuinely new behavioral context. It also discloses that definitions and examples are optional ('any definition and any examples').

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

Conciseness4/5

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

Front-loaded with what is returned, then purpose, then semantics. The korpus/andmestik example is longer than strictly necessary but does concrete work by teaching how a gloss constrains usage, so it earns its place; register routing at the end is a tight pointer.

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 an output schema present the description need not enumerate return fields, yet it still explains their structure and the truncation counter. Two-parameter, read-only tool with nothing an agent needs left unstated.

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 baseline is a 3, but the description adds meaning the schema lacks: it explains the relationship between max_synsets and the returned synset_count, which is the only non-obvious behavioral aspect of truncation. The word-form constraint is repeated from the schema rather than extended.

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?

Opening sentence names a specific resource (Estonian WordNet synsets), scopes it to one per sense, and enumerates the returned fields (lemmas, definition, examples). It does not explicitly differentiate itself from the closest sibling, find_related_words, but the 'synset per sense' framing is distinctive enough to separate it from morphological and related-word tools.

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 the intended question ('is this the right word here?') and prescribes the method: read each definition against the context, not just lemmas. It also redirects register questions to check_officialese and classify_register, an explicit alternative routing. It stops short of saying when to prefer find_related_words instead.

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

tokenizeA
Read-onlyIdempotent

Split Estonian text into sentences and words (every token in order, punctuation included).

NameRequiredDescriptionDefault
textYesEstonian text.

Output Schema

NameRequiredDescription
wordsNo
sentencesNo

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is clear. The description adds useful tokenization behavior—preserving order and including punctuation—but does not go much further beyond what the annotations provide.

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?

A single front-loaded sentence with no filler. It communicates the operation and output contract efficiently.

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?

With one parameter, an output schema, and annotations covering safety and idempotency, the description is largely complete. It adequately explains the output categories, though it does not explicitly mention deterministic behavior or input expectations, which are covered elsewhere.

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?

The input schema has full description coverage for the single `text` parameter, so the baseline is 3. The description implies the input is Estonian text but adds no format, length, or encoding details beyond the schema.

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 states a specific verb and resource: 'Split Estonian text into sentences and words.' It also clarifies the exact output semantics ('every token in order, punctuation included'), making the tool's purpose immediately distinguishable from linguistic-analysis siblings such as lemmatize or pos_tag.

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

Usage Guidelines3/5

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

Usage is implied by the clear purpose, but there is no explicit guidance on when to use tokenize versus alternatives like analyze_morphology or syllabify. No exclusions or prerequisites are mentioned.

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. 1 tool updatev1.1.0
    • Addedcheck_translationese
  2. 27 tool updatesv0.9.0
    • Changedanalyze_morphology8 fields changed
      • changedInput schema / properties / all_analyses / description
        Previous value: -"Return every ambiguous analysis per word instead of only the most likely one."New value: +"Return every reading left after in-context disambiguation, in an `analyses` list, instead of only the most likely one."
      • removedInput schema / properties / all_analyses / title
        Removed value: -"All Analyses"
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to analyse morphologically."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"analyze_morphologyArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"analyze_morphologyOutput"
    • Changedcheck_abbreviation_hyphenation11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for abbreviation case-ending hyphenation (MCPst → MCP-st)."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_abbreviation_hyphenationArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_capitalization11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for capitalization errors (Algustäheortograafia)."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_capitalizationArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_compound_familiarity20 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text whose compound nouns are checked for calque / translationese risk."New value: +"Estonian text to check."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_compound_familiarityArguments"
      • removedOutput schema / properties / all_compounds / default
        Removed value: -null
      • removedOutput schema / properties / all_compounds / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / all_compounds / title
        Removed value: -"All Compounds"
      • removedOutput schema / properties / compounds_analysed / default
        Removed value: -null
      • removedOutput schema / properties / compounds_analysed / title
        Removed value: -"Compounds Analysed"
      • removedOutput schema / properties / note / default
        Removed value: -null
      • removedOutput schema / properties / note / title
        Removed value: -"Note"
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / suspect_compounds / default
        Removed value: -null
      • removedOutput schema / properties / suspect_compounds / items / additionalProperties
        Removed value: -true
      • changedOutput schema / properties / suspect_compounds / items / type
        Previous value: -"object"New value: +"string"
      • removedOutput schema / properties / suspect_compounds / title
        Removed value: -"Suspect Compounds"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • addedOutput schema / properties / unattested_compounds
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / wordnet_checked
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / title
        Removed value: -"_CompoundFamiliarityResult"
    • Changedcheck_compounds11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for wrongly split compound words."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_compoundsArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_defined_terms17 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"A long Estonian legal document to map defined terms ('edaspidi «X»') and § / lõige / punkt cross-references."New value: +"Whole Estonian legal document."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_defined_termsArguments"
      • removedOutput schema / properties / cross_references / default
        Removed value: -null
      • removedOutput schema / properties / cross_references / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / cross_references / title
        Removed value: -"Cross References"
      • removedOutput schema / properties / defined_terms / default
        Removed value: -null
      • removedOutput schema / properties / defined_terms / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / defined_terms / title
        Removed value: -"Defined Terms"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_DefinedTermsResult"
    • Addedcheck_domain_terms
    • Changedcheck_hyphenation13 fields changed
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian word (no whitespace) to find safe line-break positions for."New value: +"One Estonian word, no whitespace."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"check_hyphenationArguments"
      • removedOutput schema / properties / breaks / default
        Removed value: -null
      • removedOutput schema / properties / breaks / title
        Removed value: -"Breaks"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / preferred / default
        Removed value: -null
      • removedOutput schema / properties / preferred / title
        Removed value: -"Preferred"
      • removedOutput schema / properties / summary_estonian
        Removed value: -{
        -  "default": null,
        -  "title": "Summary Estonian",
        -  "type": "string"
        -}
      • removedOutput schema / properties / syllable_count / default
        Removed value: -null
      • removedOutput schema / properties / syllable_count / title
        Removed value: -"Syllable Count"
      • removedOutput schema / properties / word
        Removed value: -{
        -  "default": null,
        -  "title": "Word",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_HyphenationResult"
    • Changedcheck_legalese14 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian legal text to lint for plain-language simplification while protecting legal terms of art."New value: +"Estonian statute or contract text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_legaleseArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / terms_of_art / default
        Removed value: -null
      • removedOutput schema / properties / terms_of_art / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / terms_of_art / title
        Removed value: -"Terms Of Art"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_LegaleseResult"
    • Changedcheck_numbers11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for number-formatting (decimal comma, thousands space)."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_numbersArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_object_case11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for direct-object case errors under negation and partitive-governing verbs."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_object_caseArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_officialese14 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian non-legal text (report, academic, business) to check for kantseliit / bureaucratic density."New value: +"Estonian non-legal prose (report, academic, business)."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_officialeseArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / metrics / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / metrics / default
        Removed value: -null
      • removedOutput schema / properties / metrics / title
        Removed value: -"Metrics"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_OfficialeseResult"
    • Changedcheck_punctuation11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for missing commas before subordinating conjunctions."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_punctuationArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_redundancy11 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to check for pleonasm / redundant word pairs."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_redundancyArguments"
      • removedOutput schema / properties / issues / default
        Removed value: -null
      • removedOutput schema / properties / issues / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / issues / title
        Removed value: -"Issues"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_CheckResult"
    • Changedcheck_style18 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to compute style metrics for (repetition, passive voice, sentence length, hedging)."New value: +"Estonian text to measure."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_styleArguments"
      • removedOutput schema / properties / hedging / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / hedging / default
        Removed value: -null
      • removedOutput schema / properties / hedging / title
        Removed value: -"Hedging"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / passive_voice / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / passive_voice / default
        Removed value: -null
      • removedOutput schema / properties / passive_voice / title
        Removed value: -"Passive Voice"
      • removedOutput schema / properties / repetition / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / repetition / default
        Removed value: -null
      • removedOutput schema / properties / repetition / title
        Removed value: -"Repetition"
      • removedOutput schema / properties / sentence_length / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / sentence_length / default
        Removed value: -null
      • removedOutput schema / properties / sentence_length / title
        Removed value: -"Sentence Length"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_StyleResult"
    • Changedcheck_term_consistency17 fields changed
      • addedInput schema / properties / glossary
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "maxItems": 1000,
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional domain lemmas (base forms) for this call only, added to any server glossary. Not stored."
        +}
      • changedInput schema / properties / text / description
        Previous value: -"Estonian document to check for the same thing being named several different ways."New value: +"The whole Estonian document, not one paragraph at a time."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"check_term_consistencyArguments"
      • removedOutput schema / properties / degraded / default
        Removed value: -null
      • removedOutput schema / properties / degraded / title
        Removed value: -"Degraded"
      • removedOutput schema / properties / groups / default
        Removed value: -null
      • removedOutput schema / properties / groups / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / groups / title
        Removed value: -"Groups"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / rules_run
        Removed value: -{
        -  "additionalProperties": true,
        -  "default": null,
        -  "title": "Rules Run",
        -  "type": "object"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / terms_analysed / default
        Removed value: -null
      • removedOutput schema / properties / terms_analysed / title
        Removed value: -"Terms Analysed"
      • removedOutput schema / properties / text
        Removed value: -{
        -  "default": null,
        -  "title": "Text",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_TermConsistencyResult"
    • Changedclassify_register22 fields changed
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"classify_registerArguments"
      • removedOutput schema / properties / colloquial_markers / default
        Removed value: -null
      • removedOutput schema / properties / colloquial_markers / title
        Removed value: -"Colloquial Markers"
      • removedOutput schema / properties / consistency / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / consistency / default
        Removed value: -null
      • removedOutput schema / properties / consistency / title
        Removed value: -"Consistency"
      • removedOutput schema / properties / formal_markers / default
        Removed value: -null
      • removedOutput schema / properties / formal_markers / title
        Removed value: -"Formal Markers"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / score / default
        Removed value: -null
      • removedOutput schema / properties / score / title
        Removed value: -"Score"
      • removedOutput schema / properties / structure / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / structure / default
        Removed value: -null
      • removedOutput schema / properties / structure / title
        Removed value: -"Structure"
      • removedOutput schema / properties / tier / default
        Removed value: -null
      • removedOutput schema / properties / tier / title
        Removed value: -"Tier"
      • removedOutput schema / properties / tier_estonian / default
        Removed value: -null
      • removedOutput schema / properties / tier_estonian / title
        Removed value: -"Tier Estonian"
      • removedOutput schema / properties / word_count / default
        Removed value: -null
      • removedOutput schema / properties / word_count / title
        Removed value: -"Word Count"
      • removedOutput schema / title
        Removed value: -"_RegisterResult"
    • Changedcommon_legal_usage20 fields changed
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian (legal) word to look up canonical collocations for, e.g. 'hagi', 'kohustus', 'taotlus'."New value: +"One Estonian word, any inflected form."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"common_legal_usageArguments"
      • removedOutput schema / properties / common_after / default
        Removed value: -null
      • removedOutput schema / properties / common_after / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / common_after / title
        Removed value: -"Common After"
      • removedOutput schema / properties / common_before / default
        Removed value: -null
      • removedOutput schema / properties / common_before / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / common_before / title
        Removed value: -"Common Before"
      • removedOutput schema / properties / found / default
        Removed value: -null
      • removedOutput schema / properties / found / title
        Removed value: -"Found"
      • removedOutput schema / properties / frequency / default
        Removed value: -null
      • removedOutput schema / properties / frequency / title
        Removed value: -"Frequency"
      • removedOutput schema / properties / lemma / default
        Removed value: -null
      • removedOutput schema / properties / lemma / title
        Removed value: -"Lemma"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / word
        Removed value: -{
        -  "default": null,
        -  "title": "Word",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_LegalUsageResult"
    • Changedfind_related_words9 fields changed
      • removedInput schema / properties / n / title
        Removed value: -"N"
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian word to find semantically related words for."New value: +"One Estonian word, any form."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"find_related_wordsArguments"
      • removedOutput schema / properties / matches / default
        Removed value: -null
      • removedOutput schema / properties / matches / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / matches / title
        Removed value: -"Matches"
      • removedOutput schema / properties / word
        Removed value: -{
        -  "default": null,
        -  "title": "Word",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_RelatedWordsResult"
    • Changedlemmatize6 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to reduce to dictionary-form lemmas."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"lemmatizeArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"lemmatizeOutput"
    • Changednamed_entities6 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to extract named entities (people, places, organisations) from."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"named_entitiesArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"named_entitiesOutput"
    • Changedparadigm58 fields changed
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian word (lemma or inflected form) to generate the full paradigm for."New value: +"One Estonian word, lemma or inflected form."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"paradigmArguments"
      • removedOutput schema / properties / ambiguity_estonian / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / ambiguity_estonian / default
        Removed value: -null
      • removedOutput schema / properties / ambiguity_estonian / title
        Removed value: -"Ambiguity Estonian"
      • addedOutput schema / properties / ambiguity_estonian / type
        Added value: +"string"
      • removedOutput schema / properties / forms / default
        Removed value: -null
      • removedOutput schema / properties / forms / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / forms / title
        Removed value: -"Forms"
      • removedOutput schema / properties / input
        Removed value: -{
        -  "default": null,
        -  "title": "Input",
        -  "type": "string"
        -}
      • removedOutput schema / properties / invariant / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / invariant / default
        Removed value: -null
      • removedOutput schema / properties / invariant / title
        Removed value: -"Invariant"
      • addedOutput schema / properties / invariant / type
        Added value: +"boolean"
      • removedOutput schema / properties / invariant_estonian / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / invariant_estonian / default
        Removed value: -null
      • removedOutput schema / properties / invariant_estonian / title
        Removed value: -"Invariant Estonian"
      • addedOutput schema / properties / invariant_estonian / type
        Added value: +"string"
      • removedOutput schema / properties / lemma / default
        Removed value: -null
      • removedOutput schema / properties / lemma / title
        Removed value: -"Lemma"
      • removedOutput schema / properties / note
        Removed value: -{
        -  "default": null,
        -  "title": "Note",
        -  "type": "string"
        -}
      • removedOutput schema / properties / other_paradigms / anyOf
        Removed value: -[
        -  {
        -    "items": {
        -      "additionalProperties": true,
        -      "type": "object"
        -    },
        -    "type": "array"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / other_paradigms / default
        Removed value: -null
      • addedOutput schema / properties / other_paradigms / items
        Added value: +{
        +  "type": "object"
        +}
      • removedOutput schema / properties / other_paradigms / title
        Removed value: -"Other Paradigms"
      • addedOutput schema / properties / other_paradigms / type
        Added value: +"array"
      • removedOutput schema / properties / paradigm_count / default
        Removed value: -null
      • removedOutput schema / properties / paradigm_count / title
        Removed value: -"Paradigm Count"
      • removedOutput schema / properties / paradigm_key / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / paradigm_key / default
        Removed value: -null
      • removedOutput schema / properties / paradigm_key / title
        Removed value: -"Paradigm Key"
      • addedOutput schema / properties / paradigm_key / type
        Added value: +"string"
      • removedOutput schema / properties / partofspeech / default
        Removed value: -null
      • removedOutput schema / properties / partofspeech / title
        Removed value: -"Partofspeech"
      • removedOutput schema / properties / partofspeech_estonian / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / partofspeech_estonian / default
        Removed value: -null
      • removedOutput schema / properties / partofspeech_estonian / title
        Removed value: -"Partofspeech Estonian"
      • addedOutput schema / properties / partofspeech_estonian / type
        Added value: +"string"
      • removedOutput schema / properties / ranked_by_corpus_frequency / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / ranked_by_corpus_frequency / default
        Removed value: -null
      • removedOutput schema / properties / ranked_by_corpus_frequency / title
        Removed value: -"Ranked By Corpus Frequency"
      • addedOutput schema / properties / ranked_by_corpus_frequency / type
        Added value: +"boolean"
      • removedOutput schema / properties / reading_estonian / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / reading_estonian / default
        Removed value: -null
      • removedOutput schema / properties / reading_estonian / title
        Removed value: -"Reading Estonian"
      • addedOutput schema / properties / reading_estonian / type
        Added value: +"string"
      • removedOutput schema / properties / summary_estonian / default
        Removed value: -null
      • removedOutput schema / properties / summary_estonian / title
        Removed value: -"Summary Estonian"
      • removedOutput schema / properties / word_class / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / word_class / default
        Removed value: -null
      • removedOutput schema / properties / word_class / title
        Removed value: -"Word Class"
      • addedOutput schema / properties / word_class / type
        Added value: +"string"
      • removedOutput schema / properties / word_class_estonian / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • removedOutput schema / properties / word_class_estonian / default
        Removed value: -null
      • removedOutput schema / properties / word_class_estonian / title
        Removed value: -"Word Class Estonian"
      • addedOutput schema / properties / word_class_estonian / type
        Added value: +"string"
      • removedOutput schema / title
        Removed value: -"_ParadigmResult"
    • Changedpos_tag6 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to part-of-speech tag."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"pos_tagArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"pos_tagOutput"
    • Changedspell_check7 fields changed
      • removedInput schema / properties / suggestions / title
        Removed value: -"Suggestions"
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to spell-check."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"spell_checkArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"spell_checkOutput"
    • Changedsyllabify6 fields changed
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian word (no whitespace) to split into syllables."New value: +"One Estonian word, no whitespace."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"syllabifyArguments"
      • removedOutput schema / properties / result / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / result / title
        Removed value: -"Result"
      • removedOutput schema / title
        Removed value: -"syllabifyOutput"
    • Changedsynonyms11 fields changed
      • removedInput schema / properties / max_synsets / title
        Removed value: -"Max Synsets"
      • changedInput schema / properties / word / description
        Previous value: -"A single Estonian word to look up WordNet synonyms for."New value: +"One Estonian word in dictionary form, spelled as the dictionary spells it (kohv, not kohvi or Kohv)."
      • removedInput schema / properties / word / title
        Removed value: -"Word"
      • removedInput schema / title
        Removed value: -"synonymsArguments"
      • removedOutput schema / properties / synset_count / default
        Removed value: -null
      • removedOutput schema / properties / synset_count / title
        Removed value: -"Synset Count"
      • removedOutput schema / properties / synsets / default
        Removed value: -null
      • removedOutput schema / properties / synsets / items / additionalProperties
        Removed value: -true
      • removedOutput schema / properties / synsets / title
        Removed value: -"Synsets"
      • removedOutput schema / properties / word
        Removed value: -{
        -  "default": null,
        -  "title": "Word",
        -  "type": "string"
        -}
      • removedOutput schema / title
        Removed value: -"_SynonymsResult"
    • Changedtokenize8 fields changed
      • changedInput schema / properties / text / description
        Previous value: -"Estonian text to split into sentences and words."New value: +"Estonian text."
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / title
        Removed value: -"tokenizeArguments"
      • removedOutput schema / properties / sentences / default
        Removed value: -null
      • removedOutput schema / properties / sentences / title
        Removed value: -"Sentences"
      • removedOutput schema / properties / words / default
        Removed value: -null
      • removedOutput schema / properties / words / title
        Removed value: -"Words"
      • removedOutput schema / title
        Removed value: -"_TokenizeResult"
  3. 1 tool updatev0.6.0
    • Changedparadigm25 fields changed
      • addedOutput schema / properties / ambiguity_estonian / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / ambiguity_estonian / type
        Removed value: -"string"
      • addedOutput schema / properties / invariant / anyOf
        Added value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / invariant / type
        Removed value: -"boolean"
      • addedOutput schema / properties / invariant_estonian / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / invariant_estonian / type
        Removed value: -"string"
      • addedOutput schema / properties / lemma / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / lemma / type
        Removed value: -"string"
      • addedOutput schema / properties / other_paradigms / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / other_paradigms / items
        Removed value: -{
        -  "additionalProperties": true,
        -  "type": "object"
        -}
      • removedOutput schema / properties / other_paradigms / type
        Removed value: -"array"
      • addedOutput schema / properties / paradigm_key / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / paradigm_key / type
        Removed value: -"string"
      • addedOutput schema / properties / partofspeech / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / partofspeech / type
        Removed value: -"string"
      • addedOutput schema / properties / partofspeech_estonian / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / partofspeech_estonian / type
        Removed value: -"string"
      • addedOutput schema / properties / ranked_by_corpus_frequency / anyOf
        Added value: +[
        +  {
        +    "type": "boolean"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / ranked_by_corpus_frequency / type
        Removed value: -"boolean"
      • addedOutput schema / properties / reading_estonian / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / reading_estonian / type
        Removed value: -"string"
      • addedOutput schema / properties / word_class / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / word_class / type
        Removed value: -"string"
      • addedOutput schema / properties / word_class_estonian / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / word_class_estonian / type
        Removed value: -"string"
  4. 7 tool updatesv0.5.6
    • Addedcheck_defined_terms
    • Addedcheck_legalese
    • Addedcheck_officialese
    • Addedcheck_term_consistency
    • Changedclassify_register1 field changed
      • addedOutput schema / properties / structure
        Added value: +{
        +  "additionalProperties": true,
        +  "default": null,
        +  "title": "Structure",
        +  "type": "object"
        +}
    • Addedcommon_legal_usage
    • Changedparadigm10 fields changed
      • addedOutput schema / properties / ambiguity_estonian
        Added value: +{
        +  "default": null,
        +  "title": "Ambiguity Estonian",
        +  "type": "string"
        +}
      • addedOutput schema / properties / invariant
        Added value: +{
        +  "default": null,
        +  "title": "Invariant",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / invariant_estonian
        Added value: +{
        +  "default": null,
        +  "title": "Invariant Estonian",
        +  "type": "string"
        +}
      • addedOutput schema / properties / other_paradigms
        Added value: +{
        +  "default": null,
        +  "items": {
        +    "additionalProperties": true,
        +    "type": "object"
        +  },
        +  "title": "Other Paradigms",
        +  "type": "array"
        +}
      • addedOutput schema / properties / paradigm_count
        Added value: +{
        +  "default": null,
        +  "title": "Paradigm Count",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / paradigm_key
        Added value: +{
        +  "default": null,
        +  "title": "Paradigm Key",
        +  "type": "string"
        +}
      • addedOutput schema / properties / partofspeech_estonian
        Added value: +{
        +  "default": null,
        +  "title": "Partofspeech Estonian",
        +  "type": "string"
        +}
      • addedOutput schema / properties / ranked_by_corpus_frequency
        Added value: +{
        +  "default": null,
        +  "title": "Ranked By Corpus Frequency",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / reading_estonian
        Added value: +{
        +  "default": null,
        +  "title": "Reading Estonian",
        +  "type": "string"
        +}
      • addedOutput schema / properties / word_class_estonian
        Added value: +{
        +  "default": null,
        +  "title": "Word Class Estonian",
        +  "type": "string"
        +}
  5. 21 tool updatesv0.2.4
    • First observedanalyze_morphology
    • First observedcheck_abbreviation_hyphenation
    • First observedcheck_capitalization
    • First observedcheck_compound_familiarity
    • First observedcheck_compounds
    • First observedcheck_hyphenation
    • First observedcheck_numbers
    • First observedcheck_object_case
    • First observedcheck_punctuation
    • First observedcheck_redundancy
    • First observedcheck_style
    • First observedclassify_register
    • First observedfind_related_words
    • First observedlemmatize
    • First observednamed_entities
    • First observedparadigm
    • First observedpos_tag
    • First observedspell_check
    • First observedsyllabify
    • First observedsynonyms
    • First observedtokenize

TDQS

A3.8/5.0

Scored across 28 tools

Disambiguation4/5

Tool boundaries are unusually well signposted: descriptions explicitly cross-reference siblings (find_related_words vs synonyms, check_officialese vs check_legalese, check_style vs check_translationese, check_compound_familiarity vs check_domain_terms). The only residual overlap is among the register/prose tools (check_style, check_officialese, classify_register) which touch similar metrics like impersonal voice and noun density, but the text guides selection by genre.

Naming Consistency4/5

Mostly a predictable snake_case scheme with check_* for every linting tool, which makes the large check family scannable. Deviations are minor: bare-verb analysis tools (tokenize, lemmatize, syllabify, paradigm) and the reversed spell_check rather than check_spelling.

Tool Count3/5

At 28 tools this is on the heavy side, though the domain (Estonian morphology, orthography, style, legal drafting) is genuinely broad and each check targets a distinct phenomenon. Still, the surface could likely be consolidated (e.g. merging the many narrow legal checks) without losing capability.

Completeness4/5

Covers the full language-tooling lifecycle: tokenize, morph analysis, lemma/POS, paradigm generation, syllabify, hyphenation, spell check, NER, plus a deep set of orthography/style/legal checks. Minor gaps remain, e.g. no syntax/agreement parsing and no general grammar-check for sentence structure beyond the curated rule lists.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers