Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
제작자가 쓴 설명(영어 원문)
Swiss official gazettes (SHAB + cantonal) — procurement & notices, person-data rubrics excluded
이 세 가지는 절대 하나의 점수로 합치지 않아요. 의견, 측정, 인기는 서로 다른 것이니까요.
이 서버는 아직 쉬운 말로 된 요약을 쓰지 못했어요. 아래는 레지스트리에서 읽어 온 사실이에요.
쓰고 있는 AI 앱을 고른 다음 설정을 복사하세요.
필요한 것
어떤 앱을 쓰세요?
위에서 앱을 고르세요. 기억해 두었다가 다음부터는 버튼에 “…에 설치”라고 표시해요.
Claude Desktop → Settings → Developer → Edit Config를 열고 claude_desktop_config.json에 이 내용을 붙여 넣으세요
{
"mcpServers": {
"amtsblatt": {
"command": "uvx",
"args": [
"amtsblatt-mcp"
]
}
}
}터미널에서 이 명령어를 실행하세요
claude mcp add amtsblatt -- uvx amtsblatt-mcp프로젝트의 .cursor/mcp.json 또는 ~/.cursor/mcp.json에 붙여 넣으세요
{
"mcpServers": {
"amtsblatt": {
"command": "uvx",
"args": [
"amtsblatt-mcp"
]
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
프로젝트의 .vscode/mcp.json에 붙여 넣으세요
{
"servers": {
"amtsblatt": {
"type": "stdio",
"command": "uvx",
"args": [
"amtsblatt-mcp"
]
}
}
}브라우저가 앱을 열지 물어본 다음, 앱이 설정을 보여 주고 확인을 요청해요. 키 값은 비워 두니 직접 입력하세요.
이 서버는 내 컴퓨터에서 실행되는데, ChatGPT는 인터넷에 있는 서버에만 연결할 수 있어요. 다른 앱을 고르세요.
선택한 앱은 이 기기의 쿠키에만 저장돼요. 계정은 필요 없어요.
이 설정은 제작자의 레지스트리 정보로 만들었어요. README와 다르면 README를 따르세요.
내 컴퓨터에서 실행돼요. 설치하면 AI 앱에 도구 목록이 나타나요.
누구나 볼 수 있는 정보를 점검했고, 코드는 읽지 않았어요. 해당하지 않는 항목은 개수에서 뺐어요. · 2026년 11월 8일 점검
레지스트리 이름이 GitHub 계정 malkreide 기준으로 확인되었고, 이 계정이 저장소를 소유하고 있어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
아직 GitHub에서 이 저장소를 읽어 오지 않았어요
내 컴퓨터에서 실행되는 서버라 인터넷 엔드포인트가 없어요
내 컴퓨터에서 실행되며, 대신 로컬 설정을 사용해요
내 컴퓨터에서 실행돼요. 도구 목록은 인터넷 엔드포인트가 있는 서버에서만 읽을 수 있어요
레지스트리에서 이 카테고리의 활성 서버 전체와 비교했어요. 스타는 게시자가 저장소를 소유한 경우에만 세요.
해당하는 기본 점검 1개 중 1개를 통과했어요. 코드는 읽지 않았어요. 키나 토큰을 넣기 전에 서버가 어떤 권한을 요구하는지 확인하고, 꼭 필요한 권한만 있는 키를 쓰세요.
레지스트리에 필수 키가 나와 있지 않아요. 다만 처음 쓸 때 로그인을 요구하는 서버도 있어요.
내 컴퓨터에서 실행돼요. AI 앱이 필요할 때 실행하고, 데이터는 제작자의 서버를 거치지 않아요(서버 자체가 온라인 서비스를 호출하는 경우는 제외).
GitHub 저장소는 마지막으로 – 변경됐고, 최신 버전(0.23.0)은 42일 전 레지스트리에 올라왔어요.
Claude Desktop, Claude Code, Cursor, VS Code처럼 MCP를 지원하는 앱에서 쓸 수 있어요. 내 컴퓨터에 Python (uv)도 있어야 해요.
같은 카테고리에는: Spec Driven Development, Remote Desktop Commander, UniMCP
같은 카테고리에서 다른 제작자가 만든 서버예요. 스타 순으로 정렬했어요.
카드 보는 법:↓ 주간 다운로드i★ GitHub 스타i세 기둥: 리뷰 · 점검 · 사용 정도i업데이트 = 최신 버전을 레지스트리에 공개한 날i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Aula virtual (Moodle) y SIU Guaraní de universidades argentinas: cursos, entregas, notas, historia.
제작자의 저장소에서 쓰인 그대로 가져왔어요. PopNx MCP가 검토하거나 보증한 내용이 아니에요. HTML, 이미지, 스크립트는 제거했어요. 링크를 누르면 이 사이트를 벗어나요.
🇨🇭 Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)
MCP server for amtsblattportal.ch — the Swiss official gazette portal
(SHAB + 27 cantonal gazettes). Public procurement and official notices,
person-data rubrics excluded by design.
🇩🇪 Deutsche Version
The Amtsblattportal publishes roughly 2.79 million official notices: public procurement, cantonal and communal announcements, enactments, spatial planning — and also bankruptcies, debt collection, inheritance calls and civil-status records naming natural persons.
This server exposes only the first group. Rubrics carrying systematic natural-person data are not queryable, and no tool accepts a person's name, birth date or address. That is a deliberate data-protection decision, explained in Data Protection & Scope.
Anchor demo query: *"Which public tenders did canton Ticino publish this month?"*
→ gazette_search_procurement(canton="TI", only_language=True, language="it") → gazette_get_publication(id=…)
For procurement in any other canton — including Zürich, Bern and Basel-Stadt — use swiss-procurement-mcp; see Boundary with swiss-procurement-mcp.
OB-ZG was never filled after the simap switch, and that ZH routes everything through simap.ch — so it explains instead of returning nothing. Activity is measured, not read off the rubric labellanguage_mix rather than guessed at, and only_language=True gives a single-language viewprovenancepip install amtsblatt-mcp
uvx amtsblatt-mcp
From source:
git clone https://github.com/malkreide/amtsblatt-mcp
cd amtsblatt-mcp pip install -e ".[dev]"
{
"mcpServers": { "amtsblatt": { "command": "uvx", "args": ["amtsblatt-mcp"] } } }
export MCP_TRANSPORT=streamable-http
export MCP_API_KEY="$(openssl rand -hex 32)" # mandatory — fails loud if unset export PORT=8000 amtsblatt-mcp
The endpoint is `/mcp`.
Migrating from SSE. Until 0.18.0 this server spoke SSE only, on
/sse+/messages. MCP spec2026-07-28reclassifies HTTP+SSE as
deprecated with a twelve-month removal window and removes protocol-level
sessions, so streamable-http is now the default.
MCP_TRANSPORT=ssestill
works and still carries the full bearer-auth, rate-limit and CORS stack — it
logs a warning at startup naming the deadline. **Update the client URL when
you switch**: the path change is the part that breaks silently.
| Variable | Default | Purpose | |||
|---|---|---|---|---|---|
MCP_TRANSPORT | stdio | stdio, streamable-http (alias http), or the deprecated sse | |||
MCP_HOST | 127.0.0.1 | HTTP bind address. Defaults to loopback; set 0.0.0.0 to expose on all interfaces (the Docker image does this deliberately). | |||
MCP_STATELESS | _(on)_ | streamable-http runs with no session tracking at all — the native mode of spec 2026-07-28, which has no protocol-level sessions. Removes session hijacking and session affinity as questions rather than answering them (SEC-009, SCALE-002). 0 / false / no restores sessions for handshake-era clients; any other value keeps the default. Ignored on sse, which has no stateless mode. | |||
MCP_CORS_ORIGINS | _(unset)_ | Comma-separated origins allowed to call the endpoint from a browser. Unset means no cross-origin browser access at all — stdio and non-browser clients are unaffected. Mcp-Session-Id is exposed and accepted for the listed origins, so a browser client can hold a session. * is honoured but logs a warning and disables credentials, because browsers reject a wildcard origin together with credentials. | |||
MCP_API_KEY | — | Bearer token; required on every HTTP transport | |||
MCP_RATE_LIMIT / MCP_RATE_WINDOW | 60 / 60 | Sliding-window rate limit | |||
RUBRICS_TTL | 86400 | Taxonomy cache TTL (seconds) | |||
LOG_LEVEL | INFO | DEBUG \ | INFO \ | WARNING \ | ERROR. Structured JSON, one object per line, always on stderr — stdout carries the MCP protocol on a stdio transport. |
Built on structlog. Every event emitted during a tool call carries that call's correlation_id, bound via contextvars — so a retry or an egress denial logged deep in the HTTP path can be joined to the request that caused it, without threading context through every signature.
| Level | Emitted when |
|---|---|
DEBUG | a tool call was entered (tool_call_started) — tells you whether a hung call ever started |
INFO | a tool call finished cleanly, with latency |
WARNING | upstream retry, egress denied, auth failure, rate limit |
ERROR | a tool call raised |
Records carry the exception *type* only — never its message and never an upstream response body.
{"event":"tool_call_started","tool":"gazette_search_procurement","correlation_id":"23221af26ae640c7","level":"debug","timestamp":"2026-07-27T22:20:07.494276Z"}
{"status":"ok","latency_ms":312,"event":"tool_call","tool":"gazette_search_procurement","correlation_id":"23221af26ae640c7","level":"info","timestamp":"2026-07-27T22:20:07.806Z"}
Ship these to your SIEM and alert on auth_failed, rate_limited, egress_denied, green_gate_violation and blocked_publication_requested — the last two mean something tried to reach a rubric this server does not serve.
| Tool | Signature | Notes |
|---|---|---|
gazette_search_publications | (keyword?, rubric?, sub_rubric?, canton?, date_start?, date_end?, limit=20, page=0, language='de', only_language=False) | Green rubrics enforced. Without rubric, all green rubrics are injected — a keyword-only query can never reach a blocked one. |
gazette_search_detailed | same filters + `top_n=3` | Aggregated. Search *and* full text for the top top_n hits in one call, fetched in parallel. Same green gate on every expanded document; blocked ones are withheld and counted, never rendered. |
gazette_search_procurement | (keyword?, canton?, date_start?, date_end?, include_inactive=False, limit=20, page=0, language='de', only_language=False) | OB-* rubrics plus the gazette-native sub-rubrics AR-VS40, AR-OW40, BA-SH40. A canton with neither gets a simap.ch explainer and no HTTP call. No CPV — the source has none. |
gazette_get_publication | (id, response_format='markdown') | Full official text from XML. Re-checks the rubric after fetching; content from a blocked rubric is discarded. |
gazette_list_rubrics | (language='de', rubric_class='green', response_format='markdown') | rubric_class='all' shows the full taxonomy with traffic-light classes and reasons — listed ≠ queryable. |
gazette_source_status | (response_format='markdown') | Reachability, latency, cache age, scope metrics. |
All tools are readOnlyHint=True.
| Question | Tool chain |
|---|---|
| Tenders in Ticino this quarter | gazette_search_procurement(canton="TI", only_language=True, language="it") |
| Procurement simap.ch does not have | gazette_search_procurement(canton="VS") — 150 Valais awards, none on simap |
| Tenders in any other canton | → use swiss-procurement-mcp |
| What is even queryable here? | gazette_list_rubrics() |
| Why can't I search bankruptcies? | gazette_list_rubrics(rubric_class="all") |
| Zoning changes in Zurich | gazette_search_publications(rubric="RP-ZH") |
| Full text of a notice | gazette_get_publication(id="fbf0ff9e-…") |
| Everything published about one company | → use register-mcp |
The Amtsblattportal systematically publishes personal data of natural persons. Those publications are public — but making them *systematically queryable by name* through an AI agent is a repurposing the publication never intended, and a profiling instrument under the revised Swiss FADP (revDSG).
Four rules follow, and they are enforced in code, not in documentation:
🔴 Konkurse (KK), Schuldbetreibungen (SB), Schuldenrufe (LS, SR), Nachlass (NA), Erbschaft/Testament/Ableben (ES, TE-*, VA-*), Familie & Zivilstand (FZ-*, BV-*, BU-*), gerichtliche Vorladungen (UV, GB-*, GE-*, SJ-BE), Baugesuche (BP-*), Grundbuch (GR-*), Meldungskatalog GR (AA-GR).
🟡 Deferred: Steuerwesen, Anzeigen, Bewilligungen, Bildungs- und Kirchenwesen and the general catch-all rubrics.
The full audit trail — including three documented extensions to the source specification — is in docs/rubric-classification.md.
How much each decision covers is measured, not estimated. docs/coverage-matrix.md enumerates the source's own rubric axis and marks this server's reach into it: 84.2 % of 2 804 063 publications are reachable, 12.6 % blocked by decision, 3.3 % still unclassified. The insolvency group alone is 321 704 publications — present in the source, out of reach here on purpose. Without that figure, "out of scope" and "not in the source" read the same in a review, and this repository made exactly that mistake once (see ARCH-003 in SECURITY.md).
register-mcpFor publications about a specific company, use [register-mcp](https://github.com/malkreide/re
앞부분만 보여 드려요. 나머지는 저장소에서 읽어 보세요