# Bizmoon MCP server reference

> Live US federal and state regulatory changes and funding programs for AI agents, with citations to the official register. This file is the full reference as markdown; the HTML version with live example responses is at https://bizmoon.ai/mcp/docs and a site map for agents is at https://bizmoon.ai/llms.txt.

## Protocol

- Endpoint: https://bizmoon.ai/api/mcp (Model Context Protocol over stateless streamable HTTP)
- Send JSON-RPC 2.0 by POST with headers `content-type: application/json` and `accept: application/json, text/event-stream`.
- Responses are server-sent events; the JSON-RPC message is on the last `data:` line.
- No session is required: `initialize` is optional and every request stands alone.
- Tool results wrap their payload as JSON text in `result.content[0].text`, with `result.isError` set on failures. All tools are read-only.

List available tools:

```bash
curl -s -X POST https://bizmoon.ai/api/mcp -H "content-type: application/json" -H "accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

## Auth and limits

| | Free | API key (Professional plan) |
| --- | --- | --- |
| History | Last 90 days | Everything |
| Results per call | 25 | 50 |
| Rate limit | 30/min, 300/day per visitor | 60/min per key, 1,000/day per organization |
| Tools | 5 public | 5 public + 5 organization |

Send the key as `authorization: Bearer bm_sk_...` - the same header in every client:

- Claude Code: `claude mcp add ... --header "Authorization: Bearer bm_sk_..."`
- Claude.ai and Claude Desktop: Settings > Connectors > Add custom connector; an org admin adds a request header named Authorization
- OpenAI and xAI APIs: `"authorization": "bm_sk_..."` beside `server_url` on the mcp tool
- Gemini CLI: `"headers": { "Authorization": "Bearer bm_sk_..." }` beside `httpUrl`
- OpenClaw: `"headers": { "Authorization": "Bearer bm_sk_..." }` on the server entry
- Cursor, VS Code, and Windsurf: `"headers": { "Authorization": "Bearer bm_sk_..." }` in the MCP config
- cURL or any HTTP client: `-H "authorization: Bearer bm_sk_..."`
- REST API (/api/v1): same bearer header on every request

Keys are created under Settings, then API keys (Professional plan). A missing or malformed header falls back to the free tier; an invalid bm_sk_ key returns HTTP 401.

## Public tools

### search_regulatory_changes

Search regulations. Search rules and notices across every register Bizmoon monitors, newest first, each with an AI summary and the official source URL. Funding opportunities are left out; search_funding_programs covers those.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `jurisdiction` | string | no | US_FED for federal, or a two-letter state code such as CA (US_STATE_CA also works). Omit for all jurisdictions. Unrecognized values return a tool error instead of silently widening the search. e.g. "CA" |
| `agency` | string | no | Case-insensitive substring match on the issuing agency name. e.g. "Department of Public Health" |
| `category` | string | no | Either "regulation" or "funding". Omit to search regulations and uncategorized documents while leaving funding opportunities out. Pass "funding" to search those here instead. e.g. "regulation" |
| `keyword` | string | no | Case-insensitive substring matched against title, AI summary, and description. e.g. "health" |
| `from` | string (date) | no | YYYY-MM-DD. Only documents published on or after this date. The free tier floors this at 90 days ago and reports the clamp in lookbackClampedTo. e.g. "2026-08-01" |
| `to` | string (date) | no | YYYY-MM-DD. Only documents published on or before this date (the whole day is included). e.g. "2026-09-01" |
| `limit` | integer | no | Max results per call. Default 20. Free tier caps at 25, API key at 50. e.g. 10 |
| `offset` | integer | no | Pagination offset. Default 0. Ask again with offset advanced by your limit until offset plus the results you have reaches total. A page is a snapshot: documents published between calls shift the window, so a recurring agent should advance its date rather than page far. e.g. 20 |
- Responses include total (all matches), the page of results, and lookbackClampedTo when the free-tier window was applied.
- Every result carries publishedDate, effectiveDate, agencies, an AI summary, and the canonical url to cite.

```bash
curl -s -X POST https://bizmoon.ai/api/mcp \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_regulatory_changes","arguments":{"jurisdiction":"CA","keyword":"health","limit":1}}}'
# key tier: add -H "authorization: Bearer bm_sk_..."
```

Response fields:

| Field | Type | Description |
| --- | --- | --- |
| `results[].id` | string | Document id; pass to get_regulatory_change |
| `results[].title` | string | null | Document title |
| `results[].jurisdiction` | string | US_FED or US_STATE_XX |
| `results[].source` | string | The official register the document came from |
| `results[].agencies` | string[] | Issuing agencies |
| `results[].category` | string | null | "regulation", "funding", or null when unclassified |
| `results[].docType` | string | null | Source-specific document type |
| `results[].publishedDate` | string | null | YYYY-MM-DD publication date |
| `results[].effectiveDate` | string | null | YYYY-MM-DD effective date when stated |
| `results[].summary` | string | null | AI summary of the document |
| `results[].url` | string | null | Canonical official URL to cite |
| `total` | integer | All matches, not just this page |
| `offset` | integer | Offset this page started at |
| `limit` | integer | Effective limit after tier clamping |
| `lookbackClampedTo` | string | null | ISO timestamp the window was floored to on the free tier, else null |

### get_regulatory_change

Read one document. One document in full: agencies, published and effective dates, summary, description, and the canonical URL to cite.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | The document id returned by search_regulatory_changes, changes_since, or search_funding_programs. e.g. "278724" |
- Unknown ids return { "error": "not_found", "id": "..." } as a normal result.

```bash
curl -s -X POST https://bizmoon.ai/api/mcp \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_regulatory_change","arguments":{"id":"(from a search result)"}}}'
# key tier: add -H "authorization: Bearer bm_sk_..."
```

Response fields:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Document id |
| `title` | string | null | Document title |
| `jurisdiction` | string | US_FED or US_STATE_XX |
| `source` | string | The official register |
| `agencies` | string[] | Issuing agencies |
| `category` | string | null | "regulation", "funding", or null |
| `docType` | string | null | Source-specific document type |
| `publishedDate` | string | null | YYYY-MM-DD |
| `effectiveDate` | string | null | YYYY-MM-DD when stated |
| `summary` | string | null | AI summary |
| `description` | string | null | Longer extracted description |
| `categories` | string[] | Source-provided category labels |
| `url` | string | null | Canonical official URL to cite |

### list_jurisdictions

Show coverage. Coverage and freshness for every source: the latest publication and when the register was last checked.

No parameters.
- Call this first in a session to learn what data exists and how fresh it is.
- jurisdiction values from this tool are exactly what the other tools accept.

```bash
curl -s -X POST https://bizmoon.ai/api/mcp \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_jurisdictions","arguments":{}}}'
# key tier: add -H "authorization: Bearer bm_sk_..."
```

Response fields:

| Field | Type | Description |
| --- | --- | --- |
| `jurisdictions[].jurisdiction` | string | US_FED or US_STATE_XX |
| `jurisdictions[].source` | string | Register name |
| `jurisdictions[].slug` | string | Stable source identifier |
| `jurisdictions[].lastRunAt` | string | null | ISO timestamp the register was last checked |
| `jurisdictions[].lastRunStatus` | string | null | "success", "error", or "empty_clean" |
| `jurisdictions[].latestPublished` | string | null | YYYY-MM-DD of the newest document |

### changes_since

What changed since a date. Everything published since a date, newest first. Built for scheduled agents: store the newest publishedDate you saw and pass it back next run.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `since` | string (date or ISO timestamp) | yes | Documents published on or after this moment. e.g. "2026-08-25" |
| `jurisdiction` | string | no | US_FED for federal, or a two-letter state code such as CA (US_STATE_CA also works). Omit for all jurisdictions. Unrecognized values return a tool error instead of silently widening the search. e.g. "CA" |
| `limit` | integer | no | Max results per call. Default 20. Free tier caps at 25, API key at 50. e.g. 10 |
| `offset` | integer | no | Pagination offset. Default 0. Ask again with offset advanced by your limit until offset plus the results you have reaches total. A page is a snapshot: documents published between calls shift the window, so a recurring agent should advance its date rather than page far. e.g. 20 |
- For a recurring run, advance `since` to the newest publishedDate you stored rather than paging: it stays correct as new documents arrive and never re-reads what you already have.

```bash
curl -s -X POST https://bizmoon.ai/api/mcp \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"changes_since","arguments":{"since":"(7 days ago)","jurisdiction":"US_FED","limit":1}}}'
# key tier: add -H "authorization: Bearer bm_sk_..."
```

Response fields:

| Field | Type | Description |
| --- | --- | --- |
| `results[].id` | string | Document id; pass to get_regulatory_change |
| `results[].title` | string | null | Document title |
| `results[].jurisdiction` | string | US_FED or US_STATE_XX |
| `results[].source` | string | The official register the document came from |
| `results[].agencies` | string[] | Issuing agencies |
| `results[].category` | string | null | "regulation", "funding", or null when unclassified |
| `results[].docType` | string | null | Source-specific document type |
| `results[].publishedDate` | string | null | YYYY-MM-DD publication date |
| `results[].effectiveDate` | string | null | YYYY-MM-DD effective date when stated |
| `results[].summary` | string | null | AI summary of the document |
| `results[].url` | string | null | Canonical official URL to cite |
| `total` | integer | All matches, not just this page |
| `offset` | integer | Offset this page started at |
| `limit` | integer | Effective limit after tier clamping |
| `lookbackClampedTo` | string | null | ISO timestamp the window was floored to on the free tier, else null |

### search_funding_programs

Find funding. Federal and state grants and incentive programs, with deadlines and the official program page.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `jurisdiction` | string | no | US_FED for federal, or a two-letter state code such as CA (US_STATE_CA also works). Omit for all jurisdictions. Unrecognized values return a tool error instead of silently widening the search. e.g. "CA" |
| `agency` | string | no | Case-insensitive substring match on the issuing agency or program office. e.g. "Commerce" |
| `keyword` | string | no | Case-insensitive substring matched against title, AI summary, and description. e.g. "manufacturing" |
| `from` | string (date) | no | YYYY-MM-DD lower bound on publication date (free tier floors at 90 days ago). |
| `to` | string (date) | no | YYYY-MM-DD upper bound on publication date, inclusive. |
| `limit` | integer | no | Max results per call. Default 20. Free tier caps at 25, API key at 50. e.g. 10 |
| `offset` | integer | no | Pagination offset. Default 0. Ask again with offset advanced by your limit until offset plus the results you have reaches total. A page is a snapshot: documents published between calls shift the window, so a recurring agent should advance its date rather than page far. e.g. 20 |

```bash
curl -s -X POST https://bizmoon.ai/api/mcp \
  -H "content-type: application/json" \
  -H "accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_funding_programs","arguments":{"jurisdiction":"OH","keyword":"manufactur","limit":1}}}'
