# Plain Insurance (remote · app.plain.insurance)

Business insurance quotes for Danish companies, active policies and unsigned offers for review.

- Trust score: 74/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `app.plain.insurance`: 74/100 (this document), [markdown](https://verifymcp.io/servers/insurance-plain-mcp/api-mcp.md), [page](https://verifymcp.io/servers/insurance-plain-mcp/api-mcp)

## Channel facts

- Endpoint: `https://app.plain.insurance/api/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `1.0.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Endpoint Security**: 83/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - No authorisation is required to call this server. Nothing on it is marked destructive, but we can't show that an anonymous caller can only read: full credit needs the server to list at least one tool and every tool to be verifiably read-only. We use a best-effort check of tool names and descriptions to tell read-only tools from tools that change things, so some genuinely read-only tools may not get full credit. Names that start with a read verb (get, list, read, search and similar) and accurate readOnlyHint annotations help. Meet that to earn full credit, or require authorisation.
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC is configured correctly; the domain's records validate against the full chain to the root.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 66/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 1714 tokens (~214/item across 8 items; 8 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 7/100
  - Stability observed for 2 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 99/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 95% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 8 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 8 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

## Install

### How do I install the Plain Insurance MCP server?

Plain Insurance is a hosted endpoint at https://app.plain.insurance/api/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add --transport http insurance-plain-mcp 'https://app.plain.insurance/api/mcp'
```

### Cursor

```json
{
  "mcpServers": {
    "insurance-plain-mcp": {
      "url": "https://app.plain.insurance/api/mcp"
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "insurance-plain-mcp": {
      "type": "http",
      "url": "https://app.plain.insurance/api/mcp"
    }
  }
}
```

### Codex

```toml
[mcp_servers.insurance-plain-mcp]
url = "https://app.plain.insurance/api/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "insurance-plain-mcp": {
      "type": "remote",
      "url": "https://app.plain.insurance/api/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add insurance-plain-mcp --url 'https://app.plain.insurance/api/mcp' --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  insurance-plain-mcp:
    url: "https://app.plain.insurance/api/mcp"
```

### Netclaw

```json
{
  "McpServers": {
    "insurance-plain-mcp": {
      "Transport": "http",
      "Url": "https://app.plain.insurance/api/mcp"
    }
  }
}
```

### Vellum

```bash
assistant mcp add insurance-plain-mcp -t streamable-http -u 'https://app.plain.insurance/api/mcp'
```

### Other

```json
{
  "mcpServers": {
    "insurance-plain-mcp": {
      "type": "http",
      "url": "https://app.plain.insurance/api/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-05 (score 74, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-11-04 (score 73, 0)

- [security] Tool “list_onboarding_catalog” rewrote its description, which is the text the model reads
- [functional improvement] Stability: unverified → 0.03

### 2026-11-03 (score 73)

First indexed and scored.

## MCP tools (8)

### `list_onboarding_catalog` (~267 tokens)

List products and questions

Lists the insurance products a Danish company can be offered and the questions to answer before quoting. Pass the company's CVR to resolve industry-specific questions and options. Use product slugs in `products` and question names as keys in `answers`. Employee FTE questions are listed as two whole-number questions, `<name>.fullTime` and `<name>.partTime`, each from 0 to 9999 inclusive; when required, send both counts, including zero. Numeric questions publish min/max limits when configured. Products with automaticQuote:false need manual review and list no questions. A product's requiredProducts must be selected with it; its questions include theirs. MultiSelect answers may be left out and default to an empty list. Enum fields use {value, label: {da, en}}; use value for logic and label for display. Read-only: nothing is created. Works without signing in. For an existing customer, call list_companies first and select the company with set_company_context. Use its CVR when collecting questions and quoting.

Input parameters:

- `cvr` (string): Danish company registration number (CVR), eight digits, e.g. 39488914.
- `region` (string): Market. Only Denmark (dk) is supported. Optional; defaults to dk.

Output parameters:

- `errors` (array): Products that are listed but cannot currently be quoted, e.g. pricing_configuration.
- `productDependencies` (array): Products that require another product.
- `products` (array): Products that can be offered.

### `quote_onboarding_products` (~604 tokens)

Quote products

Calculates indicative prices for up to twenty products for the company with this CVR, from one flat `answers` object. A plain key answers a question for the company and for every selected product that asks it; `<product>.<name>` answers one product's question. Stored answers and company discounts are not reused; supply required answers explicitly. An optional partnerCode applies that partner's discount. Enum fields use {value, label: {da, en}}. Each product has a status.value: only `quoted` products have a price; `contactPlain` products need an individual offer from Plain and `unavailable` ones cannot be offered (see `issue`). Prices are in DKK (major units) per billingFrequency.value period, with annualPrice for comparison and totals across products. State prices with each quote's `display` text in the customer's language, and always show the `disclaimer`. When pricePerEmployee is true, the price is per employee: say so using the quote's notice, as the customer selects the covered employees on Plain. Unknown answer keys are ignored and reported in warnings; required answers are never inferred. Nothing is bound, created or charged. Works without signing in, as a public new-company quote. Quotes for an existing customer must use the selected, authorized company's CVR. Active products return status.value alreadyInsured with no new-offer price and are excluded from totals and creation; held prerequisites do not need to be selected again. Check list_companies.canCreateOffers before promising to create offers. Quoting itself only needs policies:read. For existing companies, use get_onboarding_payment_link after creating offers for authenticated review; continueUrl is the public new-company signup page and does not apply private policy exclusions.

Input parameters:

- `answers` (object, required): Every answer in one object, keyed by the catalog question `name`. A plain name answers that question for the company and for every selected product that asks it; `<product>.<name>` (e.g. loesoerefors…
- `cvr` (string, required): Danish company registration number (CVR), eight digits, e.g. 39488914.
- `partnerCode` (string): Optional partner discount code, 2-64 letters, digits, hyphens or underscores. Must be active.
- `products` (array, required): The products to quote: 1 to 20 distinct slugs, including any products they require.
- `region` (string): Market. Only Denmark (dk) is supported. Optional; defaults to dk.
- `startDate` (string): Policy start date (YYYY-MM-DD). Defaults to today. Must be between today and one year ahead.

Output parameters:

- `continueUrl` (string): Where the customer reviews this quote on Plain and continues to sign up. Opening it creates nothing.
- `disclaimer` (object): Show with the prices: they are indicative, and nothing binds until the customer signs on Plain.
- `expiresAt`: Until when quoteId can be used for /start, unless prices change first; then request a new quote.
- `quoteId` (string|null): Identifies these prices; pass it as `quoteId` to /start with the exact original quote request. Only quoted products become offers. Null when no product is quoted.
- `quotes` (array): One quote per selected product, in request order.
- `startDate` (string): The insurance start date the prices apply to; today when the request has none.
- `totals`: Totals of the quoted products; null when no product is included.
- `warnings` (array): Non-fatal problems with ignored answers. Omitted when there are none.

### `create_onboarding` (~350 tokens)

Create unsigned insurance offers

Recalculates an approved quote and creates offered, unsigned policies, ready for the customer to review and sign on Plain. Send the exact quote request again with its quoteId before expiresAt; offers are created for the products with status.value quoted only. Active insurance is rechecked before creation. Retry a failed request on the same connection with the same idempotency key and body. No insurance is accepted, activated or charged. When state.value is awaiting_verification, ask the person for the emailed code. Creates offers for the selected, authorized existing company without recreating it, or onboards a new company. For an existing company, select it with set_company_context and use its CVR; administrator access is required. Uses the connected user's identity: omit email and name. Requires signing in with onboarding:write consent; calling it prompts sign-in when needed. Check list_companies first. idempotencyKey is required. If the connected user's email is confirmed, no email code is needed. Do not reuse a retry key across reconnections; obtain a fresh quote after expiry or insurance changes.

Input parameters:

- `email` (string): Email address of the person signing up; a verification code is sent here.
- `idempotencyKey` (string): Random key of 32-128 letters, digits, hyphens or underscores. Retry a failed request with the same key and body.
- `name` (string): Full name of the person signing up. Must not contain links or markup.
- `quote` (object, required): The company, products and answers to price. Send the same object again in /start.
- `quoteId` (string, required): The `quoteId` of the quote the person approved.

Output parameters:

- `capability` (string): Secret proof of this signup. Keep it private and send it with onboardingId.
- `continuationToken`: Secret token for /payment-handoff, valid for 15 minutes after verification.
- `onboardingId` (string): Identifies this signup.
- `policyIds` (array): IDs of the offered policies, once created.
- `state` (object): awaiting_verification: ask the person for the emailed code; email_confirmed: call /verify-email again to finish; verified: offers are ready.

### `verify_onboarding_email` (~98 tokens)

Confirm the signup email

Confirms the signup email with the eight-digit code the person received. Codes expire after 15 minutes and allow five attempts. Keep the returned capability and continuationToken private. Does not activate insurance.

Input parameters:

- `capability` (string, required): From the /start result.
- `code` (string, required): The eight-digit code from the verification email. Valid for 15 minutes, five attempts.
- `onboardingId` (string, required): From the /start result.

Output parameters:

- `capability` (string): Secret proof of this signup. Keep it private and send it with onboardingId.
- `continuationToken`: Secret token for /payment-handoff, valid for 15 minutes after verification.
- `onboardingId` (string): Identifies this signup.
- `policyIds` (array): IDs of the offered policies, once created.
- `state` (object): awaiting_verification: ask the person for the emailed code; email_confirmed: call /verify-email again to finish; verified: offers are ready.

### `get_onboarding_payment_link` (~120 tokens)

Get the link to sign on Plain

Returns a one-time link, valid for five minutes, where the person reviews the offers and sets up payment on Plain. The person must open and confirm it. Setting up payment does not accept the offers or charge money. Use the same authorized connection that created the offers and keep the target company selected; continuationToken may then be omitted.

Input parameters:

- `capability` (string, required): From the /start result.
- `continuationToken` (string): The continuationToken from the /verify-email result.
- `onboardingId` (string, required): From the /start result.

Output parameters:

- `expiresAt` (string): When the link expires (ISO 8601 date-time).
- `url` (string): One-time link to open in the person's browser. Valid for five minutes.

### `list_companies` (~97 tokens)

List permitted companies

Requires signing in to Plain; calling it prompts sign-in when needed. Lists companies explicitly approved for this Plain connection that you still have access to, and marks the active company. Reports granted scopes and whether the connection can create unsigned offers. Check this before quoting for an existing company or offering to create offers. Reconnect requesting onboarding:write to approve offer creation, or reconnect to approve additional companies. Company permissions are checked separately when creating offers.

Output parameters:

- `canCreateOffers` (boolean)
- `companies` (array)
- `scopes` (array)

### `set_company_context` (~65 tokens)

Set active company

Requires signing in to Plain. Changes the active Plain company for subsequent tool calls on this connection. Use an exact companyId from list_companies. All chats sharing this authorization share the selection. Already-running requests may finish for the previous company.

Input parameters:

- `companyId` (string, required)

Output parameters:

- `companyId` (string)
- `companyName` (string)
- `isCurrent` (boolean)

### `list_active_policies` (~113 tokens)

List active policies

Requires signing in to Plain; calling it prompts sign-in when needed. Lists the active insurance policies for the currently selected Plain company on this connection, including product, carrier, dates, price and billing details. Amounts are in major currency units (e.g. DKK). totalPrice is the total price the customer pays; it is legally required to be split into the insurance premium and fees (statutory fees and taxes). Whenever you mention a price, state the total and its split into premium and fees.

Output parameters:

- `policies` (array)

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/insurance-plain-mcp/api-mcp#diagnostics

## Score history

- 2026-11-05: 74
- 2026-11-04: 73
- 2026-11-03: 73

## Common questions

### What is the Plain Insurance MCP server?

Plain Insurance is an MCP server listed in the public MCP registry as insurance.plain/mcp. Business insurance quotes for Danish companies, active policies and unsigned offers for review. This page covers its hosted endpoint (https://app.plain.insurance/api/mcp).

### Is the Plain Insurance MCP server safe to use?

Plain Insurance scores 74 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Plain Insurance MCP server expose?

Plain Insurance exposes 8 tools: list_onboarding_catalog, quote_onboarding_products, create_onboarding, verify_onboarding_email, get_onboarding_payment_link, and 3 more. Their descriptions and schemas cost roughly 1,714 tokens of context every time the server is loaded.

### Does the Plain Insurance MCP server require authentication?

No. We connected to Plain Insurance without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.

### Is the Plain Insurance MCP server still maintained?

Plain Insurance is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What did VerifyMCP test on the Plain Insurance MCP server?

VerifyMCP ran 13 checks on Plain Insurance, covering TLS certificate, Authorization, HTTPS, HSTS header and 9 more. Supply Chain Security and Provenance & Transparency do not apply to a hosted endpoint, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.

## Links

- Remote endpoint: https://app.plain.insurance/api/mcp
- Website: https://plain.insurance/en/
- Changelog RSS feed: https://verifymcp.io/servers/insurance-plain-mcp/api-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/insurance-plain-mcp/api-mcp/changelog.json
- Trust report (JSON): https://verifymcp.io/servers/insurance-plain-mcp/api-mcp.json
- HTML version of this page: https://verifymcp.io/servers/insurance-plain-mcp/api-mcp
