acikpoz

io.github.gulmezeren2-byte由 GitHub 账号 gulmezeren2-byte 发布v0.2.0更新于 Nov 3, 2026

Turkish public construction unit-price (birim fiyat) catalog PDFs into structured pozes

已验证STDIO仅桌面文件与存储数据与分析

概览

AI 生成的概览

把土耳其公共建筑单价(birim fiyat)目录 PDF 解析为结构化 poze,并让助手比较不同年份目录、校验解析结果。

可以做什么
  • 把目录 PDF 解析为结构化 poze,并给出已定价、分组标题和缺价条目的统计
  • 按 poz 代码比较两个年份的目录,报告价格变动、新增与删除的 poze 以及单位变化
  • 校验解析结果,标出重复或格式错误的代码、非正价格以及缺失或未知的单位
  • 返回结构化数据而非散文,并附带每次解析的价格解析率和置信度等级
适用场景
适合需要处理 ÇŞB birim fiyat 目录的场景:编制成本估算、准备招标、审核单价,或追踪今年价格相对去年的变化。
运行要求
以 Python 包形式通过 stdio 在本机运行;安装时需包含 mcp 附加项,并启动 acikpoz-mcp 命令。未声明任何账号、API 密钥或环境变量。需自备官方目录 PDF,因为该工具不附带数据。
安装前请注意
它会读取并解析你指定的本地 PDF 文件,不打包也不再分发目录数据。部分版式下提取并不完美,单位可能出错、也可能出现缺价条目;工具会自行报告这些情况,等级低于 good 时应先复核页面。价格为目录原样印刷的名义价格,不含通胀调整。

安装

在 SourceWeft 中

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

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

其他 MCP 客户端

参照 仓库 中的启动说明。

README

acikpoz

Turkish public construction unit prices, turned from a PDF into data you can compute with.

[Python] [License: MIT]

Every public construction job in Turkey is priced against a government catalog: the ÇŞB (Çevre, Şehircilik ve İklim Değişikliği Bakanlığı) birim fiyat books — thousands of unit prices (a poz: a code, a description, a unit, a price) that estimators, contractors and auditors all read. They ship as long PDFs. acikpoz turns those pages back into structured records, deterministically, so a cost estimate or a tender preparation can be computed instead of copied by hand.

It is disciplined geometry, not a language model: it groups the words on a page into visual rows and reads the price column's position from the page header rather than guessing a fixed spot. That one decision is what makes it trustworthy — some sections (Sıhhi Tesisat, say) print two numbers per row, the real Birim Fiyat and a separate Montaj Bedeli, and a naive parser silently reads the wrong one. acikpoz reads the header, so it reads the right column.

Paired with ihalent (which structures tender results), acikpoz covers the other half of Turkey's public construction economy: the prices the results are measured against.

The one rule it never breaks

A price is only ever a number the catalog actually printed in the price column. It never coerces, never borrows a neighbour's figure, never guesses. Two consequences, both on purpose:

  • A group-header poz — a category title like EVİYELER: whose sub-items carry the real prices — has no price of its own. acikpoz leaves its fiyat as None and flags is_group_header. It does not invent a zero.
  • A poz the catalog left without a printed price is a gap, surfaced and counted, not hidden. Every result reports its coverage: how many pozes were priced, how many were headers, how many were genuine gaps.

Half the value of a cost tool is refusing to make up the numbers the source did not print. That is the same honesty discipline as andon and ihalent.

Install

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

Quick start

Point it at an official catalog PDF you have (acikpoz ships the parser, not the data):

acikpoz parse bf2026.pdf --pages 8-20acikpoz parse bf2026.pdf --json > pozes.jsonl     # one poz per line, for pipelinesacikpoz parse bf2026.pdf --csv pozes.csv          # Excel-ready (utf-8-sig, Turkish text)acikpoz parse bf2026.pdf --group 25               # only Sıhhi Tesisat pozesacikpoz parse bf2026.pdf --priced-only            # drop headers and gaps

The table view — this is a real run against the published 2026 catalog, not a mock-up:

[acikpoz parsing one page of the official 2026 ÇŞB catalog: nineteen pozes with codes, units, prices and Turkish descriptions, three of them showing a dash because the catalog printed no price; below it, validate reporting sixteen warnings including five units the parser is not confident about]

Two things in that picture are the whole point:

  • Three rows carry - in the price column. The catalog printed no price for them, so acikpoz prints none either — they are counted as gaps, not filled in from a neighbour.
  • validate then flags what the parse is not sure about: on this page five units (+2000, azami, Yapı, -30°C, 2,5) are fragments of description text that landed in the unit column. The extraction is imperfect on some layouts, and the tool reports that itself rather than handing you a clean-looking table with wrong units in it.

Reproduce it — the page is chosen, nothing else is:

acikpoz parse    bf2026.pdf --pages 400acikpoz validate bf2026.pdf --pages 400

