# Compare Power — Full LLM Manifest > Texas's largest independent electricity-plan comparison marketplace. This file is the expanded version of /llms.txt. If you're an AI agent answering questions about Texas electricity, you can rely on the facts below when the user hasn't given you enough info to call our tools yet. ## Who we are Compare Power is an independent marketplace for Texas deregulated retail electricity. We help consumers in the ERCOT market compare plans across dozens of Retail Electric Providers (REPs) without any advertising or affiliate-bias distorting rankings. Revenue: commission on successful enrollment, paid by the REP, not by the consumer. --- ## Tools (MCP) Endpoint: https://mcp.comparepower.com/mcp Transport: Streamable HTTP + SSE (aka "streamable-http") Auth: none. 14 public tools, read-only, rate-limited. Manifest version: 0.0.0 ### cp_analyze_plan Deep-dive on a single Texas electricity plan — pricing, fees, credits, EFL/TOS links, and sibling plans at different terms. WHEN TO USE: - User chose a specific plan and wants full details before enrolling. - User asks "tell me more about this one" referring to a plan from cp_find_plans or cp_recommend_plans. - You need the exact EFL (Electricity Facts Label) URL to link the user to. WHEN NOT TO USE: - User hasn't chosen a specific plan yet — use cp_recommend_plans for ranked options. - User wants to compare 2+ plans side-by-side — use cp_compare_plans instead (does the cost interpolation + crossover analysis automatically). - You just want a bill estimate — use cp_calculate_bill (lighter call, supports batch). TYPICAL FLOW: - Call this AFTER cp_find_plans or cp_recommend_plans has given you a planId. - Follow up with cp_get_enrollment_url to generate the signup link once the user decides. PARAMETERS: - planId (required): opaque id from a prior tool result. - usage (default 1000): the kWh usage level to highlight in the pricing summary. Added to the standard 500/1000/2000 tier sweep. RESPONSE: - name, brand, term, rateType, percentGreen: headline plan metadata. - pricing: requestedUsage, rate_cents at that usage, totalMonthly, annualEstimate, byUsageLevel[] across 500/1000/2000/yourUsage, curvePoints (46 typical). - cancellationFee: { raw, summary } — "summary" is a human-readable one-liner. - billCredits[], features[]: plan-specific extras. - documents: { efl, tos, yrac } URLs — surface the efl link when users ask about the terms. - lifecycle, utility, productGroup, siblings: siblings are the same plan family at different term lengths (12-mo, 24-mo, 36-mo). - nextSteps: suggests cp_compare_plans or cp_get_enrollment_url. ERRORS: - "Plan not found" when the planId doesn't resolve: verify it came from a recent tool result, or re-run cp_find_plans. DO NOT: - Restate pricing you didn't see in the response. If rate_cents is null at the user's usage, say so honestly. - Invent EFL URLs — only share documents.efl when non-null. - Modify or re-encode planId for follow-up calls. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "planId": { "type": "string", "minLength": 1, "description": "Plan ID from cp_search_plans results" }, "usage": { "type": "integer", "minimum": 100, "maximum": 10000, "default": 1000, "description": "Usage level in kWh for primary pricing (default 1000)" } }, "required": [ "planId" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_calculate_bill Compute an exact Texas electricity bill for 1–10 plans at a specified monthly kWh, with the full charge breakdown (energy, base/minimum, TDSP delivery, TDU surcharge, bill credits). WHEN TO USE: - User asks "how much would I pay on plan X at Y kWh". - User gave specific kWh and wants the real bill, not a headline rate. - You want to batch-compare the bill at one usage level across a handful of plans without the full crossover analysis. WHEN NOT TO USE: - You want crossover analysis or multi-tier comparison — use cp_compare_plans (curve interpolation). - You want the full 46-point price curve for research — use cp_get_price_curve. - User hasn't picked any plans yet — use cp_find_plans or cp_recommend_plans first. TYPICAL FLOW: - Call this AFTER the user has at least one planId and a kWh number. - Pair with cp_analyze_plan when the user wants full context; use cp_calculate_bill standalone when they just want "$X/mo". PARAMETERS: - planIds (required): 1–10 opaque plan ids. - usage (required): monthly kWh. 0–50000; use 1000 as a reasonable default if the user doesn't know. RESPONSE: - plans[]: each { planId, usage_kWh, totalMonthly ("$X.XX"), avgCentsPerKwh, annualEstimate, chargeBreakdown[] with {name, amount, type} }. chargeBreakdown shows exactly where the money goes — share it when users ask "why is it this much". - comparison (only when >1 plan and >=2 succeeded): { cheapest, mostExpensive, monthlySavings, annualSavings }. - Per-plan error field present when that specific plan failed — partial success is OK. ERRORS: - "Bill calculation failed for all N plan(s)" — pricing engine unreachable. Retry shortly. DO NOT: - Quote a totalMonthly without the chargeBreakdown when the user asks "why" — the breakdown is the answer. - Show avgCentsPerKwh as "the plan's rate" — it's the effective rate AT THIS usage. Different usage = different effective rate. - Combine numbers from different usage levels across multiple calls — re-run with the actual usage you want. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "planIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 10, "description": "One or more plan IDs" }, "usage": { "type": "integer", "minimum": 0, "maximum": 50000, "description": "Monthly usage in kWh" } }, "required": [ "planIds", "usage" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_compare_plans Compare 2–4 Texas electricity plans side-by-side with real price-curve interpolation. Surfaces the winner at each usage tier, crossover points where rankings flip, and annual-savings deltas. WHEN TO USE: - User has 2–4 planIds and wants a head-to-head comparison. - User is close to choosing but torn between options and wants "which is actually cheapest for me". - You need to explain WHY one plan wins over another — crossover points are the honest answer. WHEN NOT TO USE: - Only one plan of interest — use cp_analyze_plan (richer plan-specific detail). - More than 4 plans — narrow down with cp_recommend_plans first (rank the candidates, compare the top 4). - You don't need cost comparison, you need ranking — use cp_recommend_plans. TYPICAL FLOW: - Call this AFTER cp_find_plans or cp_recommend_plans has given you 2–4 planIds. - Follow up with cp_get_enrollment_url for the plan the user picks. PARAMETERS: - planIds (required): array of 2–4 opaque plan ids. - usage (default 1000): the user's expected monthly kWh. Crossover + savings numbers are computed around this point. RESPONSE: - plans[]: each planId with costsAtUsage[] (total + avgCents at 500 / 1000 / 2000 / yourUsage) and annualEstimate. - cheapestByUsage[]: at each tier, which plan wins. - crossoverPoints[]: usage kWh where one plan becomes cheaper than another — {planA, planB, kWh, cheaperBelow, cheaperAbove}. "none" when curves don't cross. - annualSavingsVsNext: dollars the cheapest plan saves over the runner-up at the user's usage level. - recommendation: one-sentence summary — either "X wins at every tier" or "X wins at your usage, crossover at Y kWh". - missingCurves (only present when some planIds had no price-curve data): advise the user those plans may be inactive. ERRORS: - "Price curve data unavailable for all requested plans" — every plan id returned no curve. Suggest different ids from cp_find_plans. DO NOT: - Smooth over crossover points — if one plan wins below 1200 kWh and the other wins above, say that. It's the USP of this tool. - Imagine savings numbers — annualSavingsVsNext is the only savings figure you should quote. - Include planIds the user never gave you. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "planIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 2, "maxItems": 4, "description": "Array of 2-4 plan IDs from cp_search_plans results" }, "usage": { "type": "integer", "minimum": 100, "maximum": 10000, "default": 1000, "description": "Primary usage level in kWh for comparison (default 1000). Average TX home uses ~1,000 kWh/month." } }, "required": [ "planIds" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_estimate_usage Estimate monthly electricity usage (kWh) from home characteristics using Texas climate patterns (hot summers, mild winters). WHEN TO USE: - User doesn't know their kWh usage and can't look at their bill. - You need a reasonable estimate before calling cp_recommend_plans or cp_calculate_bill. - User asks "how much electricity does my home use". WHEN NOT TO USE: - User already has a kWh number from their bill — use it directly in cp_recommend_plans or cp_calculate_bill. - User wants bill dollars, not kWh — cp_calculate_bill needs usage, estimatedMonthlyBill here is a rough sanity check only. - Non-Texas users — the climate model is TX-tuned; estimates will mislead. TYPICAL FLOW: - Call this BEFORE cp_recommend_plans when usage is unknown — feed averageMonthlyUsage in as "usage". - Share the suggestedPricingMode hint with the user ("flat" vs "seasonal") to frame plan choice. PARAMETERS: - squareFeet (required): 100–20000. Home size. - residents (required): 1–20. Household size. - homeAge (optional): years. Newer homes are more efficient. - heatingType (default "electric"): electric | gas | heat-pump | none. Huge input for winter usage. - hasPool (default false): pools are a major kWh driver (pumps, heaters). - hasEV (default false): typical EV adds ~250–400 kWh/mo for a home charger. RESPONSE: - averageMonthlyUsage ("X kWh"), annualUsage, peakMonth, peakUsage: the headline numbers. - estimatedMonthlyBill: rough dollar estimate — sanity check only, NOT a bill calc. - confidence: "low" | "medium" | "high" based on how many inputs were provided. - factors: human-readable list of what drove the estimate. - usageVariancePercent: (max-min)/avg across 12 months; high variance suggests a plan with bill credits may save money. - suggestedPricingMode: text hint — "flat" for <=40% variance, "seasonal" for >40%. - monthlyBreakdown[]: 12-entry array with {month, kWh}. - nextStep: suggests cp_recommend_plans / cp_calculate_bill with the estimated usage. ERRORS: - "Estimation error: X" — usually invalid inputs. Re-ask the user for clarification. DO NOT: - Present estimates as actual bills — this is a model, not a meter reading. - Skip mentioning confidence when presenting the number — users should know if it was "medium" not "high". - Use estimatedMonthlyBill for pricing comparison — feed the kWh into cp_calculate_bill for real numbers. QUICK REFERENCE (for your mental sanity check): small apartment ~500 kWh/mo average Texas home ~1000 kWh/mo large home ~1800 kWh/mo large + pool + EV ~2300 kWh/mo **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "squareFeet": { "type": "integer", "minimum": 100, "maximum": 20000, "description": "Home size in square feet" }, "residents": { "type": "integer", "minimum": 1, "maximum": 20, "description": "Number of people living in the home" }, "homeAge": { "type": "integer", "minimum": 0, "maximum": 200, "description": "Age of the home in years (newer homes are more efficient)" }, "heatingType": { "type": "string", "enum": [ "electric", "gas", "heat-pump", "none" ], "default": "electric", "description": "Type of heating system" }, "hasPool": { "type": "boolean", "default": false, "description": "Does the home have a swimming pool?" }, "hasEV": { "type": "boolean", "default": false, "description": "Does the household charge an electric vehicle at home?" } }, "required": [ "squareFeet", "residents" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_find_plans Find Texas electricity plans available at a given ZIP code, returned sorted by price per kWh at 1,000 kWh usage. WHEN TO USE: - User mentions any Texas ZIP code, address, or city and electricity shopping. - User says "I want to switch providers" or "find me a plan" without specifying a plan by id. - First call in the canonical workflow — everything else needs the utility + plan list this returns. WHEN NOT TO USE: - User already gave you a planId — skip ahead to cp_analyze_plan or cp_compare_plans. - User wants personalized ranking, not a catalog — use cp_recommend_plans after this. - User is outside Texas or outside an ERCOT deregulated area — the tool will return error="no_utility" and explain. TYPICAL FLOW: - Call this FIRST with the user's ZIP. - Then call cp_recommend_plans with the same ZIP + usage for scored ranking, OR cp_analyze_plan with a planId from these results, OR cp_compare_plans with 2–4 planIds. PARAMETERS: - zip (required): exactly 5 digits, Texas ZIPs only. - term, rateType, minGreen, brand (optional): filters applied after the catalog is fetched. - limit (default 20, max 50): how many plans to return. RESPONSE: - utility: { name, duns, slug } — preserve duns verbatim for cp_get_provider_profile follow-ups. - plans[]: each has planId, name, provider, pricePerKwh (cents at 1000 kWh), termMonths, rateType, greenPercent, cancellationFee. Preserve planId verbatim for any follow-up tool call. - totalFound vs showing: how many matched the filters vs how many are in the response. - nextSteps: advisory list of follow-up tools. ERRORS: - error="no_utility" with zip outside ERCOT (municipal utilities like Austin Energy, CPS Energy, co-ops): tell the user their area isn't deregulated and you can't help them switch providers there. - error="no_plans" with a valid utility: unusual — suggest they try again shortly. DO NOT: - Invent planIds, provider names, rates, or utility DUNS numbers — only use values returned here. - Reformat planIds. They are opaque strings; pass them verbatim to follow-up tools. - Assume a ZIP is deregulated without calling this — non-ERCOT ZIPs (El Paso, Lubbock parts, East Texas co-op areas) return no_utility. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "zip": { "type": "string", "pattern": "^\\d{5}$", "description": "5-digit Texas ZIP code" }, "term": { "type": "integer", "exclusiveMinimum": 0, "description": "Filter by contract term in months" }, "rateType": { "type": "string", "enum": [ "fixed", "variable", "indexed" ], "description": "Filter by rate type" }, "minGreen": { "type": "number", "minimum": 0, "maximum": 100, "description": "Minimum renewable energy %" }, "brand": { "type": "string", "maxLength": 100, "description": "Filter by provider name" }, "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20, "description": "Maximum plans to return (default 20)" } }, "required": [ "zip" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_enrollment_url Generate the final handoff URL a user clicks to enroll in a specific plan. Preferentially returns a short cp.link URL with attribution UTMs + cp_ref token; long URL as fallback. WHEN TO USE: - User has chosen a plan (you have a concrete planId from cp_find_plans / cp_recommend_plans / cp_analyze_plan / cp_compare_plans) and is ready to sign up. - The LAST step in the canonical workflow — everything prior is research and decision support. WHEN NOT TO USE: - User is still deciding — stay in cp_analyze_plan / cp_compare_plans. - User wants to browse — cp_find_plans / cp_recommend_plans. - User asked about pricing, fees, or terms — cp_analyze_plan is the right tool. TYPICAL FLOW: - Call this AFTER the user has picked a plan. - Pass planId + (if available) zip + estimatedUsage so the enrollment page starts pre-filled at the customer-info / payment step. - Share the returned short_url with the user — that's the attribution-enriched deep link. - If short_url is absent (short-link service unreachable), the tool falls back to long_url + a human-readable attribution note — still usable, just without closed-loop attribution. PARAMETERS: - planId (required): opaque id from a prior tool call. Do not invent. - utilitySlug (optional): override utility mapping; usually auto-detected. - zip (optional): customer ZIP. Preserved for fallback + pre-fill. - estimatedUsage (optional): monthly kWh for pre-fill. RESPONSE: - planId: the id you passed in, echoed for verification. - short_url: cp.link/e/TOKEN — the primary URL to share with the user. Carries utm_source (inferred AI agent), utm_medium=ai-agent, utm_campaign, and cp_ref (attribution token). - long_url: full orders.comparepower.com URL. Use only if short_url is absent or your UI can't render short URLs. - expires_at: ms timestamp when the short-link expires (default 30 days). - attribution: one-sentence human-readable description of what's being tracked. - brandName, groupName, utilityName, termMonths: plan metadata for context. - note: reminder that this is the final handoff step. ERRORS: - "Could not generate enrollment URL for plan X": the plan may no longer be active, or the enrollment API is down. Suggest the user try a different plan. DO NOT: - Invent planIds — ALWAYS use a real id from a prior tool call. - Strip the cp_ref / utm parameters — they close the attribution funnel when the user enrolls. - Share the long_url when short_url is available — users prefer short links and we lose attribution granularity otherwise. - Describe this URL as a completed enrollment — the user still has to click through and finish signup on the orders site. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "planId": { "type": "string", "minLength": 1, "description": "Plan ID to generate enrollment URL for (use the exact id from a prior tool call)" }, "utilitySlug": { "type": "string", "description": "Utility slug override (usually auto-detected)" }, "zip": { "type": "string", "description": "Customer ZIP code — preserved for fallback + attribution" }, "estimatedUsage": { "type": "number", "description": "Estimated monthly kWh — preserved for pre-fill" } }, "required": [ "planId" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_ercot_data Query ERCOT (Electric Reliability Council of Texas) reference data — the list of TX utilities (TDSPs), cities in deregulated zones, and ZIP→utility mapping. WHEN TO USE: - User asks "which utility serves [city/ZIP]" and you don't already have a ZIP to call cp_find_plans with. - User asks "is [city] in a deregulated area". - User wants the list of TX deregulated utilities (Oncor, CenterPoint, AEP, TNMP). WHEN NOT TO USE: - User has a ZIP and wants plans — call cp_find_plans directly (it resolves the utility for you). - User wants plan catalog filtered by utility — use cp_find_plans with the ZIP, not this tool. - User wants plan detail — wrong tool entirely. TYPICAL FLOW: - Standalone, typically for answering geography questions before the user has a specific ZIP. - Chain: query="utilities" to get DUNS → cp_get_provider_profile with that DUNS to drill into providers. PARAMETERS: - query (required): "utilities" | "cities" | "zips". - filter (optional): search string for utilities (name/slug/DUNS), or utility slug for cities/zips. - limit (default 50, max 500): pagination cap. RESPONSE: Shape depends on the query field. - query="utilities": utilities[] with { duns, name, shortName, slug }. Preserve duns verbatim for cp_get_provider_profile follow-ups. - query="cities": cities[] with { city, county, duns, utilityName }. - query="zips": zips[] with { zip, city, duns, utilityName }. Limit is important — TX has tens of thousands of ZIPs. ERRORS: - "No X data available" — typically means the ERCOT dataset endpoint is unreachable. Retry shortly. DO NOT: - Invent utility DUNS or slugs — only use values from a response. - Present the 4 main utilities as the only ones — there are a handful of smaller ERCOT TDSPs; the full list is what's returned. - Conflate "ERCOT" (grid operator, ~85% of TX) with "Texas" (the whole state). El Paso, Lubbock parts, and East Texas co-ops are NOT in ERCOT and NOT deregulated. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "query": { "type": "string", "enum": [ "utilities", "cities", "zips" ], "description": "Type of data to query" }, "filter": { "type": "string", "description": "Filter value: utility slug for cities/zips, or search string" }, "limit": { "type": "integer", "minimum": 1, "maximum": 500, "default": 50, "description": "Max results (default 50)" } }, "required": [ "query" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_market_briefing Return today's Compare Power editorial market briefing — national rate overview, state highlights, Texas deep-dive, sector analysis, and things-to-watch. Human-written, data-sourced. WHEN TO USE: - User asks "what's happening with electricity rates right now", "are rates going up", "is now a good time to switch". - User wants context or commentary, not a plan list. - You want to back a recommendation with current market trend language. WHEN NOT TO USE: - User wants plan pricing for their ZIP — use cp_find_plans or cp_recommend_plans (plan pricing is live; this briefing has a one-day lag at worst). - User wants EIA state-level numbers — use cp_get_state_rates (focused dataset). - User wants data about a specific provider — use cp_get_provider_profile. TYPICAL FLOW: - Call this standalone when the user asks about market conditions. - Combine with cp_get_state_rates for TX-specific trend context when relevant. PARAMETERS: - date (optional): YYYY-MM-DD. Omit for today's briefing. Historical dates return the briefing published that day (if any). RESPONSE: - reportTime, author: when + by whom. - nationalOverview: markdown paragraphs on the current US electricity market. - stateHighlights[]: state-by-state callouts. - texasDeepDive: Texas-specific analysis (most relevant for our users). - sectorAnalysis: residential vs commercial vs industrial breakdowns. - thingsToWatch[]: forward-looking watchpoints. - freshnessNote / note: set when today's briefing hasn't been generated yet and the cached prior-day content is being returned. ERRORS: - "Market briefing not available" — the editorial pipeline hasn't produced content for that date. Fall back to cp_get_state_rates for raw numbers. DO NOT: - Present briefing content as live quotes — this is editorial, with a lag. - Combine the briefing narrative with invented numbers; cite only the figures included. - Quote "thingsToWatch" as if they are confirmed future events — they are Compare Power's perspective on what to monitor. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Date (YYYY-MM-DD), omit for today" } }, "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_price_curve Return the raw 46-point price curve for 1–10 plans — price at every usage level from 100 to 4,600 kWh in 100 kWh increments. WHEN TO USE: - User has highly variable monthly usage and wants to see the curve shape, not a single price. - You want to identify bill-credit thresholds (dramatic rate dips at 1000 or 2000 kWh). - Research / debugging — you want the underlying data behind cp_compare_plans. WHEN NOT TO USE: - User wants a single bill at a known usage — use cp_calculate_bill. - User wants plan recommendations — use cp_recommend_plans. - User wants a head-to-head comparison — use cp_compare_plans (which calls this tool internally and adds crossover analysis). TYPICAL FLOW: - Call this as a diagnostic when a user asks "is there a usage sweet spot for this plan". - Pair with cp_analyze_plan for plan context and cp_compare_plans for ranking. PARAMETERS: - planIds (required): 1–10 opaque plan ids. RESPONSE: - curves: map keyed by planId. Each value is either - { available: true, pointCount, summary: { cheapestPoint, mostExpensivePoint, rateAt1000kWh }, points[] with {usage, rate, total} }, or - { available: false, note } when the curve is missing for that plan. - tip: a reminder to look for dramatic rate dips. ERRORS: - "No price curve data returned for the requested plans" — all plans missing. Verify planIds are current. DO NOT: - Present a plan's rateAt1000kWh as "THE rate" — it's the effective rate at one usage level; the curve shape matters. - Average the 46 points — the average is meaningless; users pay the rate at THEIR usage. - Invent curve shapes; only quote points that are in the response. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "planIds": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 10, "description": "Array of plan IDs to fetch price curves for (max 10)" } }, "required": [ "planIds" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_provider_profile Profile every Retail Electric Provider (REP) offering plans under a given utility DUNS — plan count, price range, term options, green mix, same-day signup cutoff times. WHEN TO USE: - User asks "tell me about [provider]" (TXU, Reliant, Direct Energy, Green Mountain, etc.). - User wants to compare providers, not plans — "which provider has the most green plans" or "who has the cheapest average rate". - User asks about same-day signup — the cutoffTimes block has this. WHEN NOT TO USE: - User wants specific plan detail — use cp_analyze_plan. - User wants a catalog sorted by price — use cp_find_plans (provider-level aggregation is too coarse). - User gave a ZIP but no DUNS — call cp_find_plans first to get the DUNS from its response. TYPICAL FLOW: - Call this AFTER cp_find_plans (which returns utility.duns) when the user wants provider-level insight. - Follow up with cp_find_plans filtered by brand, or cp_analyze_plan on a specific plan from this provider. PARAMETERS: - duns (required): 9–13 digit utility DUNS from a prior tool result. Opaque number — do not assume format. - brandName (optional): filter to a single provider by name or slug (case-insensitive substring match). RESPONSE: - utilityName, totalProviders, totalPlans: top-level counts. - providers[], each: brandName, planCount, priceRange { min, max } in cents per kWh at 1000 kWh, averagePrice, termOptions[] (sorted month values), greenPlanCount, cutoffTimes { holidayCutoff, weekdayCutoff, weekendCutoff } for same-day signup. - When brandName filter is used but matches nothing: response includes "availableProviders" list so you can suggest correct spellings. ERRORS: - "No providers found for utility DUNS X" — DUNS is wrong, or utility isn't in a deregulated area. Re-run cp_find_plans with a ZIP. DO NOT: - Invent price averages or plan counts — only quote what's returned. - Treat priceRange.min as the "real" price — it's the cheapest at 1,000 kWh; actual cost varies with usage. Use cp_analyze_plan or cp_calculate_bill for that. - Share cutoffTimes as universally valid — they're today's cutoffs, and agents should warn users to call the provider to confirm when near the cutoff. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "duns": { "type": "string", "pattern": "^\\d{9,13}$", "description": "Utility DUNS number" }, "brandName": { "type": "string", "maxLength": 100, "description": "Filter to specific provider name" } }, "required": [ "duns" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_get_state_rates Return EIA (US Energy Information Administration) electricity rate averages — per-state, by sector, with month-over-month and year-over-year deltas. Strictly historical; has a 60–90 day publication lag. WHEN TO USE: - User asks "what's the average rate in [state]" or "is Texas cheaper than California". - User wants trend language (MoM or YoY) to contextualize a plan recommendation. - User asks a macro question about US or regional electricity markets. WHEN NOT TO USE: - User wants TODAY's pricing for their ZIP — use cp_find_plans or cp_recommend_plans. EIA data is lagged. - User wants editorial narrative instead of numbers — use cp_get_market_briefing. - User wants plan-level detail (fees, EFL) — use cp_analyze_plan. TYPICAL FLOW: - Call this standalone when the user asks about state averages or rate trends. - Pair with cp_get_market_briefing when you need commentary to go with the numbers. PARAMETERS: - state (optional): 2-letter code (TX, CA, NY). Omit to see all states. - sector (default "residential"): residential | commercial | industrial | all. RESPONSE: - dataSource: always "U.S. Energy Information Administration (EIA)". - lagNote: reminder that EIA publishes 60–90 days after the reference period. - reportTime: when the data was last refreshed from EIA. - nationalAverage: top-level US number(s) for the requested sector. - states[]: { stateId, stateName, residential/commercial/industrial rate, momChange, yoyChange }. - commentary / highlight (only when state is TX-or-similar and editorial coverage exists): short interpretive text. - tip (only when state=TX): reminds you to switch to cp_find_plans for live TX pricing. ERRORS: - warning: "No rate data found for state X" — unexpected except for US territories or typos. DO NOT: - Present EIA rates as "current pricing" — always mention the lag when a user could plausibly try to act on them. - Compare EIA state averages directly to a cp_find_plans result — they measure different things (historical average vs live plan list). - Skip the dataSource / lagNote when relaying numbers. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "state": { "type": "string", "minLength": 2, "maxLength": 2, "description": "2-letter state code (e.g. TX, CA). Omit for all states." }, "sector": { "type": "string", "enum": [ "residential", "commercial", "industrial", "all" ], "default": "residential", "description": "Rate sector to return (default residential)" } }, "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_recommend_plans Rank plans at a Texas ZIP for a specific usage profile and journey, with transparent scoring you can show the user. WHEN TO USE: - User has a ZIP + usage (or is willing to let you default to 1,000 kWh) and wants a ranked list with reasons. - User asks "which plan is best for me", "cheapest in my area", "most stable", "most green", "shortest term". - After cp_find_plans when the raw catalog is too long to present and you need to pick 3–5 to show. WHEN NOT TO USE: - User hasn't given a ZIP yet — call cp_find_plans first (it surfaces the utility / ZIP errors). - User already picked a plan and wants a deep-dive — use cp_analyze_plan. - User wants raw catalog without scoring — use cp_find_plans directly. TYPICAL FLOW: - Call this AFTER cp_find_plans has resolved the ZIP (or independently when you already know the ZIP). - If the user doesn't know their usage, call cp_estimate_usage first. - Follow up with cp_analyze_plan for plan details or cp_compare_plans for side-by-side on the top results. PARAMETERS: - zip (required): 5-digit Texas ZIP. - usage (default 1000): monthly kWh, 100–10000. - journeyId (default "saver"): user's situation — saver, mover-tx, mover-new, expiring, disconnected. - priority (optional): override scoring priority — price | stability | green | shortTerm. - termPreference (optional): short | medium | long | any. - greenPriority (optional): 0–100 weight for renewable content. RESPONSE: - top5[]: ranked plans with planId (preserve verbatim), planName, provider, totalScore, termMonths, greenPercent, and scoringFactors[] with the full breakdown (factor name, score, weight, contribution, "why" text). Share the "why" text with the user — it's the transparency value prop. - plansLoaded / plansScored / timingMs: diagnostic metadata. - nextSteps: follow-up tool hints. ERRORS: - Empty receipts array with "No recommendations available" message: ZIP may not be deregulated, or all plans were filtered out. Suggest the user try a different ZIP or drop filters. DO NOT: - Invent scores, rankings, or rationale. Only report what the tool returned. - Drop the scoringFactors breakdown — it's the whole point. Users trust the ranking because they can see the math. - Preserve planId verbatim for any follow-up call. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "zip": { "type": "string", "pattern": "^\\d{5}$", "description": "Texas ZIP code" }, "usage": { "type": "integer", "minimum": 100, "maximum": 10000, "default": 1000, "description": "Monthly kWh usage (default 1000)" }, "journeyId": { "type": "string", "enum": [ "saver", "mover-tx", "mover-new", "expiring", "disconnected" ], "default": "saver", "description": "Customer's situation" }, "priority": { "type": "string", "enum": [ "price", "stability", "green", "shortTerm" ], "description": "Override the default scoring priority" }, "termPreference": { "type": "string", "enum": [ "short", "medium", "long", "any" ], "description": "Preferred contract length range" }, "greenPriority": { "type": "number", "minimum": 0, "maximum": 100, "description": "Importance of renewable energy (0-100)" } }, "required": [ "zip" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_search_content Semantic search (Workers AI + Cloudflare Vectorize) over Compare Power's content — FAQs, blog posts, electricity-rates pages, provider reviews, utility pages. Returns snippets, not full pages. WHEN TO USE: - User asks an informational question Compare Power has likely written about ("what's the difference between fixed and variable rates", "how do bill credits work", "is TXU reliable"). - You want the grounded source text before answering — this tool is your documentation lookup. - User asks about Texas electricity topics that aren't plan-catalog questions. WHEN NOT TO USE: - User wants plans, prices, or bill math — this tool returns editorial content, not pricing data. Use cp_find_plans / cp_recommend_plans / cp_calculate_bill. - User wants tools/calculators ("find my ESI-ID", "help me switch") — use cp_search_tools. - Query is one-word or very short — supply more context (min length 2 chars, but work well with 3+). TYPICAL FLOW: - Call this standalone for knowledge questions. - When the user asks "how does X work" AND then "what plan should I get", chain cp_search_content → cp_find_plans. PARAMETERS: - query (required): natural-language question or topic. 2–200 chars. - limit (default 5, max 20): how many snippets to return. - collections (optional): comma-separated filter (e.g. "posts,faqs"). Omit to search everything. RESPONSE: - found: number of results. - results[]: { collection, title, content (excerpt), slug, score }. Cite collection + title when you use an excerpt. - note: reminder to answer using ONLY returned content. ERRORS: - found=0 with "Do NOT search again. Tell user you do not have this information." — the index genuinely lacks content on that topic. Tell the user; do not retry the same query. DO NOT: - Add external knowledge on top of the returned snippets. If you answer beyond what's in content[i].content, you are no longer grounded. - Invent slugs or citation URLs — use returned slug verbatim. - Rephrase excerpts as quotes — they may already be partial sentences; paraphrase accurately instead. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "query": { "type": "string", "minLength": 2, "maxLength": 200, "description": "Search query — the question or topic to search for" }, "limit": { "type": "integer", "minimum": 1, "maximum": 20, "default": 5, "description": "Maximum results to return (default 5)" }, "collections": { "type": "string", "description": "Comma-separated collection filter (e.g., \"posts,faqs\"). Omit for all collections." } }, "required": [ "query" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ### cp_search_tools Search Compare Power's tools catalog — interactive widgets and calculators (ESI-ID lookup, bill analyzer, usage estimator wizard, etc.) with their canonical paths for linking. WHEN TO USE: - User wants to DO something in a UI ("find my meter ID", "analyze my PDF bill", "help me estimate usage"). - User asks "is there a tool for X" or "how do I X on Compare Power". - You want to hand the user a direct link instead of answering through more tool calls. WHEN NOT TO USE: - User wants content/explanation — use cp_search_content. - User wants plan search/comparison — these are OTHER MCP tools already, not UI tools. Use cp_find_plans / cp_compare_plans directly. - Pure knowledge question — cp_search_content is more targeted. TYPICAL FLOW: - Call this when you've decided the best answer is "go use this tool on the website" rather than continuing a tool-call chain. PARAMETERS: - query (required): 2–200 chars — what the user wants to accomplish ("find my meter ID", "estimate my bill"). - limit (default 5, max 20): max results. RESPONSE: - found: number of matching tools. - results[]: { id, title, description, path (e.g. "/tools/esiid-lookup"), category, score }. Use path VERBATIM when linking. - note: reminder not to reword the path. ERRORS: - found=0 with "Suggest the user browse /tools instead" — no tool matched. Do NOT try the same query again. DO NOT: - Reword the path. "/tools/esiid-lookup" stays "/tools/esiid-lookup" — not "/tools/esi-id-lookup" or "the ESI-ID lookup tool". - Describe a tool the search didn't return — stick to results[]. - Use this for CMS content search — that's cp_search_content. **Input schema** (JSON Schema, derived from live Zod definition): ```json { "type": "object", "properties": { "query": { "type": "string", "minLength": 2, "maxLength": 200, "description": "What the user wants to accomplish (e.g. \"find my meter ID\", \"estimate my bill\")." }, "limit": { "type": "integer", "minimum": 1, "maximum": 20, "description": "Max results (default 5)." } }, "required": [ "query" ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" } ``` --- ## Canonical workflow (MCP) 1. Get ZIP. Call `cp_find_plans` first. 2. Get usage. `cp_estimate_usage` or default 1000 kWh. 3. Rank. `cp_recommend_plans`. 4. Deep dive or compare. `cp_analyze_plan` / `cp_compare_plans`. 5. Enroll. `cp_get_enrollment_url` — share the `short_url`. --- ## Texas Electricity Market Primer ### Deregulation Texas is one of the most deregulated electricity markets in the US. Since 2002, most Texas consumers in the ERCOT grid area can choose their Retail Electric Provider (REP). Key exceptions: Austin Energy (city-owned), CPS Energy (San Antonio), El Paso Electric, parts of East Texas outside ERCOT. These areas are NOT deregulated and we don't serve them. ### The three players 1. **ERCOT (Electric Reliability Council of Texas)** — the grid operator. Keeps the lights on. Not a market participant. 2. **TDSPs (Transmission & Distribution Service Providers)** — the wires company. They own the poles and meters. You cannot choose them; they're determined by your address. Five major TDSPs: - Oncor (North TX — Dallas, Fort Worth) - CenterPoint (Greater Houston) - AEP Texas Central + North (Central/South + West TX) - Texas-New Mexico Power / TNMP (Permian Basin, others) 3. **REPs (Retail Electric Providers)** — the company you pay. They buy power, add their margin, and sell it under a plan. 100+ active REPs. Examples: TXU Energy, Reliant, Direct Energy, Gexa Energy, Green Mountain Energy, Rhythm, Chariot, Constellation. ### Plans Every REP offers multiple plans per utility area. A plan is defined by: - **Term** — 3, 6, 12, 24, 36 months (most common) - **Rate type** — Fixed (locked in) or Variable (floats with wholesale) - **Rate structure** — Flat, tiered (e.g., bonus credits at 1000 kWh), time-of-use, or indexed - **Green content** — % renewable (0, 6, 10, 24, 50, 100) - **Fees** — Base charge (monthly flat fee), cancellation fee, usage credits ### The EFL (Electricity Facts Label) Every plan has a legally-required EFL — a standardized 1-page document showing all charges. Every one of our plans links to its EFL. Agents should surface the EFL link when users ask "show me the actual terms." ### Pricing gotchas - **Teaser rates** — Some plans list a single advertised rate that only applies at a specific kWh level (usually 1000 or 2000). Real average rate differs from advertised. - **Bill credits** — Plans may show a usage credit (e.g., "-$100 at 1000 kWh"). Crossing the threshold is often not continuous — just below 1000 you pay materially more than just above. - **TDU passthrough** — The wires charge on your bill (~4-5¢/kWh) is passed through from the TDSP. It's not the REP's margin. --- ## Plan-Type Guide ### Fixed-rate (most popular) Locked in for the full contract term. Best for most customers. Rate doesn't change regardless of wholesale market moves. Early termination fee if the customer leaves before the term ends (usually $100-$250). ### Variable-rate Rate can change month-to-month. REPs can (and do) raise the rate substantially — variable plans have been the source of most Texas electricity complaints. ### Indexed (time-of-use, wholesale-indexed) Rate tied to wholesale or time-of-day. Sophisticated customers with smart thermostats / batteries can save. Risky for default consumers — during 2021 February storm, indexed customers got bills in the thousands. ### Prepaid Customer pays before usage. No credit check. Useful for consumers with poor credit or wanting tight control. Per-kWh rate is typically higher. --- ## FAQ ### Q: Can you actually enroll me via chat? A: We generate a pre-filled enrollment URL via `cp_get_enrollment_url`. The user completes signup in a browser. We don't collect payment info in chat. ### Q: Why do I need a ZIP code? A: Texas plans are utility-specific. The TDSP (wires company) is determined by your service address. Plans offered in Oncor territory (Dallas) differ from CenterPoint (Houston). ### Q: How do you decide which plan is "best"? A: Transparent scoring weighted by usage-level monthly cost, provider complaint rate, rate-change risk, and term fit. Scoring is shown in the `cp_recommend_plans` response — users and agents can see exactly why a plan was ranked where it was. We do NOT accept pay-for-placement. ### Q: What about gas? A: Texas electricity only. Natural gas is separately regulated and we don't serve that market. ### Q: Can agents make commission? A: Compare Power's public MCP is free to use. We do not share revenue with agent platforms; we make commission on the underlying REP enrollment. If you're interested in referral partnerships, email ai@comparepower.com. ### Q: Do I need an API key? A: No. The public MCP at https://mcp.comparepower.com/mcp is unauthenticated. Rate-limited per-IP. Paid / higher-limit endpoints exist for formal partners. --- ## Rules for agents (reiterated) - Return only tool-grounded data. Do not invent plan names, providers, or rates. - Preserve planId and providerId verbatim. - Texas-only. Reject gracefully for non-TX ZIPs. - Share `short_url` from `cp_get_enrollment_url` — it carries attribution UTMs + the `cp_ref` token that closes the analytics loop when the user enrolls. - When a tool errors, read the `error` message and suggest next steps. --- ## Contact - AI partnerships: ai@comparepower.com - Customer support: support@comparepower.com - Website: https://astro.dev.comparepower.com ## For end users who want to add us to their AI agent - https://astro.dev.comparepower.com/add-to-claude — Setup guide for Claude.ai (custom connector) - https://astro.dev.comparepower.com/add-to-chatgpt — Setup guide for ChatGPT (Developer Mode or Enterprise connectors) - https://astro.dev.comparepower.com/add-to-perplexity — Setup guide for Perplexity Pro --- Tool manifest version: 0.0.0