scb-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., "@scb-mcphow many workplaces are there in Uppsala län?"
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.
scb-mcp
An MCP server over Statistics Sweden's business register. Point an assistant at it and it can search, count and read Swedish workplaces and legal entities without knowing anything about cursors, path versions or API keys.
No dependencies. The protocol is implemented against the specification rather than
wrapped, which is the point: the handshake, the framing and the error codes are all in
src/, in about three hundred lines you can read.
Use it
// Claude Desktop, claude_desktop_config.json
{
"mcpServers": {
"scb": {
"command": "npx",
"args": ["-y", "scb-mcp"],
"env": { "SCB_API_KEY": "the key you were given" }
}
}
}The key goes in the environment, never on the command line and never in a path. It
travels in the X-API-Key header that the register's contract asks for, and it is not
written to the log.
Related MCP server: SCB MCP Server
The tools
tool | what it does |
| Workplaces, filtered on one of kommun, län, näringsgren or size class |
| The same filters, but only the number |
| One workplace by its CFAR number |
| The same, over legal entities |
| |
| One legal entity by organisation number |
Every search takes limit and follows the register's cursor until it has that many.
full: true asks for every available variable instead of the usual selection.
See it work
node --experimental-strip-types examples/handshake.tsA stubbed register, the real protocol:
-> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05"}}
<- {"protocolVersion":"2024-11-05","capabilities":{"tools":{"listChanged":false}},"serverInfo":{"name":"scb-mcp","version":"0.1.0"}}
-> {"jsonrpc":"2.0","method":"notifications/initialized"}
(notification, nothing to answer)
-> {"jsonrpc":"2.0","id":2,"method":"tools/list"}
<- 6 tools: search_workplaces, count_workplaces, get_workplace, search_legal_entities, count_legal_entities, get_legal_entity
-> {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"count_workplaces","arguments":{"...
<- ok: { "count": 1403 }
-> {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"search_workplaces","arguments":{...
<- ok: { "count": 2, "hasMore": true, "items": [ { "cfarNr": "10000001", "namn": "Nordvik Bygg AB", "kommun": "0486",
-> {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"get_workplace","arguments":{"cfa...
<- tool error: no such resource in the register: {"message":"unknown path"}Three decisions
A tool that fails is a result, not a protocol error. The last line above is a 404
from the register, and it comes back inside tools/call with isError: true. A model
reads that and tries a different identifier. A JSON-RPC error would take the whole
turn down for something the model could have handled.
Paging is not the model's problem. The register hands out pages with limit and
cursorId and says hasMore when there is more. The search tools follow that until
they have what was asked for and report whether anything was left, so a model never
has to hold a cursor across turns.
The register filters on one thing at a time. That is the API's restriction, not
this server's, and giving two filters comes back as
the register filters on one thing at a time; kommun and lan were both given rather
than one of them being dropped quietly.
Development
npm run check # types
npm test # 56 tests, no network, no key
npm run buildfetch is injected into the client, which is why every test runs offline. The
register's own contract is at apiafr.scb.se; the paths here follow it, including the
/v1 segment and the /count and /full variants.
MIT licensed.
Available Tools
6 toolscount_legal_entitiesA
Count legal entities in the register, with the same filters as the search. Cheaper than listing them.
| Name | Required | Description | Default |
|---|---|---|---|
| lan | No | County code, two digits, for example 04 for Södermanland. | |
| kommun | No | Municipality code, four digits, for example 0486 for Strängnäs. | |
| naringsgren | No | Industry code (SNI), for example 41200 for building construction. | |
| anstalldaklass | No | Size class code for the number of employees. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. 'Count' implies a read-only aggregate and the cost note hints at performance characteristics, but it doesn't state permissions, rate limits, or confirm the return value is a number.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the resource and the differentiator front-loaded. Nothing wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter count tool with fully documented schema and no output schema, this is close to sufficient. The only mild gap is not spelling out that the result is a numeric total.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so each filter (lan, kommun, naringsgren, anstalldaklass) is already documented with examples. The description only adds the cross-reference that these filters mirror the search tool; it adds no new syntax or semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (count) and resource (legal entities in the register), plus a scope note tying filters to the search. It distinguishes itself from search_legal_entities implicitly via 'cheaper than listing them,' though it never names the sibling outright.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Cheaper than listing them' gives a clear when-to-use condition: choose this over the search/list tool when only a total is needed. It stops short of naming search_legal_entities or stating explicit exclusions, so it lands at 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
count_workplacesA
Count workplaces in the register, with the same filters as the search. Cheaper than listing them.
| Name | Required | Description | Default |
|---|---|---|---|
| lan | No | County code, two digits, for example 04 for Södermanland. | |
| kommun | No | Municipality code, four digits, for example 0486 for Strängnäs. | |
| naringsgren | No | Industry code (SNI), for example 41200 for building construction. | |
| anstalldaklass | No | Size class code for the number of employees. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavioral disclosure. It adds useful efficiency context ("cheaper than listing them") but does not state read-only behavior, permissions, rate limits, or return format for the count.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is a single, front-loaded sentence with no wasted material. It immediately conveys the operation and the key efficiency tradeoff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple count tool with four optional, fully documented filters and no output schema, the description is mostly complete. It could say more about the returned count or filter behavior, but the core operation is adequately covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four filter parameters. The description adds only the general point that these are the same filters as search, without adding syntax or meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Count workplaces in the register." It also distinguishes the tool from listing-oriented siblings by saying it uses "the same filters as the search" and is "cheaper than listing them," though it does not explicitly name the sibling search tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: use this when you need a count with search-equivalent filters, and prefer it over listing results because it is cheaper. It does not explicitly state when not to use it or name the alternative tool, but the intended choice is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_legal_entityA
Read one entry from the register by its peOrgNr.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | Return every available variable. | |
| peOrgNr | Yes | The organisation number of the legal entity. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full behavioral burden. 'Read' does signal a non-mutating operation, but it says nothing about authentication needs, what happens when the peOrgNr does not exist, or rates/limits — and the 'full' flag's behavioral effect on payload size is left entirely to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single eight-word sentence with the key parameter front-loaded and zero wasted phrasing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and the schema is fully documented, but with no output schema the description gives no hint of the returned record's shape or that 'full=true' returns every available variable. That is a real gap for an agent deciding what to expect back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented; the description only reinforces that peOrgNr is the lookup key. It adds no format or syntax guidance beyond the schema, which is the expected baseline when the schema does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (one entry from the register) qualified by the lookup key, which cleanly separates it from the plural siblings search_legal_entities and count_legal_entities. The only weakness is that 'the register' is unnamed and the legal-entity framing is carried entirely by the tool name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The singular 'one entry by its peOrgNr' implies a single-record lookup versus the search/count siblings, but it never says when to prefer this over search_legal_entities or what to do when the key is unknown. Usage is inferable from the name, not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workplaceB
Read one entry from the register by its cfarNr.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | Return every available variable. | |
| cfarNr | Yes | The workplace identifier used by the register. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description's only behavioral signal is 'Read', which conveys non-mutating intent. It says nothing about what happens if the cfarNr does not exist, whether an error or empty result is returned, or any access constraints, leaving the full disclosure burden largely unmet.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficient, though the terseness leaves little room for the context an agent would need to handle edge cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Without annotations or an output schema, the description should carry more weight. For a simple keyed lookup it is minimally adequate, but it omits not-found behavior and the effect of the 'full' parameter, both of which an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented in the schema. The description restates cfarNr's role but does not mention the optional 'full' flag that controls return verbosity, adding no meaning beyond the structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Read one entry from the register by its cfarNr.' This clearly distinguishes a single-record fetch from list-style siblings like search_workplaces and count_workplaces, though it never names them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'by its cfarNr' implies you must already have an identifier, which implicitly separates it from search_workplaces. However, there is no explicit when-to-use guidance, no stated fallback when the identifier is unknown, and no named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_legal_entitiesA
Search legal entities in Statistics Sweden's business register. Filter on one of kommun, lan, naringsgren, anstalldaklass, or leave the filters out to read from the top of the register.
| Name | Required | Description | Default |
|---|---|---|---|
| lan | No | County code, two digits, for example 04 for Södermanland. | |
| full | No | Return every available variable instead of the usual selection. | |
| limit | No | How many legal entities to return. Paging is followed for you. | |
| kommun | No | Municipality code, four digits, for example 0486 for Strängnäs. | |
| naringsgren | No | Industry code (SNI), for example 41200 for building construction. | |
| anstalldaklass | No | Size class code for the number of employees. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full disclosure burden. It does add genuine behavioral context by revealing that unfiltered calls read from the top of the register (default ordering) and that paging is handled transparently, but it says nothing about permissions, rate limits, or what a result record contains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, and the most decision-relevant information (what is searched, then how to filter) is front-loaded. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With six optional parameters, no annotations, and no output schema, the description should ideally say what a returned entity looks like and how the default projection differs from `full`. It covers the filtering decision adequately but leaves the return shape and sibling routing unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the parameters are already well documented and the baseline is 3. The phrase 'filter on one of' hints that the four filter codes are alternatives rather than combinable, which the schema never states — a useful semantic addition, though `limit` and `full` are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search legal entities') plus the concrete data source ('Statistics Sweden's business register'), which is far more informative than a bare name restatement. It does not explicitly distinguish itself from siblings like count_legal_entities or get_legal_entity, so the agent must infer the search-vs-count-vs-fetch split from the verb alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a real usage rule — 'filter on one of ... or leave the filters out to read from the top of the register' — which tells the agent both the filtered path and the unfiltered fallback. However, it never says when to prefer count_legal_entities (to get totals without consuming the limit) or get_legal_entity (to fetch a single record), leaving the sibling routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_workplacesA
Search workplaces in Statistics Sweden's business register. Filter on one of kommun, lan, naringsgren, anstalldaklass, or leave the filters out to read from the top of the register.
| Name | Required | Description | Default |
|---|---|---|---|
| lan | No | County code, two digits, for example 04 for Södermanland. | |
| full | No | Return every available variable instead of the usual selection. | |
| limit | No | How many workplaces to return. Paging is followed for you. | |
| kommun | No | Municipality code, four digits, for example 0486 for Strängnäs. | |
| naringsgren | No | Industry code (SNI), for example 41200 for building construction. | |
| anstalldaklass | No | Size class code for the number of employees. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the useful default behavior of reading from the top of the register when no filters are supplied, but it does not explicitly confirm read-only semantics, describe permissions or rate limits, or explain what the returned records contain.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence with the core purpose front-loaded and the fallback behavior stated immediately after. Every clause earns its place with no repetition or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with six optional parameters, no annotations, and no output schema, the description covers purpose and basic filtering but leaves gaps around return values and output shape. It is minimally adequate but not fully complete for an agent that needs to understand what comes back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters thoroughly. The description reinforces that the four named filters are optional and can be omitted, but it omits any mention of the 'full' or 'limit' parameters, so it adds only marginal meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Search workplaces in Statistics Sweden's business register'), making the purpose immediately clear. It does not explicitly distinguish this tool from siblings like search_legal_entities or count_workplaces, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives implied usage guidance by naming the four filter fields and noting that filters can be omitted to read from the top of the register. However, it does not say when to use this tool instead of count_workplaces, get_workplace, or other siblings, nor does it state any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
count_legal_entities - First observed
count_workplaces - First observed
get_legal_entity - First observed
get_workplace - First observed
search_legal_entities - First observed
search_workplaces
TDQS
Scored across 6 tools
The set factorizes cleanly into two resources (workplaces, legal entities) × three operations (get, search, count), and each tool name states both explicitly. The descriptions reinforce this, including a clear note that count is a cheaper alternative to search and that get uses a distinct identifier (cfarNr vs peOrgNr). No two tools can be reasonably confused.
Every tool follows the same snake_case verb_noun pattern (get_/search_/count_ plus the resource), with parallel naming across the two entity types. The pattern is fully predictable, so an agent can infer tool names for a resource without reading descriptions.
Six tools is tightly scoped: exactly the three read operations needed for each of the two register resources, with no redundant or filler tools. The count/search pairing is justified by an explicit cost tradeoff rather than duplication.
For a read-only statistical register, the surface covers the core lifecycle: filtered search, cheap counting, and single-record retrieval by key. The notable gap is discoverability of filter vocabularies (valid kommun/lan/naringsgren/anstalldaklass codes) and pagination semantics, which agents must currently guess at.
Maintenance
Related MCP Connectors
Swedish company data: segment companies by industry, place and size, and look up any company.
71Swedish company data (Bolagsverket, SCB) for AI agents, verified, with history and annual reports
Swedish B2B intelligence for AI agents: insolvency risk, procurement, BRF health and more.
Swedish public data as read-only tools: registries, statistics, domains, transport, energy.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables searching and retrieving detailed information about Swedish companies, including financial data and annual reports from Bolagsverket (Swedish Companies Registration Office), with intelligent caching for fast responses.-
- AlicenseNot gradedqualityCmaintenanceEnables LLMs to search, access, and retrieve official Swedish statistics from Statistics Sweden (SCB), providing access to 1,200+ tables covering demographics, economy, environment, labor market, and education with 75+ years of historical data.9MIT
- AlicenseBqualityDmaintenanceEnables interaction with the Norwegian Business Registry (Brønnøysundregistrene) API to search and retrieve detailed information about Norwegian companies, subunits, roles, organization forms, municipalities, and NACE industry codes.189 npm1MIT
- AlicenseNot gradedqualityDmaintenanceProvides access to Norway's official business registry for searching companies, looking up organizational details, and identifying company roles and sub-units. It utilizes data from Brønnøysundregistrene to enable detailed queries by industry, municipality, or organization number.8 npmMIT