ClaimPilot — подача страхового случая

← На главную

ClaimPilot — MCP Server

ClaimPilot exposes its claim intake and triage as a Model Context Protocol (MCP) server, so an external AI client (Claude Desktop, Claude Code, the MCP Inspector, or any MCP-capable tool) can create claims, poll their status, read the adjuster-facing claim card, and browse the claim list — the same operations a human gets from the web form and Filament admin.

This page is also published as a rendered web page on the live site at https://strahovanie.up-money.ru/docs/mcp (served by App\Http\Controllers\DocsController from the bundled copy at app/resources/docs/mcp.md).

MCP is model-agnostic. The client is the host application / agent framework that speaks MCP — not the LLM itself. An agent built on any model — including Russian models such as GigaChat or YandexGPT — can connect to this server, provided its host/framework implements MCP. Named ready-made MCP clients today are tools like Claude Desktop, Claude Code, the MCP Inspector, and Cursor; GigaChat/YandexGPT do not ship a native MCP client, but an agent you build around them can act as one.

This is a server, not an agent: ClaimPilot publishes tools; the client is the third-party AI tool. ClaimPilot itself never calls out to an LLM on the client's behalf. (The triage pipeline does use LLMs internally — see pipeline.md — but that runs server-side and is fully audited regardless of how the claim was created.)

MCP is self-describing: the client learns everything from the server's instructions, tool descriptions, and input schemas at connect time. The shapes below mirror the code exactly (App\Mcp\*); the shared formatter App\Mcp\Support\ClaimPresenter guarantees code and docs do not drift.

Built on the official laravel/mcp package. Server class: App\Mcp\Servers\ClaimPilotServer.

Tools

Tool Annotation Purpose
submit_claim state-changing (not read-only) Create a claim and start the triage pipeline.
get_claim_status read-only Status + completed pipeline stages for one claim.
get_claim_card read-only Full adjuster-facing claim card.
list_claims read-only List claims, with Filament-style filters.
mark_reply_sent destructive, idempotent Stamp the reply draft as sent.

submit_claim (state-changing)

Creates a claim with status = received, channel = mcp, and dispatches the same App\Services\ClaimPipeline chain the web form uses. Returns immediately with the claim uuid — processing is asynchronous (see Async model). Validation rules are the same as the web form (ClaimIntakeController::textFieldRules()), not a copy.

Input (all required):

Param Type Notes
claimant_name string max 255
claimant_contact string phone or email, max 255
incident_description string 10–10000 chars, free text (any language)
incident_date string YYYY-MM-DD, today or earlier

Returns { uuid, status, message }status is "received"; message tells the client to poll get_claim_status.

No file upload. MCP tool arguments are JSON; photos and document scans are binary. For phase 1, submit_claim is text-only. Damage photos and policy scans still go through the web form, which feeds the vision stages. A text-only claim runs the full pipeline — the photo/document stages simply have nothing to analyze, and synthesis works from the narrative alone (often landing in needs_info). Binary intake over MCP is a deliberate phase-2 item.

get_claim_status (read-only)

Input: uuid (string, required) — public claim reference returned by submit_claim.

Returns:

{
  "uuid": "…",
  "status": "received|processing|triaged|needs_info|failed",
  "stages_completed": ["vision_photos", "vision_documents", "synthesis", "notify"],
  "stages_pending": [],
  "is_finished": true
}

is_finished is true once status is triaged, needs_info, or failed. If status stays received with nothing in stages_completed, the queue worker is probably not running.

get_claim_card (read-only)

Input: uuid (string, required).

Returns:

{
  "uuid": "…",
  "status": "triaged",
  "claimant_name": "…",
  "claimant_contact": "…",
  "incident_type": "auto_accident|property_water|property_fire|theft|health|other|null",
  "severity": "minor|moderate|major|total_loss|null",
  "severity_confidence": 0.82,
  "estimated_amount_min": 40000,
  "estimated_amount_max": 120000,
  "ai_summary": "…",
  "client_reply_draft": "…",
  "red_flags": [{ "code": "…", "severity": "low|medium|high", "explanation": "…" }],
  "missing_documents": ["…"]
}

Amounts are in RUB and may be null (the model estimates conservatively). incident_type, severity, and the amounts are null until synthesis has run.

list_claims (read-only)

All inputs optional; filters combine with AND; newest first.

Param Type Allowed values
status string received, processing, triaged, needs_info, failed
incident_type string auto_accident, property_water, property_fire, theft, health, other
severity string minor, moderate, major, total_loss
limit integer 1–100, default 25

Returns a JSON array:

[{ "uuid": "…", "claimant_name": "…", "incident_type": "…", "severity": "…",
   "status": "…", "red_flag_count": 1, "created_at": "2026-06-18T16:00:00+00:00" }]

mark_reply_sent (destructive, idempotent)

Input: uuid (string, required).

Sets client_reply_sent_at to now if not already set (same as the Filament "mark as sent" button). Idempotent: calling it again keeps the original timestamp.

Returns { uuid, client_reply_sent_at }client_reply_sent_at is ISO-8601.

Resources

Read-only context the client can pull without invoking a tool:

Name URI MIME Content
claim_card claimpilot://claims/{uuid} application/json Same payload as get_claim_card.

The resource and the get_claim_card tool share ClaimPresenter::card(), so they never drift. (The ai_calls audit log is intentionally not exposed over MCP — it can contain raw provider responses; it stays admin-only in Filament.)

Prompts

Name Arguments Purpose
review_claim uuid (required) An adjuster-style review prompt: loads the claim card and asks the model to assess narrative/evidence consistency, validate the red flags, judge the RUB estimate, and critique the Russian reply draft, ending with an approve / request-info / escalate recommendation.

Async model

submit_claim returns as soon as the claim row is created and the chain is dispatched — it does not wait for triage. The pipeline (photos → documents → synthesis → notify) runs in the queue. Clients should poll get_claim_status until is_finished, then read get_claim_card.

A queue worker must be running, or the claim stays in received forever:

php artisan queue:work --tries=1 --timeout=900

Errors

Tools return a clear, actionable error (not a generic 500) the model can act on:

Authentication

How to connect

MCP Inspector (quickest check)

cd app
php artisan mcp:inspector claimpilot

Lists all tools/resources/prompts and lets you call them interactively.

Claude Code

From the app directory, register the local server (stdio):

claude mcp add claimpilot -- php /absolute/path/to/app/artisan mcp:start claimpilot

…or commit a project-scoped .mcp.json:

{
  "mcpServers": {
    "claimpilot": {
      "command": "php",
      "args": ["artisan", "mcp:start", "claimpilot"]
    }
  }
}

Claude Desktop

Add to claude_desktop_config.json (use absolute paths — Desktop does not inherit your shell):

{
  "mcpServers": {
    "claimpilot": {
      "command": "php",
      "args": ["/absolute/path/to/app/artisan", "mcp:start", "claimpilot"]
    }
  }
}

A queue worker still has to be running separately for submitted claims to progress past received.