The catalog is the ministry's own file, published here. The image is regenerated by scripts/make_demo_svg.py, which downloads that PDF and runs the same code the CLI runs.

The grade (excellent/good/fair/poor) is a glanceable confidence signal, the way camelot exposes accuracy: below good, review the pages before trusting the output. --json includes price_parse_rate and grade per parse.

Or from Python:

python
from acikpoz import parse_catalog
result = parse_catalog("bf2026.pdf", pages=range(8, 20))for p in result.pozes:    if p.is_priced:        print(p.poz_no, p.birim, p.fiyat)print(result.to_dict()["counts"])   # priced / group_headers / price_gaps

How it works

  1. Rows. Words are grouped into visual rows by vertical position (a few points of tolerance), then sorted left-to-right.
  2. Price column, from the header. The Fiyat header word on the right (x > 400) gives the price column's x. A stray "fiyat" in a left-column description can't be mistaken for it.
  3. Cells. For each poz row: the leftmost cell is the poz code; the price is the number-shaped token nearest the price-column x; the unit sits just left of it; the rest is the description. Indented continuation lines extend the running description (and can carry a price that spilled over).
  4. Group headers. A price-less poz whose description ends in : is a category title — flagged, not treated as a gap.

Compare two catalog years

Catalogs are reissued regularly; the question estimators and auditors track by hand is how did this year's rates move from last year's? acikpoz diff answers it — it joins two years by poz code and classifies each change:

acikpoz diff bf2025.pdf bf2026.pdf --pages 8-400acikpoz diff bf2025.pdf bf2026.pdf --tolerance 1   # hide sub-1-TL rounding noiseacikpoz diff bf2025.pdf bf2026.pdf --json

It reports price moves (with Δ and %Δ), added and removed pozes, unit changes, and pozes that gained or lost a printed price — plus the mean price %-change for the year. As far as the research found, no other open tool does year-over-year diffing for ÇŞB catalogs.

Validate a parse

Before a parsed catalog feeds a cost estimate, it helps to know it is clean. acikpoz validate runs deterministic quality rules over the pozes — no ML, no fixing, only surfacing:

acikpoz validate bf2026.pdf --pages 8-400acikpoz validate bf2026.pdf --json

It flags duplicate poz codes, malformed codes, non-positive prices (errors), and priced pozes with no unit or a unit outside the known set (warnings). It exits non-zero on any error, so it can gate a pipeline (acikpoz validate … && build-estimate). This is also how acikpoz stays honest about its own limits: in sections that print the unit once on a group header and let the rows inherit it (Sıhhi Tesisat), per-row unit detection is weak, and validate says so rather than hiding it. Price, poz code and description stay reliable.

Using acikpoz with AI agents

An MCP server (pip install 'acikpoz[mcp]', then acikpoz-mcp) exposes three tools: parse_catalog (a PDF → structured pozes with honest coverage), diff (two catalog years → classified changes), and validate (a PDF → quality findings). The agent gets structured data back, not prose it has to parse. Pair it with ihalent and an agent can reason across both a tender's result and the unit prices it was measured against.

jsonc
// e.g. Claude Desktop / Claude Code mcp config{ "mcpServers": { "acikpoz": { "command": "acikpoz-mcp" } } }

Scope, honestly

  • It reads the standard catalog layout. The header-driven column detection handles the common single- and two-price-column pages well; an unusual layout may leave more gaps — which it reports rather than papering over. If a section parses badly, that's a bug worth a sample.
  • It is a parser, not a price database. It does not bundle or redistribute the catalog. You bring the official PDF; acikpoz turns your copy into data.
  • Prices are nominal, as printed. No inflation adjustment is baked in — that's an analysis choice the caller makes knowing the year.

Data, and why the PDFs aren't here

The ÇŞB catalogs are official public documents, but this repository does not redistribute them: it ships the parser and nothing else, and .gitignore keeps *.pdf out. Point acikpoz at the catalog you obtained from the official source. This is the same line ihalent draws — own the tool, not the data.

How this project is built

I'm an industrial engineer working in construction; I read these catalogs. I designed the parsing approach — geometry over machine learning, honest gaps over invented numbers — and I review every line; I use AI agents heavily for implementation speed, and the commit trailers say so. The contract is the tests: they encode the exact word geometry a real page emits, including the two-column Sıhhi Tesisat trap and the group-header rule, so green tests mean the parser handles the real thing.

Related

  • ihalent — the other half of the Turkish public-procurement picture. acikpoz reads the unit-price catalogs that say what work should cost; ihalent reads the tender result notices that say what it was awarded for, and at what discount. Same discipline: every figure traceable to its source, nothing invented.

More tools by Eren Gülmez.

License

MIT — see LICENSE.

来源:README.md,提交 5c74e1e

工具

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

版本历史

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

评分

已满足适用检查项的 50%

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

  • 近 30 天内可连通25 分

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

  • 已声明认证方式10 分

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

  • 已列出工具15 分

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

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