vergabe-api: German public procurement notices

io.github.applehorsefrogPublished by GitHub account applehorsefrogv0.4.0Updated Oct 25, 2026

German public tenders as normalised JSON (CPV, NUTS, deadlines). Free sample; search paid via x402.

Overview

AI-generated overview

Remote MCP server for German public procurement notices, with free samples and statistics and paid full-text search and notice lookup via x402 USDC payments.

What you can do
Fetch the latest German public calls for tenders, optionally filtered by CPV code or prefix, with personal contact data removed and CC0 licensing. View how many notices were imported per publication day over the last 30 days, split by kind. Read the API descriptor covering endpoints, prices, x402 payment details, data source, licence and legal notice. Search notices by full text and structured filters such as CPV, NUTS, deadline, buyer type and value, and retrieve a single notice by UUID with lots, deadlines, links and winners. The two search tools are paid and, on the remote endpoint, only return the HTTP URL and payment requirements rather than data.
When to use it
Use it when you need to find or monitor German public tender opportunities, awards or procurement statistics and want the data as normalised JSON inside an assistant. It suits procurement research and bid screening; the free tools alone are enough for a quick look at recent calls.
Requirements
Remote Streamable HTTP endpoint, no account or API key. Paid tools cost $0.01 and $0.002 per call in USDC on Base mainnet via x402; the remote server cannot pay, so payment needs the local stdio server (Node 20+, npx) with a funded wallet key in VERGABE_PAYER_KEY, or another x402 HTTP client.
Before you install
Paid tools spend real USDC on Base mainnet per call. The local server needs a wallet private key in VERGABE_PAYER_KEY, which signs transfer authorisations; use a dedicated low-balance wallet. The remote endpoint cannot pay and returns payment requirements instead of results. Queries and payment details go to a third-party operator.

Installation

In SourceWeft

  1. Open vergabe-api: German public procurement notices in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.applehorsefrog%2Fvergabe-api/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "vergabe-api-german-public-procurement-no": {
      "type": "http",
      "url": "https://vergabe-api.applehorsefrog.workers.dev/mcp"
    }
  }
}

README

vergabe-api

German public procurement notices, above and below the EU thresholds, as a normalised JSON API for software agents and procurement tools. Paid per call with x402 (HTTP 402, USDC). No account, no API key, no subscription.

Base URL: https://vergabe-api.applehorsefrog.workers.dev (a branded domain under viono-insights.de will follow). Payments settle on Base mainnet in USDC since 2026-09-14; the facilitator is PayAI.

What you get

Every day roughly 1,000 notices are published on the official German notification service (Datenservice Öffentlicher Einkauf, eForms-DE). The raw feed is a ZIP of XML files, 20 MB per day, with organisation contacts, lots, deadlines and classifications scattered over UBL extensions. This API turns each notice into one flat record:

fieldmeaning
id, notice_id, versionnotice UUID and version
published, issue_datepublication day of the export, issue date from the notice
kindcompetition (calls for tenders), result (awards), planning, change
notice_type, subtype, procedure, legal_basis, natureeForms codes (cn-standard, open, vgv, works ...)
title, descriptionGerman text, personal contact data removed
cpv_main, cpv_additionalCPV codes without check digit
buyer_name, buyer_type, buyer_city, buyer_postal, buyer_nuts, buyer_websitecontracting authority (organisation level only)
place_nuts, place_cityplace of performance
estimated_value, currencyif stated
deadline_date, deadline_time, deadline_kindearliest lot deadline; tender or participation
documents_url, submission_urlwhere the tender documents live
lotsarray of lots with title, CPV, NUTS, value, deadline, period
winners, total_awardedfor award notices, organisation names only
source_urlthe original notice at oeffentlichevergabe.de

Coverage on a sample day (2026-09-10): 1,067 notices, 589 calls for tenders, 569 of them with a submission deadline, 1,036 with CPV, 985 with NUTS.

Endpoints

endpointpricenotes
GET /freeservice descriptor
GET /openapi.jsonfreeOpenAPI 3.1
GET /v1/statsfreenotices per day, last 30 days
GET /v1/sample?cpv=72free5 latest calls for tenders, compact fields
GET /v1/notices$0.01filtered list, up to 100 records
GET /v1/notice/{id}$0.002one full record
POST /mcpfreeremote MCP server (Streamable HTTP), free tools
GET /.well-known/x402freex402 discovery manifest

Filters for /v1/notices

kind (default competition; result, planning, change, all), cpv (codes or prefixes, comma separated: 45,7131), nuts (prefixes: DE2,DE1), q (substring in title, description, buyer), since / until (publication day), deadline_after / deadline_before, nature, procedure, legal_basis, buyer_type, min_value, limit (max 100), offset (max 5000), fields=full (all columns incl. lots), sort=deadline.

GET /v1/notices?cpv=45,71&nuts=DE2&deadline_after=2026-09-20&limit=20GET /v1/notices?q=Photovoltaik&since=2026-09-01&fields=fullGET /v1/notices?kind=result&cpv=72&since=2026-09-01

Paying with x402

A request without payment returns 402 with a PAYMENT-REQUIRED header describing the amount (USDC), network and receiving address. Any x402 client handles this automatically, for example @x402/fetch:

ts
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";import { ExactEvmScheme } from "@x402/evm";import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); // holds USDC on Baseconst fetchWithPay = wrapFetchWithPaymentFromConfig(fetch, {  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],});const r = await fetchWithPay("https://vergabe-api.applehorsefrog.workers.dev/v1/notices?cpv=72");console.log(await r.json());

Prices are in USD and settled in USDC on Base (eip155:8453); there are no other fees on our side. The same code runs against Base Sepolia by setting X402_NETWORK=eip155:84532 and X402_FACILITATOR=https://x402.org/facilitator in wrangler.jsonc.

MCP server

Two ways to use the data from an MCP client (Claude Desktop, Claude Code, Cursor, any MCP host):

Remote, free tools only (no install): Streamable HTTP endpoint https://vergabe-api.applehorsefrog.workers.dev/mcp with sample_tenders, tender_stats, describe_api. The paid tools are listed there too but only return the payment requirements, because the remote server has no wallet.

Local, with paid tools (stdio, Node 20+): the client pays per call from a wallet you control.

json
{  "mcpServers": {    "vergabe": {      "command": "npx",      "args": ["-y", "github:applehorsefrog/vergabe-api"],      "env": { "VERGABE_PAYER_KEY": "0x<private key of a wallet holding USDC on Base>" }    }  }}

Tools: search_tenders ($0.01 per call, all filters of /v1/notices), get_tender ($0.002), sample_tenders, tender_stats, describe_api (free). Without VERGABE_PAYER_KEY the paid tools return the x402 payment requirements and the HTTP URL instead of data. Use a dedicated low-balance wallet for the key; the server never sends it anywhere, it only signs USDC transfer authorisations (EIP-3009) for the exact price of each call. Source: mcp/server.mjs.

Data source, licence, privacy

Data: Datenservice Öffentlicher Einkauf, https://oeffentlichevergabe.de, published under CC0 1.0. Every response carries X-Data-Source and X-Data-License headers. Code in this repository: MIT.

Contact persons, e-mail addresses, phone and fax numbers are removed during import (etl/etl.py), both from structured fields and from free text. Only organisation-level data is served. If you find personal data that slipped through, open an issue and it will be removed.

This is a technical data service, not legal advice. Deadlines and conditions must be verified at the source before bidding.

How it runs

  • src/index.ts: Cloudflare Worker (Hono) with @x402/hono payment middleware, a D1 (SQLite) database and the remote MCP endpoint.
  • mcp/server.mjs: local MCP server (stdio) that pays for the paid endpoints with @x402/fetch.
  • etl/etl.py: downloads the daily eForms ZIP, parses it with lxml, scrubs personal data, writes INSERT statements.
  • .github/workflows/daily-etl.yml: runs the ETL twice a day (06:30 and 14:00 UTC), re-imports the last three days and loads the rows with wrangler d1 execute.

Local development:

npm installnpx wrangler d1 execute vergabe --local --file=schema.sqlpython etl/etl.py --day 2026-09-10 --out etl/out/d.sql && for f in etl/out/d*.sql; do npx wrangler d1 execute vergabe --local --file=$f; donenpx wrangler dev

Provider, legal notice, privacy

Operated by Dr. Josua Decker, Viono Insights (https://viono-insights.de). Legal notice (Impressum, § 5 DDG): https://viono-insights.de/impressum.html, also served at GET /impressum. Privacy notice for this API (Art. 13 GDPR): GET /datenschutz. Contact: [email protected]. The GitHub account that publishes this repository is an automated account operated with Claude on behalf of the provider.

Disclosure

This service was built with substantial AI assistance (Claude); the provider reviews and is responsible for it. Issues and pull requests are welcome; automated contributions are labelled as such.

Source: README.md at commit b22fb79

Tools

5

sample_tenders

Free sample: latest German calls for tenders

FREE. The 5 most recent German public calls for tenders (compact fields) from oeffentlichevergabe.de, optionally filtered by one CPV code or prefix. Data: CC0, personal contact data removed.

Parameterscpv

tender_stats

Free: notices per day

FREE. Imported notices per publication day for the last 30 days, split by kind.

Takes no parameters.

describe_api

Service description, prices, legal notice

FREE. Endpoints, prices, x402 payment details (USDC on Base), data source and licence, provider and legal notice, how to use the paid tools.

Takes no parameters.

search_tenders

Search German procurement notices (paid, see description)

PAID ($0.01 USDC on Base per call via x402). Full-text and structured search over German public procurement notices (CPV, NUTS, deadline, buyer type, value). This remote server cannot pay on your behalf: the tool returns the exact HTTP URL and payment requirements; use the local MCP server (npx -y github:applehorsefrog/vergabe-api) or an x402 HTTP client to get data.

Parametersqcpvkindnutssortlimitsinceuntilfieldsnatureoffsetmin_value+5 more

get_tender

Get one procurement notice (paid, see description)

PAID ($0.002 USDC on Base per call via x402). One notice by UUID with lots, deadlines, links and winners. Returns the HTTP URL and payment requirements; pay via the local MCP server or an x402 HTTP client.

Parametersidrequired

Version history

1
  1. v0.4.0LatestSep 16, 2026

Score

100% 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 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts