Skip to main content
Glama

dk-regnskab-mcp

Give Claude (or any MCP client) the published annual reports of Danish companies: key figures for the latest year and the year before, read straight from the XBRL filings at the Danish Business Authority (Erhvervsstyrelsen). No API key needed.

"What were revenue and equity for CVR 24256790 last year, and how did they change?"

Quickstart

Requires Node.js 22.18 or newer.

git clone https://github.com/mikkelmanniche-dk/dk-regnskab-mcp
cd dk-regnskab-mcp && npm install && npm run build

Claude Code

claude mcp add dk-regnskab -- node /absolute/path/to/dk-regnskab-mcp/dist/index.js

Claude Desktop: add this to claude_desktop_config.json:

{
  "mcpServers": {
    "dk-regnskab": { "command": "node", "args": ["/absolute/path/to/dk-regnskab-mcp/dist/index.js"] }
  }
}

Related MCP server: Register UZ MCP Server

Tools

Tool

Input

Returns

get_financials

cvr, optional year (the year the reporting period ends in)

Company name, period, currency, auditor, key figures (current and previous year), notes on gaps, source document URL

list_filings

cvr, optional limit (1–50)

Published filings, newest first, with document links

Key figures: revenue, gross profit, operating profit, profit before tax, profit for the year, average employees, total assets, current assets, cash, equity, liabilities.

How it works

flowchart LR
  C[Claude / MCP client] -- stdio --> S[dk-regnskab-mcp]
  S -- "search by CVR" --> I[(distribution.virk.dk<br/>filing index)]
  S -- "download XBRL (gzip)" --> D[(Filing documents)]
  S --> P[Parse contexts & facts<br/>by namespace, not prefix]
  P --> F[Key figures + notes]

Pitfalls it handles

Real Danish filings are messier than the taxonomy suggests. The parser was built against actual filings:

  • Dimensional facts are not totals. A filing reports equity once in total and again per component (share capital, retained earnings). Only dimensionless contexts are used, so share capital is never reported as equity.

  • Conflicting values. Some filings report two different values for the same fact and period (e.g. 0 and 1 employees). The figure is left empty with a note instead of guessed.

  • Missing revenue is usually legal. Most small companies (reporting class B) may omit revenue and report gross profit. The result says so.

  • Namespace prefixes vary between filings, so concepts are matched by namespace URI.

  • Documents are gzip-compressed without saying so. Detected by magic bytes.

  • The document named "AARSRAPPORT" is not always the one with the numbers. Every XML document in a filing is parsed, and the one that yields the most figures wins.

  • Two taxonomies. Danish GAAP for most companies, IFRS (ESEF) for listed ones. Both are supported.

Limitations

  • Lookup by CVR number only. Searching by company name needs the CVR register, which requires an approved account for system-to-system access. Planned.

  • Only companies that file machine-readable annual reports. Sole proprietorships and some other company types don't.

  • Key figures only, not the full statements, notes or management's review.

  • Group vs. parent figures in IFRS filings are not yet distinguished beyond ignoring dimensional contexts.

  • The filing index answers over plain HTTP only, so the server must run locally or server-side, not in a browser.

  • Data terms: the filings are public data from the Danish Business Authority. Check their terms of use for your use case; this project does not make claims about them.

Development

npm test          # parser tests against synthetic fixtures (no network)
npm run typecheck
npm run build

Roadmap

  • Company name search via the CVR register

  • Group vs. parent figures for IFRS filings

  • Multi-year history in one call

  • Publish to npm for npx usage

License

MIT. Built by Mikkel Manniche.

Available Tools

2 tools
get_financialsGet key financials from an annual reportA

Read a Danish company's published annual report (XBRL) and return key figures for the reporting year and the year before: revenue, gross profit, profit, equity, assets, cash, employees, plus auditor. Values are in the filing's currency (usually DKK). Small companies often omit revenue legally; notes explain gaps and conflicts instead of guessing.

ParametersJSON Schema
NameRequiredDescriptionDefault
cvrYesDanish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted).
yearNoCalendar year the reporting period ends in. Omit for the latest annual report.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden. It discloses that values use the filing currency, often DKK, and that revenue may be legally omitted by small companies—with notes explaining gaps and conflicts instead of guessing. This goes beyond input mechanics, though it does not specify behavior for missing filings or errors.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: the first states the action and result, the second clarifies currency, and the third handles edge cases around omitted revenue and guessing. The key information is front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description enumerates all returned fields, explains the two-year comparison, and covers the main edge case. The two parameters are fully documented in the schema, so an agent has enough information to invoke the tool correctly and interpret the results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes both parameters fully, with 100% coverage, so the baseline is 3. The description adds useful output context such as 'reporting year and the year before' and currency, but it does not add new per-parameter constraints or syntax beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Read a Danish company's published annual report (XBRL)' and return key figures. It clearly enumerates the outputs, making it easy to distinguish from the sibling tool list_filings, which is about discovering filings rather than extracting financials.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes the context clear: use this when you need key financial numbers from a Danish annual report, including the prior-year comparison and currency behavior. It does not explicitly name list_filings as an alternative or state when not to use this tool, so exclusions are absent, but the intended use is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_filingsList published filingsA

List what a Danish company has published with the Danish Business Authority (Erhvervsstyrelsen): annual reports, half-year reports and their documents, newest first.

ParametersJSON Schema
NameRequiredDescriptionDefault
cvrYesDanish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted).
limitNoHow many filings to return.

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses only the ordering behavior ('newest first') but omits other behavioral traits such as pagination, error handling for invalid CVR, empty results, or the exact response structure. Given the lack of annotations, this is a significant gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the primary action and resource, includes relevant details (filing types, ordering) without redundancy or fluff. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (2 params, no nested objects), but with no output schema and no annotations, the description should provide more context on return format or edge cases. It covers the core behavior but leaves an agent without details on what the response looks like or how failures are handled. Adequate for basic invocation, not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for both parameters (cvr and limit), including format and constraints. The description itself adds no parameter information beyond what the schema already provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List'), a clear resource (filings published by a Danish company), and enumerates the types (annual reports, half-year reports, their documents) plus ordering (newest first). It inherently distinguishes from the sibling get_financials, which likely focuses on financial figures rather than filings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies its purpose clearly but never explicitly names alternatives or gives when-to-use/when-not-to-use guidance. An agent could infer that this tool is for listing filings while get_financials handles financial data, but no direct comparison or exclusion is stated.

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.

  1. 2 tool updatesv0.1.0
    • First observedget_financials
    • First observedlist_filings

TDQS

A3.6/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: one lists filings, the other extracts financial data from a specific filing. There is no overlap or ambiguity between them.

Naming Consistency5/5

Both tool names follow a consistent verb_noun pattern (list_ and get_), which is predictable and aligned with common conventions.

Tool Count2/5

With only two tools, the server feels very thin. While the tools are individually useful, the set is minimal and likely insufficient for comprehensive company data retrieval, missing operations like searching or fetching specific filing documents.

Completeness2/5

The domain appears to be company financial data from the Danish Business Authority, but the surface is incomplete: there is no way to search companies, list companies, fetch raw documents, or get detailed financial statements. The existing tools cover listing and reading key figures, but many obvious workflows (e.g., retrieving a specific filing's full details) are missing.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Provides comprehensive Norwegian business intelligence through Brønnøysund and Statistics Norway APIs, enabling company search, financial analysis, ownership mapping, market research, and automated financial data extraction.
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables access to Slovak Registry of Financial Statements data, allowing users to search companies, retrieve financial reports, balance sheets, income statements, and analyze Slovak business financial data through natural language queries.
    25
    2
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables querying and analyzing XBRL financial data through natural language, using an API key for authentication.
    5 npm
    1
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to search and look up Danish and Norwegian company registry (CVR) data, including company details, bankruptcy status, and more.
    2
    4 npm
    MIT