dk-regnskab-mcp
This MCP server lets Claude (or any MCP client) read Danish companies' published annual reports and financial data directly from the Danish Business Authority, no API key required.
Search Danish companies by name or CVR number (requires free CVR credentials) to get CVR, status, type, industry, address.
List a company's filings with document links, filtered by year, newest first.
Get key financials for a chosen year or latest report — revenue, profit, equity, assets, cash, employees — with previous-year comparison, currency, auditor, scope (group vs parent), and explanatory notes for gaps.
Get multi-year financial history for trend analysis, up to 15 years.
Get every tagged fact from an annual report (staff costs, dividends, depreciation, etc.), with optional concept filtering.
All tools are read-only, structured, and handle real-world XBRL quirks like group/parent scope, corrected filings, and missing figures.
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 and address. 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 buildRoadmap
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 and address. 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 | Best matches first; empty when nothing matches. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, so safety is covered. The description adds valuable behavioral context: it matches all words of the query against current company names, returns specific fields (name, status, type, industry, address), and discloses the CVR_USER/CVR_PASSWORD requirement with the error message on failure. This goes beyond annotations and is highly informative.
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, each earning its place: purpose and use case, matching behavior and return fields, and authentication requirement. The most critical info (use first, needs CVR number) is front-loaded. No wasted words.
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 an output schema and annotations covering safety, the description is complete. It covers when to use, what it does, what it returns, authentication prerequisites, and error behavior. Nothing essential is missing for an agent 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 the baseline is 3. The description adds meaning by explaining that the query can be a company name or an 8-digit CVR number, and that it matches all words. It also clarifies the return fields. This adds value beyond the schema, though it doesn't dive into edge cases or matching nuances, so 4 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 clearly states the tool's function: finding a Danish company's CVR number by name, and also checking a CVR number. It explicitly distinguishes itself from siblings by noting that 'every other tool needs the CVR number', positioning this as the entry point. This is a specific verb+resource with clear differentiation.
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 ('Use it first when you only have a name') and explains that all other tools require the CVR number, making the selection logic unambiguous. It also mentions the authentication prerequisite and the error behavior, which helps the agent anticipate failure modes.
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.
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 role: search_company finds the CVR number, list_filings shows available filings, get_financials gives one year's key figures, get_financials_history gives trends, and get_report_facts covers any other line item. The descriptions cross-reference each other explicitly, so an agent can easily select the right tool.
All tool names follow a consistent verb_noun pattern: get_, search_, list_. Even though the verbs vary, the structure is uniform and the nouns clearly reflect the resource being acted on (financials, company, filings, facts). No mixed casing or inconsistent conventions.
Five tools is an ideal size for a read-only financial data server. Each tool covers a distinct, necessary operation without redundancy or bloat, and the set feels purpose-built rather than padded.
The tool surface covers the full research workflow: identify the company, list available filings, retrieve summary figures, view historical trends, and extract arbitrary detailed facts. There are no obvious dead ends—even document links are provided via list_filings, and get_report_facts can access any XBRL-tagged line item.
Maintenance
Related MCP Connectors
Agent-native SEC filing data: statements assembled, filings read and synthesized. No API key.
Query financial statements, KPIs, ratios, cash forecasts and budgets from your general ledger
Normalized SEC EDGAR fundamentals. 3 of 6 tools free; the rest $0.04-$0.10 per call in USDC.
Citable US facts w/ curated query templates: SEC financials, bank call reports, nonprofits. No key.
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.9 npm1-
- AlicenseAqualityDmaintenanceEnables AI assistants to search and look up Danish and Norwegian company registry (CVR) data, including company details, bankruptcy status, and more.29 npmMIT