# key tier: add -H "authorization: Bearer bm_sk_..."
```

Response fields:

| Field | Type | Description |
| --- | --- | --- |
| `results[].id` | string | Document id; pass to get_regulatory_change |
| `results[].title` | string | null | Document title |
| `results[].jurisdiction` | string | US_FED or US_STATE_XX |
| `results[].source` | string | The official register the document came from |
| `results[].agencies` | string[] | Issuing agencies |
| `results[].category` | string | null | "regulation", "funding", or null when unclassified |
| `results[].docType` | string | null | Source-specific document type |
| `results[].publishedDate` | string | null | YYYY-MM-DD publication date |
| `results[].effectiveDate` | string | null | YYYY-MM-DD effective date when stated |
| `results[].summary` | string | null | AI summary of the document |
| `results[].url` | string | null | Canonical official URL to cite |
| `total` | integer | All matches, not just this page |
| `offset` | integer | Offset this page started at |
| `limit` | integer | Effective limit after tier clamping |
| `lookbackClampedTo` | string | null | ISO timestamp the window was floored to on the free tier, else null |

## Organization tools (API key required)

- `search_analyses` (`severity`, `urgency`, `area`, `category`, `keyword`, `days`): The AI relevance analyses Bizmoon produced for your organization: severity, urgency, affected areas, recommended actions.
- `get_document_details` (`analysisId`): Full analysis by analysisId: key provisions, compliance deadlines, funding details, and the underlying document.
- `get_compliance_deadlines` (`days`): Compliance deadlines extracted from your analyses, with days remaining and overdue flags.
- `get_watchlist_matches` (`days`): Documents that matched your organization's watchlists recently.
- `get_funding_opportunities` (`days`): Grant and funding analyses relevant to your organization, with deadlines and funding details.

## Errors

Failures are normal tool results with `isError: true` and a JSON payload:

- Rate limited: `{ "error": "rate_limited", "retryAfterSeconds": 42, "tier": "anon", "upgrade": "https://bizmoon.ai/pricing" }`
- Tool failed: `{ "error": "tool_failed", "message": "Unknown jurisdiction \"California\". Use US_FED or a two-letter state code such as CA." }`
- Not found: `{ "error": "not_found", "id": "999999999" }`

## REST API

The organization tools are also plain JSON endpoints under https://bizmoon.ai/api/v1 (OpenAPI 3.1 spec: https://bizmoon.ai/api/v1/openapi.json), bearer-authenticated with the same bm_sk_ key. MCP is for agents; REST is for code.

| Method | Path | Returns |
| --- | --- | --- |
| POST | /analyses/search | Search your organization's policy analyses |
| GET | /analyses/{id} | One analysis in full, with the underlying document |
| GET | /deadlines | Upcoming compliance deadlines |
| GET | /funding | Funding opportunities for your organization |
| GET | /watchlist/matches | Recent watchlist matches |
| GET | /reports | Generated compliance reports |
