suomi-mcp
# suomi-mcp
[](https://www.npmjs.com/package/datakytkin-mcp)
[](https://github.com/datakytkin/suomi-mcp/actions/workflows/ci.yml)
[](LICENSE)
**[English summary below ↓](#english)**
Osa [datakytkin](https://github.com/datakytkin)-projektia. Kokoelma MCP-työkaluja,
jotka tuovat suomalaista avointa dataa suoraan tekoälyavustajien käyttöön – ilman
selaimessa kikkailua, PDF-latauksia tai leikepöytää.
Paikallisesti ajettava **MCP-palvelin (stdio)**, joka tuo Claude Desktopin (tai
muun MCP-yhteensopivan clientin) käyttöön 11 työkalua suomalaisiin avoimen
datan rajapintoihin:

| Työkalu | Lähde | Mitä tekee |
| --- | --- | --- |
| `hae_yritystiedot_prh` | PRH / YTJ avoin data (`avoindata.prh.fi/opendata-ytj-api/v3`) | Yrityksen perustiedot Y-tunnuksella tai nimellä: nimi, Y-tunnus, yritysmuoto, **toimiala (TOL), kotipaikka, verkkosivu**, rekisteröintipäivä, toiminnan tila, **rekisterimerkinnät** (ALV-, ennakkoperintä-, työnantajarekisteri). |
| `hae_julkiset_hankinnat_hilma` | Hilma – julkiset hankinnat (`hankintailmoitukset.fi`) | Hakee avoinna olevat hankintailmoitukset hakusanalla: otsikko, hankintayksikkö, määräaika, suorat linkit ilmoitukseen ja tarjouspyyntöön. |
| `hae_hankintailmoitus` | Hilma – julkiset hankinnat | Yhden hankinnan **kaikki tiedot**: koko kuvaus, arvioitu arvo, menettely, CPV-koodit, osat, vastuullisuuskriteerit, TED-numero, linkit. |
| `hae_kaupparekisteri_muutokset_prh` | PRH – rekisteröidyt ilmoitukset (`avoindata.prh.fi/opendata-registerednotices-api/v3`) | Yrityksen perustiedot + aikajana kaupparekisteriin rekisteröidyistä ilmoituksista: hallitus- ja nimenmuutokset, tilinpäätökset, osakepääoma, konkurssi/saneeraus/selvitystila. Täysi kattavuus. |
| `tarkista_alv_tunnus` | EU **VIES** | Tarkistaa EU-ALV-tunnuksen voimassaolon + palauttaa nimen ja osoitteen. Käytä ennen ALV 0 % -laskutusta EU-maahan. |
| `hae_porssisahko` | porssisahko.net avoin API | Suomen pörssisähkön (spot) tuntihinnat: hinta nyt, seuraavat tunnit, vuorokauden halvin ja kallein tunti. c/kWh sis. ALV 25,5 %. |
| `hae_saa` | Ilmatieteen laitos, avoin data (WFS) | Sääennuste tunneittain paikkakunnalle: lämpötila, tuuli, sade, ilmankosteus. |
| `laske_inflaatio` | Tilastokeskus StatFin (elinkustannusindeksi) | Rahan ostovoiman muutos vuosien välillä, yhtenäinen sarja vuodesta 1951. "Paljonko 1000 € vuonna 1985 on nyt." |
| `hae_asuntojen_hinnat` | Tilastokeskus StatFin (ashi/13mu) | Vanhojen osakeasuntojen neliöhinnat ja kauppamäärät **postinumeroalueittain**, talotyypeittäin. |
| `hae_polttoaineen_hinnat` | Tilastokeskus StatFin (khi/11xx) | Bensiini (95/98), diesel ja kevyt polttoöljy: keskihinta viimeisimmältä tilastokuukaudelta + muutos ed. kuukauteen ja vuoden takaiseen. |
| `tarkista_iban` | – (ei rajapintaa) | IBAN-tilinumeron rakenne + tarkistusnumero (mod-97). Suomalaiselle IBANille kansallinen tilinumero ja arvio pankista. |
> **PRH:** vanha `avoindata.prh.fi/bis/v1` on poistettu käytöstä. Tämä palvelin
> käyttää nykyistä **v3**-rajapintaa (sama avoin YTJ-yrityshaku, ei API-avainta).
>
> **Hilma:** käytetään Hilman julkista hakurajapintaa, joka ei vaadi avainta.
> Koko ilmoituksen eForms-XML:n saa erikseen AVP-read-rajapinnasta (ilmainen
> tilausavain) – sitä ei tässä tarvita.
## Pikakäyttö
Vaatii **Node.js 18+** polussa (kehitetty ja testattu Node 20:llä).
Lisää Claude Desktopin konfiguraatioon:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"datakytkin": {
"command": "npx",
"args": ["-y", "datakytkin-mcp"]
}
}
}
```
Käynnistä Claude Desktop uudelleen. Ei tarvita erillistä asennusta – `npx` hakee
paketin npm:stä.
### Jos näet virheen `fetch is not defined`
Claude Desktop käynnistää palvelimen omalla `PATH`:llaan, ja `npx` valitsee
`#!/usr/bin/env node` -rivin kautta **ensimmäisen `node`:n `PATH`:ssa** – usein
vanhan järjestelmä-Noden (esim. v16), josta puuttuu `fetch`. Vaihda tällöin
suoraan absoluuttiseen Node 18+ -binääriin ja globaaliin asennukseen:
```bash
# asenna halutulla Nodella (esim. nvm:n Node 20)
"$(nvm which 20)" "$(dirname "$(nvm which 20)")/npm" install -g datakytkin-mcp
# tulosta polut configia varten:
echo "command: $(nvm which 20)"
echo "entry: $("$(nvm which 20)" "$(dirname "$(nvm which 20)")/npm" root -g)/datakytkin-mcp/dist/index.js"
```
```json
{
"mcpServers": {
"datakytkin": {
"command": "/ABSOLUUTTINEN/POLKU/node/v20.x.x/bin/node",
"args": ["/ABSOLUUTTINEN/POLKU/node/v20.x.x/lib/node_modules/datakytkin-mcp/dist/index.js"]
}
}
}
```
`node` ajetaan tässä eksplisiittisesti, joten `PATH`:n vanha Node ei häiritse.
Päivitys: `npm install -g datakytkin-mcp@latest` samalla Nodella.
## Testikehotteet
1. *"Hae PRH:sta yrityksen tiedot Y-tunnuksella 1629284-5."*
2. *"Etsi Hilmasta avoimet pilvipalveluihin liittyvät hankintailmoitukset, näytä 5."*
3. *"Hae YTJ:stä kaikki yritykset joiden nimessä on 'Reaktor' ja listaa Y-tunnukset."*
4. *"Näytä Hilmasta it-konsultoinnin tarjouspyynnöt ja niiden määräajat."*
5. *"Listaa Y-tunnuksen 1629284-5 viimeisimmät kaupparekisteriin rekisteröidyt muutokset."*
6. *"Onko yrityksellä 1234567-8 merkintöjä konkurssista tai saneerauksesta? Milloin hallitus on viimeksi muuttunut?"*
7. *"Mikä on pörssisähkön hinta nyt ja milloin tänään on halvinta?"*
8. *"Onko ALV-tunnus DE811128135 voimassa ja kenelle se kuuluu?"*
9. *"Millainen sää Rovaniemellä on seuraavat 12 tuntia?"*
10. *"Paljonko 500 markkaa vuonna 1990 on nykyrahassa?"*
11. *"Näytä kaikki tiedot Hilman tietoturvakonsultoinnin dynaamisesta hankintajärjestelmästä."*
12. *"Mitä maksaa neliö postinumerossa 33720?"*
13. *"Paljonko diesel maksaa nyt ja miten hinta on muuttunut vuodessa?"*
14. *"Onko IBAN FI21 1234 5600 0007 85 muodoltaan oikein ja minkä pankin tili?"*
## Kehitys
```bash
git clone https://github.com/datakytkin/suomi-mcp.git
cd suomi-mcp
nvm use 20 # tai: nvm install 20
npm install
npm run typecheck # tarkista että kääntyy
npm test # vitest: työkalut (mockattu fetch), rekisteri, auth, mcp-server
npm run dev # käynnistä palvelin stdio-tilassa (= npx tsx src/index.ts)
```
Palvelin puhuu MCP:tä stdin/stdout-yhteydellä; lokit menevät stderriin.
Käännetty ajo:
```bash
npm run build # tuottaa dist/
npm start # = node dist/index.js
```
Uuden työkalun lisääminen: ks. [CONTRIBUTING.md](CONTRIBUTING.md). Käytännössä:
luo `src/tools/<lahde>.ts`, vie siitä `export const tool: ToolDefinition`, valmista –
`src/tools/registry.ts` löytää sen automaattisesti sekä stdio-palvelimeen että
Gatewayhin.
Claude Desktop -konfiguraatio repo-checkoutista (kehitykseen / omiin muutoksiin):
```json
{
"mcpServers": {
"datakytkin": {
"command": "npx",
"args": ["tsx", "/ABSOLUUTTINEN/POLKU/suomi-mcp/src/index.ts"]
}
}
}
```
## Datasilta-Gateway (kokeellinen)
Sama työkalusetti tarjottuna **keskitettynä HTTP-palvelimena**, jotta asiakkaan ei
tarvitse asentaa mitään paikallisesti – hän liittää yhden URL:n + tokenin suoraan
Claude Desktopiin tai Grokin Custom Connectors -kenttään.
Gateway (`src/gateway.ts`, `src/auth.ts`) elää tässä samassa repossa
(**Open Core**): koodi on MIT, kaupallinen arvo on hostatussa palvelussa +
data-integraatioissa, ei transporttikoodissa. Jos/kun mukaan tulee laskutusta tai
asiakastietoa, ne eriytetään omaksi (privaatiksi) osakseen.
```bash
npm install
DATASILTA_DEV_ALLOW_ANY=1 PORT=3000 npm run dev:gateway
```
Päätepisteet:
| Reitti | Kuvaus |
| --- | --- |
| `GET /sse?token=demo` | HTTP+SSE-kuljetus (laajin connector-tuki). Client postaa viestit `POST /messages?sessionId=…`. |
| `POST /mcp` | Streamable HTTP -kuljetus (spec-nykyinen). Token joko `Authorization: Bearer …` tai `?token=…`. Stateless. |
| `GET /healthz` | Tila + työkalulista |
| `GET /` | Lyhyt käyttöohje |
Mock-tokenit: `demo` (pro), `123` (free), `enterprise`. Kehityksessä
`DATASILTA_DEV_ALLOW_ANY=1` hyväksyy minkä tahansa ≥3 merkin tokenin.
Kovennukset: plan-kohtainen rate limit (free 20 / pro 120 / enterprise 600
kutsua/min, `RateLimit-*` + `Retry-After` -otsakkeet), rinnakkaisten SSE-sessioiden
katto per asiakas, `X-Request-Id` + pyyntöloki, graceful shutdown (SIGTERM/SIGINT
sulkee SSE-sessiot siististi – tärkeä konttiympäristöissä).
Julkinen testaus ngrokilla:
```bash
ngrok http 3000
# -> https://xxxx.ngrok-free.app/sse?token=demo Grokiin / Claudeen
```
> **Kokeellinen.** CORS on täysin auki ja auth on mock. Älä aja tätä julkisesti
> ilman oikeaa tokenvalidointia ja CORS-rajausta. `?token=` URL:ssa vuotaa
> lokeihin – tuotannossa `Authorization: Bearer`.
## Ei virallinen tuote
`datakytkin` on itsenäinen avoimen lähdekoodin projekti. Se käyttää PRH:n ja
Hilman julkisia rajapintoja, mutta ei ole PRH:n, Hanselin, Hilman tai minkään
viranomaisen hyväksymä, tukema tai ylläpitämä. Data tulee sellaisenaan lähteestä.
---
## English
**suomi-mcp** is part of the [datakytkin](https://github.com/datakytkin) project:
a set of [Model Context Protocol](https://modelcontextprotocol.io) tools that bring
Finnish open government data straight into AI assistants – no browser tabs, PDF
downloads or copy-paste.
A locally run **MCP server (stdio)** exposing 11 tools to Claude Desktop (or any
MCP-compatible client):
| Tool | Source | What it does |
| --- | --- | --- |
| `hae_yritystiedot_prh` | Finnish Patent and Registration Office (PRH) / Business Information System, open data v3 | Company details by Business ID or name: name, Business ID, company form, industry (TOL), domicile, website, registration date, status, and register entries (VAT / prepayment / employer register). |
| `hae_julkiset_hankinnat_hilma` | Hilma – Finnish public procurement notices (`hankintailmoitukset.fi`) | Search open procurement notices by keyword: title, contracting entity, deadline, direct links to the notice and tender documents. |
| `hae_hankintailmoitus` | Hilma – Finnish public procurement notices | All details of a single procurement: full description, estimated value, procedure, CPV codes, lots, sustainability criteria, TED number, links. |
| `hae_kaupparekisteri_muutokset_prh` | PRH – registered notices open data | Company basics + a timeline of entries registered in the Finnish Trade Register: board and name changes, financial statements, share capital, bankruptcy / restructuring / liquidation. Full coverage. |
| `tarkista_alv_tunnus` | EU VIES | Validates an EU VAT number and returns the registered name and address. Use before zero-rated intra-EU invoicing. |
| `hae_porssisahko` | porssisahko.net open API | Finnish day-ahead electricity spot prices by hour: price now, upcoming hours, cheapest and most expensive hour of the day. c/kWh incl. 25.5% VAT. |
| `hae_saa` | Finnish Meteorological Institute open data (WFS) | Hourly weather forecast for a place: temperature, wind, precipitation, humidity. |
| `laske_inflaatio` | Statistics Finland StatFin (cost-of-living index) | Purchasing power of a sum between two years, continuous series since 1951. |
| `hae_asuntojen_hinnat` | Statistics Finland StatFin (ashi/13mu) | Resale flat €/m² and transaction counts by postal-code area, by dwelling type. |
| `hae_polttoaineen_hinnat` | Statistics Finland StatFin (khi/11xx) | Petrol (95/98), diesel and light fuel oil: latest monthly average price + change vs previous month and year. |
| `tarkista_iban` | – (no API) | IBAN structure + check digits (mod-97), offline. For Finnish IBANs also the national account number and a bank guess. |
Tool names and all output are in Finnish (that is the data's language).
### Install
Requires **Node.js 18+**. Add to your Claude Desktop config
(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS,
`%APPDATA%\Claude\claude_desktop_config.json` on Windows):
```json
{
"mcpServers": {
"datakytkin": {
"command": "npx",
"args": ["-y", "datakytkin-mcp"]
}
}
}
```
Restart Claude Desktop.
**Seeing `fetch is not defined`?** Claude Desktop launches the server with its own
`PATH`, and `npx` may pick an old system `node` (e.g. v16) that lacks `fetch`.
Install globally with a Node 18+ binary and point `command` straight at it:
```bash
npm install -g datakytkin-mcp
npm root -g # entry = <printed path>/datakytkin-mcp/dist/index.js
```
```json
{
"mcpServers": {
"datakytkin": {
"command": "/absolute/path/to/node18+/bin/node",
"args": ["/absolute/path/to/lib/node_modules/datakytkin-mcp/dist/index.js"]
}
}
}
```
### Not an official product
`datakytkin` is an independent open-source project. It consumes public APIs from
PRH and Hilma but is not endorsed, supported or operated by PRH, Hansel, Hilma or
any public authority. Data is served as-is from the source. See
[SECURITY.md](SECURITY.md) for notes on the data sources and responsible use.
## Lisenssi / License
[MIT](LICENSE)
TDQS
Scored across 11 tools
Every tool targets a clearly different dataset or operation. Even adjacent tools such as PRH company info vs. PRH changes, procurement search vs. notice detail, and IBAN vs. VAT validation are easy to distinguish by name and description.
The tools follow a predictable Finnish pattern: hae_ for data lookups, tarkista_ for validations, and laske_ for calculations. The snake_case convention and object-plus-source naming (e.g. hae_polttoaineen_hinnat, hae_kaupparekisteri_muutokset_prh) are consistent throughout.
With 11 tools, the surface is broad enough to cover several Finnish public-data domains without feeling bloated. Each tool serves a concrete, non-redundant purpose and the count fits the general-purpose national data scope.
The set covers paired operations well (procurement list/detail, company info/changes) and includes validation and calculation utilities. A couple of conceivable additions exist, such as a Finnish business ID validator or population-data lookup, but the current surface has no obvious dead ends.