northbridge-diligence
The northbridge-diligence server provides automated SEC EDGAR-based first-pass financial screening and due diligence for public companies. Key capabilities:
Resolve company (
resolve_company): Convert ticker or name to SEC CIK, handling ambiguous names by returning candidates.Company profile (
get_company_profile): Legal name, industry, fiscal year-end, state of incorporation, and links to latest filings.Multi-year financials (
get_key_financials): Curated income statement, balance sheet, and cash flow from XBRL with every value traced to its source filing.Screening metrics (
compute_screening_metrics): Code-calculated ratios (growth, margins, leverage, liquidity) and red flags, with meaningfulness indicators to prevent misinterpretation.List filings (
list_filings): Recent SEC filings with direct EDGAR URLs, filterable by form type.Risk factors (
get_risk_factors): Extract Item 1A from the latest 10-K, with conservative extraction and a fallback URL for manual review.Disclosure signals (
scan_disclosure_signals): Search for qualitative risk language (going-concern, material weaknesses, customer concentration, goodwill impairment) and classify as absent, boilerplate, or genuine.Fetch concept (
get_financial_concept): Escape hatch to retrieve annual time series for any single XBRL tag or friendly metric.
All computations are performed in code rather than by the model, ensuring trustworthiness. The server handles XBRL complexities, self-throttles for SEC API limits, uses exponential-backoff retries, and includes local caching for performance.
Click on "Install 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., "@northbridge-diligenceScreen Apple Inc. for key financial ratios"
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.
Northbridge Diligence — SEC EDGAR MCP + Screening Skill
Chidrupa Mamunooru · Delivery Engineer take-home
A two-layer tool for Northbridge Capital Partners' deal team:
Data layer (MCP server) — wraps the SEC EDGAR APIs into a focused set of tools a model can call to answer diligence questions, with every number traced to its source filing.
Intelligence layer (skill) — sits on top and turns a company name into a first-pass screening memo an analyst would hand to a deal lead.
The goal is the one the client stated: "get this data via Claude so our analysts save time, and the deal team can trust those numbers."
Trust is enforced structurally, not by asking the model nicely. Three things are load-bearing:
Every figure carries its filing — accession number, form type, period end, XBRL tag, and a resolvable EDGAR URL.
The code computes; the model narrates. Ratios, the judgment of whether a ratio is meaningful, and the risk flags are all produced in Python against fixed thresholds. The skill is forbidden from doing arithmetic or inventing a flag.
The behaviour is pinned by tests — 146 offline tests plus a golden-set regression, so a tag-mapping tweak that would silently change a margin fails the build instead.
Architecture
company name ──► [ company-screen skill ] (intelligence layer)
│ selects tools, narrates the result, writes the memo
│ does NOT compute ratios or decide risk
▼
[ northbridge-diligence MCP server ] (data layer, src/northbridge_diligence/server.py)
│ thin MCP shim: decorators + uniform error envelope
▼
[ edgar_client.py ] (all logic: HTTP, XBRL, math, flags)
│
▼
SEC EDGAR REST APIsedgar_client.py holds all logic so it is unit-testable and reusable off-server; server.py is a thin registration layer. The sample memos were assembled following the skill's template from the tool functions' outputs — the same functions the MCP server exposes to a Claude client, without the intermediate protocol round-trip.
One fetch, not eighteen
Financial data comes from data.sec.gov/api/xbrl/companyfacts/CIK##########.json — one request returns every XBRL fact the filer has ever reported. An earlier design called companyconcept once per curated line item — 17 of those, plus the ticker-map lookup — so 18 requests per screen, 18 chances to hit a rate limit, and 18 partial-failure modes.
A full screen is now two HTTP calls: the ticker→CIK map (cached) and one companyfacts blob (cached). A test asserts this and asserts no companyconcept URL is ever requested, so the property can't regress.
The same blob also hands us every prior-year comparative for free — a FY2025 10-K carries FY2023 and FY2024 columns — so a five-year history needs no extra requests.
Related MCP server: OpenCapital MCP Server
Setup
Prerequisites: Python 3.10 or newer, and Claude Code or Claude Desktop. Nothing else — SEC EDGAR is public, so there is no account, API key or cost.
1. Get the code and install it
git clone https://github.com/chidrupa99/northbridge-diligence.git
cd northbridge-diligence
python3 scripts/doctor.py # runs on ANY Python; checks yours is >= 3.10 first
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install --upgrade pip # editable installs need pip >= 21.3
pip install -e .
export EDGAR_USER_AGENT="Your Org you@example.com" # Windows: set EDGAR_USER_AGENT=...
python scripts/doctor.py # 11 checks; each failure prints its own fixexport sets an environment variable — a value the terminal remembers and passes to programs it launches. SEC returns HTTP 403 to unidentified clients, so this is required. It is a contact string, not a credential.
2. Install the plugin
/plugin marketplace add /absolute/path/to/northbridge-diligence
/plugin install northbridge-diligenceRestart, and that is the install. The plugin ships the MCP server config and the skill together, so the two cannot end up on different Claude surfaces — which is the most common way this tool gets installed wrong.
Confirm with python scripts/doctor.py: check 11 reports wired: Plugin (bundled).
On Windows, edit one line in plugin/.mcp.json before installing: change the command to ${CLAUDE_PLUGIN_ROOT}/../.venv/Scripts/edgar-mcp.exe. A single bundled config cannot cover both platforms — the interpreter path differs and there is no conditional syntax.
3. Use it
Say: "Screen Beyond Meat for the deal team". See Triggering the skill for what else fires it and how to tell it worked.
Not using Claude Code? Plugins are a Claude Code feature, so two surfaces need a different route.
Claude Desktop chat (Cowork) — register the server by hand in claude_desktop_config.json, and enable the skill for your claude.ai account via Customize in the sidebar. Cowork sessions do not read ~/.claude/skills/. Quit the app before editing its config — it flushes its own preferences over your write while running.
claude.ai web and mobile — not possible. edgar-mcp speaks MCP over stdio, so the client launches it as a local child process, and a process in Anthropic's cloud cannot spawn a binary on your laptop. An account-synced skill will still trigger there but its tools are unreachable, which looks installed and produces nothing.
Full walkthrough for both — per-platform config paths, the merge case when other MCP servers are already registered, the surface matrix, and hand-installing the skill for Claude Code — is in DEPLOYMENT.md.
Installing for a team? → DEPLOYMENT.md — security posture, egress requirements, troubleshooting
Extending or maintaining it? → DEVELOPING.md — test harness, fixtures, tuning knobs, invariants
Triggering the skill
There is no command to remember. Say it in plain language:
"Screen Beyond Meat for the deal team"
Any ticker or company name works — BYND, Target, TGT, "size up Dollar General", "run a first pass on Casey's".
The skill triggers on the request, not on a keyword. Its frontmatter description is what Claude matches against, so all of these fire it:
What an analyst actually types | Fires? |
"Screen Beyond Meat for the deal team" | ✓ |
"Can you size up Tractor Supply as a comp?" | ✓ |
"Run a first pass on Casey's General Stores" | ✓ |
"Pull the financials on TGT" | ✓ |
"What do we think of Ollie's Bargain Outlet?" | ✓ |
"What's Apple's stock price today?" | ✗ — not in EDGAR; this reads filings, not market data |
How to tell it worked
A correct result has two tells:
[S1]-style source markers throughout — on every figure in the memoA Sources table at the bottom, mapping each marker to a filing accession number and URL
Figures without source markers mean the skill is not being used. Claude answered from its own knowledge instead of calling the tools, and those numbers are not traceable to a filing. Two causes, in order of likelihood:
Surface mismatch — the MCP server and the skill landed on different clients. Installing the plugin makes this impossible; if you registered by hand instead, check the surface matrix in the Not using Claude Code? section and complete both cells of one row.
python scripts/doctor.pycheck 11 reports which surfaces are wired.Skill not copied, or client not restarted — check
~/.claude/skills/company-screenexists and restart the client.
That second tell is the whole reason attribution is structural rather than prompted: a memo either carries citations on every number or it visibly does not, and a reader can tell in one glance which one they are holding.
If the company name is ambiguous — "Delta", "American" — the skill returns candidates and asks which you mean rather than guessing. That is deliberate: screening the wrong "Bank of X" is a silent and expensive error.
See samples/BYND_screening_memo.md for what a finished result looks like.
The tools — what each does and why
Scoping the toolset was the main judgment call. The principle: one tool = one diligence question an analyst actually asks, each returning source-attributed data, nothing that overlaps.
Tool | What it does | Why it exists |
| ticker/name → CIK; flags ambiguous names | Everything keys off CIK. Ambiguity is surfaced (not guessed) because screening the wrong "Bank of X" is a silent, costly error. Every tool raises the same disambiguation payload, so the model never has to learn two shapes. |
| identity, SIC industry, fiscal year-end, latest 10-K/10-Q | Orients a screen (who/what/where) and anchors the fiscal calendar before pulling numbers. |
| curated multi-year IS/BS/CF, each value source-tagged | The financial-trajectory + capital-structure backbone. Returns |
| growth, margins, leverage, liquidity — computed in code — plus | The client must trust the numbers. LLM arithmetic isn't trustworthy, so ratios are calculated in Python, returned with the sourced inputs, and each marked `meaningful: true |
| recent filings + direct EDGAR URLs | Source citation, latest annual/quarterly report, and recent 8-K events worth a second look. |
| full-text sweep for going-concern doubt, material weaknesses, customer concentration and goodwill impairment — with a computed boilerplate-vs-signal verdict | The numbers cannot show what a company is worried about. Two things make this more than a search box: the phrasing is calibrated against real filings, and the judgment of whether a hit means anything is computed rather than narrated — language present in every annual report is template text, language that comes and goes is news. Deliberately kept out of |
| Item 1A from the latest 10-K | The "risk section worth a second look," and the verification step for anything |
| any one metric/US-GAAP tag as a time series | Escape hatch for questions the curated set doesn't cover (R&D, capex). Keeps the curated tools focused while staying flexible. Tag names are validated against a strict pattern before they reach a URL. |
The second scoping decision: ~500 concepts down to 17
Scoping happened twice — once at the tool surface above, and once at the data layer. The second is less visible and arguably more consequential.
Filers do not report a common set of concepts. Measured across seven filers in different industries: Beyond Meat reports 376 US-GAAP concepts, Apple 503, JPMorgan 917. Between them they use 2,220 distinct concepts, of which only 49 are common to all seven — a shared core of roughly 2%, and mostly plumbing (share counts, tax line items). Almost nothing you would build a screen on.
So CONCEPT_MAP curates that down to 17 concepts a first-pass PE screen actually turns on, each mapped to an ordered list of candidate US-GAAP tags:
Statement | Concepts |
Income |
|
Balance sheet |
|
Cash flow |
|
17 concepts, 33 candidate tags — 11 of the 17 need more than one spelling, because filers disagree:
"revenue": [
"RevenueFromContractWithCustomerExcludingAssessedTax", # post-ASC 606: Apple, Target, Tesla
"Revenues", # JPMorgan, Pfizer, Realty Income
"RevenueFromContractWithCustomerIncludingAssessedTax",
"SalesRevenueNet", # legacy, pre-2018
],The order encodes preference, not just alternatives: the modern tag wins where both exist, and the legacy tag fills the years before the transition.
No single revenue tag covers all seven filers above. The two leading tags cover six each — but not the same six. The contract-revenue tag misses JPMorgan; Revenues misses Beyond Meat. That is why this is a list rather than a string, and why the merge happens per fiscal year rather than per tag.
Curation is not a ceiling. Anything outside the 17 stays reachable through get_financial_concept, by friendly name or raw tag — so the curated set keeps the common path focused without making the uncommon question impossible.
Attribution model
Every financial datapoint is a SourcedValue carrying period_end, fiscal_year, form, accession, xbrl_tag, filed, a resolvable source_url, and — when the figure was later revised — restated plus originally_reported. The skill renders these as [S#] markers mapping to a Sources table. If a number has no source, it does not go in the memo.
The design decision the whole thing turns on: code computes, the model narrates
The first version of this tool put the interesting judgment in the skill prompt: "flag negative equity rather than quoting the exploded ratio," "call out current ratio below 1." It produced good memos. It was also unfalsifiable — two runs could disagree, and nobody could point at the line that decided.
So the judgment moved into Python:
Ratio meaningfulness. _guarded_ratio returns (value, meaningful, caveat). A negative denominator, a zero denominator, or a denominator near zero relative to the numerator all yield meaningful: false with an explanation. Beyond Meat's debt/equity is arithmetically −417.0; the tool returns that number marked unmeaningful with "denominator is negative — the ratio is not interpretable; report the negative balance itself instead." The skill is instructed never to quote an unmeaningful figure.
Risk flags. _detect_flags returns a structured list — code, severity, message, evidence (SourcedValues) — against the thresholds in one THRESHOLDS dict that is returned with the response, so the reader always sees the bar that fired:
NEGATIVE_EQUITY · EARNINGS_QUALITY · LIQUIDITY · LEVERAGE · COVERAGE · NEGATIVE_EBITDA · REVENUE_DECLINE · CASH_BURN · STALE_DATA · MISSING_DATA · TAG_DISCONTINUED · MIXED_TAG_BASIS · RESTATED
The payoff is that an analyst can re-run compute_screening_metrics("BYND") and get byte-identical flags. That is not a property a prompt can have. The skill's remaining job — deciding what leads the memo, what a deal lead actually needs to know — is exactly the part that should be a language model's.
XBRL is messier than it looks — what the client handles
These are the cases that separate a working screen from a demo. Each is covered by a test named after the failure it prevents.
Filers switch tags mid-history. Given the tag ladders above, the naive implementation is first-tag-wins: try the modern tag, and if it returns anything, stop. That silently truncates history at the ASC 606 transition — Ford came back with 10 years instead of 19, Target 10 instead of 18. Fixed by merging candidates per fiscal year rather than per tag. Where a series spans more than one tag, mixed_tag_basis says so and an info flag fires.
Fiscal years aren't calendar years. Target's fiscal 2009 ended 2010-01-30. Taking end[:4] labels it 2010 and puts two "2009"s in the series. The fix reads the filer's own fy label out of the facts — within one accession, the fact with the latest period end is that report's own year — and carries the offset over to comparatives the index didn't cover directly. A test pins 2010-01-30 → FY2009.
Filers abandon tags. Target stopped tagging GrossProfit after FY2017. A positional slice (series[-5:]) happily returned FY2013–2017 gross profit and set it beside FY2021–2025 revenue — which would have produced a gross margin dividing an eight-year-old numerator by a current denominator. Every series is now windowed by fiscal year against a reference_fiscal_year derived from anchor items, and each point-in-time metric reads its exact year or nothing. An abandoned tag becomes a visible gap plus a TAG_DISCONTINUED flag, never a stale number.
Filers restate. When the same period appears in multiple filings, RESTATEMENT_POLICY (default as_last_reported) picks one, and the value carries restated: true with originally_reported so the change is auditable rather than invisible.
Currency. Units are chosen preferring USD and never mixed; if line items span currencies, every metric is marked unmeaningful rather than quietly dividing dollars by euros.
Other error & edge-case handling
Missing SEC header → 403: detected and turned into an actionable message.
Bad ticker / private company: clear "no SEC filer matched" (EDGAR only covers registered filers).
Ambiguous names: returns candidates instead of guessing, from every tool.
Rate limits & transient failures: self-throttled to ~8 req/s (under SEC's 10/s), with exponential-backoff retries on 429/5xx that honour
Retry-After. 403/404 are not retried — they won't get better.Caching: a bounded, TTL'd, thread-safe cache (64 entries, 1h) so a deal sprint's repeat screens are instant and gentle on EDGAR.
STATSexposes requests/cache hits/retries.Messy 10-K HTML: risk-factor extraction is conservative; failure returns the source URL for manual review.
Uniform error envelope at the server layer (
{"error": ..., "recoverable": ...}) so one bad call never crashes the model's turn.
Tests
146 offline tests plus a golden-set regression, in about a second. Three things about them are deliberate:
Recorded fixtures, not hand-written mocks. Real EDGAR responses for two filers chosen for what they break. Beyond Meat gives negative equity, negative EBITDA and positive net income on a loss-making operating business; Target gives a January fiscal year end, a mid-history tag switch, and an abandoned GrossProfit. Hand-written mocks never invent a January-FYE retailer that stops tagging gross profit — real filings do, which is the point.
Named after failure modes, not functions — test_january_year_end_uses_the_filers_own_label_not_the_calendar_year, test_abandoned_tag_becomes_a_gap_not_a_stale_number, test_a_full_screen_costs_two_http_calls. EDGAR rarely crashes you; it hands you a plausible wrong number, so each test pins one specific way that happens.
The golden set is the behavioural contract. It snapshots entire screen outputs and, on failure, names the field — flags lost: ['LIQUIDITY'] — rather than dumping a 200-line dict. I verified the harness actually bites by moving the current-ratio threshold from 1.0 to 0.5 and confirming it reported exactly that.
One limit worth stating: the suite is offline, so it verifies logic, not installation — it passes with EDGAR unreachable and no contact header set. scripts/doctor.py covers that gap. Running and extending the suite is documented in DEVELOPING.md.
Design decisions & seams
What I deliberately left out (scope discipline — each is a defensible next addition, not an oversight):
Public comps / peer benchmarking. High value, but it needs a peer-selection method (SIC is too crude) and multiplies API load. It's the first thing I'd add (see below), built on
get_key_financials.Open-ended full-text search.
scan_disclosure_signalswraps EDGAR's FTS endpoint, but only behind curated phrases with a computed verdict. A general "search filings for X" tool was deliberately not exposed: an arbitrary phrase gives the model no way to tell boilerplate from news, which is the entire difficulty.extra_phrasesis the escape hatch, and it carries the caveat.Quarterly / TTM data. The screen is annual-first for signal clarity. The plumbing (
annual_series) generalizes to quarterly with a filter change.Insider / ownership (Forms 3/4/5) and institutional holdings. Useful for a deeper look, noise for a first pass.
Where the seams are (known limitations):
US-GAAP XBRL only. Foreign private issuers (20-F / IFRS) and non-XBRL filers won't populate
get_key_financials; the tool says so rather than returning partial nonsense."Total debt" is approximated as long-term + current debt tags; finance-lease and other debt-like items aren't fully assembled. Flagged where it matters.
EBITDA is a proxy — operating income plus D&A from the cash flow statement. It is not any filer's adjusted definition and shouldn't be compared to one.
Thresholds are one global set. A 4.0x debt/EBITDA bar means different things in software and in distribution. Industry-relative bands are a real improvement, but they need a defensible peer set first — which is the comps tool.
Risk-factor extraction is heuristic (heading match on messy HTML); it degrades to "here's the source, read it yourself" instead of fabricating. The heuristic has been through one real failure: anchoring on the last heading match returned 2,958 characters of the wrong section on Dollar General's 10-K — where Item 1C cross-references Item 1A — and reported it as a successful extraction. It now uses the widest start/end pairing to identify the real end marker, then takes the last heading before it, which excludes both contents rows and later cross-references. A filer with a stranger document structure could still defeat it.
Covenant compliance is not searchable. A covenant pack was built and then removed:
"covenant violation","waiver from our lenders"and"not in compliance with the covenants"each returned zero hits even against a genuinely distressed filer, while bare"covenant"returned 84 (Beyond Meat) and 274 (Target) of pure boilerplate. A pack that always reports "absent" is worse than no pack, because absence is written into the memo as a finding. Stated as a gap instead.Disclosure phrases trade precision for recall, on purpose. The first version used the full formal wording —
"material weakness in our internal control over financial reporting"— which matched 0 Target filings while"material weakness"matched 23. An over-specific phrase produces a falseabsent, and that is the most damaging error this tool can make. Precision is recovered downstream by the boilerplate classification and the requirement to read the filing.
Sample output
Two real screens, generated live from EDGAR, each as Markdown and a self-contained HTML one-pager. The brief asks for one; a second is included because a single company cannot show that the tool discriminates.
Beyond Meat — the distress case. Five flags fire. It demonstrates the thing that separates a real screen from a naive one: FY2025 net income is positive (+$219M) while the operating business lost −$334M. A naive tool reports "profitable." This one raises an EARNINGS_QUALITY flag naming the ~$553M of profit that came from outside the operating business, marks debt/equity unmeaningful because equity is negative, and tells the deal lead to identify the non-operating item first — because that item is not isolable from XBRL, and saying so is more useful than guessing at it.
Target — the healthy case. Every solvency flag stays silent, which is the harder thing to demonstrate. Revenue is flat over five years while operating income fell 43%, so the finding is a margin problem inside a sound balance sheet. The one flag that does fire — LIQUIDITY, current ratio 0.94 — is shown in the memo to be an artefact of applying one global threshold to a retailer, where payables structurally exceed receivables, rather than a finding. That is a seam this README already declares, caught working in public. Target also exercises the January fiscal year end, a mid-history tag switch across six series, and a gross margin derived because GrossProfit has been untagged since FY2017.
What I'd build next (another week)
Comps tool. Assemble a peer set (SIC + size band, human-overridable) and return side-by-side growth, margin and leverage with the same attribution. A margin falling 240bp means one thing alone and another against five peers — and it's what would make industry-relative thresholds defensible instead of one global set.
Linkbase-aware statements. Statement structure lives in each filing's
_pre.xmland_cal.xml, not incompanyfacts._cal.xmldeclares which lines sum to which subtotals, giving a free reconciliation check — JPMorgan's net interest income ($95.4bn) plus noninterest income ($87.0bn) ties exactly to $182.4bn of revenue._pre.xmlexplains gaps: JPMorgan's income statement has no operating income line at all, which turns a bareMISSING_DATAflag into a structural answer. It would surface candidates for a human, never auto-substitute — mapping pretax income onto operating income would break the report-gaps-never-estimate invariant, and for a bank the difference is the loan loss provision.A covenant signal that actually works. Exact-phrase search failed and was cut (see seams). The tractable version reads the debt footnote and Item 7 liquidity discussion directly instead of pattern-matching the filing — it targets the one capital-structure question this screen cannot answer.
Year-over-year risk-factor diff. A newly added risk factor is a far stronger signal than any standing one. The section extractor already spans Items 1A/3/7/9A, so the plumbing exists; the open problem is aligning risk factors across years in a way that survives rewording.
Widen the golden set. 15–20 filers covering a foreign issuer, a recent IPO, a restatement and a spin-off, run in CI. Trust needs tests, and the tests need coverage.
Available Tools
8 toolscompute_screening_metricsA
The screen result, computed IN CODE (not by the model): revenue CAGR & YoY
growth, gross/operating/net margins, total debt, debt/equity, debt/EBITDA,
current ratio, interest coverage, EBITDA and latest operating cash flow —
PLUS flags (code-detected red flags such as negative equity, weak
liquidity, high leverage, cash burn, stale data, and net income that is
positive while the operating business loses money) and data_quality.
Read this carefully before writing anything:
Every metric has a
meaningfulboolean and acaveat. If meaningful=false, DO NOT quote the number — state the caveat instead (e.g. a debt/equity of -417x really just means equity is negative).flagsis the authoritative list of concerns. Report every high- and medium-severity flag. Do not invent flags that are not in the list, and do not suppress ones that are.Do not recompute or round-trip any arithmetic yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| years | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description fully discloses behavior: the computation is done in code, the output structure (metrics with `meaningful` and `caveat`, `flags`, `data_quality`), and warnings against recomputation. No contradictions.
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 front-loaded with purpose and lists metrics and usage instructions. While detailed, it is relatively well-structured and each sentence adds value, but could be more concise.
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?
Given no output schema, the description thoroughly explains the output structure and usage. However, it fails to explain input parameters, which are essential for correct invocation, making it somewhat incomplete.
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 0% and the description does not explain the parameters `query` or `years`. The context implies `query` is the screen result and `years` is the time horizon, but this is not explicit, leaving the agent to guess.
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 computes screening metrics and flags from a screen result, listing specific metrics and flags. It distinguishes from sibling tools which focus on data retrieval rather than computation.
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 provides explicit instructions on how to use the output (e.g., respect `meaningful` boolean, report flags verbatim, do not recompute). However, it lacks explicit guidance on when to invoke this tool versus alternatives, though the context of requiring a screen result is implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_company_profileA
Identity card for a company: legal name, tickers, exchange, SIC industry, fiscal year-end, state of incorporation, and links to its latest 10-K/10-Q. Use this to orient a screen (who/what/where) before pulling numbers. Accepts a ticker or name.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It clearly states what the tool returns (legal name, tickers, links to 10-K/10-Q, etc.), but it does not explicitly confirm that it is a read-only operation or mention any potential errors or limitations. Nonetheless, the description is fairly transparent.
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 concise at three sentences: the first defines the tool, the second provides usage guidance, and the third specifies input. Every sentence earns its place 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?
Given no output schema, the description sufficiently lists the expected return fields (legal name, tickers, exchange, etc.) and the input type. For a simple profile retrieval tool, this is complete and aligned with the context signals.
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 no description for the single 'query' parameter, but the description clarifies that it accepts a 'ticker or name,' adding meaningful context 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 identifies the tool as an 'identity card' for a company, listing specific data points (legal name, tickers, exchange, etc.) and explicitly distinguishes it from sibling tools by stating it is for orientation before pulling numbers.
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 provides explicit guidance on when to use the tool ('to orient a screen before pulling numbers') and what input it accepts ('ticker or name'), effectively differentiating it from the financial data tools listed as siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_financial_conceptA
Flexible escape hatch: fetch the annual series for a single financial
concept — either a friendly name from the curated map (e.g. "revenue",
"operating_cash_flow", "capex") or a raw US-GAAP XBRL tag (e.g.
"ResearchAndDevelopmentExpense"). Use when the curated get_key_financials
set doesn't cover something the user asks about. Returns which tag matched.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| years | No | ||
| metric_or_tag | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries the burden. It mentions input types (friendly name or raw XBRL tag), that it returns the annual series, and which tag matched. It doesn't discuss side effects or auth, but for a read-only data fetch this is adequate. The 'escape hatch' framing sets expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff. Front-loaded with 'Flexible escape hatch' to set context. Every word adds 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?
Given 3 parameters, no output schema, and no annotations, the description is mostly sufficient but missing explanation of `query`. It connects to the sibling tool and explains the main parameter. Could improve by clarifying what `query` is (e.g., company ticker or CIK).
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 0%, so description must compensate. It explains `metric_or_tag` with examples (friendly names like 'revenue' and raw tags like 'ResearchAndDevelopmentExpense'). However, the `query` parameter (presumably a company identifier) is not explained, and `years` is only hinted at by 'annual series'. Partial coverage.
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 it fetches 'annual series for a single financial concept' and distinguishes itself from the curated `get_key_financials` by being a flexible escape hatch for concepts not covered there. The verb 'fetch' and resource 'financial concept' are specific.
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?
Explicitly says 'Use when the curated get_key_financials set doesn't cover something the user asks about.' This provides clear when-to-use guidance and names the sibling alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_key_financialsA
Curated multi-year financials (income statement, balance sheet, cash flow)
from annual 10-K XBRL data. Returns each line item as a time series where
every value carries its provenance: fiscal year, period end, form,
accession number, and a source URL. Use this for the financial-trajectory
and capital-structure parts of a screen. years = how many fiscal years
back (default 5).
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| years | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that data is sourced from annual 10-K XBRL, curated, and returns each line item as a time series with provenance (fiscal year, period end, form, accession number, URL). It does not mention authentication or rate limits, but it transparently covers data origin and output structure. No contradictions with annotations (none exist).
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 extremely concise: two sentences plus a brief note about years. It front-loads the core functionality and adds critical detail without redundancy. Every sentence adds value, making it efficient for an AI agent.
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 no output schema, the description adequately explains the return structure (time series with provenance fields). It covers the data source and use case. However, it could be more specific about the content of line items (e.g., which metrics are included) to fully prepare the agent. Overall, it is fairly complete for a financial data retrieval tool.
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 0%, so description must compensate. Only the 'years' parameter is explained ('how many fiscal years back (default 5)'). The 'query' parameter, which is required, gets no explanation whatsoever in either schema or description. This is a significant gap for the most important parameter.
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 returns curated multi-year financials (income statement, balance sheet, cash flow) from 10-K XBRL data, specifying the verb 'get' and resource 'key financials'. It distinguishes from siblings by targeting 'financial-trajectory and capital-structure parts of a screen', which sets it apart from tools like get_risk_factors or get_financial_concept.
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 says 'Use this for the financial-trajectory and capital-structure parts of a screen', giving clear context for when to use it. It also explains the years parameter's role. While it doesn't explicitly state when not to use it or list alternatives, the guidance is sufficient given the sibling tool list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_risk_factorsA
Extract the Item 1A "Risk Factors" section from the company's latest 10-K, plus the source URL. Use this for the risk-signal part of a screen. Extraction is conservative: if the section can't be confidently isolated from the filing's HTML, it returns a note and the source URL rather than a guess — flag that to the user so they open the filing directly.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses conservative extraction, failure mode (returns note and URL instead of guess), and source URL behavior. Could mention auth or rate limits but not critical for this tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states core purpose, second adds behavioral nuance. Efficient, 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 single-parameter tool with no output schema, description covers extraction logic and failure handling. Missing input clarification is a gap, but overall adequate given simplicity.
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?
Only parameter 'query' has 0% schema description coverage. Description does not explain what 'query' represents (e.g., company identifier). Agent must infer from context, risking misuse.
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?
Clearly states it extracts Item 1A 'Risk Factors' from the latest 10-K, specifies the use case 'for risk-signal part of a screen', and distinguishes from sibling tools like get_key_financials.
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 context on when to use ('for the risk-signal part of a screen') and explains the conservative extraction behavior, including how to handle failure (flag to user to open filing). Missing explicit when-not-to-use or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filingsA
Recent SEC filings for a company, each with a direct EDGAR document URL.
Optionally filter by form (e.g. ["10-K", "10-Q", "8-K"]). Use this to cite
sources, find the latest annual/quarterly report, or spot recent 8-K events
worth a second look. limit caps the count (default 15).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| form_types | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that returns include a direct EDGAR URL, supports optional form filtering, and a limit parameter with default 15. However, it does not mention ordering, date range, pagination, or behavior when no results are found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no wasted words. The first sentence states purpose and output, the second provides usage guidance and parameter hints. Front-loads the key 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?
For a simple tool with 3 parameters and no output schema, the description covers basic usage and output. However, it lacks details about the query parameter format, result ordering, and the meaning of 'recent', which limits completeness for an AI agent.
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 0% (no descriptions in schema). The description adds meaning for 'form_types' (example list) and 'limit' (default 15). However, the required 'query' parameter is not explained, leaving ambiguity about what it accepts (e.g., ticker, CIK).
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 lists recent SEC filings with direct EDGAR URLs, specifying verb 'list' and resource 'SEC filings'. It distinguishes from siblings like 'resolve_company' and 'get_company_profile', which serve different purposes.
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 provides explicit use cases: citing sources, finding reports, spotting 8-K events. It mentions optional filtering by form types. It does not explicitly state when not to use, but the sibling tools are all different, so confusion is unlikely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_companyA
Resolve a ticker OR company name to its SEC CIK.
Call this FIRST for any company. Accepts a ticker ("MSFT") or a name ("Microsoft"). Returns a single {"resolved": {...}} match, or when a name is ambiguous, {"ambiguous": true, "candidates": [...]} — in that case ask the user which company they mean instead of guessing. EDGAR only covers SEC-registered (public) filers.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Describes both success and ambiguous outcomes, and notes EDGAR covers only SEC-registered filers. Without annotations, it carries the burden well.
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 adds value: purpose, usage, edge case handling. No unnecessary 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?
Given no output schema, description covers both output shapes and domain restriction. Adequate for a simple one-param tool.
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?
With 0% schema coverage, description adds full meaning: query accepts ticker or name, with examples. Single parameter is well-explained.
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?
Clearly states the tool resolves a ticker or company name to SEC CIK, with examples. Distinguishes it from sibling tools which focus on financial data.
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?
Explicitly says 'Call this FIRST for any company' and advises asking user on ambiguous results. No explicit exclusion or alternative mention, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_disclosure_signalsA
Sweep a company's filings for the risk LANGUAGE that never appears in the numbers: going-concern doubt, material weaknesses, restatements, covenant breaches, customer concentration, goodwill impairment. Use this alongside compute_screening_metrics for the risk-signals part of a screen — the financial tools cannot see any of it.
Each signal comes back with a computed assessment, and that is the field to
read first:
"absent" — the phrase appears in no filing since 2001. This is a real negative finding; report it as one.
"likely_boilerplate" — present in EVERY annual report, so it is standing risk-factor or audit-report template text. Do NOT report it as a finding without reading the filing.
"changed_over_time" — present in some years and not others. The highest- signal case; read the years that differ.
"present_non_annual" — appears outside the 10-Ks, so likely a discrete event. Read the filing.
A hit means the words are in the document, NOT that the condition applies.
Verify anything present via get_risk_factors or the linked filing before
writing it up. These signals are deliberately separate from flags in
compute_screening_metrics, which stays reserved for red flags code can verify
arithmetically. extra_phrases appends your own exact phrases to the sweep.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| extra_phrases | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly explains the behavioral traits: it returns computed assessments (absent, likely_boilerplate, etc.) with definitions, warns that a hit is not a condition, and advises verification. Since no annotations are provided, the description fully covers the tool's behavior.
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 relatively long but well-structured with bullet points for assessment values. Every sentence adds value, though brevity could be improved slightly. It is appropriately front-loaded with the core action.
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?
Given no output schema, the description explains the four possible assessment outcomes and their meanings. It also positions the tool relative to siblings. The coverage is sufficient for a tool of this complexity, though explicit enumeration of output fields would improve completeness.
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 schema has 0% description coverage, but the description adds meaning by explaining extra_phrases ('appends your own exact phrases'). It does not explicitly describe the query parameter, but context from sibling tools implies it is a company identifier. This compensation raises the score above baseline.
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 scans a company's filings for specific risk language (e.g., going-concern doubt, material weaknesses). It distinguishes itself from the sibling tool compute_screening_metrics by noting that financial tools cannot see these qualitative signals.
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 advises using this tool alongside compute_screening_metrics for the risk-signals part of a screen, implying when it is appropriate. It does not explicitly list when not to use it, but the context is clear.
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. Dates show when Glama detected each change.
8 tool updates
v1.0.0- First observed
compute_screening_metrics - First observed
get_company_profile - First observed
get_financial_concept - First observed
get_key_financials - First observed
get_risk_factors - First observed
list_filings - First observed
resolve_company - First observed
scan_disclosure_signals
TDQS
Scored across 8 tools
Each tool has a clearly distinct and well-defined purpose: resolving company identifiers, retrieving profile info, financial data, computed metrics, filing lists, risk text, flexible concept access, and disclosure language scanning. No overlap or ambiguity.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., resolve_company, get_company_profile, compute_screening_metrics). The verbs are descriptive, and the pattern is uniform, making intention clear.
With 8 tools, the server is well-scoped for its purpose of SEC-based financial due diligence. Each tool addresses a necessary step without being excessive or minimal.
The tool set covers the full workflow: company identification, profile, financials, computed metrics, filing access, risk factors, and disclosure signals. The escape hatch for arbitrary concepts fills any gaps, making it comprehensive.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
SEC MCP — SEC EDGAR public APIs (free, no auth)
EDGAR MCP — SEC EDGAR public APIs (free, no auth)
SEC XBRL MCP — wraps SEC EDGAR XBRL API (data.sec.gov)
Query SEC EDGAR filings, XBRL financials, and company data through MCP. STDIO & Streamable HTTP.
Related MCP Servers
- AlicenseCqualityBmaintenanceMCP server for accessing SEC EDGAR filings. Connects AI assistants to company filings, financial statements, and insider trading data with exact numeric precision.21355AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceHosted MCP server providing read-only access to US public company fundamentals, segment breakdowns, peer comparisons, and earnings data sourced directly from SEC filings.MIT
- AlicenseAqualityAmaintenanceAn MCP server that enables models to access SEC EDGAR filings, filing text, and XBRL financial facts with caching, rate limiting, and iXBRL stripping.8MIT
- AlicenseNot gradedqualityBmaintenanceAn MCP server that enables natural-language queries over SEC EDGAR filings and live market data, providing hybrid retrieval with reranking for company snapshots, quotes, fundamentals, and macro indicators.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/chidrupa99/northbridge-diligence'
If you have feedback or need assistance with the MCP directory API, please join our Discord server