Skip to main content
Glama
remoprinz

Swiss Health MCP Server

compare_insurers

Compare health insurance premiums from multiple Swiss insurers based on canton, year, age group, and franchise to identify cost-effective options.

Instructions

Vergleicht mehrere Versicherer für ein bestimmtes Profil.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
insurer_namesYesListe von Versicherer-Namen (z.B. ['CSS', 'Helsana', 'Swica'])
cantonYesKanton (2-Buchstaben-Code)
yearYesJahr (2016-2026)
age_bandYesAltersgruppe
franchise_chfYesFranchise in CHF

Implementation Reference

  • The main handler function executing the tool logic: resolves insurer names to IDs using helper functions, queries the premiums table in Supabase for matching criteria, selects the cheapest model per insurer, sorts by price, and returns a formatted markdown table comparison with price difference and disclaimer.
    async function compareInsurers(params: {
      insurer_names: string[];
      canton: string;
      year: number;
      age_band: string;
      franchise_chf: number;
    }): Promise<string> {
      const db = getSupabase();
      
      const { insurer_names, canton, year, age_band, franchise_chf } = params;
    
      // Finde ALLE Versicherer-IDs für jeden Namen (z.B. Helsana hat 0312, 1322, 1479, 1568)
      const matchedInsurers: { searchName: string; ids: string[]; primaryId: string | undefined }[] = 
        insurer_names.map(searchName => ({
          searchName,
          ids: findAllInsurerIds(searchName),
          primaryId: findInsurerIdByName(searchName)
        }));
    
      // Sammle alle IDs und tracke welche zu welchem Namen gehören
      const allIds: string[] = [];
      const idToSearchName = new Map<string, string>();
      
      for (const m of matchedInsurers) {
        for (const id of m.ids) {
          allIds.push(id);
          idToSearchName.set(id, m.searchName);
        }
      }
    
      const notFound = matchedInsurers.filter(m => m.ids.length === 0).map(m => m.searchName);
    
      if (allIds.length === 0) {
        return `⚠️ Keine der Versicherer gefunden: ${insurer_names.join(", ")}\n\nVerfügbare Versicherer: CSS, Helsana, Swica, Assura, Concordia, Sanitas, KPT, ÖKK, Visana, Groupe Mutuel, Sympany, Atupri, EGK, Aquilana, Galenos`;
      }
    
      // Hole Prämien für ALLE IDs
      const { data: premiums, error } = await db
        .from("premiums")
        .select("insurer_id, monthly_premium_chf, model_type")
        .eq("canton", canton.toUpperCase())
        .eq("year", year)
        .eq("age_band", age_band)
        .eq("franchise_chf", franchise_chf)
        .in("insurer_id", allIds);
    
      if (error || !premiums || premiums.length === 0) {
        return `❌ Keine Prämien gefunden für: ${canton}, ${year}\n\nGesuchte IDs: ${allIds.join(", ")}`;
      }
    
      // Gruppiere nach SUCHNAME (nimm günstigsten Tarif pro Versicherer)
      const bestByName = new Map<string, { premium: number; model: string; id: string }>();
      for (const p of premiums) {
        const searchName = idToSearchName.get(p.insurer_id) || p.insurer_id;
        const existing = bestByName.get(searchName);
        if (!existing || p.monthly_premium_chf < existing.premium) {
          bestByName.set(searchName, { 
            premium: p.monthly_premium_chf, 
            model: p.model_type,
            id: p.insurer_id 
          });
        }
      }
    
      // Formatiere Ergebnis
      let result = `📊 Versicherungsvergleich\n`;
      result += `📍 ${canton} | ${year} | ${age_band} | CHF ${franchise_chf} Franchise\n\n`;
    
      const sorted = [...bestByName.entries()]
        .sort((a, b) => a[1].premium - b[1].premium);
      
      sorted.forEach(([searchName, data], index) => {
        const displayName = getInsurerName(data.id);
        result += `${index + 1}. ${displayName}: CHF ${data.premium.toFixed(2)}/Monat (${data.model})\n`;
      });
    
      if (notFound.length > 0) {
        result += `\n⚠️ Nicht gefunden: ${notFound.join(", ")}\n`;
      }
    
      if (sorted.length >= 2) {
        const diff = sorted[sorted.length - 1][1].premium - sorted[0][1].premium;
        result += `\n💰 Differenz günstigste/teuerste: CHF ${diff.toFixed(2)}/Monat\n`;
      }
    
      result += DISCLAIMER;
      return result;
    }
  • Input schema for validating tool parameters: requires array of insurer names, canton code, year, age band, and franchise amount.
    inputSchema: {
      type: "object" as const,
      properties: {
        insurer_names: { type: "array", items: { type: "string" }, description: "Liste von Versicherer-Namen (z.B. ['CSS', 'Helsana', 'Swica'])" },
        canton: { type: "string", description: "Kanton (2-Buchstaben-Code)" },
        year: { type: "number", description: "Jahr (2016-2026)" },
        age_band: { type: "string", enum: ["child", "young_adult", "adult"], description: "Altersgruppe" },
        franchise_chf: { type: "number", description: "Franchise in CHF" }
      },
      required: ["insurer_names", "canton", "year", "age_band", "franchise_chf"]
    }
  • src/index.ts:159-173 (registration)
    Tool registration in the TOOLS array used for ListToolsRequestSchema response, defining name, description, and inputSchema.
    {
      name: "compare_insurers",
      description: "Vergleicht mehrere Versicherer für ein bestimmtes Profil.",
      inputSchema: {
        type: "object" as const,
        properties: {
          insurer_names: { type: "array", items: { type: "string" }, description: "Liste von Versicherer-Namen (z.B. ['CSS', 'Helsana', 'Swica'])" },
          canton: { type: "string", description: "Kanton (2-Buchstaben-Code)" },
          year: { type: "number", description: "Jahr (2016-2026)" },
          age_band: { type: "string", enum: ["child", "young_adult", "adult"], description: "Altersgruppe" },
          franchise_chf: { type: "number", description: "Franchise in CHF" }
        },
        required: ["insurer_names", "canton", "year", "age_band", "franchise_chf"]
      }
    },
  • src/index.ts:498-500 (registration)
    Dispatch registration in the switch statement within CallToolRequestSchema handler, mapping tool name to the compareInsurers function call.
    case "compare_insurers":
      result = await compareInsurers(args as any);
      break;
  • Helper function to find all insurer IDs matching a search name (handles multiple IDs per insurer), crucially used in the handler for comprehensive comparison.
    function findAllInsurerIds(searchName: string): string[] {
      const search = searchName.toLowerCase().trim();
      const ids: string[] = [];
      
      for (const [id, name] of Object.entries(INSURER_NAMES)) {
        if (name.toLowerCase().includes(search) || search.includes(name.toLowerCase())) {
          ids.push(id);
        }
      }
      
      return ids;
    }

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/remoprinz/swiss-health-mcp'

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