ihalent

io.github.gulmezeren2-byte由 GitHub 账号 gulmezeren2-byte 发布v0.3.0更新于 Oct 25, 2026

Turkish public-tender (EKAP) award intelligence: firm histories, discounts, competition, red flags

已验证STDIO仅桌面数据与分析商业与电商

概览

AI 生成的概览

本地 MCP 服务器,将土耳其公共招标(EKAP)结果公告整理为结构化中标数据,并回答企业历史、折扣、竞争与风险信号等问题。

可以做什么
分析招标数据集:总览金额、折扣、竞争情况与数据缺口,并计算中标集中度(HHI)。
适用场景
当你已经拥有或能够收集 EKAP 结果公告,并希望助手跨多条中标记录进行分析,而不是逐条阅读公告时使用。
运行要求
作为本地 Python 进程运行,需安装带 MCP 附加组件的软件包。服务器读取由环境变量 IHALENT_AWARDS 指定的 JSONL 中标数据文件。公告的采集不包含在内,需由其他工具完成。
安装前请注意
它只读取你指定的数据集,本身不抓取也不再分发数据。企业名称匹配较为保守,同一家公司可能显示为多种拼写。中标金额为公告所印的名义里拉,未做通胀调整;未公布估算价时折扣留空而不猜测。

安装

在 SourceWeft 中

  1. 打开 控制台中的 ihalent,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

ihalent

Turkish public-tender award intelligence: who won, for how much, at what discount, against how many bidders.

[CI] [PyPI] [Python] [License: MIT]

Built on top of saidsurucu/ihale-mcp — ihale-mcp reaches EKAP; ihalent structures and analyzes what it returns.

Every public tender in Turkey ends with a Sonuç İlanı — a result notice that states the estimate, the contract price, the winner, and how many firms bid. The notices are public. They are also one at a time, unstructured, and impossible to reason across: you cannot ask EKAP "what has this company won in the last two years" or "how far below estimate does this authority actually award." ihalent turns those notices into structured records and answers exactly those questions — firm histories, discount (kırım) distributions, and competition metrics — with every number traceable back to the notice it came from.

[ihalent overview, winner concentration and procurement red flags over nine real awards from the December-2025 / January-2026 window]

That is real output over nine real construction awards from the December-2025 / January-2026 window (in examples/). The -2.96% at the bottom of the range is not a bug: Istanbul University awarded a 615-million-lira campus job at 2.96% above its own estimate, through an emergency "pazarlık" procedure — a contract signed over the public estimate, which is precisely the kind of thing that should be easy to see and currently is not.

Why this exists

I'm an industrial engineer and I work in construction. When our firm weighs a public tender, the questions that decide the bid are all about other people's history: how far below estimate does this authority award, how many firms usually show up, what has a given competitor been winning and at what price. All of that is public — it is sitting in tens of thousands of result notices on EKAP — and none of it is queryable. So everyone rebuilds a private, partial version of it by hand, in spreadsheets, badly.

There is already an excellent tool for reaching this data: saidsurucu/ihale-mcp solved authenticated EKAP access and hands you the notices. ihalent is the layer above it — the one that turns a pile of notices into an answer. It does not re-scrape EKAP; it structures what you have collected and does the analytics that don't exist yet.

What it answers

A firm's history — every award across the dataset, folded across spelling variants:

$ ihalent firm examples/sample-awards.jsonl "ÖZDEN YEL"ÖZDEN YEL  wins: 1   joint ventures: 1   total contract value: 19.709.997,40 TLDiscount (kırım) — ÖZDEN YEL         ┌────────┬────────┬────────┬────────┐│ mean   │ median │ min    │ max    │├────────┼────────┼────────┼────────┤│ 33.87% │ 33.87% │ 33.87% │ 33.87% │└────────┴────────┴────────┴────────┘based on all 1 awards.  top awarding authorities:      1x  DSİ 14. Bölge Müdürlüğü

Where the discounts are — grouped and sorted, highest first:

$ ihalent discounts examples/sample-awards.jsonl --by authorityMean discount by authority                                     ┌──────────────────────────────────┬────────┬────────┬────────┐│ authority                        │   mean │ median │ awards │├──────────────────────────────────┼────────┼────────┼────────┤│ DSİ 14. Bölge Müdürlüğü          │ 33.87% │ 33.87% │    1/1 ││ Ziraat Bankası Genel Müdürlüğü   │ 31.41% │ 31.41% │    1/1 ││ İstanbul YİKOB                   │ 26.98% │ 26.98% │    1/1 ││ İSKİ Genel Müdürlüğü             │ 26.66% │ 26.66% │    1/1 ││ İTÜ Rektörlüğü                   │ 22.68% │ 22.68% │    1/1 ││ Esenler Belediyesi               │ 21.99% │ 21.99% │    1/1 ││ Ağrı İl Özel İdaresi             │ 19.99% │ 19.99% │    1/1 ││ Kağıthane Belediyesi             │ 17.41% │ 17.41% │    1/1 ││ İstanbul Üniversitesi-Cerrahpaşa │ -2.96% │ -2.96% │    1/1 │└──────────────────────────────────┴────────┴────────┴────────┘awards column: used / considered (excluded lack an estimate).

