Skip to main content
Glama
INDUSS Research Intelligence MCP Server

INDUSS Research Intelligence MCP Server

by viraj43

INDUSS Research Intelligence MCP Server

An MCP (Model Context Protocol) server that acts as an institutional research backend for AI assistants (Claude, ChatGPT, Cursor, VS Code, Windsurf, or any MCP-compatible client). The LLM handles reasoning and orchestration; this server handles all data retrieval, extraction, validation, calculation, and citation generation.

Status

The architecture is now considered stable: 15 tools proving the full pattern end-to-end (context → route → search → extract → normalize → validate → cite → calculate → report), built entirely on reusable engines rather than per-tool logic. Adding the remaining ~30 tools from the spec is now purely additive — new source profiles and new tool files composing existing engines, no structural changes expected.

Related MCP server: INDUSS Research Intelligence MCP Server

Architecture

Tools are thin orchestrators. All reusable logic lives in engines (src/core/*) and sources (src/sources/*), driven by one shared ResearchContext so the same inputs always resolve to the same sources, the same query, and the same citations — a tool call is deterministic.

Claude / ChatGPT / Cursor
        │  MCP Protocol
   INDUSS MCP Server (src/index.ts)
        │
 ┌──────────────────────────────────────────────────┐
 │ src/tools/registerTools.ts                        │  Tool Registry (15 tools, thin orchestration)
 │ src/tools/toolRegistry.ts                          │  Tool Metadata (category/inputs/outputs/sources)
 │                                                     │
 │ src/types/context.ts                               │  ResearchContext — the one input shape every
 │                                                     │  research tool takes (company/sector/country/
 │                                                     │  listed/objective/date)
 │                                                     │
 │ src/core/pipeline/searchPipeline.ts                │  Universal Search Pipeline — the ONLY caller
 │                                                     │  of core/exa/search.ts. Every search-backed
 │                                                     │  tool goes through this, end to end:
 │                                                     │  Router → Exa → Normalizer → Extractor →
 │                                                     │  Validator → Citation Engine → Response
 │ src/core/pipeline/fetchDocument.ts                 │  Deep-extraction document fetcher (opt-in)
 │                                                     │
 │ src/core/router/objective-router.ts                │  objective → source names
 │ src/core/router/source-router.ts                   │  source names → domain allowlist
 │ src/core/exa/{client,search,contents}.ts           │  Exa REST integration
 │ src/core/extraction/*                              │  HTML / PDF / Table extraction
 │ src/core/normalization/normalizer.ts               │  text/number normalization
 │ src/core/citations/citationEngine.ts               │  builds + dedupes + flattens citations
 │ src/core/citations/sourcePriority.ts               │  Source Priority Engine — Tier + Authority +
 │                                                     │  Recency → Confidence
 │ src/core/quality/validationEngine.ts                │  Validator stage: CIN format, financial
 │                                                     │  statement plausibility (grows to cover
 │                                                     │  hallucination/citation-completeness checks)
 │ src/core/financial/financialEngine.ts              │  Financial Calculator over FinancialStatement
 │                                                     │  objects (Income Statement/Balance Sheet/
 │                                                     │  Cash Flow)
 │ src/core/reports/reportEngine.ts                   │  Report orchestration (delegates to renderers/)
 │ src/core/renderers/{html,markdown}/*               │  Pure ResearchSection → string renderers
 │ src/core/pdf/pdfEngine.ts                           │  PDF Generator (Playwright, HTML → PDF)
 │                                                     │
 │ src/sources/{mca,sec,company,government,macro,     │  Each source is fully self-contained: domains,
 │   news,industry,exchange,regulator,legalMedia,     │  query templates per research angle, trust
 │   financialData,privateData,socialSentiment}/      │  tier, baseline authority score
 │   index.ts                                         │
 └──────────────────────────────────────────────────┘
        │
 Public Data Sources (Exa, domain-restricted per src/sources/*)

Search flow: tool builds a ResearchContext (with its fixed objective) → runSearchPipeline() → source-router resolves domains from the matched sources → the first matching source's query template is used → Exa (cached) → Normalizer → optional deep Extractor → optional Validator → Citation Engine (Source Priority scoring + dedupe) → tool shapes the result.

Report flow: tool assembles ResearchSection[] (each carrying its own summary, tables, citations, and confidence) into a ReportInput → core/reports/reportEngine.ts → core/renderers/{markdown,html}/reportRenderer.ts → (for PDF) core/pdf/pdfEngine.ts (Playwright). The HTML renderer produces a full cover page + table of contents + numbered sections; a section's metadata.tone (info/success/warning/danger) and metadata.label wrap it in a colored callout card, and summary supports a light markdown subset (**bold**, - bullets, > blockquotes) — see ReportInputSchema/ResearchSectionSchema in src/types/schemas.ts.

PDF delivery: generate_pdf returns the rendered PDF as a base64 MCP resource content block embedded directly in the tool response — this is what makes it retrievable by a remote client (e.g. Claude.ai talking to a Railway deployment), since a server-local file path is meaningless off-box. It's also written to reports/ locally and, when MCP_BASE_URL is set (httpStream/production), served over GET /reports/:filename (registered via server.getApp()), so the response additionally includes a downloadUrl.

Setup

npm install
npx playwright install chromium
cp .env.example .env   # fill in EXA_API_KEY
npm run build
npm start               # stdio transport, for Claude Desktop / Cursor etc.

For local development with auto-reload:

npm run dev

For HTTP transport (remote MCP clients):

MCP_TRANSPORT=httpStream npm start

With Docker (includes Redis + Postgres)

docker compose up --build

Testing

npm test          # vitest — financial engine, citation engine, source priority, quality engine, report engine
npm run typecheck

Tools implemented in this slice (19)

Category

Tools

Company Intelligence

search_company, company_profile, company_overview

Financial Intelligence

financial_statements, ratio_analysis

Funding Intelligence

funding_history

Competitor Intelligence

discover_competitors, listed_peer_comparison

Industry Intelligence

industry_overview, market_size

News Intelligence

latest_news, negative_news

Litigation & Compliance

litigation_history

Promoter Intelligence

promoter_background

Report Generation

generate_report, generate_institutional_report

PDF & Export

generate_markdown, generate_pdf

Ops

health_check (also surfaces the full tool capability registry)

negative_news (soft signal: press + Glassdoor/Reddit sentiment) and litigation_history (hard signal: SEBI/NCLT orders + legal-journalism case coverage) are deliberately split — they answer different due-diligence questions and shouldn't be conflated into one keyword screen.

generate_institutional_report — the composite orchestrator

Every tool above also has its core logic exported as a plain function (getCompanyProfile, getFinancialStatements, etc., alongside each registerXTool), so core/orchestration/institutionalReport.ts can call them directly, in-process — no re-entering the MCP protocol per phase. A single generate_institutional_report call runs company profile, financials, industry, server-ranked competitors, funding, and a combined litigation/promoter/negative-news risk screen in parallel (Promise.allSettled, one phase failing doesn't sink the rest), composes the results into ResearchSections with deterministic templated text (no LLM tokens spent server-side), and renders whichever of json/markdown/html/pdf the caller asked for. The calling model gets a finished report instead of having to plan and narrate ~10 separate tool calls itself.

Two quality mechanisms run underneath every company-subject tool (including this composite one):

  • Entity verification (core/quality/entityVerification.ts) — a result must contain the searched company's distinctive name tokens, not just one word it happens to share with an unrelated company (fixes the "Big Bang Boom" query pulling in "Nirmal Bang" or "BB Food").

  • Evidence metadata (tools/shared/evidenceMetadata.ts) — every response's metadata includes sourcesChecked (human-readable labels), primarySources/secondarySources counts, and how many raw hits were dropped as false positives, so a clean screen reads as "checked SEBI, NCLT, Indian Kanoon... — no matches" rather than going quiet.

financial_statements also never returns bare nulls: when data can't be found it returns { status: "not_available", reason, recommendedSources } instead.

Every tool returns the standard envelope:

{
  "success": true,
  "data": {},
  "citations": [],
  "confidence": 0.98,
  "metadata": {}
}

Every Citation carries the four components the Source Priority Engine scores it on:

{
  "source": "mca.gov.in",
  "url": "...",
  "publicationDate": "...",
  "evidenceSnippet": "...",
  "tier": "official_filing",
  "authority": 0.95,
  "recencyPenalty": 0,
  "confidenceScore": 0.96
}

Adding a new tool

  1. If the objective needs a source not already covered, add a new profile under src/sources/<name>/index.ts (domains + searchTemplates + tier + confidence + supportsPDF/HTML) and register it in src/sources/index.ts. Otherwise, add the objective → source mapping to src/core/router/objective-router.ts and reuse existing sources.

  2. Create src/tools/<category>/<toolName>.ts. Accept a context: ResearchContextInputSchema.required({...}) parameter, call withObjective(args.context, "<objective>"), then runSearchPipeline({ context, templateKey, subject, ... }) — never call core/exa/search.ts directly.

  3. Export a <toolName>Meta: ToolMeta alongside the register function (category/inputs/outputs/requiredSources/caching/estimatedRuntimeMs) and add it to src/tools/toolRegistry.ts.

  4. Register the tool in src/tools/registerTools.ts.

  5. If the tool does deterministic calculation only (no search), add pure functions to the relevant engine under src/core/<engine>/ (or a new engine folder) with unit tests in tests/.

  6. For fact validation beyond Zod's type checks (format/plausibility rules), add functions to src/core/quality/validationEngine.ts.

Notes on infra

  • Redis is optional at runtime: if unreachable, the cache layer (src/cache/cache.ts) transparently falls back to an in-process memory store, so the server still works without docker compose up.

  • Postgres is optional and only used for the query/result history schema in src/db/migrations.sql; tools function without DATABASE_URL set.

  • BullMQ (src/queue/queue.ts) is wired up for future long-running report jobs but no tool enqueues to it yet in this slice.

Available Tools

15 tools
company_overviewB
Read-only

Produces a narrative business overview (what the company does, products/services, target market) sourced from the company's own site and LinkedIn.

Inputs: context (required).

company_profileA
Read-only

Retrieves registry-grade company profile facts (CIN, incorporation date, registered office) by searching MCA/Tofler/Zauba/OpenCorporates and the company's own site.

Inputs: context (required).

discover_competitorsA
Read-only

Searches industry-analyst and news sources for named competitors/rivals of a company and extracts candidate competitor names via text-pattern heuristics. Results should be treated as a starting candidate list, not a verified peer set.

Inputs: context (required).

financial_statementsA
Read-only

Locates a company's annual report / financial statement filing and extracts structured line-item tables (revenue, net profit, EBITDA, assets, equity, debt) from the underlying HTML or PDF document.

Inputs: context (required).

funding_historyA
Read-only

Searches Crunchbase, Tofler, MCA, and OpenCorporates for a company's funding rounds, investors, and valuation mentions, and extracts candidate round/amount facts from the retrieved text.

Inputs: context (required).

generate_markdownA
Idempotent

Renders a structured report (see generate_report's schema) into a GitHub-flavored Markdown document with a table of contents, per-section confidence/sources, and a consolidated citation list.

Inputs: title (required), sections (required), subtitle, companyName, +1 more.

generate_pdfA

Renders a structured report (see generate_report's schema) into an institutional-layout PDF (headers, footers, page numbers, TOC, tables, per-section confidence, citations) via headless-browser HTML-to-PDF conversion, and writes it to the local reports directory.

Inputs: title (required), sections (required), subtitle, companyName, +1 more.

generate_reportA
Idempotent

Assembles a structured research report from ResearchSections (each carrying its own summary, tables, citations, and confidence) into the standard report envelope. Use after gathering facts with other tools; this tool does no research of its own.

Inputs: title (required), sections (required), subtitle, companyName, +1 more.

health_checkA
Read-onlyIdempotent

Reports server health: config validity, Redis cache connectivity, Postgres configuration status, and the tool capability registry.

Inputs: no named parameters.

industry_overviewA
Read-only

Retrieves an industry overview (structure, key players, growth drivers) from top-tier consulting/research sources (Deloitte, PwC, EY, KPMG, McKinsey, Bain, BCG, IMARC, Statista, NASSCOM).

Inputs: context (required).

latest_newsB
Read-only

Retrieves recent news coverage of a company from Reuters, Economic Times, Mint, Business Standard, and Moneycontrol, sorted by publish date.

Inputs: context (required), daysBack.

market_sizeA
Read-only

Finds market size and CAGR figures for an industry from analyst/research sources (IMARC, Statista, McKinsey, NASSCOM, etc.) and extracts numeric estimates via pattern matching.

Inputs: context (required).

negative_newsA
Read-only

Screens news sources for adverse media on a company (fraud, litigation, regulatory action, layoffs, defaults) for due-diligence / risk-screening purposes.

Inputs: context (required).

ratio_analysisA
Read-onlyIdempotent

Performs deterministic financial ratio analysis (profitability, liquidity, leverage, returns) plus multi-period CAGR trend over a set of FinancialStatement objects (Income Statement / Balance Sheet / Cash Flow). Pure calculation — no search, no LLM tokens.

Inputs: statements (required), companyName.

search_companyA
Read-only

Discover a company's official website, LinkedIn, and registry presence via domain-restricted Exa search. Use this first to resolve a company name to authoritative source URLs before calling other company tools.

Inputs: context (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 15 tools

    Disambiguation5/5

    Each tool targets a distinct aspect of the research workflow: company identification, profile facts, narrative overview, financial statements, ratio analysis, funding, competitors, industry, market size, news, adverse news, and report generation/rendering. Even the three generate_* tools are clearly differentiated by output type (structured report, Markdown, PDF), so there is no ambiguity.

    Naming Consistency3/5

    All tool names are snake_case and readable, but they mix noun-only names (company_profile, financial_statements, industry_overview) with verb_noun names (search_company, discover_competitors, generate_report). The pattern is not fully consistent, though the naming still conveys the tool's purpose without confusion.

    Tool Count5/5

    With 15 tools, the server sits at the upper end of the ideal range but each tool fills a distinct role in the company-research pipeline, from health check to PDF generation. No tool feels redundant or out of place, making the count well-scoped for the stated purpose.

    Completeness5/5

    The tool set covers the entire research lifecycle: company resolution, profile extraction, financial statement parsing, ratio analysis, funding and competitor research, industry and market overviews, news and risk screening, and finally report assembly and rendering. There are no obvious dead ends or missing steps for the server's intended domain.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Provides 17 research tools for comprehensive company intelligence, covering aspects like overview, products, financials, and competitors. Supports both natural language answers and structured JSON output for automation.
      18
      MIT
    • F
      license
      A
      quality
      C
      maintenance
      Enables AI assistants to perform institutional research and due diligence by retrieving, extracting, validating, and citing data from public sources, then generating reports in markdown, HTML, or PDF.
      23
      -
    • F
      license
      A
      quality
      C
      maintenance
      Enables AI assistants to perform institutional research on companies, financials, industry, news, litigation, and risk, and to generate cited markdown, HTML, or PDF reports through MCP.
      32
      -