@pipeworx/swissmedic
MCP serverDev toolsSwissmedic authorised human medicines, the 'Zugelassene Arzneimittel
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the ask pipeworx tool from @pipeworx/swissmedic
Install @pipeworx/swissmedic
The server’s own address, for the clients that take one directly. Or connect ahel onceand every client you use reads it from one address, with the account kept on ahel rather than in each client’s config.
Claude Code
claude mcp add --transport http --scope user pipeworx-swissmedic 'https://gateway.pipeworx.io/swissmedic/mcp'Run it once in your project, then open /mcp to approve any sign-in the server asks for.
Claude Desktop
https://gateway.pipeworx.io/swissmedic/mcpAdd a custom connector in Settings, paste this address, and approve the sign-in.
Cursor
cursor://anysphere.cursor-deeplink/mcp/install?name=pipeworx-swissmedic&config=eyJ1cmwiOiJodHRwczovL2dhdGV3YXkucGlwZXdvcnguaW8vc3dpc3NtZWRpYy9tY3AifQ==Open the link and Cursor adds the server at that address.
ChatGPT
https://gateway.pipeworx.io/swissmedic/mcpIn Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.
Codex
codex mcp add pipeworx-swissmedic --url 'https://gateway.pipeworx.io/swissmedic/mcp'Run it once, then sign in with codex mcp login pipeworx-swissmedic if the server asks for an account.
From the project's README
As published by pipeworx-io/mcp-swissmedic in README.md.
Swissmedic's authorised human medicines register (Switzerland) — the "Zugelassene Arzneimittel HAM" list: every authorised product and each of its authorised dosage strengths, with the marketing-authorisation holder, medicine category, dispensing category (prescription tier) and authorisation dates. Keyless.
Part of Pipeworx — an MCP gateway connecting AI agents to 1683+ live data sources.
Tools
swissmedic_search(query?, holder?, category?, dispensing_category?, limit?, offset?)— free-text/filtered search with real offset+limit pagination and atotal_matchescount. Answers "is X authorised in Switzerland", "who holds the Swiss authorisation for X", "what dispensing category is X in".swissmedic_product(name)— every authorised dosage strength for one product by name (exact match preferred, falls back to substring withmatch_typemarked). The export carries no indication text and no per-product URL, so this returns the authoritative Swissmedic download instead.swissmedic_recent_changes(since)— products first authorised, or with a dosage strength newly authorised, since a date — a real signal from the source's own date columns.swissmedic_dataset_info()— the authoritative bulk-download URL, source page, row count, and the full lists of distinct medicine categories and dispensing categories used by the filters.
Auth
Keyless.
Data sources
- https://www.swissmedic.ch/dam/swissmedic/en/dokumente/internetlisten/zugelassene_arzneimittel_ham_ind.xlsx.download.xlsx/Zugelassene_Arzneimittel_HAM.xlsx — the authorised human medicines XLSX, linked from swissmedic.ch's "Listen und Verzeichnisse" page. Verified live 2026-09-25: HTTP 200, 1,005,371 bytes, 11,086 data rows. Swissmedic states the lists are "updated monthly" — there is no finer-grained cadence published.
This pack fetches EMA-sized data, not ema-article57-sized data — and that difference decides the architecture
The file is ~1 MB compressed, ~4.8 MB of sheet XML. That is the same size class the sibling ema-medicines pack already parses live per request without issue, and roughly 9x smaller than the file that made the ema-article57 pack build a local R2-backed copy instead (164,314 rows / 63 MB of sheet XML there, versus 11,086 rows / 4.8 MB here). So swissmedic fetches live, same pattern as ema-medicines: one parsed copy held per isolate for 12 hours (DATASET_TTL_MS) plus a 12-hour Cloudflare edge cache on top — Swissmedic's own monthly update cadence makes anything shorter needless re-downloading of an unchanged file. If a refresh fails while an earlier copy is in hand, the earlier copy is served rather than an error.
Licence — this is a live proxy, not a mirror, so no separate reuse grant is needed
Swissmedic's general Legal Notice is more restrictive-sounding than EMA's ("downloading or copying content... requires written consent from the copyright holders" — a page written for the site broadly, not this specific public list). That question does not need resolving here: per the proxy-vs-mirror rule (mirror-needs-grant-proxy-does-not, CLAUDE.md), a pack that calls a public, keyless upstream live on each cache-miss is a client, not a publisher, and needs no explicit grant — only bulk-copying/mirroring the dataset would. This pack does the former (fetch-and-cache, same as ema-medicines), never the latter.
Schema — row 7 is the header, bilingual DE/FR source
Rows 1-6 are a title block (bilingual German/French, the same shape as most Swiss federal exports), row 7 is the header, rows 8+ are records. Ten columns: authorisation number, dosage-strength number, product name, marketing-authorisation holder, medicine category ("Heilmittelcode" — e.g. "Impfstoffe" = vaccines, "Blutprodukte" = blood products), dispensing category at dosage level, dispensing category at medicine level, first-authorisation date, dosage-authorisation date, validity duration ("unbegrenzt" = unlimited, for most rows in this export).
The two date columns are Excel serial dates (days since 1899-12-30, the Lotus-1-2-3-compatibility epoch Excel still carries) — converted to ISO YYYY-MM-DD on the way out (excelSerialToIso in src/index.ts). Verified against a known row: Vivotif's first_authorisation_date serial converts to 1980-12-09, consistent with its real-world authorisation history.
There is no indication text and no per-product URL beyond the authorisation number. swissmedic_product's response points to the authoritative Swissmedic download rather than paraphrasing an indication that is not in the data.
dispensing_category matches either column
Every product carries a dispensing category at the medicine level and, separately, one per dosage strength — they usually agree but are not guaranteed to. swissmedic_search's dispensing_category filter matches a row if EITHER column equals the requested value, so a caller does not need to know which level Swissmedic happened to record a mismatch at. Distinct values observed live: A, A+, B, B/D, D, E.
swissmedic_recent_changes uses real dates, unlike ema-article57's sibling tool
EMA's Article 57 export (ema-article57 pack) carries no date column at all, so that pack's recent_changes can only diff its own snapshots. This file has two real date columns, so swissmedic_recent_changes filters directly on first_authorisation_date/dosage_authorisation_date >= since — no snapshot history required. Verified live 2026-09-25: since: "2026-01-01" returned 384 real changes, including dosage-level re-authorisations from August 2026.
Reused parser
src/xlsx.ts is a copy of mcps/ema-medicines/src/xlsx.ts (the hand-rolled zip+XML reader) rather than a shared dependency — both files are small and a Worker pack shouldn't pull in a shared xlsx-parsing package for what is, on each side, one regex-based scanner over one file shape. Keep them in sync by eye if the underlying approach ever needs to change; the lazy [^>]*? attribute match in CELL_RE is load-bearing (see the comment above it) and must not be "simplified" to greedy.
Quick Start
Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
{
"mcpServers": {
"swissmedic": {
"url": "https://gateway.pipeworx.io/swissmedic/mcp"
}
}
}
What this endpoint actually serves
tools/list at https://gateway.pipeworx.io/swissmedic/mcp returns the tools in the table
above plus the shared Pipeworx meta-tools — ask_pipeworx,
discover_tools, search_within, remember/recall and the rest of the
gateway-wide set. So the tool count you see is larger than this table: a
single-pack endpoint currently lists roughly 30 shared tools alongside the
pack's own. The connection's initialize response states its exact scope, and
is the authoritative answer for a given day.
This is deliberate, not multiplexing by accident. The meta-tools are what let a
scoped connection answer a question this pack does not cover — via
ask_pipeworx, which routes across the whole catalog — without you adding a
second MCP server. There is currently no way to mount a pack endpoint without
them; if the extra schemas cost you more context than the routing is worth,
connect to the full gateway once rather than to several pack endpoints.
Or connect to the full Pipeworx gateway to get every pack's tools listed directly, instead of just this one's:
{
"mcpServers": {
"pipeworx": {
"url": "https://gateway.pipeworx.io/mcp"
}
}
}
Both URLs reach the same gateway and the same 1683+ data sources. The
only difference is which pack's tools are listed directly; ask_pipeworx
reaches all of them from either one.
No MCP client? Call it over HTTP
curl -X POST https://gateway.pipeworx.io/v1/tools/swissmedic_search \
-H 'Content-Type: application/json' \
-d '{"query":"Vivotif","limit":5}'
No account needed for the first calls. Inspect any tool: GET https://gateway.pipeworx.io/v1/tools/swissmedic_search. Find one: POST https://gateway.pipeworx.io/v1/tools/search_packs with {"query":"..."}.
Standalone (no gateway account)
This package also runs as a local stdio MCP server — no Pipeworx account, no gateway round-trip:
{
"mcpServers": {
"swissmedic": {
"command": "npx",
"args": ["-y", "@pipeworx/mcp-swissmedic"]
}
}
}
Or run it directly to confirm it starts:
npx -y @pipeworx/mcp-swissmedic
It speaks MCP over stdin/stdout and answers initialize/tools/list/tools/call
for only this pack's tools — none of the shared meta-tools the gateway
connection above adds. Same source, same tools, no ask_pipeworx routing.
Using with ask_pipeworx
Instead of calling tools directly, you can ask questions in plain English — this works on the pack endpoint above as well as on the full gateway:
ask_pipeworx({ question: "your question about Swissmedic data" })
The gateway picks the right tool and fills the arguments automatically.
More
License
MIT
Tools it offers (40)
What this server listed when ahel dialed its public endpoint in Sep 2026, with no key and no account of yours. The names are the server’s own.
ask_pipeworxask_pipeworx_betaask_pipeworx_groundedsearch_withindeep_researchdiscover_toolsresolve_entitycompare_entitiessubscribeunsubscribelist_subscriptionsrecent_alertsentity_profilerecent_changesvalidate_claimcompany_factsscan_dependencybet_researchpolymarket_arbitragepolymarket_edgespolymarket_kalshi_spreadpolymarket_fill_riskpolymarket_edge_trackerkalshi_weather_edgeresolution_auditresolution_diffrelease_calendar_marketspipeworx_trendingsuggest_questionsgenerate_llms_txt
Signals
- Last commit
- Sep 2026
Advanced
- Delivery
- swissmedic MCP server → your ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
io-github-pipeworx-io-swissmedic- Source
- github.com/pipeworx-io/mcp-swissmedic
- Hosted endpoint
https://gateway.pipeworx.io/swissmedic/mcp