Competition — how many valid bids show up, and how often exactly one does (a single-bid award is a flag procurement watchdogs care about). It's in the overview above.

The one rule

A number is never shown without the ground it stands on. A mean discount always comes with "over how many awards, and how many were dropped for a missing estimate." A firm's total contract value says so when some of its wins had no published price, so you read it as a floor, not the full figure. A discount is None, never 0, when the estimate wasn't published — ihalent does not invent the numbers the government didn't print. Half the value of a tool like this is refusing to guess.

Install

pip install ihalent           # add [mcp] for the MCP server: pip install "ihalent[mcp]"

Or from source: pip install git+https://github.com/gulmezeren2-byte/ihalent.

The workflow

ihalent reads a JSONL file of awards. You produce it by collecting result notices — the easy path is ihale-mcp — and letting ihalent structure them:

# 1. collect: with ihale-mcp connected to your agent, save what its#    get_tender_announcements returns (one or many tenders) to bundle.json
# 2. structure:ihalent ingest bundle.json -o awards.jsonl
# 3. ask:ihalent overview  awards.jsonlihalent firm      awards.jsonl "ACME İNŞAAT"ihalent discounts awards.jsonl --by province --min 5

Every command takes --json for pipelines and agents. Or skip collection and try the bundled example directly:

git clone https://github.com/gulmezeren2-byte/ihalent && cd ihalentpython examples/build_sample.py       # parses the real notices in examples/notices/ihalent overview examples/sample-awards.jsonl

Commands

commandwhat it does
ihalent overview AWARDSvalue, discount, competition and the data gaps of a dataset
ihalent firm AWARDS "NAME"one company's wins, total value, discount, and where it wins
ihalent discounts AWARDS --by Xmean/median discount grouped by authority, province or tender_type
ihalent single-bid AWARDSawards with a single valid bid — no real competition (a watchdog flag)
ihalent concentration AWARDS [--authority X]winner concentration (HHI) — do the same few firms win everything?
ihalent flags AWARDSper-award red flags: single bid, near-estimate price, no estimate, high drop-off
ihalent parse NOTICE.mdone result notice → structured JSON
ihalent ingest BUNDLE.jsoncollected ihale-mcp/EKAP output → awards JSONL

Using it with AI agents

The result notice is unstructured text; the interesting questions are aggregate. That is an awkward fit for an agent working notice-by-notice, and a natural fit for a tool: --json output with stable fields, an exit code that means something, and a firm-name match that folds spelling variants so an agent doesn't have to.

There is a native MCP server (pip install 'ihalent[mcp]') that exposes the analytics as tools — overview, firm, discounts, concentration, flags, parse_notice, ingest_bundle — over a dataset you point it at:

IHALENT_AWARDS=awards.jsonl ihalent-mcp

No local Python? The Dockerfile builds the same server: docker build -t ihalent . && docker run --rm -i -e IHALENT_AWARDS=/data/awards.jsonl -v "$PWD:/data:ro" ihalent.

Pair it with ihale-mcp and an agent can collect notices and reason across them in one session: ihale-mcp fetches, ihalent structures and aggregates. The Python API (ihalent.ingest_bundle, ihalent.analytics.firm_profile) is three calls deep if you'd rather script it.

Scope, honestly

  • This is analytics, not a scraper. Collection is ihale-mcp's job (it does it well); ihalent deliberately owns the layer above and stays a pure function of the data you give it — no network, no signing keys, nothing that breaks when EKAP rotates a header.
  • Company-name folding is conservative on purpose. It merges legal-form suffixes and Turkish spelling variants, and it would rather show two rows for one firm than one row for two — so firm reports how many distinct spellings a query matched, and warns you if that is more than one.
  • The parser tracks one document: the result notice. Bid-level detail (who else bid, at what price) is not in the notice and so is not here. Discount is the estimate-to-contract gap, which the notice does carry.
  • Award values are nominal lira, as printed. Comparing 2023 and 2026 contracts is your analysis to make with the dates in hand; ihalent does not silently inflation-adjust.

What ihalent is not

It is not a replacement for ihale-mcp — it sits on top of it. It is not a live dashboard or a paid tender-alert service; it is a library and a CLI you point at data you control. And it does not redistribute a dataset: it ships the handful of real notices in examples/ and the code to structure your own.

A note on the data

Public-tender results are public information, published by the state for public scrutiny. ihalent structures what EKAP already discloses. Company names that appear are legal entities in their public commercial capacity, not private individuals.

How this project is built

I designed the model and the analytics and I review every line; I use AI agents (Claude Code) heavily for implementation speed, and the commit trailers say so. The contract is the tests — 80 of them, built on the exact JSON shapes EKAP and ihale-mcp emit, including a result notice with a negative discount and a cancelled tender. They don't care who typed them.

Related

  • acikpoz — the other half of the Turkish public-procurement picture. ihalent reads the tender result notices that say who won and at what discount; acikpoz reads the unit-price (birim fiyat) catalogs that say what the work should have cost. Same discipline: every figure traceable to its source, nothing invented.

More tools by Eren Gülmez.

License

MIT — Mehmet Eren Gülmez

来源:README.md,提交 f1f5940

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.3.0最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分