Business insurance quotes for Danish companies, active policies and unsigned offers for review.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
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.
The company, products and answers to price. Send the same object again in /start.
The `quoteId` of the quote the person approved.
Full name of the person signing up. Must not contain links or markup.
Email address of the person signing up; a verification code is sent here.
Random key of 32-128 letters, digits, hyphens or underscores. Retry a failed request with the same key and body.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
claude mcp add --transport http mcp https://app.plain.insurance/api/mcp
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.
| Argument | Type | Description |
|---|---|---|
| name | string | Full name of the person signing up. Must not contain links or markup. |
| string | Email address of the person signing up; a verification code is sent here. | |
| quote* | object | The company, products and answers to price. Send the same object again in /start. |
| quoteId* | string | The `quoteId` of the quote the person approved. |
| idempotencyKey | string | Random key of 32-128 letters, digits, hyphens or underscores. Retry a failed request with the same key and body. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"quote",
"quoteId"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Full name of the person signing up. Must not contain links or markup."
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 254,
"description": "Email address of the person signing up; a verification code is sent here."
},
"quote": {
"type": "object",
"required": [
"cvr",
"products",
"answers"
],
"properties": {
"cvr": {
"type": "string",
"pattern": "^[0-9]{8}$",
"description": "Danish company registration number (CVR), eight digits, e.g. 39488914."
},
"region": {
"type": "string",
"const": "dk",
"default": "dk",
"description": "Market. Only Denmark (dk) is supported. Optional; defaults to dk."
},
"answers": {
"type": "object",
"description": "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. loesoereforsikring.basement) answers only that product's question and takes precedence. Employee FTE questions are answered as `<name>.fullTime` and `<name>.partTime` head counts: integers from 0 to 9999 inclusive. When required, send both counts explicitly, including zero.",
"maxProperties": 100,
"propertyNames": {
"type": "string",
"maxLength": 300,
"minLength": 1
},
"additionalProperties": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string",
"maxLength": 256
},
"maxItems": 100
}
],
"description": "The answer's JSON type follows the catalog question's `type.value`: Text is a string; NumberWhole is an integer and NumberDecimal a number (numeric strings are accepted); Date is a YYYY-MM-DD string; Boolean is true or false; Select is one option key from `options` as a string; MultiSelect is an array of option keys."
}
},
"products": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"maxLength": 100,
"description": "Product slug from the catalog."
},
"maxItems": 20,
"minItems": 1,
"description": "The products to quote: 1 to 20 distinct slugs, including any products they require.",
"uniqueItems": true
},
"startDate": {
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
"description": "Policy start date (YYYY-MM-DD). Defaults to today. Must be between today and one year ahead."
},
"partnerCode": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{2,64}$",
"description": "Optional partner discount code, 2-64 letters, digits, hyphens or underscores. Must be active."
}
},
"description": "The company, products and answers to price. Send the same object again in /start.",
"additionalProperties": false
},
"quoteId": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "The `quoteId` of the quote the person approved."
},
"idempotencyKey": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{32,128}$",
"description": "Random key of 32-128 letters, digits, hyphens or underscores. Retry a failed request with the same key and body."
}
},
"description": "Creates unsigned offers from an approved quote; public signup also creates the company.",
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| capability* | string | From the /start result. |
| onboardingId* | string | From the /start result. |
| continuationToken | string | The continuationToken from the /verify-email result. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"onboardingId",
"capability"
],
"properties": {
"capability": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "From the /start result."
},
"onboardingId": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "From the /start result."
},
"continuationToken": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "The continuationToken from the /verify-email result."
}
},
"description": "Requests a link for the person to review the offers and set up payment on Plain.",
"additionalProperties": false
}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.
No arguments.
{
"type": "object",
"properties": {}
}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.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {},
"additionalProperties": false
}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, but their questions remain listed so answers can still be collected. 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.
| Argument | Type | Description |
|---|---|---|
| cvr | string | Danish company registration number (CVR), eight digits, e.g. 39488914. |
| region | string | Market. Only Denmark (dk) is supported. Optional; defaults to dk. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cvr": {
"type": "string",
"pattern": "^[0-9]{8}$",
"description": "Danish company registration number (CVR), eight digits, e.g. 39488914."
},
"region": {
"type": "string",
"const": "dk",
"default": "dk",
"description": "Market. Only Denmark (dk) is supported. Optional; defaults to dk."
}
},
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| cvr* | string | Danish company registration number (CVR), eight digits, e.g. 39488914. |
| region | string |
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.
| Argument | Type | Description |
|---|---|---|
| companyId* | string |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"companyId"
],
"properties": {
"companyId": {
"type": "string",
"maxLength": 256,
"minLength": 1
}
},
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| code* | string | The eight-digit code from the verification email. Valid for 15 minutes, five attempts. |
| capability* | string | From the /start result. |
| onboardingId* | string | From the /start result. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"onboardingId",
"capability",
"code"
],
"properties": {
"code": {
"type": "string",
"pattern": "^[0-9]{8}$",
"description": "The eight-digit code from the verification email. Valid for 15 minutes, five attempts."
},
"capability": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "From the /start result."
},
"onboardingId": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "From the /start result."
}
},
"description": "Confirms the signup email with the emailed code.",
"additionalProperties": false
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 3, 2026.
| Market. Only Denmark (dk) is supported. Optional; defaults to dk. |
| answers* | object | 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. loesoereforsikring.basement) answers only that product's question and takes precedence. Employee FTE questions are answered as `<name>.fullTime` and `<name>.partTime` head counts: integers from 0 to 9999 inclusive. When required, send both counts explicitly, including zero. |
| products* | array | The products to quote: 1 to 20 distinct slugs, including any products they require. |
| startDate | string | Policy start date (YYYY-MM-DD). Defaults to today. Must be between today and one year ahead. |
| partnerCode | string | Optional partner discount code, 2-64 letters, digits, hyphens or underscores. Must be active. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"cvr",
"products",
"answers"
],
"properties": {
"cvr": {
"type": "string",
"pattern": "^[0-9]{8}$",
"description": "Danish company registration number (CVR), eight digits, e.g. 39488914."
},
"region": {
"type": "string",
"const": "dk",
"default": "dk",
"description": "Market. Only Denmark (dk) is supported. Optional; defaults to dk."
},
"answers": {
"type": "object",
"description": "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. loesoereforsikring.basement) answers only that product's question and takes precedence. Employee FTE questions are answered as `<name>.fullTime` and `<name>.partTime` head counts: integers from 0 to 9999 inclusive. When required, send both counts explicitly, including zero.",
"maxProperties": 100,
"propertyNames": {
"type": "string",
"maxLength": 300,
"minLength": 1
},
"additionalProperties": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string",
"maxLength": 256
},
"maxItems": 100
}
],
"description": "The answer's JSON type follows the catalog question's `type.value`: Text is a string; NumberWhole is an integer and NumberDecimal a number (numeric strings are accepted); Date is a YYYY-MM-DD string; Boolean is true or false; Select is one option key from `options` as a string; MultiSelect is an array of option keys."
}
},
"products": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
"maxLength": 100,
"description": "Product slug from the catalog."
},
"maxItems": 20,
"minItems": 1,
"description": "The products to quote: 1 to 20 distinct slugs, including any products they require.",
"uniqueItems": true
},
"startDate": {
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
"description": "Policy start date (YYYY-MM-DD). Defaults to today. Must be between today and one year ahead."
},
"partnerCode": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{2,64}$",
"description": "Optional partner discount code, 2-64 letters, digits, hyphens or underscores. Must be active."
}
},
"description": "The company, products and answers to price. Send the same object again in /start.",
"additionalProperties": false
}