insurance-mcp-poc

insurance-mcp-poc

MCP server that exposes life-insurance back-office tools (policy document search, application status, product/underwriting rules) to LLM agents. Enables agents to retrieve policy documents, check application status, and evaluate underwriting rules via hybrid search and rule lookup.

Category
访问服务器

README

insurance-mcp-poc

A Model Context Protocol server that exposes a life-insurance back office — policy documents, in-flight applications, and product/underwriting rules — as tools an LLM agent can call.

The point of the POC: an agent shouldn't need a bespoke integration per assistant. Implement the domain once as an MCP server, and any MCP-capable client (Claude Code, Microsoft Foundry agents, an internal chat surface) gets the same three tools with the same contracts.

All data in this repository is synthetic. The schema, products, rules, and documents were invented for this demo and are not derived from any production system.

Built alongside Microsoft Applied Skills: Integrate model context protocol tools with agents in Microsoft Foundry. That assessment covers the client side — attaching an MCP tool to a Foundry agent and validating its calls. This repository is the other half: the server those tools come from.

Quickstart

Requires Docker and Node 20+.

npm install
npm run setup     # starts Postgres+pgvector, seeds the corpus, runs the smoke test

npm run setup is the whole demo: it stands up the database, embeds and inserts 12 documents, then connects to the MCP server as a real MCP client and exercises every tool. Expected tail:

Connected. Server exposes 3 tools:
  - search_policy_documents: Search policy documents
  - get_application_status: Get application status
  - lookup_product_rules: Look up product rules
...
All tool calls completed.

Then npm run demo walks the chained flow an agent actually performs — see below. Tear down with npm run db:down.

The tools

Tool What it does
search_policy_documents Vector search over contracts, riders, underwriting guidelines, and procedures. Optional product_code filter. Returns ranked excerpts with doc_id so answers can cite a source.
get_application_status Looks up an application by number; returns status, the step it is blocked on, assigned underwriter, and the full event timeline.
lookup_product_rules Returns issue limits and underwriting rules for a product. Given applicant_age / face_amount / state, also evaluates hard eligibility and reports which dimensions failed.

Try, once connected: "Rowan Kessler's application is stuck — what's it waiting on, and what does the guideline actually say about that requirement?" No single tool answers that. The agent chains all three, and npm run demo shows the same chain step by step:

[1] get_application_status("APP-100242")
      -> Rowan Kessler, age 61, SecureTerm 20-Year
      -> status=pending_underwriting  blocked on: awaiting_paramedical
      -> rules fired: TRM20-AGE-01, TRM20-FACE-01
[2] lookup_product_rules("TRM-20", age=61, face=1500000)
      -> TRM20-AGE-01 [require_evidence]: Applicants over 60 require a paramedical exam…
      -> TRM20-FACE-01 [refer]: Face amounts above $1,000,000 are referred…
[3] search_policy_documents("when is a paramedical examination required")
      -> GUIDE-UW-01  (rrf 0.03154, vector rank 6, text rank 1)

Note step 3: the right document ranked 6th by vector similarity but 1st by full-text. Fusing the two rankings is what surfaces it.

How retrieval works

Hybrid search, fused with Reciprocal Rank Fusion (score = Σ 1/(60 + rank_i)).

Two things forced this design, both found by testing rather than assumed:

  • Weighted score blending doesn't work here. Cosine similarity lands around 0.1–0.4 while ts_rank_cd returns values an order of magnitude smaller, so any fixed weighting lets whichever metric happens to be larger dominate. RRF combines ranks, which are scale-free.
  • websearch_to_tsquery ANDs every term, so a full-sentence question matches zero documents and the hybrid silently degrades to vector-only. The operators are rewritten to OR, making the lexical side rank by how many query terms a document contains.

Each result reports vector_rank and text_rank alongside the fused score, so it stays visible which half did the work — and a text_rank of null means that document matched no query term.

Connecting it to Claude Code

claude mcp add insurance --  node /absolute/path/to/insurance-mcp-poc/src/index.js

Or add to .mcp.json:

{
  "mcpServers": {
    "insurance": {
      "command": "node",
      "args": ["/absolute/path/to/insurance-mcp-poc/src/index.js"],
      "env": { "DATABASE_URL": "postgres://insurance:insurance@localhost:55432/insurance" }
    }
  }
}

How it fits together

MCP client (Claude Code / Foundry agent)
        │  stdio, JSON-RPC
        ▼
   src/index.js          tool definitions + zod input schemas
        │
        ├── src/embed.js  query → vector
        └── src/db.js     pg pool
                 │
                 ▼
        Postgres 16 + pgvector      docker-compose, port 55432

Layout: src/index.js (server and tools) · src/embed.js (embedding) · src/db.js (pool) · db/init.sql (schema + seed) · scripts/seed.mjs (documents + embeddings) · scripts/smoke.mjs (MCP client test).

Swapping in a real embedding model

src/embed.js ships a deterministic hashed bag-of-words projection so the repo runs offline with no API key. It matches on vocabulary overlap, not meaning — good enough to demonstrate the retrieval path, not good enough for production.

Replacing it is a one-function change. Keep EMBEDDING_DIM in sync with the vector(n) column in db/init.sql, then re-run npm run seed:

export async function embed(text) {
  const response = await fetch(`${process.env.AZURE_OPENAI_ENDPOINT}/openai/deployments/${process.env.EMBEDDING_DEPLOYMENT}/embeddings?api-version=2024-02-01`, {
    method: 'POST',
    headers: { 'api-key': process.env.AZURE_OPENAI_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ input: text }),
  });
  const { data } = await response.json();
  return data[0].embedding;
}

Notes and limitations

Worth stating plainly, since they're the things a reviewer would ask about:

  • No approximate index, on purpose. An early version had ivfflat ... WITH (lists = 10) over 12 rows. It silently returned wrong and short result sets — a single probe scans a near-empty partition. Approximate indexes only pay off at volume. At this corpus size an exact scan is both correct and instant; db/init.sql says where to add HNSW once the corpus justifies it.
  • Rules are data, not an engine. underwriting_rules.condition holds plain-language conditions for the agent to reason over. Only the hard limits (age band, face band, state availability) are actually evaluated in code. A production version would compile these to an executable rule set — an LLM interpreting underwriting conditions free-hand is not something to ship.
  • No authentication or tenancy. The server trusts its caller completely. Real deployment needs per-caller authorization, since these tools read customer data.
  • The embedding is lexical, and hybrid search is a mitigation, not a cure. Fusing full-text ranking with the vector side fixed most of the misranking, but neither half understands meaning: a query that shares no vocabulary with the target document will still miss it. A real embedding model is the actual fix; the fusion then makes it better still.

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选