Metadata-Version: 2.4
Name: hub-equity-mcp
Version: 2.0.0
Summary: Hub-Equity Model Context Protocol server: standardized XBRL financial data (SEC and ESEF) for Claude Desktop, Cursor, and any MCP-aware client
Author-email: Hub-Equity <contact@hub-equity.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://hub-equity.com
Project-URL: Documentation, https://hub-equity.com/mcp
Project-URL: Pricing, https://hub-equity.com/pricing
Project-URL: Repository, https://github.com/Hub-Equity/hub-equity-mcp
Project-URL: Issues, https://github.com/Hub-Equity/hub-equity-mcp/issues
Project-URL: Changelog, https://github.com/Hub-Equity/hub-equity-mcp/blob/main/CHANGELOG.md
Keywords: mcp,model-context-protocol,xbrl,sec,edgar,esef,ifrs,us-gaap,financial-data
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: mcp<2.0.0,>=1.14.1
Requires-Dist: pydantic>=2.0.0
Requires-Dist: httpx<1.0,>=0.25.0
Provides-Extra: dev
Requires-Dist: pytest<10.0.0,>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio<2.0.0,>=0.23.0; extra == "dev"
Requires-Dist: respx<1.0.0,>=0.20.0; extra == "dev"
Requires-Dist: ruff<1.0.0,>=0.1.0; extra == "dev"
Dynamic: license-file

<!-- mcp-name: com.hub-equity/hub-equity-mcp -->

# hub-equity-mcp

**Standardized XBRL financial data for LLM agents.** A Model Context Protocol (MCP)
server that exposes normalized financial facts from US SEC (EDGAR) and European
ESEF filings to Claude Desktop, Cursor, and any MCP-aware client.

Hub-Equity serves standardized **European ESEF** filings
alongside US SEC data through one consistent hub-concept vocabulary, so an agent
can ask for `REVENUE` or `TOTAL_ASSETS` and get a comparable, source-linked value
whether the issuer files with the SEC or under ESEF.

> **Maturity.** The public REST API behind this connector runs in production and
> powers Hub-Equity's own chat. The package follows Semantic Versioning; it keeps
> the Beta classifier while its install base is young.

## Why

- **One vocabulary across two regimes.** SEC us-gaap and ESEF ifrs-full concepts
  are mapped to a single set of standardized hub codes, so cross-issuer and
  cross-taxonomy comparison works out of the box.
- **Every number is source-linked.** Facts carry their filing, period, and
  provenance so an agent can cite rather than guess.
- **Restatement-aware.** Explicit amendments and silent restatements (a figure a
  later filing reprinted differently, with no amendment filed), each change with
  the filing that made it.
- **Read-only and closed-world.** Every tool advertises `readOnlyHint=true`,
  `idempotentHint=true`, `destructiveHint=false`, `openWorldHint=false` per the
  MCP spec, so clients can reason about safety and caching without introspection.
- **No database credentials.** The published package talks only to the public
  REST API (`https://api.hub-equity.com`) over HTTPS. It never ships or requires
  a database key.

## Install

```bash
pipx run hub-equity-mcp
```

`pipx run` (or `uvx hub-equity-mcp`) fetches and starts the server in an isolated
environment; `pip install hub-equity-mcp` works too. Requires Python 3.12 or newer.

## Authentication and access

The server talks only to the public REST API, which needs a `hubq_` key (env
var `HUBEQUITY_API_KEY`).

- **Free key.** Create an account and a key in a minute at
  https://hub-equity.com/settings/api-keys. Gives the base tool set (entity
  search, normalized facts, time series, segments, screener, data-quality
  grade, FX conversion, and more).
- **Paid plan.** Unlocks the premium tools (restatement diffs, calculation
  trees, cross-period compare, cross-issuer compare, validation checks, extension
  concepts) and raises the rate limit. See the table below.

The published package never reaches the database directly, only the REST API.

## Configure your client

### Claude Desktop

Add to `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`,
Windows: `%APPDATA%\Claude\claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "hub-equity": {
      "command": "pipx",
      "args": ["run", "hub-equity-mcp"],
      "env": {
        "HUBEQUITY_API_KEY": "INSERT_YOUR_API_KEY"
      }
    }
  }
}
```

Without `HUBEQUITY_API_KEY`, every tool call answers `HUBEQUITY_API_KEY is not set` with the link to a Free key.

### Cursor

Add to `.cursor/mcp.json` (project root) or the global Cursor MCP settings:

```json
{
  "mcpServers": {
    "hub-equity": {
      "command": "pipx",
      "args": ["run", "hub-equity-mcp"],
      "env": {
        "HUBEQUITY_API_KEY": "INSERT_YOUR_API_KEY"
      }
    }
  }
}
```

### Environment variables

- `HUBEQUITY_API_KEY` (required): a `hubq_` key. A Free key opens the base
  tools; a paid plan opens the premium tools and the higher rate limit.
