MCP server

Tearoff in your AI

Tearoff is an MCP server. Add it to Claude, ChatGPT or Cursor, sign in with your own Tearoff seat, and ask about roofing permits, firms and hail in your market.

The server

Connector URL: https://tearoffdata.com/api/mcp

Read-only. Every tool reads. None writes, deletes or sends anything, and it reads only the markets your workspace subscribes to.

Your own seat. The first time you connect, your AI opens a Tearoff sign-in (OAuth through Clerk). The seat that opens the board is the seat your AI reads with. There is no key to paste.

Coverage on every answer. Each answer names the permit offices it read, the dates it covers, and the offices it left out and why, so a partial count never passes for a whole one.

120 requests per 60 seconds, per workspace. A runaway loop is refused, not billed.

Tools

17 tools, as the server lists them

  • Find places find_places

    What your AI reads

    Place ids look like aurora-city or arapahoe-county-unincorporated, never a bare town name; call this to get one. `metro`, the whole market, is always valid. Search the closed list of places this market knows: the metro and each permit office (a town, or a county for its unincorporated land), one id each — the id every answer's coverage names. Does not answer permit counts by itself. There is no whole-county id: a county id is only its land outside every town, and a town id is the whole town, across county lines, never part of a county id. For a whole county ("Douglas County"), call its unincorporated id and each of its towns, and say which you counted and that a town crossing the line counts whole; find_places does not say which county a town is in.

  • Find firms find_firms

    What your AI reads

    Search contractors in this market by name. Use before firm_profile. Firms that have pulled roofing permits are listed first, then the rest, each group by name: a licence roster or the state register can name an electrician or a builder too, so a name alone does not make a firm a roofer. Each match carries roofingPermits, the roofing permits it has pulled on file in any year, counted as whos_winning counts, and roofingWords, that count for a reader ("2 roofing permits", or "no roofing permits on record"). Every permit on file is a roofing permit. For permits by year or office, call firm_profile.

  • Find storms find_storms

    What your AI reads

    Hail swaths the ledger has joined to parcels, newest first. Pass no query, or "latest", for the most recent storms; a day, month or year (2026-08-26, 2026-08, 2026) narrows the list. Each storm id is day:threshold, one per hail size of the day, where threshold is the hail size in inches; the lowest threshold of a day is its widest footprint and the usual choice for leads. Use before storm_aftermath or prospect_list by storm. Does not list individual roofs. There is no address lookup and no hail lookup for one point: owners come only from the county roll, as prospect_list's rows for a zip or a storm, so do not page a whole zip to find one house. A month can hold several hail days: for "the September storm", name the days and ask which, never pick one silently; storm_aftermath's roofs.inSwath sizes each.

  • Who's winning whos_winning

    What your AI reads

    Answers in text. For a card, call compose_card with this question. Firm league for a place and period: roofing permits naming each contractor. Every permit on file is a roofing permit; no tool tells a re-roof from a repair. Needs placeId from find_places and a period. For "the last twelve months" or "the past year" pass last-12-months, not the calendar year. "This year" is the year (2026) and "this month" the month under way, both partial: say the day they are read through. "Right now" and "lately" are the last three whole months (2026-07..2026-09 in October); a season such as "this fall" is its months so far (2026-09..2026-10). A span may end on the month under way. Over 24 months is refused: say so and offer the latest 24. A month the ledger has not read whole, such as the month under way, is listed in partialMonths with the day it is read through; say so beside the league, so "the past year" in October is never read as twelve whole months. Each firm's share is its percent of every permit naming a firm in the place and period. For "who's gaining share" pass compareTo over matched months: a month against the same month a year before (2026-08 against 2025-08), or for a year the same months of each, ending on the last whole month (2026-01..2026-09 against 2025-01..2025-09), never a partial year against a whole one (2026 against 2025). gainers and losers name the firms whose share moved most, from both leagues, and fellAway counts the firms of compareTo that pulled none in period; never page two leagues to compute share by hand. State the answer's coverage from the envelope: the offices and dates read, and what was left out. Does not profile one firm or list owners.

  • Town pulse town_pulse

    What your AI reads

    Answers in text. For a card, call compose_card with this question. Roofing permits per month for a place against seasonal rhythm when on file. Every permit on file is a roofing permit; no tool tells a re-roof from a repair. It counts every permit in the place, naming a firm or not, so its total can exceed the sum of whos_winning's firms. Needs placeId and period. For "the last twelve months" or "the past year" pass last-12-months, not the calendar year. "This year" is the year (2026) and "this month" the month under way, both partial: say the day they are read through. "Right now" and "lately" are the last three whole months (2026-07..2026-09 in October); a season such as "this fall" is its months so far (2026-09..2026-10). A span may end on the month under way. Over 24 months is refused: say so and offer the latest 24. A month the ledger has not closed is marked partial with the day it is read through; say so, and never call it the latest month. A month marked read false was not read: say it is unknown, never 0. State the answer's coverage from the envelope: the offices and dates read, and what was left out. Does not list firms or change events.

  • Storm aftermath storm_aftermath

    What your AI reads

    Answers in text. For a card, call compose_card with this question. Roofs crossed and roofing permits since a hail day, by band, over the roofs in towns whose permits we read; for the named band, roofs permitted and still open, the towns, the window and the roofs left out. Needs stormId from find_storms. In its day:threshold, threshold is the hail size in inches; the lowest threshold of a day is its widest footprint and the usual choice for leads. Permits are counted from the storm day through today in the market's timezone unless through is given. Also names the top ten roofers already working the storm (firms on those permits, most first; totalFirms counts all) and the top ten zips by roofs crossed that we read, each with its roofs still open (totalZips counts all). To compare two storms, call storm_aftermath on each with the same number of days from its storm day to through. To read storms together, as a board does when several are picked, add stormIds: every roof under any of them is counted from the first storm that crossed it, and roofs.twice counts the open roofs under two or more. Add placeId from find_places to count only the roofs one town permits, as a board on that town counts them; leave it out, or metro, for the whole market. State the answer's coverage from the envelope: the offices and dates read, and what was left out. Does not list owner names — use prospect_list for that.

  • Firm profile firm_profile

    What your AI reads

    Answers in text. For a card, call compose_card with this question. Volume, offices, and recent roofing permits for one firm, across the metro. Needs firmId from find_firms. Windows: permitsYtd and officesYtd are the market's calendar year to date (ytdYear), permitsYtd as whos_winning counts the metro's year; permits12Months is the twelve months back from the newest permit the market has on file, by day, so it is not whos_winning's last-12-months (calendar months to the month under way, for one place): never set the two side by side; offices counts every office its permits name since its first permit; recentPermits are its ten newest permits on file, of any year. State the answer's coverage from the envelope: the offices and dates read, and what was left out. Does not rank firms, export owner lists, or place a firm inside a storm (storm_aftermath names its firms).

  • This week this_week

    What your AI reads

    Answers in text. For a card, call compose_card with this question. Change events detected in the last seven days (not the calendar week) for a place, each with its sentence. Kinds: a roofer's first permit in an office, a roofer busier than usual or entering a new area, an office's unusual permit month, a licence expiring, the week's findings, and records to check. Hail reported, permits after a storm, new roofing businesses on the state register and firms out of good standing name no office, so only metro has them. Needs placeId. An event with verify=true is a lead to check, not a fact. State the answer's coverage from the envelope: the offices and dates read, and what was left out.

  • Prospect list prospect_list

    What your AI reads

    Answers in text. For a card, call compose_card with this question. With stormId: the band's open roofs (no roofing permit on the roof since the hail day, in towns whose permits we read), best leads first: roofs with a street address, then most roofing permits within 300 m since the hail, then the larger hail. A zip with stormId narrows them to that zip, ranks staying the storm's. A zip alone lists every roof the county roll holds there, not open leads: rank and the storm fields are null, owner-occupied numbered houses first, then other numbered addresses, then the rest, by street. For "open", "best doors" or who to knock in a zip, pass a stormId too. total counts every match. Each row is the board's storm file's row: roof id, rank, situs, owner and mailing address (public record), hail size, permits within 300 m since the hail, issuing office, the roof's own permit since the hail, last permit contractor and centroid. Amber rows are portal-collected. Up to 500 a page, so a 10,000-roof band is 20 pages. Needs zip or stormId. Does not rank contractors. State the answer's coverage from the envelope: the offices and dates read, and what was left out.

  • Compose card compose_card

    What your AI reads

    Draw one ledger card from a brief and the ledger questions it needs. Pass every tool you want bound and a sentence or two about what the reader should see. The brief is words only. Zips, counts, page sizes, days and hail sizes go in questions[].arguments, where the card reads them, and the brief names them in words: write "the roofs still open in the zip the user named", not "open roofs in 80015"; write "the top fifty open roofs", not "the top 50 open roofs" or "the last 12 months". A four-digit year is the one number allowed, and only where it ends a phrase (before a comma, a full stop or nothing): write "the late August hail of 2026, across the widest band", not "Aug 26" or "the August 2026 hail"; write "roofing permits so far in 2026", not "the 2026 season so far"; write "share in 2026, against the same months of 2025", not "share of 2026 against 2025". A digit in a firm's name is refused too: write "the firm the user named", not "A1 Roofing"; the card prints the name from the answer. A brief with any other digit is refused before anything runs. One card per firm, storm or place: compose a card for each, or compare them in text; to rank several firms on one card, compose a whos_winning card for their place. The server re-runs the questions, builds parts from the answers, and arranges them. The storm_aftermath recipe draws the hail swath on a map. Ledger card recipes (one word each, editable in follow-up calls): - storm_aftermath - whos_winning - town_pulse - firm_profile - this_week - prospect_list

  • Lead file lead_file

    What your AI reads

    Hands the user a downloadable CSV, never rows. list "storm" with a stormId from find_storms is the band's open roofs (no roofing permit on the roof since the hail day, in towns whose permits we read), best leads first as prospect_list ranks them, up to 10,000 roofs: the door-knocking list. Add stormIds at the same threshold to file several storms as one list. Add sub to file one knock zone: every open roof in that neighborhood (the city name where a city publishes one, else the plat; e.g. "Southshore" or "BLACKSTONE COUNTRY CLUB"). Empty sub files roofs with no neighborhood. A PARENT (CUSTOMS) plat files with PARENT. There is no zip or street filter: without sub it is the whole band, so after a zip-narrowed prospect_list say the file holds every zip. list "prospects" is not prospect_list and not a canvass list: one row per roofing contractor per permit office, ranked by permits, with share, prior-year count and licence standing, for a month (YYYY-MM, or the last whole month when omitted). The answer is a summary and a download link that works for 15 minutes; give the user the link. To read rows yourself, use prospect_list.

  • Storm door summary storm_door_summary

    What your AI reads

    Compact cells of a storm's open doors for grouping in your own model. The text lists each cell with its id, door count, centroid, zips, city and max hail — use those ids in show_door_groups. Call find_storms first, then optional storm_door_page for door-level splits (pass the same unit and gridMeters so cellIds match). Then call show_door_groups with the groups you decided (cells plus door exceptions). Each door belongs in one group; keep streets together. Put a name in a group only when the user named one. Groups live in this chat only; they are not saved on the board. Does not include owner or mailing fields.

  • Storm door page storm_door_page

    What your AI reads

    Exact open doors for a storm, paged. Needs snapshotId from storm_door_summary and at least one of cellIds, zips, bbox, or a non-empty filter in select. Repeat the summary filter so stale reflects the same door set. Pass unit and gridMeters from the summary when paging so cellIds match. The text lists each door as roofId, cellId, hail, address, zip and centroid. No owner or permit detail.

  • Storm groups read storm_groups_read

    What your AI reads

    Board-saved door groups for a storm, when the board has grouped. The text lists each group name and door count. Session groups from show_door_groups are not stored and will not appear here. Use includeDoors to page roof ids in one board group.

  • Show door groups show_door_groups

    What your AI reads

    Draw the door-groups card for this chat. Pass the groups you decided from storm_door_summary cells (and optional doorIds). The server checks doors, paints hulls, and returns the card. Groups live in this chat only; they are not saved on the board. Call this after you group. A name is a door-group label, not an assignee.

  • Door groups file door_groups_file

    What your AI reads

    A signed 15-minute CSV for one door group or all groups in this chat. Pass the same groups you sent to show_door_groups. The file has door_group and group_name columns. Groups are not saved.

  • Who am I whoami

    What your AI reads

    Returns the workspace and market this OAuth token may read.

A card inside the chat calls 4 more to page or filter itself: card_refetch, card_page, card_filter, card_present.

Claude

  1. In Claude’s connector settings (Pro and Max: Customize → Connectors → Add custom connector), paste the connector URL.
  2. Sign in with Clerk when Claude asks.
  3. Ask it to read your workspace’s ledger — who is winning, this week, a storm.

ChatGPT

  1. In ChatGPT’s app or connector settings, turn on developer mode if asked, then add the connector at the same URL.
  2. Sign in with Clerk when ChatGPT asks.
  3. Ask the same questions. Cards open inline; use full screen if a card offers it.

Cursor

  1. In Cursor Settings, open MCP and add a remote server at the connector URL.
  2. Sign in with Clerk when Cursor opens the browser. No client id to paste.

More

What Tearoff is: the front page. How it handles your data: Privacy. The rules of use: Terms of use.