git:20260728.b7e78fc to git:20260806.ad583a2

114 added, 50 removed. Audit A to A.

---
name: "IRONSCALES API Patterns"
description: >
Ironscales MCP fundamentals: API-key plus company-ID header authentication and
- the per-tenant scoping that follows from it, the tool surface across incidents,
- statistics, and allowlist management, offset/limit pagination, rate-limit
- behavior, and the HTTP error-code table.
+ the per-tenant scoping that follows from it, the nine tools this server
+ registers and what each one actually changes, offset/limit pagination without
+ a total count, rate-limit behavior, and how API failures surface to the model.
when_to_use: >-
When authenticating to the Ironscales MCP server, paging through its results, or
diagnosing an API error. Use when: ironscales, ironscales api,
ironscales mcp, ironscales tools, ironscales authentication, ironscales pagination, ironscales
error, or ironscales connection.
---
# Ironscales MCP Tools & API Patterns
## Overview
- The Ironscales MCP server provides AI tool integration with the Ironscales anti-phishing platform. It exposes tools for listing and triaging phishing incidents, classifying emails, taking remediation actions, managing sender allowlists, and accessing company-wide phishing statistics. Authentication uses an API key and company ID passed as request headers.
+ The Ironscales MCP server provides AI tool integration with the Ironscales
+ anti-phishing platform. It exposes tools for listing and investigating
+ phishing incidents, asking Ironscales' AI to classify a raw email, taking
+ remediation actions against delivered mail, managing sender allowlists, and
+ reading company-wide phishing statistics. Authentication uses an API key and
+ company ID passed as request headers.
## Connection & Authentication
### API Key + Company ID
- Ironscales uses a static API key combined with a company ID for authentication. The MCP Gateway injects these via headers:
+ Ironscales uses a static API key combined with a company ID for
+ authentication. The MCP Gateway injects these via headers on every upstream
+ call to `https://appapi.ironscales.com`:
| Header | Description |
|--------|-------------|
- | `X-Ironscales-API-Key` | Your Ironscales API key |
- | `X-Ironscales-Company-ID` | Your Ironscales company (tenant) ID |
+ | `X-IronScales-API-Key` | Your Ironscales API key |
+ | `X-IronScales-Company-ID` | Your Ironscales company (tenant) ID |
Generate credentials at: **Ironscales Platform > Settings > API**
**Environment Variables (self-hosted):**
```bash
export IRONSCALES_API_KEY="your-api-key"
export IRONSCALES_COMPANY_ID="your-company-id"
```
- The Company ID scopes all API requests to a specific tenant. MSPs managing multiple clients require a separate API key and company ID per client.
+ The Company ID scopes all API requests to a specific tenant. MSPs managing
+ multiple clients require a separate API key and company ID per client. There
+ is no cross-tenant query.
+ Requests carry a 30-second timeout.
+
## Available MCP Tools
+ This server registers nine tools and no others. Anything not in these tables
+ does not exist.
+
+ ### Navigation
+
+ The server uses progressive disclosure: it advertises the navigation tools
+ first, and the domain tools become visible once you navigate.
+
+ | Tool | Description |
+ |------|-------------|
+ | `ironscales_navigate` | Move to a domain: `incidents`, `email`, `remediation`, `stats`, `allowlist` |
+ | `ironscales_status` | Check API connection status and list available domains |
+ | `ironscales_back` | Return to the domain navigation menu |
+
### Incidents
| Tool | Description |
|------|-------------|
- | `ironscales_list_incidents` | List phishing incidents with status and type filters |
- | `ironscales_get_incident` | Get detailed information for a specific incident |
- | `ironscales_classify_email` | Classify an incident's email as phishing, spam, or legitimate |
- | `ironscales_remediate_incident` | Take a remediation action on a confirmed incident |
+ | `ironscales_incidents_list` | List phishing incidents, filtered by `status` and/or `severity` |
+ | `ironscales_incidents_get` | Get one incident in full by `incident_id` |
+ ### Email Classification
+
+ | Tool | Description |
+ |------|-------------|
+ | `ironscales_email_classify` | Submit a **raw email** to Ironscales AI and get a verdict back. Stateless — see below |
+
+ ### Remediation
+
+ | Tool | Description |
+ |------|-------------|
+ | `ironscales_remediation_act` | Take one of five remediation actions against an incident's mail |
+
### Statistics & Reporting
| Tool | Description |
|------|-------------|
- | `ironscales_get_company_stats` | Get company-wide phishing statistics and dashboard metrics |
+ | `ironscales_stats_company` | Company-wide phishing statistics for a `period` of `7d`/`30d`/`90d`/`1y` |
### Allowlist Management
| Tool | Description |
|------|-------------|
- | `ironscales_manage_allowlist` | Add, remove, or list sender allowlist entries |
+ | `ironscales_allowlist_manage` | `add`, `remove`, or `list` allowlist entries typed `email`/`domain`/`ip` |
+ ### The one tool whose name misleads
+
+ `ironscales_email_classify` does not classify an incident. It POSTs a raw
+ email you assemble (`sender` required; subject, bodies, headers, URLs, and
+ attachment metadata optional) to `/api/v1/email/classify` and returns a
+ verdict. It takes no incident ID, writes nothing, and changes no state. The
+ only tool on this server that changes incident state is
+ `ironscales_remediation_act`.
+
## Pagination
- The Ironscales API uses offset-based pagination:
+ `ironscales_incidents_list` uses offset-based pagination.
- - Pass `offset` and `limit` parameters to paginate results
- - Default `limit` is typically 50 records per page
- - The response includes `total` — the total number of matching records
+ - Pass `offset` (default `0`) and `limit` (default `50`, max `100`).
+ - **The tool response does not carry a total count.** The server unwraps the
+ vendor's list and returns only the records plus the offset and limit you
+ asked for.
- **Example response with pagination:**
+ **Example tool response shape:**
```json
{
- "incidents": [...],
- "total": 148,
+ "incidents": [ ... ],
"offset": 0,
"limit": 50
}
```
**Pagination workflow:**
- 1. Call with `offset=0` and `limit=50`
- 2. If `total > offset + limit`, call again with `offset=50`
- 3. Continue incrementing offset by `limit` until all records are retrieved
+ 1. Call with `offset=0` and `limit=50`.
+ 2. If the returned `incidents` array is exactly `limit` long, there may be
+ more — call again with `offset=50`.
+ 3. Stop when a page returns fewer than `limit` records. Do not try to compute
+ the number of pages up front; you have no total to compute it from.
+ Narrow with `status` and `severity` before paging. Those two are the only
+ filters `ironscales_incidents_list` accepts — there is no `source`
+ parameter, so a user-reported-versus-AI-detected split has to be partitioned
+ client-side from the records you get back.
+
## Rate Limiting
Ironscales enforces per-endpoint rate limits.
- - HTTP 429 responses indicate rate limiting
- - Use exponential backoff before retrying
- - Use status and date filters to limit result volumes
- - Avoid unnecessary polling
+ - HTTP 429 responses indicate rate limiting.
+ - Use exponential backoff before retrying.
+ - Use `status` and `severity` filters to limit result volumes.
+ - Avoid unnecessary polling.
## Error Handling
- ### Common Error Codes
+ Upstream HTTP failures do not reach you as a JSON error body. The server
+ raises them as tool errors whose message is prefixed by category, with the
+ vendor's `message` field appended when present.
- | Code | Meaning | Resolution |
- |------|---------|------------|
- | 400 | Bad Request | Check required parameters and classification values |
- | 401 | Unauthorized | Verify API key and company ID |
- | 403 | Forbidden | API key lacks permissions for this operation |
- | 404 | Not Found | Incident ID or resource does not exist |
- | 429 | Rate Limited | Wait and retry with exponential backoff |
- | 500 | Server Error | Retry; contact Ironscales support if persistent |
+ | Status | Message you will see | Resolution |
+ |--------|----------------------|------------|
+ | 400 | `Ironscales API error (HTTP 400): …` | Check required parameters and enum values — `status`, `severity`, `action`, `operation`, `entry_type`, `period` |
+ | 401 | `Ironscales authentication failed: …` | Verify API key and company ID |
+ | 403 | `Ironscales access forbidden: …` | API key lacks permissions for this operation |
+ | 404 | `Ironscales resource not found: …` | Incident ID or resource does not exist |
+ | 429 | `Ironscales rate limit exceeded: …` | Wait and retry with exponential backoff |
+ | 5xx | `Ironscales API error (HTTP 5xx): …` | Retry; contact Ironscales support if persistent |
- ### Error Response Format
+ Two failures are raised by the server itself before any HTTP call:
- ```json
- {
- "error": "INVALID_API_KEY",
- "message": "The provided API key is invalid.",
- "code": 401
- }
- ```
+ - `Ironscales credentials not configured…` — neither gateway-scoped nor
+ environment credentials were available.
+ - `entry_type and value are required for add/remove operations.` —
+ `ironscales_allowlist_manage` was called with `operation=add` or
+ `operation=remove` and no entry.
+ A 400 that reads like a rejected enum is usually a value that does not
+ exist. There is no `resolved` status, no `source` filter, no `block_domain`
+ or `allowlist_sender` remediation action.
+
## Best Practices
- - Use status filters (`open`, `closed`) to focus on actionable incidents
- - Combine `offset` pagination with status filters to efficiently process large incident backlogs
- - Verify incident status before attempting classification — closed incidents cannot be reclassified
- - Check `ironscales_get_company_stats` weekly to track phishing trends and identify anomalies
+ - Filter with `status` and `severity` rather than pulling the whole queue;
+ they are the only server-side filters available.
+ - Page until a short page rather than until a total — no total is returned.
+ - Verify incident status with `ironscales_incidents_list` before remediating.
+ A closed incident rejects remediation with an error that reads like a
+ permissions failure.
+ - Treat `ironscales_incidents_get` output as vendor pass-through. Only `id`,
+ `subject`, `status`, `severity`, `sender`, `created_at`, `recipients[]`,
+ `recipient_count`, and `threat_indicators[]` are read and normalised by
+ this server; verify anything else is present before branching on it.
+ - Check `ironscales_stats_company` weekly to track phishing trends. Its
+ payload is vendor pass-through too — inspect the response before writing
+ logic against a field name.
## Related Skills
- - [incidents](../incidents/SKILL.md) - Incident lifecycle, classification, and remediation
+ - [incidents](../incidents/SKILL.md) - Incident lifecycle, remediation, and allowlist management