- `HUBEQUITY_API_URL` (optional): defaults to `https://api.hub-equity.com`.
  `https://` is enforced whenever a key is set (the server refuses to send the
  Bearer key over plaintext to a non-loopback host).

## Capabilities

| Type | What |
|---|---|
| Tools | Read-only tools: discovery, facts, time series, segments, forensic checks (table below) |
| Resources | Hub catalog, statement schema, tier catalog, usage guides, coverage snapshot |
| Prompts | Analytical templates (list below) |
| Completion API | `{hub_code}` autocomplete |

## Tools

The machine-readable tier catalog is served as a resource
(`hub-equity://catalog/tool-tiers`). Free tools cover discovery and identity;
Pro tools, open on every paid plan (Builder, Team, Enterprise), add forensic
depth (calculation trees, restatement diffs on amendments and silent
restatements, cross-period comparison, cross-issuer comparison, validation results, extension concepts). The tier
of a tool mirrors the REST endpoint it calls: every Pro tool's endpoint
requires the `facts.premium` scope server-side, and the Free caps
(`get_fact_decomposition` depth 1 without roll-up components or dimensional
slices, `screen_companies` 20 results without the quality filter,
`get_segments` axes without members, `roll_up_metric` the value without its
rule) are applied by the API, not only by this package.

| Tool | Tier | What it does |
|---|---|---|
| `find_entity(query)` | Free | Search by name, ticker, or CIK. Returns the `entity_id` other tools need. |
| `get_fact(entity_id, hub_concept_code, fiscal_year, fiscal_period_type?)` | Free | One normalized value plus its filing source. |
| `get_fact_decomposition(entity_id, fiscal_year, hub_concept_code? or qname?, depth?)` | Free (depth 1, linkbase only) / Pro (depth 2-3) | Hub rollup, XBRL calc-linkbase children, and dimensional breakdown. Free: the linkbase layer, without the roll-up components and the dimensional slices. |
| `search_concept(query)` | Free | Resolve a hub code from a label or a partial code. |
| `list_hubs(category?, include_non_primary?, limit?)` | Free | Enumerate the standardized hub catalog by category. |
| `get_entity_profile(entity_id)` | Free | Sector, auditor, employees, fiscal year end, recent filings. |
| `get_metric_history(entity_id, hub_concept_code, n_years?)` | Free | N-year time series with YoY growth and CAGR. |
| `get_segments(entity_id, hub_concept_code, fiscal_year)` | Free (capped) | Dimensional axis/member breakdown (segment, geography). Free: the axes without their members; Pro: every member. |
| `get_amendments(entity_id, fiscal_year?)` | Free | 10-K/A restatement summary: every amendment, its per-concept changes (50 per amendment). |
| `get_silent_restatements(entity_id, fiscal_year?)` | Free | Silent restatements: figures a later filing reprinted differently in its comparative columns, with no amendment filed, grouped by the filing that revealed them (50 changes per filing). |
| `compare_entities(entity_ids, hub_concept_codes, fiscal_year)` | Pro (up to 10x10) | Cross-issuer comparison matrix at one period, calendar-year aligned. Accepts UUIDs, tickers or `TICKER.MIC`. |
| `roll_up_metric(entity_id, hub_concept_code, fiscal_year)` | Free (capped) | Compute a value from signed children when it is not directly tagged. Free: the value; Pro: the rule and the signed contributions behind it. |
| `convert_currency(amount, from_currency, to_currency, date?, rate_type?)` | Free | ECB reference-rate FX conversion (closing, average YTD, average prior year). |
| `screen_companies(country?, sector?, min_revenue?, ..., sort_by?, limit?)` | Free (limit 20, no quality filter) / Pro (higher) | Filter the issuer universe by metadata, revenue, audit, and data quality. |
| `get_amendment_diff(entity_id, fiscal_year?, hub_concept_code?, min_diff_pct?, kind_filter?)` | Pro | Per-concept 10-K/A diffs: materiality, kind and concept filters, label, absolute delta, both filings as sources. |
| `get_silent_restatement_diff(entity_id, fiscal_year?, hub_concept_code?, min_diff_pct?, kind_filter?)` | Pro | The same diff on the silent restatements. |
| `get_calculation_tree(filing_id, link_role?)` | Pro | The filing's calculation linkbase: every total and its components, declared sign next to the sign the filed values support. |
| `compare_filings(entity_id, fiscal_year_a, fiscal_year_b, hub_concept_codes?)` | Pro | Cross-period same-entity compare with new / removed / sign-flip / restatement flags. |
| `get_extension_concepts(entity_id, status_filter?, limit?)` | Pro | Issuer-specific qnames declared outside standard taxonomies. |
| `get_data_quality_grade(entity_id)` | Free | A+ to D grade (or none), the two gates and counts behind it, freshness, direct-vs-derived split. |
| `get_validation_results(filing_id?, entity_id?, fiscal_year?, status_filter?)` | Pro | XBRL accounting and calculation-linkbase checks. |

