{
  "markdown": "# @pipeworx/ted-eu\n\nTED (Tenders Electronic Daily) MCP — EU public procurement notices from national, regional and\nmunicipal buyers in every member state. ~700k notices a year; 1.3M construction notices on file.\nKeyless.\n\nPart of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1476+ live data sources.\n\n## Tools\n\n- `search_notices(query?, country?, category?, cpv?, date_from?, date_to?, open_only?, value_min?, value_max?, notice_type?, sort?, limit?, page?)`\n  — newest first by default. `category` takes plain English (\"construction\", \"IT services\",\n  \"medical equipment\") and resolves to CPV; `cpv` takes the code if you have it.\n- `get_notice(publication_number)` — one notice with its full buyer-written description.\n  `notice_id` / `id` accepted as aliases.\n- `cpv_lookup(term)` — plain-English category → CPV code, or what a CPV code covers.\n- `ted_search_awards(query?, winner?, buyer?, country?, winner_country?, category?, cpv?, date_from?, date_to?, value_min?, value_max?, sort?, limit?, page?)`\n  — contract-AWARD notices only: who won, for how much. Every winner on the notice is returned\n  (lots and consortium members), with `winner_countries` and `decision_date` where published.\n- `ted_supplier_history(supplier, country?, category?, cpv?, date_from?, date_to?, limit?, page?)`\n  — everything a named economic operator has won, newest first, with a summary: awarded value by\n  currency, top buyers, top CPV categories. Name matching is partial (\"Siemens\" covers every\n  Siemens entity).\n- `ted_buyer_profile(buyer, country?, category?, cpv?, date_from?, date_to?, limit?, page?)`\n  — everything a named contracting authority has awarded, with top winners and top categories.\n  Use the authority's own-language name (\"Ville de Paris\", not \"City of Paris\").\n\n## Auth\n\nNone. The public search endpoint answers unauthenticated.\n\nNote that `GET /notices/{id}` is NOT keyless — it 400s with \"Missing Authorization header\" — so\n`get_notice` fetches through the public search endpoint filtered on publication-number instead.\nSame data, no key.\n\n## What comes back\n\nEach notice is flattened out of TED's raw shape:\n\n| field | notes |\n|---|---|\n| `title` / `title_language` | English where TED has it (it usually does — all 24 languages are published), otherwise the notice's own language, and the language is always stated |\n| `title_original` | the buyer's own title, in their language, when it differs |\n| `buyer`, `buyer_country`, `buyer_city` | contracting authority |\n| `value`, `currency` | **buyer-entered and unvalidated by TED.** Not always EUR — Czech awards come back in CZK, Hungarian in HUF. Sorting by value surfaces the typos first |\n| `deadline` | deadline for receipt of requests |\n| `winner` | on award notices (`can-standard`) |\n| `notice_type` | `cn-standard` call for tenders · `can-standard` award · `pin-only` prior information |\n| `url` | the notice on ted.europa.eu |\n\nThe envelope carries `total`, `partial` and `sorted_by`. **`partial: true` means TED timed out and\nreturned an incomplete result set** — the count and total are lower bounds, not an answer.\n\n## Free text\n\n`query` searches the **full notice** via TED's `FT` operator, not just the title. It escalates:\n\n1. the whole string as an exact phrase,\n2. its first three words AND-ed, appearing anywhere,\n3. its two most specific words AND-ed.\n\nIt stops at the first attempt that finds anything and reports which in `match_strategy`. This\nmatters because `~` phrase-matches: the old title-or-description phrase search returned **zero**\nfor every ordinary multi-word query real callers sent — \"backup disaster recovery business\ncontinuity\", \"data center colocation IaaS PaaS\", \"GRC risk management compliance governance\" were\nall 0 while the AND-ed forms return real notices.\n\nWrite `OR` between two words to hedge a spelling — `fuze OR fuse artillery` becomes\n`(fuze OR fuse) AND artillery`, because AND-ing both spellings asks for the one notice that\ncontains both.\n\nThere is deliberately **no any-word fallback**. It was measured and cut: it answered \"fuze OR fuse\nartillery ammunition\" with 42 notices led by *printed matter*. A zero with an explanation beats a\npage of things you did not ask for.\n\n## Awards\n\nThe award tools search `notice-type IN (can-standard can-social can-desg can-tran)` — the four\ncontract-award subtypes. Legacy pre-eForms award forms are mapped into these by TED, so coverage\nreaches back years (2022 alone has ~296k `can-standard` notices), 2.8M+ award notices in total.\n`can-modif` (modification of an existing contract) and `veat` (intent to award) are outside the\ndefault set — filter `search_notices` by `notice_type` if you want those.\n\nTwo caveats every award response states, because they are the two things a caller will otherwise\nget wrong:\n\n- **Coverage:** TED is above-threshold EU procurement only. Below-threshold national contracts are\n  published on national portals and never appear — a supplier with no TED awards may still win\n  plenty of smaller public work.\n- **Values:** as published by the buyer, in the notice's own currency, normally excluding VAT, and\n  unvalidated by TED. Summaries sum **by currency** — there is no cross-currency grand total,\n  because that would be a made-up number.\n\n`winner-name` upstream is a per-language map of arrays carrying every winner (one per lot,\nconsortium members, duplicates included). The award tools dedupe and return the full list —\ntaking only the first, as a single `winner` string would, silently drops co-winners.\n\n## Upstream quirks worth knowing\n\n- **POST only.** `GET /v3/notices/search` is 405.\n- **`fields` must be non-empty.** Omitting it is a 400 \"Validation error on field fields\", which\n  reads like an auth wall but isn't.\n- **Sorting is not a request field.** It goes inside the query string: `... SORT BY publication-date\n  DESC`. Without it the result order is not recency, and a 2016 prior-information notice was the top\n  hit for German construction tenders.\n- **Every text field is a per-language map.** `notice-title` carries all 24 official languages and\n  `buyer-name` a map of arrays. Handing them back raw gives a caller a Latvian title for a German\n  tender, and costs ~4KB of duplicated title per notice.\n- **The real title field is `title-proc`** (the buyer's own) — `notice-title` is TED's generated\n  \"Country – CPV label – buyer title\" summary. Asking for a field that doesn't exist returns nothing\n  rather than erroring, so a typo'd field name looks like missing data.\n- **CPV is not a dense 01-99 range.** Division 28 does not exist, and TED answers a nonexistent one\n  with `QUERY_UNSUPPORTED_FIELD_VALUE`, which reads as \"found nothing\". This pack validates the\n  division first and names the valid ones.\n- **Dates are `YYYYMMDD`** in queries (not `YYYY-MM-DD`) and come back stamped with a UTC offset.\n\n## Data source\n\n`https://api.ted.europa.eu/v3/notices/search` — POST, JSON expert-query body.\nDocs: https://docs.ted.europa.eu/api/\n\nThe endpoint enumerates all 1,830 supported field names in its 400 message when you ask for an\nunsupported one — the cheapest way to find a field without guessing.\n\n## Quick Start\n\nAdd to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):\n\n```json\n{\n  \"mcpServers\": {\n    \"ted-eu\": {\n      \"url\": \"https://gateway.pipeworx.io/ted-eu/mcp\"\n    }\n  }\n}\n```\n\n### What this endpoint actually serves\n\n`tools/list` at `https://gateway.pipeworx.io/ted-eu/mcp` returns the tools in the table\nabove **plus the shared Pipeworx meta-tools** — `ask_pipeworx`,\n`discover_tools`, `search_within`, `remember`/`recall` and the rest of the\ngateway-wide set. So the tool count you see is larger than this table: a\nsingle-pack endpoint currently lists roughly 30 shared tools alongside the\npack's own. The connection's `initialize` response states its exact scope, and\nis the authoritative answer for a given day.\n\nThis is deliberate, not multiplexing by accident. The meta-tools are what let a\nscoped connection answer a question this pack does not cover — via\n`ask_pipeworx`, which routes across the whole catalog — without you adding a\nsecond MCP server. There is currently no way to mount a pack endpoint without\nthem; if the extra schemas cost you more context than the routing is worth,\nconnect to the full gateway once rather than to several pack endpoints.\n\nOr connect to the full Pipeworx gateway to get every pack's tools listed\ndirectly, instead of just this one's:\n\n```json\n{\n  \"mcpServers\": {\n    \"pipeworx\": {\n      \"url\": \"https://gateway.pipeworx.io/mcp\"\n    }\n  }\n}\n```\n\nBoth URLs reach the same gateway and the same 1476+ data sources. The\nonly difference is which pack's tools are listed **directly**; `ask_pipeworx`\nreaches all of them from either one.\n\n## Using with ask_pipeworx\n\nInstead of calling tools directly, you can ask questions in plain English —\nthis works on the pack endpoint above as well as on the full gateway:\n\n```\nask_pipeworx({ question: \"your question about Ted Eu data\" })\n```\n\nThe gateway picks the right tool and fills the arguments automatically.\n\n## More\n\n- [Docs and guides](https://pipeworx.io/docs)\n- [pipeworx.io](https://pipeworx.io)\n\n## License\n\nMIT\n",
  "bytes": 9176,
  "sha": "14e5dbe20e0a3c676de447fe0a80da5e2c7cf108f3500cdc4857bb1e90117821",
  "repo_slug": "pipeworx-io/mcp-ted-eu",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_pipeworx_io_ted_eu_749b55e0/readme"
}