onbid-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@onbid-mcpwhich properties in 강남구 have failed to sell more than three times?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
onbid-mcp
An MCP server that lets an LLM query Korean public auction (공매) property data from 온비드 (KAMCO).
Ask "which properties in 강남구 have failed to sell more than three times?" in Claude Desktop and get answers from data you collected yourself — no subscription, no scraping.
Status. Working end to end — the pipeline runs on a schedule, and the four tools are connected and answering in Claude Desktop against live data (6,902 Seoul listings, 99.9% geocoded). Remaining: final acceptance checks (M7) and a week of watching the scheduled batches. See docs/TASKS.md for the exact state.
What you get
Four tools and four resources, over stdio:
Tool | What it does |
| Filter by region, usage, property type, private-contract eligibility, price, discount rate, failure count, deadline, status. Korean names work directly ( |
| One property by management number, plus its sibling condition numbers and the original 온비드 link. |
| Distributions across six axes, plus winning-bid ratios. Aggregates only — never individual properties. |
| Address → coordinates, with a server-side daily cap. |
Resource | What it holds |
| Districts and neighborhoods that actually have listings |
| The three-level usage category tree |
| Property type codes |
| Batch timestamp, counts, geocoding rate — how fresh your data is |
Every response carries meta (source, synced_at, is_realtime: false, count, truncated,
notice) and query_echo (the filters actually applied, after defaults and clamping).
Related MCP server: BDLedger MCP Server
Before you start
This server queries your own database, not a hosted service. You collect the data, so you need your own credentials:
What | Where | Notes |
온비드 service key | Apply for the five 온비드 OpenAPIs. Approval is usually immediate for a development account. | |
Supabase project | Free tier is enough — the Seoul dataset is about 7,000 rows. Any PostgreSQL works. | |
Kakao REST API key | Geocoding. Must be the REST API key, not the JavaScript one. |
Also: Python 3.11+ and Claude Desktop (or any MCP client that speaks stdio).
Scope is Seoul, sale-type listings by default. Widening it is a one-line filter change, but the geocoding and quota numbers below assume Seoul.
Setup
git clone https://github.com/daehyub71/onbid-mcp.git
cd onbid-mcp
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in the three keys above
python scripts/migrate.py # create tables (safe to re-run)Then collect a first dataset. This takes about two minutes and stays well inside the daily API quota:
python scripts/run_batch.pyYou should see something like:
── 물건 ──
ok · 수집 6902 · 적재 6902 · 이력 0 · tombstone 0
── 좌표 ──
ok · 대상 500 · 좌표 500 (근사 0) · 실패 0 · 호출 133Run it again with --geocode-budget 1000 until dataset/status reports a geocoding rate
you're happy with — the cache absorbs most calls, so the whole 6,902 rows cost roughly 800
Kakao calls in total.
Connecting Claude Desktop
Add the server to claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"onbid": {
"command": "/absolute/path/to/onbid-mcp/venv/bin/python",
"args": ["-m", "onbid_mcp.server"],
"cwd": "/absolute/path/to/onbid-mcp",
"env": {
"PYTHONPATH": "/absolute/path/to/onbid-mcp",
"SUPABASE_DATABASE_URL": "postgresql://...",
"ONBID_SERVICE_KEY": "...",
"KAKAO_REST_API_KEY": "..."
}
}
}
}Four things trip people up here:
PYTHONPATHis required —cwdalone is not enough. Claude Desktop does not apply thecwdentry, sopython -m onbid_mcp.servercannot find the package and the process dies instantly withModuleNotFoundError. The app reports that as "Server disconnected", which looks like a connection problem rather than a path one.Use the absolute path to the venv interpreter. Claude Desktop does not inherit your shell
PATH, so a barepythonpicks up a system interpreter with none of the dependencies.Put the keys in
env. The app does not read the project's.envfile.Logs must never reach stdout. stdout is the JSON-RPC channel; this server logs to stderr for exactly that reason. If you add prints, send them to stderr.
Restart Claude Desktop, then try:
강남구에서 3회 이상 유찰된 물건 중 최저가율 60% 이하인 것 보여줘
If it fails, read ~/Library/Logs/Claude/mcp-server-onbid.log — the actual Python error is
in there, while the UI only says "Server disconnected".
To check the connection without Claude Desktop:
python scripts/mcp_smoke.py # lists tools and calls one over stdioKeeping the data fresh
Two GitHub Actions workflows are included. Add ONBID_SERVICE_KEY,
SUPABASE_DATABASE_URL, and KAKAO_REST_API_KEY to your repository secrets and they run
on their own:
Workflow | When (KST) | What |
| Mon–Sat 04:00 | Changed listings + bid rounds + geocoding |
| Sun 04:00 | Code tables + full scan — the only run that can mark ended listings |
Cron is UTC-only, so 04:00 KST is 19:00 UTC the previous day, which shifts the weekday by one. Check the last week with:
python scripts/batch_health.pyA skipped cron leaves no trace anywhere — GitHub only emails about runs that started and failed — so this counts the days instead.
Design notes worth knowing
These came from measurement, not from the API guide.
Ended listings are marked, never deleted. 온비드 returns in-progress items only, so a
listing that disappears is indistinguishable from one that never existed. Rows become
종료추정 instead, and three conditions must all hold first: full-scan mode, matching
collection scope, and a completed scan. Getting the scope wrong flipped 6,594 healthy rows
in a measured trial.
The primary key is composite. cltrMngNo alone is not unique — one management number
carries up to ten pbctCdtnNo values, and the bid-info API returns the same round history
under each. Statistics deduplicate by (management number, opening time, round); counting
rows made 13 real auction events look like 62.
Ratios are computed, not read. 온비드 ships ratio fields whose measured fill rate is 0%.
min_bid_rate is derived, and it legitimately exceeds 1.0 (measured max 150.2%, in 9.8% of
rows), so it is never clamped.
Empty results are an error, not an empty list. no_result tells the model to relax the
filters; an empty array would let it conclude "there are no such properties".
The winning-bid statistics are biased, and that matters more than the numbers. The only completed auctions visible are ones that were won and then fell through — normally completed sales never appear in the listing API. Every response carries that caveat.
Development
ruff check .
mypy core/ onbid_mcp/ api/ tests/ scripts/
pytest -q # 595 tests, no network
pytest -m db -q # 361 tests against your database, inside rolled-back transactions
pytest -m live -q # real API calls, excluded by defaultDatabase tests run against the real schema inside transactions that always roll back, so they leave no trace — verified by comparing table counts before and after. Pure tests pass with a deliberately broken connection string.
There is also a local HTTP API (api/main.py) bound to loopback only, useful for poking at
the data with curl. It is not required for MCP use.
Documentation
Specification-driven; the documents are the source of truth and are written in Korean.
docs/SPEC.md — requirements, data model, MCP tool contracts, open questions
docs/PLAN.md — architecture, milestones, test strategy, risks
docs/TASKS.md — progress dashboard and troubleshooting log
docs/API_FINDINGS.md — measured API behavior; takes precedence over the official guides, which were wrong in several places
Security
Keys live in .env (local) or GitHub Secrets / the MCP config env block (deployed), never
in code. The 온비드 API requires the service key as a query parameter and httpx logs full
request URLs at INFO level, so the client lowers the httpx logger to WARNING at import
time — otherwise enabling logging would leak the key. The settings object masks its values
in repr for the same reason.
All onbid_* tables have RLS enabled with no policies and revoked grants; access is
service_role only, verified by measurement (HTTP 401 for anon on every table). The HTTP
API refuses to bind anywhere but loopback.
Limits and non-goals
Lookup only. No ranking, scoring, or recommendation — the tools return public data and leave judgement to you. This is deliberate: 공인중개사법 restricts listing-style display and advertisement of properties.
No brokerage, no valuation, no legal or investment advice.
Seoul, sale-type listings, in-progress by default.
Winning-bid statistics come from a biased sample (see above).
License
Not yet chosen. The 온비드 API guide documents are intentionally excluded from this repository; the response structures used here are recorded in docs/API_FINDINGS.md from live measurement.
This server cannot be deployed
Maintenance
Related MCP Connectors
Korean real estate: court auctions, 10M+ MOLIT records, subscription notice facts, loan/DSR rules
Official Korean apartment sale prices (MOLIT). Clean JSON, data global models cannot know — paid pe…
Korean fact-verification tools for AI agents: business registration, address, DART, apt prices, laws
Access Korea’s G2B procurement and Nara Market data for bid notices, awards, contracts, statistics…
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables natural language access to 11 Korean building data tools including building registers, permits, comprehensive profiles with zoning, floor composition, district statistics, old building analysis, price history, demolitions, and permit pipeline.65MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying of Korean building ledger information including property details, floor plans, and pricing via natural language.-
- AlicenseNot gradedqualityCmaintenanceEnables querying Korean apartment sales and rental transaction data from the public data portal through natural language, with tools for searching transactions and computing price statistics.6 npmMIT
- FlicenseNot gradedqualityBmaintenanceEnables natural language queries to retrieve Korean real estate transaction data (land, commercial, apartments) from the public API, returning structured tables and summary statistics.-