## Resources

| URI | Type | Purpose |
|---|---|---|
| `hub-equity://catalog/hubs` | json | Full standardized hub catalog with EN/FR labels and category. |
| `hub-equity://catalog/categories` | json | Hub counts per category. |
| `hub-equity://catalog/tool-tiers` | markdown | Free vs Pro tool catalog and gating conditions. |
| `hub-equity://schema/financial-statements` | markdown | Statement structure and reading rules. |
| `hub-equity://catalog/hub/{hub_code}` | template | Forward catalog entry for one hub. |
| `hub-equity://entity/{entity_id}/profile` | template | Full entity snapshot. |
| `hub-equity://prompts/best-practices` | markdown | System-prompt guidance for client integrations. Load this before calling any tool. |
| `hub-equity://prompts/tool-usage-examples` | markdown | Per-tool few-shot examples (good and anti-pattern). |
| `hub-equity://prompts/data-coverage` | json | Live dataset snapshot (issuer and filing counts, sources, taxonomies, fiscal year range). Cached 24h. |

## Prompts

Eight analytical templates: `peer_comparison`, `quality_of_earnings`,
`restatement_audit`, `sector_overview`, `valuation_screen`,
`goodwill_impairment_risk`, `working_capital_diagnostic`, `cash_flow_consistency`.

## For client developers

Before calling any tool, fetch `hub-equity://prompts/best-practices` and inject
the markdown into your system prompt. This makes your client follow the same tool
routing, source-citation, and numeric-fidelity rules as Hub-Equity's own chat.

```python
# Pseudo-code for a typical MCP client integration
session = mcp.connect("hub-equity-mcp")
best_practices = session.read_resource("hub-equity://prompts/best-practices")
system_prompt = "You are an assistant ...\n\n" + best_practices
# now call session.call_tool("find_entity", {"query": "AAPL"}) etc.
```

## Rate limits

| Mode | Limit | Notes |
|---|---|---|
| Free key | 120 requests / minute | Base tools. |
| Builder key | 300 requests / minute | Premium tools unlocked. |
| Team key | 600 requests / minute | Premium tools unlocked. |
| Enterprise key | 1 000 requests / minute | Negotiable. |

The bucket is per API key.

On a per-minute 429 the client retries with exponential backoff (up to 3 times)
before raising `RateLimitExceeded`. A used-up daily or monthly allowance is
raised at once, with the API's message.

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `429 Too Many Requests` / `RateLimitExceeded` | Rate cap hit (120/min with a Free key, 300 to 1 000/min on a paid key) | Move to a paid plan, or slow down the tool-call fan-out. The client already backs off up to 3 times. |
| `HUBEQUITY_API_KEY is not set` on every tool call | No key in the client's `env` block | Set `HUBEQUITY_API_KEY`; a Free key takes a minute at https://hub-equity.com/settings/api-keys. |
| `HubEquityRestError: HTTP 401` | An invalid, expired or revoked `hubq_` key (`INVALID_API_KEY`) | Create a new key at https://hub-equity.com/settings/api-keys. |
| `HubEquityRestError: HTTP 403` | The key's workspace is on the Free plan and the call needs a Pro tool, or a Free cap (`depth > 1`, `limit > 20`, `min_quality_grade`) | Upgrade the plan, or stay within the Free caps. |
| `RateLimitExceeded` whose body carries `DAILY_QUOTA_EXCEEDED` / `MONTHLY_QUOTA_EXCEEDED` | The workspace's volume allowance is used up (Free 200 a day / 5 000 a month, Builder 50 000, Team 500 000 a month); raised at once, without retry | Wait for `resets_on`, or upgrade the plan. |
| Connection or timeout errors | Network issue reaching `api.hub-equity.com`, or a bad `HUBEQUITY_API_URL` | Check connectivity; confirm `HUBEQUITY_API_URL` (if set) points to a reachable `https://` host. |
| `ValueError: HUBEQUITY_API_URL must use https://` | A key is set but the URL is plain `http://` on a non-loopback host | Use `https://`, or unset `HUBEQUITY_API_URL` to fall back to the default API. |
| Server does not appear in Claude Desktop or Cursor | Config JSON error, or `pipx` not on the client's PATH | Validate the JSON; use the absolute path of `pipx` (or `uvx`) if the client cannot resolve it. |

## Run locally

```bash
python -m hub_equity_mcp.server
```

Or drive it interactively with the MCP inspector:

```bash
npx @modelcontextprotocol/inspector python -m hub_equity_mcp.server
```

The inspector lists every tool, resource and prompt and lets you call each
one.

## Development

```bash
pip install -e '.[dev]'
pytest tests/
```

Tests are hermetic: tool tests mock the REST API with `respx`, so no live backend
is needed.

## License

Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE). This connector is an open
client to the public Hub-Equity REST API; access to premium data stays gated by
API key, plan, and rate limits on the service side.
