
Prozorro
io.github.kotiniiqqPublished by GitHub account kotiniiqqv0.1.1Updated Oct 24, 2026
Ukrainian public procurement (Prozorro): open tenders, plans, competitors, red flags. No keys.
Overview
Local MCP server that syncs Ukraine's public Prozorro procurement data and lets an assistant search tenders, plans, buyers and suppliers and compute red flags.
- What you can do
- Search and read tenders and upcoming plans by words, CPV code, region, status, amount or deadline, and open a single tender with its items, lots, bids, winner and documents. Look up buyers and suppliers by EDRPOU code or name and profile their wins, buyers, categories, win rate and discounts. Compare competitors and head-to-head results, and get market overviews with counts, values and unit-price spreads. Compute four red flags for a buyer with evidence and links. Manage saved searches and digests of new tenders, and check which regions and periods are synced.
- When to use it
- Useful when you follow Ukrainian public procurement: finding open tenders in a region or category, seeing what buyers plan to purchase, profiling suppliers and competitors, or screening a buyer for warning signs. Data is computed locally from a synced copy, so it suits recurring regional or category monitoring rather than one-off lookups outside the synced area.
- Requirements
- Runs locally over stdio as a Python package, started with uvx or pip; uv or Python is needed. No API keys, since the Prozorro API is public, and no environment variables are required, though PROZORRO_MCP_DB can relocate the database. You must sync regions and a period first; a busy oblast takes about 20 minutes per week of data and roughly 350 MB on disk. Network access is needed for syncing.
Installation
In SourceWeft
- Open Prozorro in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
prozorro-mcp
An MCP server and a command-line tool for Prozorro, Ukraine's public procurement system. It keeps a local copy of the official open data for the regions you choose. Then you can ask an AI assistant (Claude, Cursor, VS Code Copilot and others), or the CLI on its own, things like:
- "Which open tenders for laboratory reagents are in Lviv oblast, and when are the deadlines?"
- "What will hospitals in my region buy next month? Show plans that are not tenders yet."
- "Who wins most of the flour tenders here, and at what price per kilogram?"
- "Who do we usually compete with (EDRPOU 12345678), and how often do we win against them?"
- "Any red flags at this buyer: single bidders, one supplier taking most of the money?"
Every number is computed by code from the data, and the assistant only writes the text. No API keys are needed: the Prozorro API is public, and nothing here calls an LLM.
[prozorro-mcp flow]Ukrainian step-by-step guide for non-developers: docs/guide.uk.md.
Try it in one minute (bundled demo, no sync)
You need uv (or plain pip install prozorro-mcp):
The demo is a real snapshot of Lviv oblast for one week (5–12 October 2026): 5,479 tenders, 1,120 of them with public bids, and 1,619 upcoming plans. Contact persons were removed.
Claude Desktop: one-click extension
Download prozorro-mcp.mcpb
and open it (or drag it into Settings → Extensions). Claude Desktop installs Python and the package by
itself, so there is nothing else to install and no config to edit. In the install dialog, type your
oblasts (for example Львівська, Волинська) and the days of history.
Your regions download in the background; until the first download finishes, Claude says the data is not ready and shows the progress. If you leave the settings empty, Claude asks which oblast and how many days to download. Every start fetches what changed since the last one. To add a region later, ask Claude: "download Volyn oblast for the last two weeks".
Connect it to other AI clients
The server runs locally over stdio. Pick your client:
Claude Code
Claude Desktop without the extension: Settings → Developer → Edit Config. The file is
%APPDATA%\Claude\claude_desktop_config.json on Windows and
~/Library/Application Support/Claude/claude_desktop_config.json on macOS:
Cursor (~/.cursor/mcp.json) and Windsurf, Cline and other clients: the same mcpServers block
as Claude Desktop.
VS Code (.vscode/mcp.json):
To try it on the demo first, add "--demo" after "serve". Restart the client after editing the config.
ChatGPT and claude.ai in the browser only connect to remote servers over HTTPS. See HTTP mode.
Sync your own data
- Regions work in any spelling:
Львів,львовская,Lviv,Kyiv city,Київська. Repeat--regionfor several. Military units hide their address by law, so their tenders have no region. Add them with--region "без регіону". - First sync walks the change feed backwards, newest change first, so tenders that are open right now
arrive in the first minutes, and stops at the start of the period. A busy
oblast takes about 20 minutes per week of data (Lviv: about 5,500 tenders and as many plans, roughly
350 MB on disk), mostly waiting on the public API, which is used
politely with 5 requests at a time and retries.
--cpv 33(or--cpv реактиви) keeps only your categories. - Next runs (
prozorro-mcp syncwith no options) fetch only what changed since the last run. Ctrl+C is safe: run the command again and it continues from where it stopped. - From the server:
prozorro-mcp serve --sync-on-startfetches what changed in the background when the client starts it (add--regionand--daysto widen the coverage). Before the first sync, the data tools returnno_datawith a request to ask the user for an oblast and a period; during a sync, results carrysync_in_progress. - Status:
prozorro-mcp statusshows what is covered. Data lives in~/.prozorro-mcp/data.db; setPROZORRO_MCP_DBto move it.
Use it without an AI client
The same numbers, as a table, CSV (opens in Excel with Cyrillic intact) or JSON. Install the command
once with uv tool install prozorro-mcp, and then:
Run sync and digest every morning with Task Scheduler or cron (the guide shows how), and you have a
daily list of new tenders without opening any website.
Tools
Eleven tools only read the local database. Each one declares readOnlyHint: true,
destructiveHint: false, idempotentHint: true and openWorldHint: false. Three more exist only in the
local stdio server, not in HTTP mode, and are marked for what they do: sync_data downloads data
(readOnlyHint: false, openWorldHint: true), watch_add saves a search and watch_remove deletes one
(destructiveHint: true). The server asks the assistant to start a download only after the user agrees.
When a question needs data that is not synced, for example another oblast or an older period, the
result says so and gives the exact sync command. It does not return an empty list that looks like
"nothing exists".
How the numbers are defined
- Open tender: status
active.tenderingoractive.enquiries, and the deadline has not passed as of the last sync. Prozorro sometimes changes the status late. - Competitive procedure: open, below-threshold, price quotation, competitive dialogue, framework
selection and similar types.
reporting(a direct contract) andnegotiationare not competitive. The full list is insrc/prozorro_mcp/models.py. - Decided tender: one that has an active award.
- Unit price: award ÷ quantity. It is computed only for tenders with exactly one item, and grouped
by the full CPV code and unit, so kilograms are never compared with tonnes. Other tenders are counted
as
excluded. - Win rate: decided tenders won ÷ decided tenders bid in. Bids become public only after the auction.
- Discount: (expected value − award) ÷ expected value, for competitive tenders without lots.
Red flags
A flag is a reason to look closer, not proof of wrongdoing.
Evals
They run without keys or network, all computed by code: prozorro-mcp eval --suite all. The latest
results are in evals/RESULTS.md.
- Flags: 35 labelled cases, including near-threshold negatives such as 29% vs 30% above the median or exactly half the money. Precision and recall are 1.0 for every flag.
- Regions and CPV words: 94 spellings, 98.9% recognized. The one miss is shown in the results.
- Reconcile: buyer and category totals from the analytics are checked against an independent recount over the raw JSON of the demo snapshot. 35 aggregates, 0 mismatches.
HTTP mode
The same tools are served over streamable HTTP. To reach it from ChatGPT or claude.ai, put it behind a reverse proxy with HTTPS (Caddy, nginx). Version 1 has no authentication: the data is public and read-only. Add rate limits at the proxy before exposing it.
Limits
- Local copy: you sync what you need. All of Ukraine for a month is about 100k requests to the public API, and that is not the intended local use.
- The period means last modification: a sync covers tenders changed in the last N days. Old tenders that are still being updated come along.
- Hidden addresses: tenders of military units have no region in Prozorro (see
--region "без регіону"). - CPV by words matches the official ДК 021 names. When the words are too broad, pass a code prefix. Tools echo the categories they used.
Development
The code is split by job: api (feed client) → sync → store (SQLite) → analytics (every number)
→ server (MCP) and cli. normalize handles regions and CPV.
Roadmap
- v2: a
price_raised_after_signingflag, for contracts whose price grew through amendments. This needs a sync of contract changes. - Later: a hosted HTTP instance for ChatGPT and claude.ai; Telegram or e-mail alerts as a separate service; owners of companies from the EDR register.
- Not planned: a "chance to win" or "recommended bid". It would be a guess dressed as a fact.
Contact
Feedback, ideas, job offers or custom projects (n8n, MCP, AI automation): [email protected]. Bug reports and feature requests are welcome in Issues.
Data and credits
Tender and plan data come from the public Prozorro API. ДК 021 (CPV) names and the region list come from ProzorroUKR/standards (Apache-2.0); see NOTICE.
MIT License.
Source: README.md at commit 4801316
Tools
0Version history
1- v0.1.1LatestOct 13, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts