# Finra Mcp Server

> MCP Server for Finra Public Data

- **Type:** MCP server
- **Install:** `agentstack add mcp-cmaurer-finra-mcp-server`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [cmaurer](https://agentstack.voostack.com/s/cmaurer)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [cmaurer](https://github.com/cmaurer)
- **Source:** https://github.com/cmaurer/finra-mcp-server

## Install

```sh
agentstack add mcp-cmaurer-finra-mcp-server
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# finra-mcp-server

A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes the [FINRA Query API](https://developer.finra.org) as a set of tools. It lets MCP-capable clients (Claude Desktop, Claude Code, and other MCP hosts) query FINRA's public regulatory and market datasets — TRACE corporate bond trades, OTC equity summaries, short interest, firm registration data, and more — in natural language.

The server handles OAuth2 authentication, token caching, request shaping, and pagination, and ships with a local catalog of datasets so a model can discover what's available before issuing a query.

## What it does

FINRA publishes a large family of datasets through a single Query API surface:

```
/data/group/{group}/name/{dataset}
```

Each dataset supports field projection, comparison filters, date-range filters, IN-list (domain) filters, sorting, and pagination. This server wraps that API with:

- **OAuth2 client-credentials flow** — fetches and caches a bearer token, refreshing automatically before expiry.
- **A generic query tool** (`finra_query`) that exposes the full filtering surface of the Query API.
- **A local dataset catalog** so the model can discover valid `group`/`dataset` combinations without guessing.
- **Curated convenience tools** for the most common datasets (TRACE bonds, short interest, OTC weekly summary, firm profile) that map friendly arguments (CUSIP, symbol, date range, CRD number) onto the underlying query shape.

## Tools

| Tool | Description |
| --- | --- |
| `finra_query` | Generic Query API request. Supports `compareFilters`, `dateRangeFilters`, `domainFilters`, field projection, sorting, and pagination. Sync cap is 5,000 records. |
| `finra_list_datasets` | List datasets in the local catalog, optionally filtered by `category` or a `search` substring. Use this first to discover valid `group`/`dataset` names. |
| `finra_describe_dataset` | Look up catalog metadata for a specific `group`/`dataset`. |
| `finra_trace_corporate_bonds` | Curated wrapper for TRACE corporate-bond trade reports (`fixedIncomeMarket/trace`). Filter by `cusip`, `symbol`, or trade-date range. |
| `finra_short_interest` | Curated wrapper for consolidated short interest (`otcMarket/consolidatedShortInterest`). Filter by `symbol` and/or settlement-date range. |
| `finra_otc_weekly_summary` | Curated wrapper for OTC equity weekly trade summary (`otcMarket/weeklySummary`). Filter by `symbol` and/or week-ending date. |
| `finra_firm_profile` | Curated wrapper for firm profile lookup (`registration/firmProfile`). Provide a CRD number. |

### `finra_query` arguments

| Argument | Type | Description |
| --- | --- | --- |
| `group` | string (required) | Dataset group, e.g. `otcMarket`, `fixedIncomeMarket`, `registration`. |
| `dataset` | string (required) | Dataset name within the group, e.g. `weeklySummary`, `trace`. |
| `fields` | string[] | Subset of fields to return. Omit for all fields. |
| `compareFilters` | object[] | Field comparisons: `{ fieldName, fieldValue, compareType }` where `compareType` is one of `EQUAL`, `NOT_EQUAL`, `GREATER`, `LESSER`, `GREATER_EQUAL`, `LESSER_EQUAL`, `LIKE`. |
| `dateRangeFilters` | object[] | `{ fieldName, startDate, endDate }` with ISO `yyyy-MM-dd` dates. |
| `domainFilters` | object[] | IN-list filters: `{ fieldName, values: [...] }`. |
| `sortFields` | string[] | Sort fields; prefix with `-` for descending. |
| `limit` | number | Max records (1–5,000 for synchronous requests). Defaults to 100. |
| `offset` | number | Pagination offset (0–500,000). Defaults to 0. |

## Dataset catalog

The server bundles a curated catalog (see [`src/catalog.ts`](src/catalog.ts)) covering these categories:

- **Equity / OTC Market** — weekly/monthly summaries, ATS and non-ATS block summaries, daily OTC list, consolidated short interest, Reg SHO daily volume, threshold list, ADF data.
- **Fixed Income** — TRACE corporate bonds, Treasury daily/monthly aggregates, agency & corporate debt breadth/sentiment indicators, 144A debt indicators, capped-volume datasets.
- **Registration** — firm profiles, registrations, disclosures, status history, broker-dealer lists, branch and individual records, registration validation, and more.
- **Firm** — Rule 4530 customer complaint filings.
- **FINRA Content** — the FINRA rulebook and industry-snapshot datasets.

The catalog is for discovery only — the API may accept additional `group`/`dataset` combinations not listed here. If `finra_describe_dataset` returns no entry, you can still try `finra_query` directly.

## Prerequisites

- **Node.js ≥ 20**
- **FINRA API credentials** — a client ID and client secret provisioned from the [FINRA API Console](https://developer.finra.org). You will need a FINRA account with access to the API Platform, and you must accept the data-set agreements for any non-public datasets you intend to query.

## Installation

```bash
git clone 
cd finra-mcp-server
npm install
npm run build
```

This compiles TypeScript from `src/` into `dist/`. The entry point is `dist/index.js`.

### npm scripts

| Script | Purpose |
| --- | --- |
| `npm run build` | Compile TypeScript to `dist/`. |
| `npm run dev` | Compile in watch mode. |
| `npm start` | Run the compiled server (`node dist/index.js`). |
| `npm run typecheck` | Type-check without emitting output. |

## Configuration

The server is configured entirely through environment variables.

| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `FINRA_CLIENT_ID` | ✅ | — | OAuth2 client ID from the FINRA API Console. |
| `FINRA_CLIENT_SECRET` | ✅ | — | OAuth2 client secret. |
| `FINRA_API_BASE` | | `https://api.finra.org` | Base URL for the Query API. |
| `FINRA_TOKEN_URL` | | `https://ews.fip.finra.org/fip/rest/ews/oauth2/access_token?grant_type=client_credentials` | OAuth2 token endpoint. |

If `FINRA_CLIENT_ID` or `FINRA_CLIENT_SECRET` is missing, the server exits at startup with an error directing you to provision credentials.

## Usage

The server speaks MCP over **stdio**. It is launched by an MCP client, which communicates with it over standard input/output — you do not run it as a long-lived HTTP service.

### Claude Desktop / Claude Code

Add the server to your MCP client configuration. For Claude Desktop, edit `claude_desktop_config.json`; for Claude Code, use `claude mcp add` or edit `.mcp.json`.

```json
{
  "mcpServers": {
    "finra": {
      "command": "node",
      "args": ["/absolute/path/to/finra-mcp-server/dist/index.js"],
      "env": {
        "FINRA_CLIENT_ID": "your-client-id",
        "FINRA_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

For Claude Code, the equivalent CLI command is:

```bash
claude mcp add finra \
  --env FINRA_CLIENT_ID=your-client-id \
  --env FINRA_CLIENT_SECRET=your-client-secret \
  -- node /absolute/path/to/finra-mcp-server/dist/index.js
```

Restart the client after editing the configuration. The FINRA tools will then be available to the model.

### Running directly

For local testing you can run the server directly. It will wait for an MCP client to connect over stdio:

```bash
export FINRA_CLIENT_ID=your-client-id
export FINRA_CLIENT_SECRET=your-client-secret
npm start
```

To exercise it interactively, use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):

```bash
FINRA_CLIENT_ID=... FINRA_CLIENT_SECRET=... \
  npx @modelcontextprotocol/inspector node dist/index.js
```

## Examples

These show the arguments a model would pass to each tool.

**Discover datasets in a category:**

```json
// finra_list_datasets
{ "category": "Fixed Income" }
```

**Recent TRACE trades for a bond by CUSIP:**

```json
// finra_trace_corporate_bonds
{ "cusip": "037833DX5", "startDate": "2026-01-01", "endDate": "2026-03-31", "limit": 200 }
```

**Short interest for a symbol:**

```json
// finra_short_interest
{ "symbol": "AAPL", "startDate": "2026-01-01", "endDate": "2026-06-01" }
```

**Look up a firm by CRD number:**

```json
// finra_firm_profile
{ "crdNumber": "7691" }
```

**Arbitrary query with the generic tool:**

```json
// finra_query
{
  "group": "otcMarket",
  "dataset": "weeklySummary",
  "compareFilters": [
    { "fieldName": "issueSymbolIdentifier", "fieldValue": "TSLA", "compareType": "EQUAL" }
  ],
  "dateRangeFilters": [
    { "fieldName": "weekStartDate", "startDate": "2026-01-01", "endDate": "2026-06-01" }
  ],
  "sortFields": ["-weekStartDate"],
  "limit": 50
}
```

Each tool returns a JSON object containing the dataset identifiers, the total `recordCount` reported by the API, the number of records `returned`, and the `records` array.

## How it works

- **Authentication** ([`src/finra-client.ts`](src/finra-client.ts)) — On the first request the client exchanges its base64-encoded `clientId:clientSecret` for a bearer token at `FINRA_TOKEN_URL`, then caches it. Tokens are reused until ~30 seconds before expiry (capped at 30 minutes) and refreshed automatically.
- **Request shaping** — Requests with filters, projections, or sorts are sent as `POST` with a JSON body; simple unfiltered requests use `GET` with query-string pagination. The total record count is read from the `record-count` response header.
- **Tool layer** ([`src/tools.ts`](src/tools.ts)) — Zod schemas validate every tool's arguments and are converted to JSON Schema for the MCP `tools/list` response. Curated tools translate friendly arguments into the underlying `compareFilters`/`dateRangeFilters` shape.

## Project structure

```
src/
  index.ts         MCP server bootstrap (stdio transport, request handlers)
  config.ts        Environment-variable configuration loader
  finra-client.ts  OAuth2 token handling + Query API client
  tools.ts         Tool definitions, Zod schemas, and handlers
  catalog.ts       Local catalog of FINRA datasets
```

## Notes & limitations

- **Synchronous queries are capped at 5,000 records.** For larger result sets, page with `limit`/`offset`. The Query API also supports an async mode for very large extracts; this server requests synchronous results.
- **Data availability depends on your FINRA entitlements.** Some datasets require accepting additional data agreements in the API Console.
- Field names (e.g. `issueSymbolIdentifier`, `tradeReportDate`, `firmCrdNumber`) follow FINRA's schema. Consult the [FINRA developer catalog](https://developer.finra.org/catalog) for the exact fields available in each dataset.

## License

Released under the [MIT License](LICENSE).

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [cmaurer](https://github.com/cmaurer)
- **Source:** [cmaurer/finra-mcp-server](https://github.com/cmaurer/finra-mcp-server)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-cmaurer-finra-mcp-server
- Seller: https://agentstack.voostack.com/s/cmaurer
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
