dk-regnskab-mcp
Read published Danish annual reports from XBRL filings via MCP tools — search companies, list filings, fetch key financials, multi-year history, and all tagged report facts.
search_company — find a company's CVR number by name or look up a known CVR (requires free CVR system-to-system credentials).
list_filings — list annual/interim filings and document links for a CVR, newest first, with optional year filter.
get_financials — get key figures for one annual report (current and previous year), including revenue, profit, equity, assets, cash, employees, currency, auditor, notes, and source document.
get_financials_history — get key figures per reporting year across up to 15 years for trend analysis.
get_report_facts — retrieve every tagged figure and text in a report (e.g. staff costs, dividends), filterable by concept name.
Handles Danish GAAP and IFRS/ESEF, separates group vs parent figures, explains missing/conflicting data, and returns structured read-only output.
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., "@dk-regnskab-mcpWhat were revenue and equity for CVR 24256790 last year?"
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.
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.
Works for small companies (Danish GAAP) and listed ones (IFRS/ESEF, back to 2015), separates group and parent figures in group reports, and explains gaps instead of guessing. Tested live against about 300 real filings.
"What were revenue and equity for CVR 24256790 last year, and how did they change?"
Quickstart
Requires Node.js 22.18 or newer. No API key needed.
Claude Code
claude mcp add dk-regnskab -- npx -y dk-regnskab-mcpClaude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"dk-regnskab": { "command": "npx", "args": ["-y", "dk-regnskab-mcp"] }
}
}Cursor: the same block goes in ~/.cursor/mcp.json (or .cursor/mcp.json in a project). Other MCP clients: run npx -y dk-regnskab-mcp over stdio.
From source
git clone https://github.com/mikkelmanniche-dk/dk-regnskab-mcp
cd dk-regnskab-mcp && npm install && npm run build
claude mcp add dk-regnskab -- node /absolute/path/to/dk-regnskab-mcp/dist/index.jsRelated MCP server: Register UZ MCP Server
Tools
Tool | Input | Returns |
|
| Matching companies with CVR number, status, company type, industry, address and employee size band; active, exactly named and larger companies first. Needs CVR credentials, see below |
|
| Published filings, newest first, with document links |
|
| Company name, period, currency, auditor, key figures (current and previous year), whether it is a group report, notes on gaps, source document URL |
|
| Key figures per reporting year, newest first |
|
| Every figure and text tagged in the annual report, e.g. staff costs or dividends |
All tools are read-only, declare an output schema and return structured content.
Key figures: revenue, gross profit, operating profit, profit before tax, profit for the year, average employees, total assets, current assets, cash, equity, liabilities.
Company name search (optional)
search_company uses the CVR register, which requires system-to-system credentials. They are free: apply at the Danish Business Authority, then pass them to the server:
claude mcp add dk-regnskab -e CVR_USER=... -e CVR_PASSWORD=... -- npx -y dk-regnskab-mcpEverything else works without them. Note that the register, like the filing index, only answers over plain HTTP, so the credentials are sent unencrypted. They only give read access to public company data.
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.
Group reports hold two sets of figures. A parent company's report often includes the consolidated group too, and Danish GAAP and IFRS mark them in opposite ways. The group is returned by default;
scope: "parent"gives the parent alone. Mixing them up can turn a group loss into a parent profit.Balance check. If total assets don't equal liabilities and equity for the chosen scope, the result says so.
A last quarter next to the full year. Some annual reports also tag Q4, with the same end date as the year. The longest period wins.
Three generations of IFRS. ESEF (2021 onwards), the Danish IFRS extension before that (revenue as
NetSales), and the 2011 IFRS taxonomy in filings before 2016. All three are read.Currency comes from the figures themselves. Maersk reports in USD but mentions DKK elsewhere in the filing.
Old reports sit far down the list. Listed companies publish 4–5 filings a year, so a chosen
yearis filtered in the index, not in the first page of results. Interim reports that carry an annual-report document are skipped.Company details can live in a sibling document, and some filers put HTML inside the company name. Both are handled.
Limitations
Name search needs CVR credentials (free, but you have to apply). Without them, look up the CVR number yourself, e.g. on datacvr.virk.dk.
Only companies that file machine-readable annual reports. Sole proprietorships and some other company types don't.
Only what the filer tagged:
get_report_factsreturns the tagged statements and details, not the untagged text of the notes or management's review.IFRS filings don't tag the number of employees (it is text in the notes), so
employeesis empty for them.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.
Tested against real filings
npm run measure runs the real tool path against about 300 companies that filed in the last year, plus a fixed set of large ones (LEGO, Arla, Carlsberg, Maersk, Novo Nordisk, older IFRS years, and a group report with both scopes). It needs network access and is not part of npm test.
Run on 25 September 2026 (v0.3.0): 311 lookups, 309 parsed, 2 companies without an XBRL annual report, 0 errors, 0 balance mismatches, median 118 ms per lookup.
Development
npm test # parser tests against synthetic fixtures (no network)
npm run measure # live check against real filings (network)
npm run typecheck
npm run build
npm run ci # typecheck + test + build, som CIRun npm run ci before merging; it mirrors .github/workflows/ci.yml. CI tests on Node 22 and 24; locally it runs on whichever Node you have.
Roadmap
Company name search via the CVR register
Multi-year history in one call
Published to npm and the official MCP Registry
License
MIT. Built by Mikkel Manniche.
Available Tools
5 toolsget_financialsGet key financials from an annual reportARead-onlyIdempotent
Read one annual report (XBRL) of a Danish company and return its key figures for that year and the year before: revenue, gross profit, operating profit, profit, equity, assets, cash, employees, plus company name, period, currency and auditor. Use it for one year's headline numbers; use get_financials_history for a trend over several years and get_report_facts for any other line item. Group reports default to the consolidated group. Values are in the filing's currency (usually DKK); a missing figure is null and notes say why (small companies may legally omit revenue). found=false when the company has no machine-readable annual report for that year.
| Name | Required | Description | Default |
|---|---|---|---|
| cvr | Yes | Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. "24256790". | |
| year | No | Calendar year the reporting period ends in (a 2024/25 financial year ending June 2025 is 2025). Omit for the latest annual report. | |
| scope | No | For group reports (koncernregnskab): "group" = the consolidated group, "parent" = the parent company alone. Ignored for single companies. | group |
Output Schema
| Name | Required | Description |
|---|---|---|
| cvr | No | |
| name | No | |
| found | Yes | |
| notes | No | Gaps, conflicts and caveats found in the filing, in plain English. |
| scope | No | Whose figures these are; "company" for a report without a group. |
| period | No | Reporting period, ISO dates. |
| source | No | The filing document the figures were read from. |
| auditor | No | |
| figures | No | Key figures; current = this report's year, previous = the year before. |
| message | No | Why nothing was found (only when found=false). |
| currency | No | |
| taxonomy | No | |
| reportType | No | |
| groupReport | No | |
| previousPeriod | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds valuable behavioral context beyond annotations: it explains missing figures are null with notes, small companies may omit revenue, and found=false indicates no machine-readable report. It does not contradict annotations and enriches the agent's understanding of edge cases.
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 well-structured and efficient. It front-loads the core purpose, then lists the return fields, then gives usage guidance, and finally notes edge cases. Every sentence contributes necessary information without redundancy, achieving conciseness while being thorough.
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 has an output schema, so return structure is documented there. The description covers all essential aspects: what it returns, when to use it versus siblings, default scope, currency, missing-value behavior, and the found=false condition. It is complete for an agent to decide when to call it and what to expect, without needing external details.
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 parameters are fully documented in the schema. The description does not add significant extra semantics beyond what the schema already provides; it reiterates defaults and formats. Given the high coverage, a baseline of 3 is appropriate, as the description adds minimal value 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 clearly states the tool reads one annual report and returns specific key figures, naming the exact financial items. It explicitly distinguishes from siblings by saying 'Use it for one year's headline numbers; use get_financials_history for a trend over several years and get_report_facts for any other line item.' This makes the purpose unambiguous and differentiates it.
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 description gives explicit guidance on when to use this tool versus alternatives: 'Use it for one year's headline numbers; use get_financials_history for a trend over several years and get_report_facts for any other line item.' It also explains the default scope for group reports and notes that omitted year retrieves the latest report, giving clear context for invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_financials_historyGet key financials over several yearsARead-onlyIdempotent
Return the same key figures as get_financials for each of a Danish company's latest annual reports, one row per reporting year, newest first. Use it for trends and growth; use get_financials when one year (with its previous-year comparison and auditor) is enough. Reads one filing per year, so it is slower than get_financials. A corrected report replaces the original; years without a machine-readable report are skipped.
| Name | Required | Description | Default |
|---|---|---|---|
| cvr | Yes | Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. "24256790". | |
| scope | No | For group reports (koncernregnskab): "group" = the consolidated group, "parent" = the parent company alone. Ignored for single companies. | group |
| years | No | How many reporting years to return, counting back from the latest. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| years | Yes | Newest first; empty when the company has no machine-readable annual reports. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, openWorld, idempotent, and non-destructive behavior ascending. The description adds valuable behavioral context beyond these: it reads one filing per year, is slower than get_financials, corrected reports replace originals, and years without machine-readable reports are skipped. No contradiction with annotations.
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?
Three sentences with no filler. The primary purpose and output shape are front-loaded, followed by usage guidance and behavioral caveats. Every sentence adds distinct value.
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 description fully covers purpose, output ordering, usage boundaries, performance, data-correctness behavior, and skipped years. The input schema documents all parameters, annotations cover safety and idempotency, and an output schema exists, so an agent has enough to invoke the tool 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%, with each parameter (cvr, scope, years) already thoroughly documented including format, defaults, constraints, and semantics. The description adds output-shape context but not additional parameter meaning, 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific verb 'Return', the resource ('a Danish company's latest annual reports'), and the output shape ('one row per reporting year, newest first'). It also explicitly distinguishes itself from get_financials by naming the sibling and the difference in scope.
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 explicit usage guidance: use this tool for trends and growth, and use get_financials when a single year with previous-year comparison and auditor is sufficient. Also gives practical caveats about speed and skipped years, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_report_factsGet all tagged figures from an annual reportARead-onlyIdempotent
Return every figure and text the company tagged in one annual report (XBRL), not only the key figures: e.g. staff costs, depreciation, receivables, dividends, the auditor's opinion. Use it when get_financials doesn't have the line item you need; filter with match to keep the answer short. Concepts are the taxonomy's own English names (fsa = Danish GAAP, ifrs = IFRS, gsd/cmn = general details). Breakdowns by dimension are left out; long texts are cut at 500 characters.
| Name | Required | Description | Default |
|---|---|---|---|
| cvr | Yes | Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. "24256790". | |
| year | No | Calendar year the reporting period ends in (a 2024/25 financial year ending June 2025 is 2025). Omit for the latest annual report. | |
| limit | No | Maximum number of facts to return; total says how many matched. | |
| match | No | Only concepts whose name contains this text, case-insensitive, e.g. "Employee" or "Dividend". | |
| scope | No | For group reports (koncernregnskab): "group" = the consolidated group, "parent" = the parent company alone. Ignored for single companies. | group |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | |
| facts | No | |
| found | Yes | |
| scope | No | Whose figures these are; "company" for a report without a group. |
| total | No | Facts matching the filter, before limit. |
| period | No | Reporting period, ISO dates. |
| source | No | The filing document the figures were read from. |
| message | No | Why nothing was found (only when found=false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark the tool as read-only and idempotent, the description adds meaningful behavioral details: concepts use taxonomy-specific English names (fsa, ifrs, gsd/cmn), breakdowns by dimension are omitted, and long texts are truncated at 500 characters. These disclosures go well beyond the structured annotations and help set expectations for output.
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 three focused sentences with no filler. The main purpose is front-loaded, followed by when-to-use guidance, then important behavioral caveats. Every sentence contributes distinct information.
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 full schema coverage, read-only annotations, and a declared output schema in context, the description covers all material usage aspects: what is returned, how it differs from get_financials, how to limit output via match, and the XBRL taxonomy behavior. No critical guidance is missing.
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?
The input schema has 100% parameter coverage, so a baseline of 3 is appropriate. The description adds extra semantic value for `match` and returned concepts by explaining that concept names come from the taxonomy (fsa = Danish GAAP, ifrs = IFRS, gsd/cmn = general details). This helps the agent craft match filters and interpret results, though it does not fully reshape parameter understanding.
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 says exactly what the tool does with a specific verb and resource: 'Return every figure and text the company tagged in one annual report (XBRL), not only the key figures.' It also distinguishes itself from get_financials by emphasizing that it returns all tagged facts, not just key figures, and gives concrete examples like staff costs and auditor's opinion.
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 description explicitly tells the agent when to use this tool: 'Use it when get_financials doesn't have the line item you need.' It also provides a practical usage tip ('filter with match to keep the answer short'), which directly helps the agent decide how to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filingsList published filingsARead-onlyIdempotent
List what a Danish company has filed with the Danish Business Authority (Erhvervsstyrelsen): annual reports, interim reports and their documents (PDF, XBRL), newest first. Use it to see which years are available or to get document links; use get_financials for the figures themselves. Returns an empty list for a CVR number with no filings (e.g. sole proprietorships). No paging: raise limit or set year to reach older filings.
| Name | Required | Description | Default |
|---|---|---|---|
| cvr | Yes | Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. "24256790". | |
| year | No | Only filings whose reporting period ends in this calendar year. Omit for all years. | |
| limit | No | How many filings to return, newest first. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cvr | Yes | |
| filings | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior. The description adds valuable behavioral context beyond that: results are newest first, an empty list is returned for CVR numbers with no filings, and there is no paging, so callers should raise the limit or set a year to reach older filings.
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 appropriately sized and front-loaded: it states the primary purpose first, then adds usage guidance, an edge case, and a pagination note. Every sentence contributes useful information without redundancy.
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 description covers what the tool returns, the main use cases, how it differs from a key sibling, empty-result behavior, and pagination limitations. Since an output schema exists, return value details are already covered structurally, so nothing essential is missing for correct invocation.
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%, and every parameter already has a meaningful description in the schema. The tool description does not add much beyond what the schema states, 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.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and a specific resource (filings with the Danish Business Authority), and enumerates the content (annual reports, interim reports, PDF, XBRL). It also distinguishes itself from the sibling get_financials by clarifying it returns filings and document links, not financial figures.
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 explicitly states when to use this tool: to see which years are available or get document links. It also names the alternative get_financials for figures, giving a clear when-not-to-use signal. Additional behavior around empty results and pagination further guides usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_companySearch Danish companies by nameARead-onlyIdempotent
Find a Danish company's CVR number by name (or check a CVR number) in the CVR register. Use it first when you only have a name; every other tool needs the CVR number. Matches all words of the query against current company names; returns name, status, company type, industry, address and employee size band, with active, exactly named and larger companies first. Needs CVR_USER and CVR_PASSWORD in the server's environment (free system-to-system access to the CVR register); without them it returns an error saying how to get access.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of companies to return. | |
| query | Yes | Company name or part of it, e.g. "Carlsberg" or "lego a/s". An 8-digit CVR number looks up that company. |
Output Schema
| Name | Required | Description |
|---|---|---|
| companies | Yes | Active companies first, then exact name matches, then the largest; empty when nothing matches. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), but the description adds behavior they cannot: all-words matching against *current* names, the result ordering (active, exact-name, larger first), the credential requirement (CVR_USER/CVR_PASSWORD) and the specific error surfaced when they are absent. That is rich operational context beyond the structured fields.
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?
Four tight sentences, each doing distinct work: purpose, routing priority, match/sort semantics, and auth requirement. Scope and the "use first" directive are front-loaded before the operational details.
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?
An output schema exists, yet the description still previews the returned fields, and it covers the auth prerequisite and failure mode that would otherwise block a successful call. Nothing an agent needs to invoke this correctly is missing.
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 both parameters are already documented and baseline is 3. The description adds meaning the schema does not: the match is against all words of the query and only current company names, which tells the agent how to phrase a query and why a miss may occur.
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 (find a company's CVR number by name) plus a secondary mode (check a CVR number) in a named register. It explicitly frames itself as the entry point that the sibling tools (get_financials, list_filings) depend on, so the agent can distinguish it from them without opening a schema.
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?
"Use it first when you only have a name; every other tool needs the CVR number" names the condition that selects this tool and implicitly excludes all siblings until a CVR number exists. Nothing about ordering or prerequisites is left to inference.
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 tool update
v0.3.2- Changed
search_company3 fields changed- changed
Output schema / properties / companies / descriptionPrevious value: -"Best matches first; empty when nothing matches."New value: +"Active companies first, then exact name matches, then the largest; empty when nothing matches." - added
Output schema / properties / companies / items / properties / employeesAdded value: +{ + "description": "Size band from the register's latest monthly employment figures, e.g. \"200-499\" or \"1000+\".", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / companies / items / requiredPrevious value: -[ - "cvr", - "name", - "status", - "companyType", - "industry", - "address" -]New value: +[ + "cvr", + "name", + "status", + "companyType", + "industry", + "address", + "employees" +]
5 tool updates
v0.3.1- Changed
get_financials4 fields changed- changed
Input schema / properties / cvr / descriptionPrevious value: -"Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted)."New value: +"Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. \"24256790\"." - changed
Input schema / properties / scope / descriptionPrevious value: -"For group reports (koncernregnskab): the consolidated group, or the parent company alone. Ignored for single companies."New value: +"For group reports (koncernregnskab): \"group\" = the consolidated group, \"parent\" = the parent company alone. Ignored for single companies." - changed
Input schema / properties / year / descriptionPrevious value: -"Calendar year the reporting period ends in. Omit for the latest annual report."New value: +"Calendar year the reporting period ends in (a 2024/25 financial year ending June 2025 is 2025). Omit for the latest annual report." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "auditor": { + "additionalProperties": false, + "properties": { + "assistance": { + "type": [ + "string", + "null" + ] + }, + "firm": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "firm", + "assistance" + ], + "type": "object" + }, + "currency": { + "type": [ + "string", + "null" + ] + }, + "cvr": { + "type": [ + "string", + "null" + ] + }, + "figures": { + "description": "Key figures; current = this report's year, previous = the year before.", + "items": { + "additionalProperties": false, + "properties": { + "current": { + "type": [ + "number", + "null" + ] + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "previous": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "key", + "label", + "current", + "previous" + ], + "type": "object" + }, + "type": "array" + }, + "found": { + "type": "boolean" + }, + "groupReport": { + "type": "boolean" + }, + "message": { + "description": "Why nothing was found (only when found=false).", + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "notes": { + "description": "Gaps, conflicts and caveats found in the filing, in plain English.", + "items": { + "type": "string" + }, + "type": "array" + }, + "period": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Reporting period, ISO dates." + }, + "previousPeriod": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "end": { + "type": [ + "string", + "null" + ] + }, + "start": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "start", + "end" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "reportType": { + "type": [ + "string", + "null" + ] + }, + "scope": { + "description": "Whose figures these are; \"company\" for a report without a group.", + "enum": [ + "group", + "parent", + "company" + ], + "type": "string" + }, + "source": { + "additionalProperties": false, + "description": "The filing document the figures were read from.", + "properties": { + "documentType": { + "type": "string" + }, + "publishedAt": { + "type": [ + "string", + "null" + ] + }, + "url": { + "type": "string" + } + }, + "required": [ + "publishedAt", + "documentType", + "url" + ], + "type": "object" + }, + "taxonomy": { + "enum": [ + "danish-gaap", + "ifrs", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "found" + ], + "type": "object" +}
- Added
get_financials_history - Added
get_report_facts - Changed
list_filings4 fields changed- changed
Input schema / properties / cvr / descriptionPrevious value: -"Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted)."New value: +"Danish CVR number, 8 digits (spaces, dashes and a DK prefix are accepted), e.g. \"24256790\"." - changed
Input schema / properties / limit / descriptionPrevious value: -"How many filings to return."New value: +"How many filings to return, newest first." - added
Input schema / properties / yearAdded value: +{ + "description": "Only filings whose reporting period ends in this calendar year. Omit for all years.", + "maximum": 2100, + "minimum": 2012, + "type": "integer" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cvr": { + "type": "string" + }, + "filings": { + "items": { + "additionalProperties": false, + "properties": { + "correction": { + "description": "True when this filing corrects (omgørelse) an earlier one.", + "type": "boolean" + }, + "cvr": { + "type": "string" + }, + "documents": { + "items": { + "additionalProperties": false, + "properties": { + "mimeType": { + "type": "string" + }, + "type": { + "description": "e.g. AARSRAPPORT, AARSRAPPORT_ESEF, HALVAARSRAPPORT.", + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "type", + "mimeType", + "url" + ], + "type": "object" + }, + "type": "array" + }, + "periodEnd": { + "type": [ + "string", + "null" + ] + }, + "periodStart": { + "type": [ + "string", + "null" + ] + }, + "publishedAt": { + "type": [ + "string", + "null" + ] + }, + "type": { + "description": "Filing type; \"regnskab\" for financial reports.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "cvr", + "type", + "periodStart", + "periodEnd", + "publishedAt", + "correction", + "documents" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "cvr", + "filings" + ], + "type": "object" +}
- Added
search_company
1 tool update
v0.2.0- Changed
get_financials1 field changed- added
Input schema / properties / scopeAdded value: +{ + "default": "group", + "description": "For group reports (koncernregnskab): the consolidated group, or the parent company alone. Ignored for single companies.", + "enum": [ + "group", + "parent" + ], + "type": "string" +}
2 tool updates
v0.1.0- First observed
get_financials - First observed
list_filings
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose, and the descriptions explicitly cross-reference each other (get_financials for one year, get_financials_history for trends, get_report_facts for other line items, list_filings for availability, search_company for CVR resolution). An agent can unambiguously pick the right tool from the overlap-prone financial tools.
All names follow a consistent verb_noun snake_case pattern: get_financials, get_financials_history, get_report_facts, search_company, list_filings. No mixed conventions or vague verbs.
Five tools is well-scoped for the domain, with each one earning its place: identity lookup, filing discovery, headline figures, multi-year history, and full fact extraction. No redundancy or filler tools.
The surface covers the main lifecycle: finding a company, listing filings, and extracting current, historical, and detailed financial figures. Minor gaps exist (e.g. fetching actual document/PDF content or interim report figures beyond listing links), but agents can work around these.
Maintenance
Related MCP Connectors
Danish company data (CVR) and annual-report financials for B2B lead research. Read-only.
SEC XBRL financials, company lookup, Treasury yields, ECB FX, token prices, perp funding spreads.
291Company lookups and annual-account financials: Sweden, Norway, Finland, UK. Pay per call (x402).
Clean annual and quarterly company financials from official SEC EDGAR XBRL data.
51
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceProvides 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.-
- AlicenseAqualityDmaintenanceEnables 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.252MIT
- FlicenseNot gradedqualityDmaintenanceEnables querying and analyzing XBRL financial data through natural language, using an API key for authentication.8 npm1-
- AlicenseAqualityDmaintenanceEnables AI assistants to search and look up Danish and Norwegian company registry (CVR) data, including company details, bankruptcy status, and more.26 npmMIT