Skip to main content
Glama
hossein-finlex

WebMCP Contract Portfolio

WebMCP Contract Portfolio

Eine kommerzielle Versicherungs-App für Finanzlinien, die Claude direkt über navigator.modelContext – die WebMCP (Web Model Context Protocol) API – bedient.

Fragen Sie „welche Verträge laufen in den nächsten 60 Tagen ab?" und die Tabelle filtert vor Ihnen. Fragen Sie nach einer Verlängerung und die Laufzeit rollt in Postgres und auf dem Bildschirm vorwärts. Der Assistent entdeckt zur Laufzeit, was die Seite kann, indem er die Tool-Schemas liest, die die Seite veröffentlicht – kein DOM-Scraping, keine Selektoren, keine Screenshots.


Ausführen

Drei Prozesse. Sie benötigen einen Anthropic-API-Schlüssel für den echten Assistenten; ohne einen funktioniert alles außer dem Modell weiterhin (siehe Ohne Schlüssel unten).

# 1. Postgres  (port 5434 — 5432 and 5433 are already taken on this machine)
docker compose up -d

# 2. Backend
cd backend
uv venv .venv && uv pip install --python .venv/bin/python -r requirements.txt
cp .env.example .env          # then put your ANTHROPIC_API_KEY in it
.venv/bin/python seed.py      # 50 contracts
.venv/bin/uvicorn app.main:app --reload --port 8000

# 3. Frontend
npm install
PORT=3002 npm start           # http://localhost:3002

Das Backend befüllt die Datenbank beim ersten Start selbst, daher wird seed.py nur benötigt, wenn Sie neu seeden oder die Größe ändern möchten (--force, --total 200).

Ohne Schlüssel

  • MOCK_LLM=1 in backend/.env tauscht Claude gegen einen skriptbasierten Stub aus, der dasselbe Protokoll spricht. Antworten sind vorgefertigt; die Tool-Aufrufe sind echt, sodass jeder Aktionspfad weiterhin funktioniert. Nützlich für Demos ohne Token zu verbrauchen.

  • Ohne Backend lädt die App weiterhin und das Bedienfeld Direkte Tool-Aufrufe in der Seitenleiste ruft die WebMCP-Tools ohne Modell im Loop auf.


Related MCP server: Salesforce MCP Server

Dokumentation

WebMCP in der Praxis – welches Problem ein In-App-Assistent tatsächlich hat, was WebMCP ist und wie Browser, Backend und Modell kommunizieren, mit Diagrammen der Tool-Aufruf-Sequenz und der Server-zu-Seite-Übergabe. Öffnen Sie die Datei in einem Browser.

CLAUDE.md – Orientierung für die Arbeit in diesem Repository: Befehle, die Schichtungsregeln und die Fallstricke, die hier bereits aufgetreten sind.


Probieren Sie diese aus

Frage

Was Sie sehen sollten

„Welche Verträge laufen in den nächsten 60 Tagen ab?"

Die Tabelle verengt sich, die Filterleiste wird lila

„Zeig mir alles von Allianz."

Filtert nach Versicherer

„Finde den Novaris D&O-Vertrag und öffne ihn."

Sucht und navigiert dann zur Detailansicht

„Verlängere die Cyber-Police von Lumen Digital Health um 12 Monate."

Laufzeit rollt 12 Monate, Verlängerungsflag wird gelöscht, Zeile blinkt

„Richte einen neuen Cyber-Vertrag für Cortex Robotics mit Markel ein, Limit 3 Mio."

Das Formular für neue Verträge öffnet sich vorausgefüllt, aber nicht abgeschickt

„Erhöhe die Prämie von FL-0146 auf 95.000."

Der Vertrag wird direkt aktualisiert

„Wie hoch ist die Gesamtprämie nach Versicherer?"

In SQL aggregiert, als Aufschlüsselung angezeigt – keine Verträge werden in den Kontext gezogen

„Welche zwei Verträge haben die höchsten Limits?"

sort_by + limit in SQL; die Tabelle sortiert neu und zeigt genau zwei

„Verlängere alles, was in den nächsten 30 Tagen abläuft."

Ein Server-Tool zeigt die Vorschau der Stapelverarbeitung. Bestätigen Sie, und es wird in einer Transaktion ausgeführt, dann navigiert WebMCP Sie zum Ergebnis

„Erstelle mir einen Verlängerungsbericht für die nächsten 90 Tage."

Wird auf dem Server generiert, dann zeigt show_report es auf dem Bildschirm

„Ist FL-0142 marktgerecht bepreist?"

Benchmark-Daten von außerhalb der App – die Seite hat keinen Zugriff darauf

Der lila Rand um das linke Fenster bedeutet, dass der Assistent steuert. Das WebMCP-Bedienfeld unten rechts listet jedes registrierte Tool auf – klicken Sie auf eines, um das JSON-Schema zu sehen, das Claude tatsächlich erhält – und protokolliert jeden Aufruf, der die Grenze überschreitet.

Alles funktioniert auch manuell: Klicken Sie auf eine Zeile, drücken Sie Bearbeiten, drücken Sie Verlängern. Mensch und Agent teilen sich dieselbe API und denselben React-State, daher gibt es keinen separaten „Agentenmodus" und keine Möglichkeit, dass die beiden uneins sind.


Architektur

Das Interessante ist, dass der Agent wirklich außerhalb der Seite lebt, was genau so funktioniert, wie WebMCP es tut: Der Browser übergibt dem Agenten eine Tool-Liste und leitet seine Tool-Aufrufe zurück.

browser (React)                backend (FastAPI)              Claude
  │  user_message + tool list        │                           │
  │─────────────────────────────────>│  messages.stream(tools=…)  │
  │                                  │──────────────────────────> │
  │          text_delta              │      streamed text         │
  │<─────────────────────────────────│<─────────────────────────── │
  │          tool_use                │   stop_reason=tool_use     │
  │<─────────────────────────────────│<─────────────────────────── │
  │                                                               │
  │  executeTool() → REST → Postgres → React state → repaint      │
  │                                                               │
  │          tool_result             │                           │
  │─────────────────────────────────>│  append, continue loop     │
  │                                  │──────────────────────────> │
  │          turn_end                │   stop_reason=end_turn     │
  │<─────────────────────────────────│<─────────────────────────── │

Claude sieht nie das DOM. Das Backend enthält keine Tool-Implementierungen – es meldet nur, was Claude aufrufen möchte. Jedes Tool wird im Browser gegen den live React-State ausgeführt.

docker-compose.yml            Postgres 17 on :5434
backend/
├── seed.py                   seeding CLI
└── app/
    ├── main.py               FastAPI: REST + /ws/agent
    ├── db.py                 engine, session dependency, readiness wait
    ├── models.py             SQLModel table + validated API schemas
    ├── repository.py         all SQL lives here
    ├── seed_data.py          12 curated contracts (terms relative to today)
    ├── seed_gen.py           deterministic generator for the rest
    ├── queries.py            filtering, sorting and aggregation in SQL
    ├── server_tools.py       tools that run here, not in the page
    ├── artifacts.py          batch records and reports
    ├── llm.py                Claude client + the mock provider
    └── agent_ws.py           the bridge: routes each tool call to the right side
src/
├── webmcp-polyfill.js        polyfill + agent-side bridge
├── useWebMcpTools.js         registration lifecycle hook
├── api.js                    REST client
├── App.js                    owns state; registers the seven tools
├── agent/agentClient.js      WebSocket client; executes tool calls
└── components/               ContractList · ContractDetail · NewContractForm ·
                              PortfolioSummary · BatchResult · ReportView ·
                              AssistantChat · ToolInspector

Warum eine manuelle Agenten-Schleife

Der Tool-Runner des Anthropic SDK führt Tools im Prozess aus. Hier leben die Tools im Browser des Benutzers, daher treibt agent_ws.py die stop_reason == "tool_use"-Schleife manuell an und wartet auf jedes Ergebnis über den WebSocket. Parallele Tool-Aufrufe werden gleichzeitig ausgeführt und in einer einzigen user-Nachricht zurückgegeben, wie die API es erwartet.

Zwei Tool-Oberflächen, eine Tool-Liste

Claude erhält eine flache Liste. Es weiß nicht und kümmert sich nicht darum, dass einige dieser Tools im Browser und einige im Backend laufen – aber die Aufteilung ist die wichtigste Designentscheidung hier.

Seiten-Tools (WebMCP, navigator.modelContext) sind die Fähigkeiten der Seite. Verwenden Sie sie, wenn der Benutzer die Änderung beobachten soll, und für Einzel-Datensatz-Arbeiten. Sie werden gegen den live React-State ausgeführt.

Server-Tools laufen im FastAPI-Prozess und berühren nie den Browser. Verwenden Sie sie, wenn das Steuern einer UI völlig falsch wäre:

Server-Tool

Warum es nicht in die UI gehört

run_renewal_batch

Das Verlängern von 14 Verträgen über die Seite bedeutet 14 Round-Trips durch das Modell, von denen jeder auf halbem Weg stoppen kann. Ein Aufruf, eine Transaktion, alles oder nichts.

generate_renewal_report

Das Zusammenstellen eines Dokuments ist Berechnung, nicht Klicken.

benchmark_rates

Marktzinsdaten liegen außerhalb der Anwendung. Keine noch so große UI-Automatisierung würde sie finden.

Das Muster, das sie verbindet, ist die Übergabe. Serverarbeit ist unsichtbar – daher gibt ein Server-Tool eine Artefakt-ID zurück, und der Assistent ruft dann ein Seiten-Tool auf, um es auf dem Bildschirm anzuzeigen:

run_renewal_batch(expiring_within_days=30)      ← server: previews, changes nothing
   → "4 contracts, €413,400. Shall I commit?"
run_renewal_batch(..., commit=true)             ← server: one transaction
   → batch_id: BATCH-0002
show_batch_result(batch_id="BATCH-0002")        ← page:  navigates the user there

Die Arbeit findet außerhalb der Seite statt; das Ergebnis landet trotzdem auf der Seite. Der Chat färbt die beiden unterschiedlich (lila = die UI hat sich bewegt, amber = Arbeit fand woanders statt) und der Inspektor listet sie unter separaten Überschriften auf, sodass nie geraten werden muss, welche Seite was getan hat.

Massenänderungen standardmäßig als Vorschau. run_renewal_batch ist ein Trockenlauf, es sei denn, commit=true. Eine Massenmutation sollte nicht passieren, nur weil ein Modell zu 80% sicher war, dass sie gewünscht ist – der Assistent zeigt den Plan und wartet.

Die Seiten-Tools

Tool

Auswirkung auf dem Bildschirm

search_contracts

Filtert, sortiert und begrenzt die sichtbare Tabelle (deshalb ist eine Agentensuche sichtbar)

summarise_portfolio

Aggregiert in SQL und öffnet die Aufschlüsselungsansicht

get_contract

Keine – gibt den vollständigen Datensatz zurück

navigate

Wechselt die Ansicht

prefill_new_contract_form

Füllt das Formular aus und stoppt. Der Mensch sendet ab.

create_contract

Schreibt in Postgres, öffnet den neuen Vertrag

update_contract

Aktualisiert die Zeile direkt

renew_contract

Rollt eine Laufzeit vor, löscht die Verlängerungsflag

show_batch_result

Zeigt einen servererzeugten Stapelverarbeitungsdatensatz an

show_report

Zeigt einen servererzeugten Bericht an

Tool-Oberfläche ist eine Kostenentscheidung

search_contracts hat sort_by / sort_dir / limit erhalten, und summarise_portfolio wurde aus einem bestimmten Grund hinzugefügt. Auf die Frage „welche zwei Verträge haben die höchste Versicherungssumme?" rief der Assistent ursprünglich search_contracts({}) auf, zog alle 50 Zeilen in den Kontext und sortierte sie selbst – 6.809 Eingabe-Tokens und zwei Tool-Aufrufe. Mit Sortierung und Limit in SQL kostet dieselbe Frage 518 Tokens und einen Aufruf, und die Arithmetik übernimmt die Datenbank statt des Modells.

Wenn Ihr Agent viel liest, um wenig zu beantworten, ist das ein fehlendes Tool, kein Prompting-Problem.

Die Tool-Argumentnamen stimmen exakt mit den API- und Datenbankspalten überein (durchgehend snake_case), sodass es keine Mapping-Schicht gibt, in der sich ein Bug verstecken kann.

prefill_new_contract_form ist der Human-in-the-Loop-Fall, den man beachten sollte: Der Agent tippt, die Person behält die Entscheidung. Der System-Prompt weist Claude an, es gegenüber create_contract zu bevorzugen, wann immer ein Detail abgeleitet wurde.


Die Daten

50 Verträge: 12 kuratierte mit einer Geschichte in ihren Notizen, plus 38 generierte.

Der Generator (seed_gen.py) ist deterministisch und kümmert sich um zwei Dinge, die ein Zufallsdaten-Skript normalerweise falsch macht:

  • Korrelierte Zahlen. Die Prämie ist ein Satz auf das Limit, mit einer Satzspanne pro Produkt (D&O 0,35–0,75 %, Cyber 0,8–1,6 %, …), und Selbstbehalte skalieren mit dem Limit. Sonst klingt nichts, was der Assistent über das Buch sagt, glaubwürdig.

  • Eine realistische Ablauf-Pipeline. Laufzeiten werden relativ zu heute gegen einen Ziel-Status-Mix platziert – etwa 10 % abgelaufen, 25 % laufen innerhalb von 90 Tagen ab, der Rest aktiv, plus zwei Entwürfe. So ist „Was muss verlängert werden?" immer eine echte Frage, und ein erneutes Seeden in sechs Monaten erzeugt immer noch ein lebendig aussehendes Buch statt eines, das vollständig abgelaufen ist.

Der Status (active / expiring / expired / draft) wird aus der Laufzeit berechnet, nie gespeichert, sodass er nicht abweichen kann. renewal_pending ist ein separates Flag, das ein Makler setzt.

Alle versicherten Unternehmen sind fiktiv. Versicherernamen sind echte Marktteilnehmer, die so verwendet werden, wie jede Broker-Demo sie verwendet; nichts hier stellt eine echte Police dar.


Der Polyfill

src/webmcp-polyfill.js erledigt zwei getrennte Aufgaben, und die Unterscheidung ist wichtig:

Seitenseite (der eigentliche Polyfill). Natives navigator.modelContext ist noch nicht überall verfügbar. Wenn es fehlt, installiert die Datei einen Stub, der die vorgeschlagene Oberfläche implementiert – registerTool, unregisterTool, provideContext – und jede Registrierung und jeden Aufruf in der DevTools-Konsole protokolliert. Die App stürzt nie ab, und das Badge im Header zeigt Ihnen, welche Version Sie haben.

Agentenseite (eine Brücke). Es gibt keine seitenorientierte API für „Sei der Agent“, daher spiegelt das Modul auch jedes registrierte Tool und stellt zusätzlich listTools() / executeTool() bereit. agentClient.js nutzt diese Brücke und sonst nichts. Der Spiegel wird sowohl in nativen als auch in polyfillierten Browsern gepflegt, sodass das Verhalten in beiden Fällen identisch ist.

Aus der DevTools-Konsole:

await webmcp.listTools()
await webmcp.executeTool('search_contracts', { product: 'Cyber', status: 'expiring' })
await webmcp.executeTool('renew_contract', { contract_id: 'FL-0142', months: 24 })

Die React-Falle, die man kennen sollte

Der naheliegende Weg, ein Tool zu registrieren, ist falsch:

useEffect(() => {
  const h = registerTool({ name: 'x', execute: () => doThingWith(contracts) });
  return () => h.unregister();
}, []);                       // `contracts` is frozen at mount forever

Auch eine erneute Registrierung bei jeder Zustandsänderung ist falsch – der Browser würde sehen, wie sich der gesamte Tool-Satz ständig ändert, und ein laufender Aufruf könnte dem Agenten unter den Füßen weggezogen werden.

useWebMcpTools.js registriert einmalig mit einer stabilen Indirektion: Das registrierte execute löst den tatsächlichen Handler aus einem Ref auf, das jeder Render aktualisiert. Die Registrierung ist stabil; die Handler sehen immer den aktuellen Zustand. Unter dem Doppel-Mount von React StrictMode können Sie bestätigen, dass genau sieben Tools registriert sind, nicht vierzehn und nicht null.


Hinweise und Grenzen

  • SEED_TOTAL / seed.py --total ändern die Buchgröße. Filtern, Sortieren und Begrenzen laufen bereits in SQL (queries.py), daher benötigt ein viel größeres Buch nur eine Paginierung in der Listenansicht.

  • Batch-Datensätze und Berichte leben im Speicher (artifacts.py, auf 50 begrenzt). Sie sind Job-Ausgabe und keine Domänendaten; eine echte Bereitstellung würde sie persistieren, da ein Massenänderungsdatensatz ein Audit-Trail ist.

  • benchmark_rates liefert erfundene Zahlen. Es steht für ein Marktdaten-Abonnement – der Punkt ist, dass es Daten sind, zu denen der Browser keinen Zugang hat.

  • Neue Vertrags-IDs stammen aus max(id) + 1. Zwei gleichzeitige Erstellungen könnten kollidieren; eine Datenbank-Sequenz ist die Ein-Zeilen-Lösung.

  • Das Gespräch lebt im Speicher pro WebSocket-Verbindung, sodass ein Neuladen einen frischen Chat startet. Das Portfolio selbst liegt in Postgres und bleibt erhalten.

  • output_config: {effort: "medium"} mit adaptivem Denken ist in llm.py gesetzt; erhöhen Sie es auf high, wenn Sie möchten, dass der Assistent mehrstufige Arbeit sorgfältiger plant.

  • Serverseitige Ablehnungs-Fallbacks sind aktiviert. Wenn Ihr Konto oder Ihre SDK-Version den Parameter ablehnt, protokolliert llm.py eine Warnung und versucht es einmal auf dem einfachen Pfad erneut, anstatt den Turn fehlschlagen zu lassen.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    An MCP server implementation that integrates Claude with Salesforce, enabling natural language interactions with Salesforce data and metadata for querying, modifying, and managing objects and records.
    6
    15
    3,172
    166
    MIT
  • F
    license
    B
    quality
    C
    maintenance
    A customer and product management MCP server using SQLite. It enables Claude Desktop users to manage client and product data through natural language interactions.
    9
    1

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hossein-finlex/web-mcp-hello'

If you have feedback or need assistance with the MCP directory API, please join our Discord server