mcp-saos
The mcp-saos server provides access to the SAOS (System Analizy Orzeczeń Sądowych) historical archive of Polish court judgments, with three main tools:
search: Full-text and filtered search across judgments. Supports filtering by:Court type:
COMMON,SUPREME,CONSTITUTIONAL_TRIBUNAL,NATIONAL_APPEAL_CHAMBER(KIO)Judge name, legal basis (e.g.,
art. 415 kc), case number, referenced regulation, and date range (dateFrom/dateTo)Pagination (10–100 results per page)
get_judgment: Retrieve full judgment details by numeric ID — includes metadata (case number, court, date, panel composition, legal bases), a summary, and the first 2000 characters of text.search_by_case: Quick lookup by case signature (e.g.,I ACa 772/13).
Important limitations:
The database is a historical archive — data ingestion stopped around 2016–2018; recent case law is not reliably available.
Administrative courts (WSA/NSA) are not indexed.
OCR artifacts may distort dates; case numbers are more reliable identifiers.
mcp-saos
Installation (one command)
Published on npm + the MCP Registry (io.github.matematicsolutions/mcp-saos). Run without cloning:
npx -y @matematicsolutions/mcp-saosMCP client configuration (stdio):
{ "mcpServers": { "mcp-saos": { "command": "npx", "args": ["-y", "@matematicsolutions/mcp-saos"] } } }(Building from source - below.)
An MCP (Model Context Protocol) server for Polish case law - a connector to SAOS (System Analizy Orzeczen Sadowych - the courts' public case-law database, run by Fundacja ePanstwo).
Part of the MateMatic "Polish legal AI" project. It runs as a separate process communicating over stdio; the chat template (a fork of mike) calls it through the MCP protocol.
Related MCP server: mcp-nsa
What SAOS is
An open database of Polish court judgments. Public REST API, no key required.
Coverage caveat: coverage is broad and includes current judgments (2024-2026 are well populated), but it is uneven by court type, and some Supreme Court resolutions exist only as citations in other judgments. Verify anything critical against sn.pl, orzeczenia.ms.gov.pl, trybunal.gov.pl.
The database covers: common courts (COMMON), the Sad Najwyzszy (Supreme Court, SUPREME), the Trybunal Konstytucyjny (Constitutional Tribunal, CONSTITUTIONAL_TRIBUNAL), the KIO (National Appeal Chamber, NATIONAL_APPEAL_CHAMBER). Administrative courts (WSA/NSA) - no data in SAOS.
MCP tools
Tool | Description |
| Full-text and filtered search (court, judge, legal basis, dates) |
| Full judgment by ID from SAOS |
| Shortcut: search by case number (e.g. "I ACa 772/13") |
| Citator: is the judgment still good law? Finds later citing judgments and scans them for overruling language near the signature |
saos_cite_check - the citator
Give it a case number (a placeholder here; use a real one):
{ "caseNumber": "III CZP NN/RR" }It searches SAOS full-text for later judgments citing that signature, scans
their reasoning for departure phrases ("odstepuje od pogladu wyrazonego",
"nie podziela pogladu", "traci moc uchwala", "uchwala skladu siedmiu sedziow"
and others) within ~500 characters of the signature, and returns one of four
verdicts: przelamanie_wykryte, uchwala_skladu_powiekszonego,
nadal_cytowany, brak_cytowan_w_saos. Each hit includes a +-200 character
fragment for human verification.
Every phrase on the list was verified against live SAOS data - the evidence table, the algorithm and the honest-limits section are in docs/CITE-CHECK.md. The short version: no hits does NOT mean the judgment is still good law, and every response says so.
Requirements
Node.js >= 18
npm >= 9
Internet access (live API saos.org.pl)
Installation and build
git clone https://github.com/matematicsolutions/mcp-saos
cd mcp-saos
npm install
npm run buildAfter npm run build, the entry point is dist/index.js.
Standalone run (test)
node dist/index.js
# the server listens on stdin/stdout, diagnostic logs go to stderrWiring into the chat template (fork of mike) - mcp-servers.json
Add an entry to your client's MCP configuration (e.g. mcp-servers.json):
{
"name": "saos",
"transport": "stdio",
"command": "node",
"args": ["C:/Users/<YOUR-USER>/mcp-saos/dist/index.js"],
"enabled": true
}Provide the absolute path to dist/index.js. On Windows use forward slashes /
or double backslashes \\.
Tests
npm run build
npm test # offline: drift test + unit tests (parser, window scan, phrase patterns)
node test/smoke.mjs # live: 5 checks against the real SAOS API, including the citatorThe smoke test checks tools/list (4 tools), search, search_by_case,
a Constitutional Tribunal lookup and saos_cite_check on a Supreme Court
resolution with known later treatment.
Architecture
stdin --> MCP JSON-RPC (stdio transport) --> src/index.ts
|
SAOS REST API
https://www.saos.org.pl/api
/search/judgments
/judgments/{id}
stdout <-- formatted text responses <--No external dependencies for HTTP/JSON - requests go through the built-in node:https.
The only production dependency: @modelcontextprotocol/sdk.
Limitations and known pitfalls
pageSizehas a hard lower limit of 10 (SAOS returns HTTP 400 for less) - the server automatically enforces a minimum of 10.courtType=ADMINISTRATIVEreturns empty results - SAOS does not index WSA/NSA.Dates in the database may contain OCR artifacts (e.g. "3013-12-04") - the case number is more reliable than the
judgmentDatefield.Coverage is uneven by court type - the server states the relevant caveats in every tool response.
saos_cite_checkis a heuristic. It reads the top citing judgments only, its phrase list cannot cover every way a court departs from a line of case law, and no hits does not confirm the judgment is current.
License
MIT - see the LICENSE file for details. Judgment data: Fundacja ePanstwo, open license (public API with no usage restrictions).
Part of the MateMatic legal stack
This server is one of five MCP connectors covering Polish jurisdiction + EU law, used by Patron (AGPL-3.0) and any other MCP-aware legal AI agent.
mcp-saos (this repo) - common courts, Supreme Court, Constitutional Tribunal, KIO
mcp-nsa - NSA + 16 WSA administrative courts
mcp-isap - Polish legislation (Dz.U. + M.P.)
mcp-krs - Polish company registry (KRS)
mcp-eu-sparql - EU law + CJEU (EUR-Lex)
All five MCP servers share the same structuredContent.citations
contract: each tool returns an array of {title, url, snippet?, ...metadata}
that legal agents can render directly in their citation panel.
See matematicsolutions/.github for the full org profile.
Available Tools
3 toolsget_judgmentARead-onlyIdempotent
Pobiera pelne orzeczenie z SAOS po jego numerycznym ID. Zwraca metadane (sygnatura, sad, data, sklad, podstawy prawne), streszczenie (jesli dostepne) oraz pierwsze 2000 znakow tresci. ID orzeczenia pochodzi z wynikow narzedzia 'search' lub 'search_by_case'. Bledy: missing_arg (brak id), not_found (id poza baza), upstream_error.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Numeryczne ID orzeczenia w bazie SAOS, np. 352475 lub '31345'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, and non-destructive behavior. The description adds details about content truncation (first 2000 characters) and summary availability, which go beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph of three sentences, each serving a purpose: action, return contents, and source/errors. It is front-loaded with the core function and contains no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter retrieval tool without output schema, the description covers purpose, input source, errors, and return structure (metadata, summary, truncated content). It is fully adequate for an agent to understand and use the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a descriptive parameter name and type. The description adds context about ID source (from search tools) and error handling, but the schema already adequately documents the parameter meaning. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (pobiera pelne orzeczenie) and the resource (SAOS by numeric ID). It lists return contents and differentiates from sibling tools (search, search_by_case) which are for finding IDs, not retrieving full records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use: when an ID is available from search or search_by_case. It lists possible errors (missing_arg, not_found, upstream_error) providing guidance on handling. While it doesn't explicitly state when not to use, the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchARead-onlyIdempotent
Przeszukuje baze orzeczen sadow polskich w SAOS (System Analizy Orzeczen Sadowych). Pokrycie obejmuje takze orzeczenia biezace (lata 2024-2026 sa dobrze reprezentowane), ale jest nierowne wg typu sadu. Sady administracyjne (WSA/NSA) NIE sa indeksowane. Daty bywaja znieksztalcone przez OCR - weryfikuj sygnature i date w zrodle. Przydatny do: analizy linii orzeczniczej, precedensow, wyszukiwania po tresci / sygnatuze / sedzim / podstawie prawnej. Bledy: invalid_court_type (zly enum), upstream_error (HTTP/timeout API).
| Name | Required | Description | Default |
|---|---|---|---|
| all | No | Wyszukiwanie pelnotekstowe - slowo lub fraza w tresci orzeczenia. | |
| dateTo | No | Data orzeczenia do (format YYYY-MM-DD), np. '2016-12-31'. | |
| dateFrom | No | Data orzeczenia od (format YYYY-MM-DD), np. '2015-01-01'. | |
| pageSize | No | Liczba wynikow na strone (min 10, max 100). Domyslnie 10. | |
| courtType | No | Typ sadu: COMMON=sady powszechne, SUPREME=Sad Najwyzszy, CONSTITUTIONAL_TRIBUNAL=Trybunal Konstytucyjny, NATIONAL_APPEAL_CHAMBER=Krajowa Izba Odwolawcza (KIO). NIE uzywaj ADMINISTRATIVE - sady admin nie sa w SAOS. | |
| judgeName | No | Nazwisko sedziego, np. 'Kowalski'. | |
| legalBase | No | Podstawa prawna, np. 'art. 415 kc' lub 'art. 6 RODO'. | |
| caseNumber | No | Sygnatura akt, np. 'I ACa 772/13' lub 'IV CSK 123/15'. | |
| pageNumber | No | Numer strony (od 0). Do paginacji wynikow. | |
| referencedRegulation | No | Przywolany akt prawny, np. 'ustawa o ochronie danych osobowych'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive. Description adds valuable behavioral details: coverage uneven by court type, dates may be OCR-distorted, possible error types. This goes beyond annotations to set proper expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is a single paragraph of 5 sentences, front-loaded with purpose, no redundant sentences. Every sentence adds information about coverage, limitations, use cases, or errors.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers scope, limitations, use cases, and errors. Missing details about result format or pagination behavior (though pageNumber parameter exists). Given no output schema, a brief note on return structure would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters are already well-documented. Description adds marginal value by warning about date distortion (relevant to dateFrom/dateTo) and mentioning courtType enumeration pitfalls, but does not elaborate on each parameter beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description starts with clear verb 'Przeszukuje' (searches) and specific resource 'baze orzeczen sadow polskich w SAOS'. It distinguishes from siblings by implying this tool is for broad search across multiple fields, while siblings like 'search_by_case' are likely more specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description provides clear context for when to use (analysis of case law, precedents, searching by content/signature/judge/legal basis) and explicitly states what not to use (administrative courts not indexed). However, it does not directly compare to sibling tools or give explicit when-not-to-use scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_caseARead-onlyIdempotent
Skrot: szuka orzeczenia po sygnaturze akt (np. 'I ACa 772/13', 'IV CSK 123/15', 'KIO/UZP 100/12'). Odpowiednik search z parametrem caseNumber. Jesli sygnatura nie znajdzie sie w SAOS, sprawa moze byc z sadu administracyjnego (WSA/NSA - nieindeksowane) lub jeszcze nieopublikowana w bazie. Bledy: missing_arg (brak caseNumber), upstream_error.
| Name | Required | Description | Default |
|---|---|---|---|
| caseNumber | Yes | Sygnatura akt, np. 'I ACa 772/13'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, and open-world. The description adds valuable context about potential missing results and reasons, and lists specific errors, enhancing transparency beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise paragraph covering purpose, examples, usage equivalence, failure scenarios, and errors, with no superfluous content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one required parameter and no output schema, the description addresses purpose, parameter, error handling, and limitations, making it sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema itself defines the parameter. The tool description provides examples and explains the format, adding modest value but not essential new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it searches for judgments by case number, provides examples, and distinguishes it from the sibling 'search' tool by noting it is an equivalent shortcut with a specific parameter.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that it is equivalent to 'search' with caseNumber, and clarifies scenarios when results may be missing (administrative court or not yet published). It gives error types but lacks explicit when-not-to-use or alternative tool guidance.
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. Dates show when Glama detected each change.
3 tool updates
v1.1.2- First observed
get_judgment - First observed
search - First observed
search_by_case
TDQS
Each tool targets a distinct operation: retrieving a judgment by ID, general search, and search by case number. There is no overlap in functionality.
Tool names mostly follow a verb_noun or verb_preposition_noun pattern, but 'search' is just a verb while 'get_judgment' uses get. However, 'search_by_case' is descriptive and consistent with 'search'.
Three tools are appropriate for a focused database query server. Each tool serves a clear purpose without redundancy.
Core operations (search and retrieve) are present, but there are gaps: no pagination for search results, and full judgment text is limited to 2000 characters. Missing features like listing courts or fetching full text could hinder some workflows.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for 3M+ Polish companies — KRS & CEIDG financials, ownership, and industry search.
Semantic search over Polish law and case law, citing the exact in-force article.
Slovak court decisions as MCP tools. 12,000+ decisions, GDPR-compliant, pseudonymized, SLA-backed.
Polish law: search statutes (ISAP), court rulings, verify citations. Free tier + paid plans + x402.
Related MCP Servers
- AlicenseAqualityCmaintenanceProvides access to Polish court judgments from the SAOS database. Enables search and retrieval of judgments with full-text search, filtering, and detailed case information.3201Apache 2.0
- AlicenseAqualityCmaintenanceMCP server for Polish administrative case-law (NSA + regional administrative courts, CBOSA) with ECLI and verifiable citations.6387MIT
- AlicenseAqualityAmaintenanceMCP server for Polish legislation (ISAP / Sejm) — search acts (Dz.U., M.P.) and fetch full texts with ELI identifiers and verifiable citations.31081MIT
- AlicenseAqualityAmaintenanceMCP server for Polish public-procurement rulings (KIO / Krajowa Izba Odwoławcza) with verifiable citations.51Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/matematicsolutions/mcp-saos'
If you have feedback or need assistance with the MCP directory API, please join our Discord server