{
  "markdown": "# kio-orzeczenia-mcp\n\n<!-- mcp-name: io.github.matematicsolutions/kio-orzeczenia-mcp -->\n\nMCP server (Model Context Protocol) for the case law of the **Krajowa Izba Odwolawcza (KIO) (National Appeals Chamber)** at the Urzad Zamowien Publicznych (Public Procurement Office) - the public database `orzeczenia.uzp.gov.pl`.\n\nIt lets Claude / Cursor / VS Code MCP agents consume KIO rulings with verifiable citations (signature + URL + date).\n\n**Status: POC v0.1.0** | License: **Apache-2.0** | Maintainer: [MateMatic](https://matematicsolutions.com)\n\n> **Preliminary warning.** The v0.1.0 connector is a proof-of-concept release. It fetches data from the public UZP case law database via HTML (no official REST API). Full legal disclaimer - see the \"Legal disclaimer\" section below. A dedicated smoke test and notification to UZP are required before production deployment.\n\n---\n\n## What KIO is\n\nThe Krajowa Izba Odwolawcza (National Appeals Chamber) is an administrative (quasi-judicial) body operating at the Urzad Zamowien Publicznych (Public Procurement Office) - KIO members are independent when adjudicating (art. 471 PZP) - which hears appeals against contracting authorities' decisions in public procurement proceedings (the Act of 11 September 2019 - Public Procurement Law). KIO rulings are made publicly available by UZP under the Act on access to public information.\n\nKIO rulings are not a source of law within the meaning of art. 87 of the Constitution of the Republic of Poland - they are reference material widely used in the practice of law firms dealing with public procurement.\n\n## Quickstart\n\n```powershell\n# Clone and enter the directory\ngit clone https://github.com/matematicsolutions/kio-orzeczenia-mcp.git\ncd kio-orzeczenia-mcp\n\n# Virtualenv\npython -m venv .venv\n.\\.venv\\Scripts\\Activate.ps1\n\n# Install\npip install -e \".[dev]\"\n\n# Offline test (signature parser)\npytest tests/test_signature.py -v\n\n# Smoke test (online - hits UZP, rate-limited 1 req/s)\npytest tests/test_smoke.py -v -m smoke\n\n# Run the server (stdio)\npython -m kio_orzeczenia_mcp.server\n```\n\n## Wiring into Claude Code\n\nAdd to `~/.claude.json` (or `.mcp.json` in the project):\n\n```json\n{\n  \"mcpServers\": {\n    \"kio-orzeczenia\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"kio_orzeczenia_mcp.server\"],\n      \"env\": {\n        \"KIO_MCP_RATE_LIMIT\": \"1.0\",\n        \"KIO_MCP_CACHE_DIR\": \"~/.matematic/cache/kio\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Code. After startup, 5 tools should be visible.\n\n### Windows 11 with Smart App Control\n\nSmart App Control blocks unsigned executables, which covers `uvx.exe`, `pip.exe`\nand the `kio-orzeczenia-mcp.exe` launcher that pip writes at install time. The `python.exe` and\n`py.exe` from the python.org installer are signed by the Python Software\nFoundation, so running the module through the interpreter works:\n\n```bash\npython -m pip install kio-orzeczenia-mcp\npython -m kio_orzeczenia_mcp\n```\n\n`pip.exe` is blocked for the same reason, so install with `python -m pip`, not\n`pip install`. If `python` is not on PATH, use the Windows launcher: `py -3 -m kio_orzeczenia_mcp`.\n\n```json\n{ \"mcpServers\": { \"kio-orzeczenia-mcp\": { \"command\": \"python\", \"args\": [\"-m\", \"kio_orzeczenia_mcp\"] } } }\n```\n\nDo not turn Smart App Control off to work around this - it cannot be re-enabled\nwithout reinstalling Windows.\n\n## 6 MCP tools\n\n### 1. `kio_search(query: SearchQuery) -> SearchResult`\n\nSearch over KIO case law. All fields optional.\n\n```jsonc\n// Arguments:\n{\n  \"phrase\": \"razaco niska cena\",\n  \"signature\": null,\n  \"date_from\": \"2024-01-01\",\n  \"date_to\": \"2024-12-31\",\n  \"pzp_article\": \"226\",\n  \"subject_index\": null,\n  \"inflection\": true,\n  \"page\": 1,\n  \"size\": 20\n}\n```\n\nReturns `{total, page, items: [OrzeczenieSummary]}`.\n\n### 2. `kio_get_orzeczenie(signature_or_id: str | int) -> Orzeczenie`\n\nFetches the full text of a single ruling.\n\n```jsonc\n// Arguments:\n\"KIO 2924/21\"   // string -> first search by signature to resolve internal_id (+1 req)\n15903           // int -> directly GET /Home/Details/15903 + /Home/ContentHtml/15903\n```\n\nReturns the full `Orzeczenie` with `content_text`, `sentence`, `reasoning` (if the parser can extract them), `pzp_articles`, `subject_index`, `doc_type`, `outcome`, `chamber_composition`, `parties`.\n\n`issue_date` may be `null` - UZP has no issue date for some older records. We do not substitute a placeholder date.\n\n### 3. `kio_recent(days: int = 30, limit: int = 20) -> list[OrzeczenieSummary]`\n\nThe most recent rulings from the last N days, sorted by date descending.\n\n```jsonc\n// Arguments:\n{ \"days\": 30, \"limit\": 20 }\n```\n\n### 4. `kio_by_pzp_article(article: str, limit: int = 20) -> list[OrzeczenieSummary]`\n\nRulings citing a specific PZP article. Uses the UZP server-side `Art` filter, which matches the provisions dictionary and is format-sensitive (`\"art. 226 ust. 1 pkt 5\"` hits, plain `\"226\"` does not). On an empty result the tool falls back to a full-text phrase search.\n\n```jsonc\n// Arguments:\n{ \"article\": \"art. 226 ust. 1 pkt 5\", \"limit\": 20 }\n{ \"article\": \"224 ust. 1\", \"limit\": 50 }   // \"art. \" prefix added automatically\n```\n\n### 5. `kio_get_pdf_url(signature_or_id: str | int) -> dict`\n\nReturns the URL to the PDF (rendered by UZP from .docx via Qt 4.8.7). **Does not fetch bytes** - we link to it.\n\n```jsonc\n// Returns:\n{\n  \"pdf_url\": \"https://orzeczenia.uzp.gov.pl/Home/PdfContent/15903?Kind=KIO\",\n  \"signature\": \"KIO 2924/21\",\n  \"internal_id\": 15903,\n  \"human_readable_citation\": \"Wyrok KIO z 2021-10-28, sygn. KIO 2924/21\"\n}\n```\n\n---\n\n### 6. `kio_coverage() -> Coverage`\n\nDeclares what this connector covers, where it comes from, and what it does NOT cover.\nEvery gap carries a stable id and a fallback. Call it before telling a user a ruling\n\"does not exist\" - the absence may be a gap in this connector, not in KIO case law.\n\n## 3 usage examples (natural language)\n\n### Example 1: \"KIO rulings on abnormally low price from the past year\"\n\nThe agent calls `kio_search`:\n\n```json\n{\n  \"phrase\": \"razaco niska cena\",\n  \"date_from\": \"2025-05-20\",\n  \"date_to\": \"2026-05-20\",\n  \"inflection\": true,\n  \"size\": 50\n}\n```\n\nResult: a list of OrzeczenieSummary with `human_readable_citation` ready to insert into a court filing.\n\n### Example 2: \"KIO rulings citing art. 226 sec. 1 point 5 PZP\"\n\nThe agent calls `kio_by_pzp_article`:\n\n```json\n{ \"article\": \"226 ust. 1 pkt 5\", \"limit\": 30 }\n```\n\n### Example 3: \"Ruling KIO 2924/21 - who were the parties and was the appeal upheld\"\n\nThe agent calls `kio_get_orzeczenie`:\n\n```json\n\"KIO 2924/21\"\n```\n\nResult: the full `Orzeczenie` with `parties`, `sentence`, `reasoning`.\n\n---\n\n## Limitations (POC)\n\n1. **Mapping signature -> internal_id requires a search** - if you query by signature, we make +1 req\n2. **Server-side PZP article filter is dictionary-based** - `Art` matches entries of the UZP provisions dictionary, so the format matters (`\"art. 226 ust. 1 pkt 5\"`, not `\"226\"`); on a miss we fall back to a phrase search, which is broader and needs verification\n3. **PDF not fetched** - only a link to the UZP page (product decision)\n4. **The sentence/reasoning parser is shallow** - in the POC we return `content_text` as plain text. Splitting into sections -> v1.0\n5. **Rate limit 1 req/s** - large lists may be slow. A 7-day cache for rulings (immutable) mitigates this.\n6. **UZP serves a fixed 10 results per page** - `size > 10` is stitched client-side from consecutive pages, i.e. +1 request per extra page\n7. **Scraping, not an API** - UZP rebuilt the search engine in July 2026 and every endpoint moved (see `DISCOVERY.md`). Run `pytest -m smoke` after any UZP-side change; `tests/test_parser_regression.py` guards the parser offline.\n\n## Cache\n\n- Rulings (immutable): **7 days**\n- Search result lists: **6 hours**\n- PZP dictionary (once implemented): **30 days**\n\nCache location: `~/.matematic/cache/kio/` (configurable via `KIO_MCP_CACHE_DIR`).\n\n## Audit log\n\nLocation: `~/.matematic/audit/kio-orzeczenia-mcp.jsonl`\n\nJSONL format (one entry per tool call). See `CONSTITUTION.md` Art. 3.\n\n**What is NOT logged**: the full text of a ruling (`content_text`, `reasoning`). We log only signatures and metadata.\n\n## Legal disclaimer\n\nThe data comes from the public UZP case law database (`orzeczenia.uzp.gov.pl`), made available under the Act of 6 September 2001 on access to public information and the Act of 11 September 2019 - Public Procurement Law.\n\nThe connector:\n\n- does not modify the source data,\n- does not de-anonymize the parties to a proceeding beyond what UZP publishes,\n- does not circumvent any technical protections,\n- identifies itself with the User-Agent header `matematic-kio-mcp/{version} (+https://matematic.co)`.\n\n**Pre-release blocker.** Before publishing the repository on GitHub, a notification to UZP (`kontakt@uzp.gov.pl`) about launching the connector is planned - User-Agent, query limit, nature of access. Status: TODO.\n\nIn case of objections from UZP or other parties - contact: `kontakt@matematic.co`.\n\n## License\n\nApache-2.0. See `LICENSE`.\n\n## Project constitution\n\nSee [`CONSTITUTION.md`](CONSTITUTION.md) - 4 governance principles (public data, rate limit, audit log, citations).\n\n## Other open connectors for Polish law\n\nOpen-source connectors by MateMatic that complement the scope of this repository:\n\n- [`mcp-saos`](https://github.com/matematicsolutions/mcp-saos) - SAOS (Supreme Court, Supreme Administrative Court, common courts)\n- [`mcp-eu-sparql`](https://github.com/matematicsolutions/mcp-eu-sparql) - EU law via Cellar SPARQL\n- [`mcp-isap`](https://github.com/matematicsolutions/mcp-isap) - Journal of Laws, Monitor Polski, ministerial gazettes (Sejm ELI API)\n\nExternal catalog of legal sources: [`worldwidelaw/legal-sources`](https://github.com/worldwidelaw/legal-sources) (bulk harvest scripts, MIT).\n",
  "bytes": 9778,
  "sha": "62af72d643de8410e9ced89d40ab40495e6c9ed02aaba97e17417e6a79f7b833",
  "repo_slug": "matematicsolutions/kio-orzeczenia-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_matematicsolutions_kio_orzecze_5bf7ab1b/readme"
}