Skip to main content
Glama
README.md
# mcp-ssb

MCP-server for **Statistisk sentralbyrå** — 3 898 statistikktabeller indeksert lokalt,
tallene hentet live. Ingen autentisering.

Dette er de faktiske norske tallene: prisvekst, boligpriser, lønn, befolkning,
arbeidsledighet. Til forskjell fra [mcp-datanorge](https://github.com/synjan/mcp-datanorge),
som bare forteller hvilke datasett som finnes.

## Hvorfor lokal indeks

SSBs eget fritekstsøk er ubrukelig. Målt 2. september 2026 mot
`data.ssb.no/api/pxwebapi/v2-beta/tables?query=`:

| Søk | SSBs søk | Denne serveren |
| --- | --- | --- |
| `konsumpris` | 1 treff — feil tabell | 16 treff, Konsumprisindeks øverst |
| `boligprisindeks` | 0 treff | 2 treff, Prisindeks for brukte boliger |
| `arbeidsledighet` | — | 11 treff |
| `befolkning` | 318 treff, FoU-personale øverst | 18 treff, befolkningstabeller |

Søket er delstreng uten stemming eller rangering. Men hele katalogen kommer i **ett
kall** — 3 898 tabeller, 6 MB — så den indekseres lokalt med FTS5 i stedet.

## Søket er bygget for norsk

Tre ting skiller det fra et vanlig fulltekstsøk:

- **Dagligtale oversettes til SSBs termer.** «Boligprisindeks» finnes ikke i noen
  tabelltittel; SSB kaller den «Prisindeks for brukte boliger». Broen er en kuratert
  liste i `src/synonyms.js`, ikke en ordbok — hver oppføring er verifisert mot katalogen.
- **Søket trapper opp.** Eksakte ord → prefiks → stammet prefiks → delvise treff. Norsk
  er et sammensetningsspråk, så «konsumpris» finnes ikke som eget ord i
  «Konsumprisindeks», og «arbeidsledighet» ikke i «Arbeidsledige». Feltet `strategi`
  sier hvilket trinn som slo til.
- **`variableNames` er indeksert.** En tabell er ofte lettest å finne på dimensjonene
  den har enn på tittelen.

## Verktøy

| Verktøy | Hva det gjør |
| --- | --- |
| `search` | Finn tabellen. Lokalt, millisekunder. |
| `table` | Dimensjonene i en tabell med gyldige koder. Bruk før `data`. |
| `data` | Tall med eksplisitt utvalg per dimensjon. |
| `latest` | Siste N perioder uten dimensjonsarbeid — «hva er tallet nå». |
| `status` / `sync` | Indeksens alder; oppfrisking. |

## Kommandolinje

```bash
ssb sok boligpriser                    # oversettes til «brukte boliger prisindeks»
ssb tabell 03013                       # dimensjoner og koder
ssb siste 03013 --perioder 3           # 138.7 · 138.9 · 139.1
ssb data 03013 --velg ContentsCode=Tolvmanedersendring --velg Konsumgrp=TOTAL --perioder 4
ssb status
```

`--json` gir rå JSON. `ssb hjelp` viser alt.

## Installasjon

```bash
npm install
npm run sync          # bygger indeksen, ~2 s
claude mcp add --scope user ssb -- node ~/Work/mcp-ssb/src/index.js
ln -sf ~/Work/mcp-ssb/src/cli.js ~/.local/bin/ssb
```

Indeksen havner i `~/.local/share/mcp-ssb/ssb.db`. Overstyr med `SSB_DB` eller
`XDG_DATA_HOME`.

## API-ene

To generasjoner brukes med vilje:

- **v2-beta** (`/api/pxwebapi/v2-beta/tables?pageSize=5000`) — hele katalogen i ett kall
- **v0** (`/api/v0/no/table/{id}`) — metadata med GET, tall med POST og json-stat2

json-stat2 er tett: én flat verdiliste pluss dimensjoner med indeks, der siste dimensjon
varierer raskest. Flatingen til rader ligger i `flattenJsonStat()` og har egne
enhetstester på et innbakt eksempel — ingen nettverk.

Dimensjoner merket `elimination` kan utelates, og da summerer SSB over dem. Det er slik
`latest` får totaltall uten å måtte velge en verdi i hver dimensjon.

## Utvikling

```bash
npm test              # 14 tester; de mot indeksen hopper over hvis den mangler
npm start             # kjør serveren på stdio
```

## Lisens

MIT for koden. Tallene er SSBs, gjenbrukbare etter deres vilkår.

TDQS

A4.1/5.0

Scored across 6 tools

Disambiguation5/5

The six tools map to distinct stages in the workflow: discovery (search), schema lookup (table), explicit queries (data), quick latest values (latest), and catalog maintenance/status (status/sync). Even though data and latest both return numbers, latest is clearly framed as a convenience shortcut, so an agent should not confuse them.

Naming Consistency4/5

All names are lowercase single words, so the style is uniform and there is no case or convention mixing. The semantic pattern is less regular, however: some are verbs (search, sync), some are nouns (table, data, status), and latest is an adjective, and none follow a verb_noun shape.

Tool Count5/5

Six tools is appropriate for a read-only statistics API: discovery, metadata, query, convenience access, and catalog health/maintenance are each represented without redundancy. The count feels well-scoped for the server's purpose.

Completeness4/5

The core workflow is complete: search finds a table, table exposes dimensions and codes, data fetches specific selections, and latest covers a common shortcut; status and sync handle catalog freshness. The only minor gap is a lack of any browse/list-all-tables capability, but search is clearly designed to cover discovery.

Maintenance

ActivityMaintained
ResponsivenessNo issues