Skip to content

Spur

com.usespur/spurusespur.comstreamable-httpv1.0.0Scanned

Real estate leads, skip tracing, direct mail, SMS & email outreach, and marketing automations

78 tools: 15 can delete or cancel things, 2 do something that can't be undone, 23 change things and 38 only read.

Tools: 15 delete, 2 irreversible, 23 write, 38 read.
  • Reads private data · 14
  • Reads text others write · 31
  • Can send data out · 10
  • 6 findings

Anlyon alternative

40 of these tools change something. Run those as governed actions.

Declare what an action changes, and Anlyon puts it under a shared limit, binds every approval to the exact request, and grades the outcome. It works on any HTTPS API you can describe as an action.

Anlyon does not run, proxy or govern this MCP server. A tool your own code calls directly is not routed through Anlyon and is not governed by it.

Import an OpenAPI spec →

Tools

Grouped by what each tool does, most consequential first. Open one for its reasons and full description; descriptions are the publisher's own words.

78 tools

Deletes or cancels 15Claude Code: deny
  • spur_change_planMoves the user to another Spur plan (ids from spur_show_billing_options; usually agent, team or brokerage).Reads text others writeNo findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Moves the user to another Spur plan (ids from spur_show_billing_options; usually agent, team or brokerage). - No paid subscription yet: returns a Stripe checkout link. No confirmation needed. - Already subscribed: switches the plan immediately and charges or credits the prorated difference to the saved card. Call once without confirm to get the exact change, ask the user to approve it, then call again with confirm=true. - Moving to the free Solo plan returns a billing-portal link where the user cancels the paid subscription.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_delete_imagePermanently delete one of the user's saved images.No findings

    Why it is in this group

    • The name "spur_delete_image" says "delete": a word for removing or ending something.
    • The description says "Permanently delete".
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Permanently delete one of the user's saved images. Refused while one of their postcard, letter or email templates still uses it, since those would show a broken image. Confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • spur_delete_letter_templatePermanently delete one of the user's letter templates.No findings

    Why it is in this group

    • The name "spur_delete_letter_template" says "delete": a word for removing or ending something.
    • The description says "Permanently delete".
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Permanently delete one of the user's letter templates. Spur defaults can't be deleted. Confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • spur_delete_message_templateDelete one of the user's email or SMS templates.No findings

    Why it is in this group

    • The name "spur_delete_message_template" says "delete": a word for removing or ending something.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Delete one of the user's email or SMS templates. Workflow steps that use it will fail until they get another template, so check spur_list_workflows and confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • spur_delete_postcard_templatePermanently delete one of the user's postcard templates.No findings

    Why it is in this group

    • The name "spur_delete_postcard_template" says "delete": a word for removing or ending something.
    • The description says "Permanently delete".
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Permanently delete one of the user's postcard templates. Spur defaults can't be deleted. Confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • spur_delete_qr_codePermanently delete a QR code.No findings

    Why it is in this group

    • The name "spur_delete_qr_code" says "delete": a word for removing or ending something.
    • The description says "Permanently delete".
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Permanently delete a QR code. Refused while one of the user's postcard templates still prints it: remove it from those first with spur_remove_postcard_qr_code. Postcards already mailed keep redirecting. Confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
  • spur_enrichRun skip tracing to find owners and their phone numbers, emails and mailing addresses.Reads text others writeNo findings

    Why it is in this group

    • The description's first verb is "run": a word for a change.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Run skip tracing to find owners and their phone numbers, emails and mailing addresses. - property_ids: find the owner of saved properties (creates/links owner records) - owner_ids: refresh contact details for existing owners Costs enrichment credits per record (check spur_get_billing_summary). Ask the user to approve the count first, then call with confirm=true.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_enroll_owners_in_workflowEnroll owners in an outreach workflow.Reads text others writeNo findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Enroll owners in an outreach workflow. The workflow will start emailing/texting/mailing them on its schedule, which uses credits. Confirm the workflow name and owner count with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_remove_postcard_qr_codeRemove the tracked QR code from one of the user's postcard templates (both sides) and show the preview.1 finding

    Why it is in this group

    • The name "spur_remove_postcard_qr_code" says "remove": a word for removing or ending something.
    • The server marks it not destructive (destructiveHint: false), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "spur_remove_postcard_qr_code" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "spur_remove_postcard_qr_code" says "remove": a word for removing or ending something.

      What this check looks for
    Description, as the server wrote it
    Remove the tracked QR code from one of the user's postcard templates (both sides) and show the preview. A QR slot from the design stays, empty.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_run_search_automationRun a search automation immediately instead of waiting for its schedule.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_run_search_automation" says "run": a word for a change.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Run a search automation immediately instead of waiting for its schedule. Uses 1 search credit (2 if the run makes more than 3 ZHomes calls), and enrichment credits if auto_enrich is on.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_send_lettersMail the letters approved in spur_preview_letter_campaign.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The name "spur_send_letters" says "send": a word for sending, and what is sent cannot be taken back.
    • The description says "Irreversible".
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe name "spur_send_letters" says "send": it sends or publishes something to other people.
    Description, as the server wrote it
    Mail the letters approved in spur_preview_letter_campaign. Irreversible and charges the user's account. Requires the preview's confirmation_token and the user's explicit approval (confirm=true).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_send_postcardsMail the postcards approved in spur_preview_postcard_campaign.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The name "spur_send_postcards" says "send": a word for sending, and what is sent cannot be taken back.
    • The description says "Irreversible".
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe name "spur_send_postcards" says "send": it sends or publishes something to other people.
    Description, as the server wrote it
    Mail the postcards approved in spur_preview_postcard_campaign. Irreversible and charges the user's account. Requires the preview's confirmation_token and the user's explicit approval (confirm=true).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_send_smsText an owner from the user's Spur number.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The name "spur_send_sms" says "send": a word for sending, and what is sent cannot be taken back.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe name "spur_send_sms" says "send": it sends or publishes something to other people.
    Description, as the server wrote it
    Text an owner from the user's Spur number. Show the user the exact message and recipient and get approval before calling with confirm=true. Costs 1 SMS credit.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_set_auto_rechargeTurns wallet auto-recharge on or off.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_set_auto_recharge" says "set": a word for a change.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Turns wallet auto-recharge on or off. When on, Spur charges the saved card amount_usd whenever the balance drops below threshold_usd, so sends never fail for lack of funds. Needs a saved card (the first spur_top_up_wallet payment saves one). Turning it on needs the user's approval of the amount and threshold (confirm=true); turning it off doesn't.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
  • spur_set_workflow_activeActivate a workflow (enrolled owners start receiving its emails, texts and mail on schedule, which uses credits) or pause it.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_set_workflow_active" says "set": a word for a change.
    • The server marks it destructive (destructiveHint: true).

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Activate a workflow (enrolled owners start receiving its emails, texts and mail on schedule, which uses credits) or pause it. Activating requires every send step to have a template and the user's explicit approval.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: false
    • openWorldHint: true
Can't be undone 2Claude Code: ask
  • spur_check_paymentAfter the user pays a Stripe checkout link from spur_top_up_wallet or spur_change_plan, confirms the payment went through and returns the new wallet balance and plan.No findings

    Why it is in this group

    • The name "spur_check_payment" says "payment": a word that usually means money moves, which cannot be taken back.
    Description, as the server wrote it
    After the user pays a Stripe checkout link from spur_top_up_wallet or spur_change_plan, confirms the payment went through and returns the new wallet balance and plan. Safe to call repeatedly.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_send_test_emailSend an email template, filled with sample data (or one owner's data), to the user's own Spur account email from their email sender, to check it in a real inbox.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The name "spur_send_test_email" says "send": a word for sending, and what is sent cannot be taken back.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe name "spur_send_test_email" says "send": it sends or publishes something to other people.
    Description, as the server wrote it
    Send an email template, filled with sample data (or one owner's data), to the user's own Spur account email from their email sender, to check it in a real inbox. Never goes to owners. Confirm with the user first.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
Changes things 23Claude Code: ask
  • spur_add_postcard_qr_codePut a tracked QR code on the back of one of the user's postcard templates and show the preview.No findings

    Why it is in this group

    • The name "spur_add_postcard_qr_code" says "add": a word for a change.
    Description, as the server wrote it
    Put a tracked QR code on the back of one of the user's postcard templates and show the preview. Each mailed postcard gets its own code under the chosen QR code, so scans are tracked per recipient (spur_get_qr_code_activity). Placement: position="auto" fills the back's QR slot (an element with class qr-box, qr-code-box, qr-placeholder or qr-callout-box, as Spur's gallery designs have) and otherwise goes in the bottom-right of the message area, left of the address block and above the USPS barcode. Corners (top_left, top_right, bottom_left, bottom_right) and x_inches/y_inches place it in the message area; spots in the USPS clear zone are refused. Replaces any QR already on the card. If it lands on the message text, call again with another corner or move the text. Create a QR code first with spur_create_qr_code if spur_list_qr_codes has none that fits.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_add_properties_to_listAdd saved properties to an existing property list.No findings

    Why it is in this group

    • The name "spur_add_properties_to_list" says "add": a word for a change.
    Description, as the server wrote it
    Add saved properties to an existing property list.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_create_email_templateSave a new email template and show its inbox preview.Can send data outNo findings

    Why it is in this group

    • The name "spur_create_email_template" says "create": a word for a change.

    What it can reach

    • outboundThe name "spur_create_email_template" says "create" and "email": it writes something other people read.
    Description, as the server wrote it
    Save a new email template and show its inbox preview. Ways to start: - From blank: start_from_blank=true gives a tested 600px responsive layout with greeting, signature and a compliant footer; pass html to replace it. - Redesign: base_template_id copies one of the user's email templates. - From scratch: pass html (or only text_body for a plain-text email). The saved template can then be used by outreach workflows (spur_create_workflow / spur_set_workflow_step_template). Email HTML guidance (see spur://email-design-guide): full HTML document, table-based layout 600px wide, inline styles on elements (a small <style> block in <head> is fine for resets/media queries), web-safe font stacks, no JavaScript, no forms, no external CSS. Images as absolute https URLs with alt text and width attributes. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use PNG or JPG in emails, not SVG. A hidden preheader <div style="display:none"> right after <body> sets the inbox snippet. Include an opt-out line ("Reply STOP" or an unsubscribe link) and the sender's postal address in the footer. Keep it under 50,000 characters. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables). The plain-text version is generated from the HTML unless you pass text_body.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_letter_templateCreate a letter template and show a preview.No findings

    Why it is in this group

    • The name "spur_create_letter_template" says "create": a word for a change.
    Description, as the server wrote it
    Create a letter template and show a preview. Pick the letter type first (top_first_page or insert_blank_page); it decides where the address prints and how much of the page the design can use. Three ways to start: - From blank: start_from_blank=true gives an empty one-page letter laid out for the letter type. - Redesign an existing template: base_template_id (yours, a Spur default or a gallery id) copies its HTML and letter type; override html or letter_type as needed. - From scratch: pass html. HTML guidance (see spur://letter-design-guide): one US Letter page (8.5"×11"), full HTML document with inline <style>, "@page { size: 8.5in 11in; margin: 0; }", no scripts. One root <div class="letter"> 8.5in wide; px/in units only (no vh/vw); no box-shadow, transforms or manual page breaks. top_first_page: leave the first 3.15in blank (an empty <div class="address-zone" style="height:3.15in">), body ≈ 3–4 short paragraphs. insert_blank_page: no address zone; letterhead up to 1.8in, body up to ~400 words. Images as absolute https URLs. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use merge fields such as {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_postcard_templateCreate a postcard template and show a preview.1 finding

    Why it is in this group

    • The name "spur_create_postcard_template" says "create": a word for a change.

    Findings

    • Info

      The description is 2,160 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...eep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped."

      What this check looks for
    Description, as the server wrote it
    Create a postcard template and show a preview. Three ways to start: - From blank: start_from_blank=true gives an empty, correctly sized canvas for the size (any side you pass HTML for replaces the blank side). - Redesign an existing template: base_template_id (yours, a Spur default or a gallery id) copies its HTML; override front_html/back_html/size as needed. - From scratch: pass both front_html and back_html. HTML guidance (see spur://postcard-design-guide): full HTML documents, inline <style>, no scripts. Fixed pixel sizing on html, body and a root .postcard at 300 px/in including 0.125" bleed: 6x4 → 1875×1275, 6x9 → 2775×1875, 6x11 → 3375×1875. Keep text 0.25" inside the edge. USPS clear zone on the back, measured from the bleed edges (Spur prints over it and covers anything there): postage 1.25"×1.25" in the top-right corner; address block 3.5"×2", 0.5" from the right edge and 1.35" from the top; USPS barcode strip 4.75"×0.625" along the bottom-right edge. Keep all text, logos, photos and QR codes out of it; a background color or texture under it is fine. The safe message area is left of the address block and above the barcode strip. Images as absolute https URLs. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use merge fields such as {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables). QR code box by default: unless the user says they don't want a QR code, every back you design includes an empty square <div class="qr-box"> in the message area (≥ 0.75in, e.g. 225×225 px at 300 px/in) with a short call to action beside it ("Scan to see your home's value"). Never write QR markup or {{qrUrl}} yourself: after saving, call spur_add_postcard_qr_code and the tracked QR fills the box (pick the code with spur_list_qr_codes, or ask the user where scans should go and spur_create_qr_code). When resending full back_html, keep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_property_listCreate a property list, optionally seeding it with saved property ids.No findings

    Why it is in this group

    • The name "spur_create_property_list" says "create": a word for a change.
    Description, as the server wrote it
    Create a property list, optionally seeding it with saved property ids.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_qr_codeCreate a tracked QR code that sends scans to destination_url.No findings

    Why it is in this group

    • The name "spur_create_qr_code" says "create": a word for a change.
    Description, as the server wrote it
    Create a tracked QR code that sends scans to destination_url. Then add it to a postcard back with spur_add_postcard_qr_code; each mailed postcard gets its own code under it so scans are tracked per recipient.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_search_automationSchedule a recurring property search.1 finding

    Why it is in this group

    • The name "spur_create_search_automation" says "create": a word for a change.

    Findings

    • Info

      The description is 2,345 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...price_drop, back_on_market, stale_listing, agent_to_fsbo and the distress stages."

      What this check looks for
    Description, as the server wrote it
    Schedule a recurring property search. Every run uses 1 search credit, or 2 when it makes more than 3 ZHomes calls (several event types, tax/sale-history events, furnished-only or description-based filters). New matches can be saved to a list and enriched automatically (auto_enrich spends skip-trace credits on every run, so confirm with the user). Examples: - "every Monday 8am Central, Dallas rentals under $2k" -> frequency="weekly", day_of_week=1, run_time="08:00", timezone="America/Chicago", location="Dallas, TX", max_amount=2000 - "last Friday of each month" -> frequency="monthly", day_of_week=5, week_of_month=-1 - "every morning, new pre-foreclosures and price drops in Houston, save to my Distress list" -> frequency="daily", run_time="07:00", location="Houston, TX", events=["preforeclosure","price_drop"], list_id=… Accepts the same advanced and event filters as spur_search_properties (min_amount / max_amount instead of min_price / max_price). Run the search once with spur_search_properties first so the user can check the results before scheduling. In automations each event fires once, on the run that first sees it, so the same property isn't saved twice; change events start reporting from the second run. "delisted" is only available here. Events (pass in `events`; a listing matches when ANY selected event fired, and is tagged with each): - Listing lifecycle: new_listing, coming_soon, coming_soon_active, price_drop, price_increase, pending, sold, back_on_market, delisted (automations only), open_house, rental_listed, rent_change, move_in_moved_up - Distress & motivation: preforeclosure, foreclosure, auction, bank_owned, distress_escalated, fsbo, agent_to_fsbo, stale_listing, new_construction - Valuation & tax: tax_assessment_posted, assessed_value_jump, tax_paid_dropped (weak), sale_recorded, zestimate_moved, equity_gap, price_below_assessed Direct events (price_drop, pending, sold, preforeclosure, fsbo, new_listing, …) work on the first search. Change events (price_increase, back_on_market, distress_escalated, agent_to_fsbo, rent_change, zestimate_moved, …) compare against what Spur saw on an earlier search of the same area, so the first search only records a baseline. Motivated-seller research usually combines price_drop, back_on_market, stale_listing, agent_to_fsbo and the distress stages.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_sms_templateSave a new SMS template and show its phone preview with segment count and checks.Can send data outNo findings

    Why it is in this group

    • The name "spur_create_sms_template" says "create": a word for a change.

    What it can reach

    • outboundThe name "spur_create_sms_template" says "create" and "sms": it writes something other people read.
    Description, as the server wrote it
    Save a new SMS template and show its phone preview with segment count and checks. The saved template can then be used by outreach workflows (spur_create_workflow / spur_set_workflow_step_template). SMS guidance: plain text, ideally one segment (160 GSM characters, or 70 if it uses emoji or other non-GSM characters; longer messages are billed per segment). Identify yourself, keep it conversational, and include opt-out wording ("Reply STOP to opt out") on first-touch messages. Links in texts from unverified numbers can be blocked, so give link-free fallback_body text when the body has a URL. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}} (see spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_create_workflowCreate a multi-step outreach sequence from saved templates.No findings

    Why it is in this group

    • The name "spur_create_workflow" says "create": a word for a change.
    Description, as the server wrote it
    Create a multi-step outreach sequence from saved templates. It's saved as an inactive draft: nothing sends until it's activated (spur_set_workflow_active) and owners are enrolled. Send steps take a saved template: email/SMS from spur_list_message_templates (design new ones with spur_create_email_template / spur_create_sms_template), direct mail from the user's saved postcard or letter templates. Wait steps space them out. Reply/open/click branches can be added afterwards in Spur → Outreach. Example: "text, wait 2 days, email, wait 5 days, postcard" -> steps=[{type:"send_sms",template_id:…},{type:"wait",days:2},{type:"send_email",template_id:…},{type:"wait",days:5},{type:"send_direct_mail",template_id:…}]

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_draft_messageDraft an email, SMS or direct-mail message with Spur's AI.Can send data outNo findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.

    What it can reach

    • outboundThe input takes a destination (input.channel): what the tool writes goes there.
    Description, as the server wrote it
    Draft an email, SMS or direct-mail message with Spur's AI. Returns text only; nothing is sent. Pass owner_id/property_id to personalize with real owner and property data. Uses 1 AI credit. Use {{merge_fields}} like {{owner_first_name}} and {{property_address}} to keep it reusable (see resource spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_manage_billingLink to the user's Stripe billing portal: update the card on file, download invoices, change or cancel the subscription.Reads text others writeNo findings

    Why it is in this group

    • The description's first verb is "link": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Link to the user's Stripe billing portal: update the card on file, download invoices, change or cancel the subscription.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • spur_save_imageDownload an image from a public https URL (the user's website, a shared photo link) and save it to the user's Spur image library, so it stays available for printing and sending.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The name "spur_save_image" says "save": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe input takes a URL (input.url): a request to a URL can carry data to whoever runs it.
    Description, as the server wrote it
    Download an image from a public https URL (the user's website, a shared photo link) and save it to the user's Spur image library, so it stays available for printing and sending. Returns the saved image's URL. JPG, PNG, WebP, GIF or SVG, up to 20 MB. For a file on the user's device, use spur_upload_image instead. Only save images the user provided or asked for.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • spur_save_propertiesSave live listings into the user's Spur properties (and optionally a property list).No findings

    Why it is in this group

    • The name "spur_save_properties" says "save": a word for a change.
    Description, as the server wrote it
    Save live listings into the user's Spur properties (and optionally a property list). Pass listing objects from spur_search_properties structuredContent.cards[].listing. Already-saved listings are refreshed, not duplicated.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_save_uploaded_imageUsed by the upload widget to save the file the user picked.No findings

    Why it is in this group

    • The name "spur_save_uploaded_image" says "save": a word for a change.
    Description, as the server wrote it
    Used by the upload widget to save the file the user picked. Not for the assistant.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_set_workflow_step_templateSet which saved template a workflow's send step uses (send_email ← email template, send_sms ← SMS template, send_direct_mail ← postcard/letter template).No findings

    Why it is in this group

    • The name "spur_set_workflow_step_template" says "set": a word for a change.
    Description, as the server wrote it
    Set which saved template a workflow's send step uses (send_email ← email template, send_sms ← SMS template, send_direct_mail ← postcard/letter template). Get step_ids from spur_get_workflow. If the workflow is active, enrolled owners get the new template from their next send.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_top_up_walletCreates a Stripe checkout link to add funds to the user's Spur wallet (pays for postcards, letters, SMS, enrichment and other usage beyond the plan).Reads text others writeNo findings

    Why it is in this group

    • The description's first verb is "create": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Creates a Stripe checkout link to add funds to the user's Spur wallet (pays for postcards, letters, SMS, enrichment and other usage beyond the plan). No money moves until the user pays on Stripe, so no confirmation is needed. If the user didn't name an amount, suggest $25, $50 or $100, or enough to cover the send they're planning.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • spur_update_email_templateEdit one of the user's email templates and show the updated inbox preview.Can send data outNo findings

    Why it is in this group

    • The name "spur_update_email_template" says "update": a word for a change.

    What it can reach

    • outboundThe name "spur_update_email_template" says "update" and "email": it writes something other people read.
    Description, as the server wrote it
    Edit one of the user's email templates and show the updated inbox preview. For tweaks pass replacements (exact find → replace in "html", "subject" or "text"); to redesign pass full html. When the HTML changes, the plain-text version is regenerated unless it was hand-written or you pass text_body. Workflows using this template send the new version from their next step. Example: replacements=[{target:"html", find:"<p style=\"margin:0 0 16px;\"></p>", replace:"<p style=\"margin:0 0 16px;\">I'd like to make a cash offer on {{property_address}}.</p>"}] Email HTML guidance (see spur://email-design-guide): full HTML document, table-based layout 600px wide, inline styles on elements (a small <style> block in <head> is fine for resets/media queries), web-safe font stacks, no JavaScript, no forms, no external CSS. Images as absolute https URLs with alt text and width attributes. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use PNG or JPG in emails, not SVG. A hidden preheader <div style="display:none"> right after <body> sets the inbox snippet. Include an opt-out line ("Reply STOP" or an unsubscribe link) and the sender's postal address in the footer. Keep it under 50,000 characters. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables). The plain-text version is generated from the HTML unless you pass text_body.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_update_letter_templateEdit one of the user's letter templates and show the updated preview.No findings

    Why it is in this group

    • The name "spur_update_letter_template" says "update": a word for a change.
    Description, as the server wrote it
    Edit one of the user's letter templates and show the updated preview. For text tweaks pass replacements (exact find → replace); to redesign, pass full html. letter_type switches between top_first_page and insert_blank_page. Spur default and gallery templates can't be edited: copy them first with spur_create_letter_template base_template_id. HTML guidance (see spur://letter-design-guide): one US Letter page (8.5"×11"), full HTML document with inline <style>, "@page { size: 8.5in 11in; margin: 0; }", no scripts. One root <div class="letter"> 8.5in wide; px/in units only (no vh/vw); no box-shadow, transforms or manual page breaks. top_first_page: leave the first 3.15in blank (an empty <div class="address-zone" style="height:3.15in">), body ≈ 3–4 short paragraphs. insert_blank_page: no address zone; letterhead up to 1.8in, body up to ~400 words. Images as absolute https URLs. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use merge fields such as {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_update_postcard_templateEdit one of the user's postcard templates and show the updated preview.1 finding

    Why it is in this group

    • The name "spur_update_postcard_template" says "update": a word for a change.

    Findings

    • Info

      The description is 2,157 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...eep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped."

      What this check looks for
    Description, as the server wrote it
    Edit one of the user's postcard templates and show the updated preview. For text tweaks pass replacements (exact find → replace on a side); to redesign, pass full front_html/back_html. Spur default and gallery templates can't be edited: copy them first with spur_create_postcard_template base_template_id. Example: change the headline -> replacements=[{side:"front", find:"Just Sold!", replace:"Just Listed!"}] HTML guidance (see spur://postcard-design-guide): full HTML documents, inline <style>, no scripts. Fixed pixel sizing on html, body and a root .postcard at 300 px/in including 0.125" bleed: 6x4 → 1875×1275, 6x9 → 2775×1875, 6x11 → 3375×1875. Keep text 0.25" inside the edge. USPS clear zone on the back, measured from the bleed edges (Spur prints over it and covers anything there): postage 1.25"×1.25" in the top-right corner; address block 3.5"×2", 0.5" from the right edge and 1.35" from the top; USPS barcode strip 4.75"×0.625" along the bottom-right edge. Keep all text, logos, photos and QR codes out of it; a background color or texture under it is fine. The safe message area is left of the address block and above the barcode strip. Images as absolute https URLs. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use merge fields such as {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables). QR code box by default: unless the user says they don't want a QR code, every back you design includes an empty square <div class="qr-box"> in the message area (≥ 0.75in, e.g. 225×225 px at 300 px/in) with a short call to action beside it ("Scan to see your home's value"). Never write QR markup or {{qrUrl}} yourself: after saving, call spur_add_postcard_qr_code and the tracked QR fills the box (pick the code with spur_list_qr_codes, or ask the user where scans should go and spur_create_qr_code). When resending full back_html, keep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_update_qr_codeRename a QR code, change where scans go, or change its colors.No findings

    Why it is in this group

    • The name "spur_update_qr_code" says "update": a word for a change.
    Description, as the server wrote it
    Rename a QR code, change where scans go, or change its colors. A new destination also applies to postcards already mailed with this code. Templates pick up new colors at send time.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_update_sms_templateEdit one of the user's SMS templates and show the updated preview.Can send data outNo findings

    Why it is in this group

    • The name "spur_update_sms_template" says "update": a word for a change.

    What it can reach

    • outboundThe name "spur_update_sms_template" says "update" and "sms": it writes something other people read.
    Description, as the server wrote it
    Edit one of the user's SMS templates and show the updated preview. Pass full text / fallback_body, or replacements (exact find → replace in "text" or "fallback"). Pass fallback_body="" to remove the fallback. SMS guidance: plain text, ideally one segment (160 GSM characters, or 70 if it uses emoji or other non-GSM characters; longer messages are billed per segment). Identify yourself, keep it conversational, and include opt-out wording ("Reply STOP to opt out") on first-touch messages. Links in texts from unverified numbers can be blocked, so give link-free fallback_body text when the body has a URL. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}} (see spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_upload_imageShow an upload box where the user picks or drops an image from their device (logo, headshot, property photo); it's saved to their Spur image library.1 finding

    Why it is in this group

    • The name "spur_upload_image" says "upload": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "spur_upload_image" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "spur_upload_image" says "upload": a word for a change.

      What this check looks for
    Description, as the server wrote it
    Show an upload box where the user picks or drops an image from their device (logo, headshot, property photo); it's saved to their Spur image library. Use this whenever the user wants to use their own image, including one they attached to the chat: attachments don't reach Spur, so ask them to drop it into the box. After uploading, the user can click "Use this image", or call spur_list_images to get the URL.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
Only reads 38Show 38 read-only tools
  • fetchFetch the full text of a record returned by search (ids look like property:…, owner:… or template:…).No findings

    Why it is in this group

    • The name "fetch" says "fetch": a word for reading.
    Description, as the server wrote it
    Fetch the full text of a record returned by search (ids look like property:…, owner:… or template:…).

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_find_ownersFind property owners in the user's Spur account by name, phone, email or mailing address text.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_find_owners" says "find": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "find" and "email": it reads mail.
    • untrusted-inputThe description's first sentence says "find" and "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Find property owners in the user's Spur account by name, phone, email or mailing address text. Use spur_get_owner for full details and portfolio.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_automation_logsRecent runs of a search automation: when, how many found/saved/enriched, and errors.No findings

    Why it is in this group

    • The name "spur_get_automation_logs" says "get": a word for reading.
    Description, as the server wrote it
    Recent runs of a search automation: when, how many found/saved/enriched, and errors.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_billing_summaryPlan, wallet balance, and this period's usage and remaining allowance per feature (searches, enrichment, SMS, postcards, letters, AI).No findings

    Why it is in this group

    • The name "spur_get_billing_summary" says "get": a word for reading.
    Description, as the server wrote it
    Plan, wallet balance, and this period's usage and remaining allowance per feature (searches, enrichment, SMS, postcards, letters, AI). Check this before large sends.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_campaign_statsDelivery and run statistics for one campaign.No findings

    Why it is in this group

    • The name "spur_get_campaign_stats" says "get": a word for reading.
    Description, as the server wrote it
    Delivery and run statistics for one campaign.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_direct_mail_analyticsLetters and postcards sent, delivered, in transit and returned, plus USPS tracking totals and spend.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_get_direct_mail_analytics" says "get": a word for reading.

    What it can reach

    • private-dataThe name "spur_get_direct_mail_analytics" says "get" and "mail": it reads mail.
    • untrusted-inputThe name "spur_get_direct_mail_analytics" says "get" and "mail": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Letters and postcards sent, delivered, in transit and returned, plus USPS tracking totals and spend.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_letter_templateFetch a letter template's HTML for reading or editing.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_get_letter_template" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe description's first sentence says "fetch" and "html": it reads web pages, which anyone can write.
    Description, as the server wrote it
    Fetch a letter template's HTML for reading or editing. For small text changes prefer spur_update_letter_template with replacements instead of resending the whole HTML.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_message_templateFetch an email template's subject, HTML and plain text, or an SMS template's text, for reading or editing.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_get_message_template" says "get": a word for reading.

    What it can reach

    • private-dataThe name "spur_get_message_template" says "get" and "message": it reads messages.
    • private-dataThe description's first sentence says "fetch" and "email": it reads mail.
    • untrusted-inputThe name "spur_get_message_template" says "get" and "message": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "fetch" and "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Fetch an email template's subject, HTML and plain text, or an SMS template's text, for reading or editing. For small changes prefer the update tool's replacements over resending everything.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_outreach_reportOutreach performance (sent, delivered, opened, replied, by channel) for all workflows or one, over an optional date range.No findings

    Why it is in this group

    • The name "spur_get_outreach_report" says "get": a word for reading.
    Description, as the server wrote it
    Outreach performance (sent, delivered, opened, replied, by channel) for all workflows or one, over an optional date range.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_ownerFull owner record: contact details, mailing address, enrichment status and their property portfolio in Spur.Reads private dataNo findings

    Why it is in this group

    • The name "spur_get_owner" says "get": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "contact": it reads contacts.
    Description, as the server wrote it
    Full owner record: contact details, mailing address, enrichment status and their property portfolio in Spur.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_postcard_templateFetch a postcard template's HTML for reading or editing.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_get_postcard_template" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe description's first sentence says "fetch" and "html": it reads web pages, which anyone can write.
    Description, as the server wrote it
    Fetch a postcard template's HTML for reading or editing. For small text changes prefer spur_update_postcard_template with replacements instead of resending whole HTML.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_propertyShow one property as a detailed card: a saved Spur property by property_id, or a live listing by zpid.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_get_property" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    Description, as the server wrote it
    Show one property as a detailed card: a saved Spur property by property_id, or a live listing by zpid. Includes owner links and enrichment status for saved properties.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • spur_get_property_statsTotals for the user's saved properties: counts by status, enrichment progress and similar portfolio-level numbers.No findings

    Why it is in this group

    • The name "spur_get_property_stats" says "get": a word for reading.
    Description, as the server wrote it
    Totals for the user's saved properties: counts by status, enrichment progress and similar portfolio-level numbers.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_qr_code_activityScan activity for a QR code: totals, which mailed recipients (owners) scanned their postcard, and recent scans of the code itself.No findings

    Why it is in this group

    • The name "spur_get_qr_code_activity" says "get": a word for reading.
    Description, as the server wrote it
    Scan activity for a QR code: totals, which mailed recipients (owners) scanned their postcard, and recent scans of the code itself. Use it to find warm leads from a postcard campaign.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_sms_conversationThe full SMS thread with one owner, oldest first.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_get_sms_conversation" says "get": a word for reading.

    What it can reach

    • private-dataThe name "spur_get_sms_conversation" says "get" and "conversation": it reads messages.
    • private-dataThe description's first sentence says "thread": it reads messages.
    • untrusted-inputThe name "spur_get_sms_conversation" says "get" and "conversation": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "thread": it reads messages, which other people can write.
    Description, as the server wrote it
    The full SMS thread with one owner, oldest first.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_get_workflowOne outreach workflow's steps in order (including reply/open branches built in the app), with the email, SMS or mail template each send step uses and its step_id.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_get_workflow" says "get": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "branch": it reads repositories.
    • untrusted-inputThe description's first sentence says "reply": it reads comments, which other people can write.
    Description, as the server wrote it
    One outreach workflow's steps in order (including reply/open branches built in the app), with the email, SMS or mail template each send step uses and its step_id.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_campaignsThe user's campaigns (bulk email, SMS, direct mail, outreach) with status and recipient progress.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_list_campaigns" says "list": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "email": it reads mail.
    • untrusted-inputThe description's first sentence says "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    The user's campaigns (bulk email, SMS, direct mail, outreach) with status and recipient progress.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_imagesThe user's saved images (logos, headshots, property photos) with their public URLs, newest first.No findings

    Why it is in this group

    • The name "spur_list_images" says "list": a word for reading.
    Description, as the server wrote it
    The user's saved images (logos, headshots, property photos) with their public URLs, newest first. Use it as <img src="…"> (or a CSS background-image) in postcard, letter or email HTML. To add one, use spur_upload_image (from the user's device) or spur_save_image (from a URL).

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_letter_templatesLetter templates available to the user, with their letter type (Top First Page or Insert Blank Page): their own (editable), Spur defaults, and Spur's built-in gallery.No findings

    Why it is in this group

    • The name "spur_list_letter_templates" says "list": a word for reading.
    Description, as the server wrote it
    Letter templates available to the user, with their letter type (Top First Page or Insert Blank Page): their own (editable), Spur defaults, and Spur's built-in gallery. Copy one with spur_create_letter_template base_template_id to redesign it, or start from blank with start_from_blank.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_message_templatesThe user's saved email and SMS templates.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_list_message_templates" says "list": a word for reading.

    What it can reach

    • private-dataThe name "spur_list_message_templates" says "list" and "message": it reads messages.
    • private-dataThe description's first sentence says "email": it reads mail.
    • untrusted-inputThe name "spur_list_message_templates" says "list" and "message": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    The user's saved email and SMS templates. These are what outreach workflow send_email / send_sms steps use.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_postcard_templatesPostcard templates available to the user: their own (editable), Spur defaults, and Spur's built-in gallery.No findings

    Why it is in this group

    • The name "spur_list_postcard_templates" says "list": a word for reading.
    Description, as the server wrote it
    Postcard templates available to the user: their own (editable), Spur defaults, and Spur's built-in gallery. Copy a default or gallery design with spur_create_postcard_template base_template_id to redesign it, or start from blank with start_from_blank.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_property_listsAll of the user's property lists with ids and sizes.No findings

    Why it is in this group

    • The name "spur_list_property_lists" says "list": a word for reading.
    Description, as the server wrote it
    All of the user's property lists with ids and sizes. Use the id with spur_list_saved_properties, spur_add_properties_to_list or outreach tools.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_qr_codesThe user's tracked QR codes: destination URL, colors, and which of their postcard templates print each one.Reads text others writeNo findings

    Why it is in this group

    • The name "spur_list_qr_codes" says "list": a word for reading.

    What it can reach

    • untrusted-inputThe description's first sentence says "url": it reads web pages, which anyone can write.
    Description, as the server wrote it
    The user's tracked QR codes: destination URL, colors, and which of their postcard templates print each one. Put one on a postcard with spur_add_postcard_qr_code; see scans with spur_get_qr_code_activity.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_return_addressesReturn addresses saved for direct mail.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_list_return_addresses" says "list": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "return" and "mail": it reads mail.
    • untrusted-inputThe description's first sentence says "return" and "mail": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Return addresses saved for direct mail. The default one is used when a campaign doesn't specify one.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_saved_propertiesList properties the user has saved in Spur, optionally filtered by city, state, list, or enrichment status.No findings

    Why it is in this group

    • The name "spur_list_saved_properties" says "list": a word for reading.
    Description, as the server wrote it
    List properties the user has saved in Spur, optionally filtered by city, state, list, or enrichment status. Shows cards and a map.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_search_automationsScheduled property searches with their schedule, filters, and next/last run times.No findings

    Why it is in this group

    • The name "spur_list_search_automations" says "list": a word for reading.
    Description, as the server wrote it
    Scheduled property searches with their schedule, filters, and next/last run times.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_sms_conversationsSMS conversations with owners, newest first, with unread counts and the last message.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_list_sms_conversations" says "list": a word for reading.

    What it can reach

    • private-dataThe name "spur_list_sms_conversations" says "list" and "conversation": it reads messages.
    • private-dataThe description's first sentence says "conversation": it reads messages.
    • untrusted-inputThe name "spur_list_sms_conversations" says "list" and "conversation": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "conversation": it reads messages, which other people can write.
    Description, as the server wrote it
    SMS conversations with owners, newest first, with unread counts and the last message. Good for triaging replies (hot leads, not interested, wrong number).

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_list_workflowsThe user's multi-step outreach workflows (email/SMS/mail sequences) with status and enrollment counts.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_list_workflows" says "list": a word for reading.

    What it can reach

    • private-dataThe description's first sentence says "email": it reads mail.
    • untrusted-inputThe description's first sentence says "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    The user's multi-step outreach workflows (email/SMS/mail sequences) with status and enrollment counts.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_parse_search_queryShow how Spur interprets a plain-English property search (filters and events) without running it.No findings

    Why it is in this group

    • The name "spur_parse_search_query" says "search": a word for reading.
    Description, as the server wrote it
    Show how Spur interprets a plain-English property search (filters and events) without running it. Free: uses no search credit. Use it to confirm intent before spending a credit, or to turn a vague request into explicit filters you can adjust. The returned arguments can be passed straight to spur_search_properties (keep the same location / status unless the user says otherwise). Exclusions ("no condos", "not foreclosures") are honoured by leaving those filters out.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_preview_letter_campaignRequired step before mailing letters.No findings

    Why it is in this group

    • The name "spur_preview_letter_campaign" says "preview": a word for reading.
    Description, as the server wrote it
    Required step before mailing letters. Renders the letter with the first recipient's real data in its letter type's layout, checks which owners have mailing addresses, estimates the cost from the user's plan (Insert Blank Page letters include the extra address page), and returns a confirmation_token. Show the preview, then ask the user to approve. Only after they approve, call spur_send_letters with the token (the widget's Send button does the same). The token expires in 30 minutes and only covers this exact template, letter type, print options, recipient set and return address.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_preview_letter_templateShow any letter template (yours, a Spur default or a gallery design) rendered with sample data, without changing anything.No findings

    Why it is in this group

    • The name "spur_preview_letter_template" says "preview": a word for reading.
    Description, as the server wrote it
    Show any letter template (yours, a Spur default or a gallery design) rendered with sample data, without changing anything.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_preview_message_draftPreview email HTML or SMS text before saving it: renders it with sample or real owner data and runs the design checks.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_preview_message_draft" says "preview": a word for reading.

    What it can reach

    • private-dataThe name "spur_preview_message_draft" says "preview" and "message": it reads messages.
    • private-dataThe description's first sentence says "preview" and "email": it reads mail.
    • untrusted-inputThe name "spur_preview_message_draft" says "preview" and "message": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "preview" and "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Preview email HTML or SMS text before saving it: renders it with sample or real owner data and runs the design checks. Nothing is saved; iterate here, then save with spur_create_email_template / spur_create_sms_template. Email HTML guidance (see spur://email-design-guide): full HTML document, table-based layout 600px wide, inline styles on elements (a small <style> block in <head> is fine for resets/media queries), web-safe font stacks, no JavaScript, no forms, no external CSS. Images as absolute https URLs with alt text and width attributes. The user's own images (logo, headshot, property photos): spur_list_images gives their URLs; if they want to use an image they have, call spur_upload_image (or spur_save_image for a link) and use the saved URL. Use PNG or JPG in emails, not SVG. A hidden preheader <div style="display:none"> right after <body> sets the inbox snippet. Include an opt-out line ("Reply STOP" or an unsubscribe link) and the sender's postal address in the footer. Keep it under 50,000 characters. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}}, {{your_phone}}, {{company_name}} (see spur://merge-variables). The plain-text version is generated from the HTML unless you pass text_body. SMS guidance: plain text, ideally one segment (160 GSM characters, or 70 if it uses emoji or other non-GSM characters; longer messages are billed per segment). Identify yourself, keep it conversational, and include opt-out wording ("Reply STOP to opt out") on first-touch messages. Links in texts from unverified numbers can be blocked, so give link-free fallback_body text when the body has a URL. Use merge fields like {{owner_first_name}}, {{property_address}}, {{your_name}} (see spur://merge-variables).

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_preview_message_templateShow a saved email (inbox view, desktop and mobile) or SMS (phone view, segment count) rendered with sample data or a real owner's data, plus design checks.Reads private dataReads text others writeNo findings

    Why it is in this group

    • The name "spur_preview_message_template" says "preview": a word for reading.

    What it can reach

    • private-dataThe name "spur_preview_message_template" says "preview" and "message": it reads messages.
    • private-dataThe description's first sentence says "show" and "email": it reads mail.
    • untrusted-inputThe name "spur_preview_message_template" says "preview" and "message": it reads messages, which other people can write.
    • untrusted-inputThe description's first sentence says "show" and "email": it reads inbound email, which other people can write.
    Description, as the server wrote it
    Show a saved email (inbox view, desktop and mobile) or SMS (phone view, segment count) rendered with sample data or a real owner's data, plus design checks. Changes nothing.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_preview_postcard_campaignRequired step before mailing postcards.No findings

    Why it is in this group

    • The name "spur_preview_postcard_campaign" says "preview": a word for reading.
    Description, as the server wrote it
    Required step before mailing postcards. Renders the postcard with the first recipient's real data, checks which owners have mailing addresses, estimates the cost from the user's plan, and returns a confirmation_token. Show the preview, then ask the user to approve. Only after they approve, call spur_send_postcards with the token (the widget's Send button does the same). The token expires in 30 minutes and only covers this exact template, recipient set, return address and size.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • spur_preview_postcard_templateShow any postcard template (yours, a Spur default or a gallery design) rendered with sample data, without changing anything.No findings

    Why it is in this group

    • The name "spur_preview_postcard_template" says "preview": a word for reading.
    Description, as the server wrote it
    Show any postcard template (yours, a Spur default or a gallery design) rendered with sample data, without changing anything.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • spur_search_propertiesSearch live listings (Zillow data) in Spur with plain English and/or structured filters, including event filters.Reads text others write1 finding

    Why it is in this group

    • The name "spur_search_properties" says "search": a word for reading.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.

    Findings

    • Info

      The description is 2,665 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...objects), or spur_create_search_automation to run the same filters on a schedule."

      What this check looks for
    Description, as the server wrote it
    Search live listings (Zillow data) in Spur with plain English and/or structured filters, including event filters. Results show as cards and a map. Uses 1 property-search credit per call from the user's Spur plan, or 2 credits when the search makes more than 3 ZHomes calls (e.g. several event types, tax/sale-history events, or description-based filters). To check how a sentence will be interpreted before spending a credit, call spur_parse_search_query first. Examples: - "3 bed houses under $2,500/mo in Austin owned 10+ years" -> location="Austin, TX", listing_status="forRent", home_type="singleFamily", min_beds=3, max_price=2500, min_ownership_years=10 - "duplexes for sale in 78704 built before 1980 with absentee owners" -> location="78704", listing_status="forSale", home_type="multiFamily", max_year_built=1979, only_absentee=true - "new pre-foreclosures or price drops of 10%+ in Dallas this week" -> location="Dallas, TX", events=["preforeclosure","price_drop"], event_within_days=7, event_min_change_pct=10 - "motivated sellers in Houston: stale, back on market, or fired their agent" -> location="Houston, TX", events=["stale_listing","back_on_market","agent_to_fsbo"] Events (pass in `events`; a listing matches when ANY selected event fired, and is tagged with each): - Listing lifecycle: new_listing, coming_soon, coming_soon_active, price_drop, price_increase, pending, sold, back_on_market, delisted (automations only), open_house, rental_listed, rent_change, move_in_moved_up - Distress & motivation: preforeclosure, foreclosure, auction, bank_owned, distress_escalated, fsbo, agent_to_fsbo, stale_listing, new_construction - Valuation & tax: tax_assessment_posted, assessed_value_jump, tax_paid_dropped (weak), sale_recorded, zestimate_moved, equity_gap, price_below_assessed Direct events (price_drop, pending, sold, preforeclosure, fsbo, new_listing, …) work on the first search. Change events (price_increase, back_on_market, distress_escalated, agent_to_fsbo, rent_change, zestimate_moved, …) compare against what Spur saw on an earlier search of the same area, so the first search only records a baseline. Motivated-seller research usually combines price_drop, back_on_market, stale_listing, agent_to_fsbo and the distress stages. Structured filters always win over what Spur infers from `query`; use query for qualitative intent (condition, style, "brick", "needs work") that only listing descriptions can match. Unset filters are left to the query. Follow up with spur_save_properties to save listings the user likes (pass the cards' listing objects), or spur_create_search_automation to run the same filters on a schedule.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • spur_show_billing_optionsShows the user's wallet balance, one-click top-up amounts, auto-recharge status and every Spur plan with prices, in a widget with Pay/Upgrade buttons.No findings

    Why it is in this group

    • The name "spur_show_billing_options" says "show": a word for reading.
    Description, as the server wrote it
    Shows the user's wallet balance, one-click top-up amounts, auto-recharge status and every Spur plan with prices, in a widget with Pay/Upgrade buttons. Use whenever the user wants to add funds, buy credits, upgrade, change or compare plans, or a send failed for billing reasons.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Exfil surface

Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.

4340 paths in this server alone from private data, through text someone else wrote, to a way out. Denying 10 outbound tools breaks every one.

deny to break every path
{
  "permissions": {
    "deny": [
      "mcp__spur__spur_create_email_template",
      "mcp__spur__spur_create_sms_template",
      "mcp__spur__spur_draft_message",
      "mcp__spur__spur_save_image",
      "mcp__spur__spur_send_letters",
      "mcp__spur__spur_send_postcards",
      "mcp__spur__spur_send_sms",
      "mcp__spur__spur_send_test_email",
      "mcp__spur__spur_update_email_template",
      "mcp__spur__spur_update_sms_template"
    ]
  }
}

Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.

Findings

Matches of fixed checks, with the text they matched.

2 warn4 info
  • The server marks "spur_remove_postcard_qr_code" not destructive (destructiveHint: false), and its own name, description or input give the class "destructive".

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "spur_remove_postcard_qr_code" says "remove": a word for removing or ending something.

    What this check looks for
  • The server marks "spur_upload_image" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "spur_upload_image" says "upload": a word for a change.

    What this check looks for
  • The description is 2,665 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...objects), or spur_create_search_automation to run the same filters on a schedule."

    What this check looks for
  • The description is 2,160 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...eep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped."

    What this check looks for
  • The description is 2,157 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...eep the qr-box and any <img data-spur-qr-merge…> inside it, or the QR is dropped."

    What this check looks for
  • The description is 2,345 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...price_drop, back_on_market, stale_listing, agent_to_fsbo and the distress stages."

    What this check looks for

History

Changes to its tool definitions and to its remote endpoint, newest first.

No change seen yet. Its tools are rescanned every day, and a remote endpoint is looked at once a week.

Install

Pinned to version 1.0.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http spur https://mcp.usespur.com/mcp
claude mcp add --transport http spur https://mcp.usespur.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__spur__spur_search_properties",
      "mcp__spur__spur_parse_search_query",
      "mcp__spur__spur_get_property",
      "mcp__spur__spur_list_saved_properties",
      "mcp__spur__spur_get_property_stats",
      "mcp__spur__spur_find_owners",
      "mcp__spur__spur_get_owner",
      "mcp__spur__spur_list_property_lists",
      "mcp__spur__spur_list_workflows",
      "mcp__spur__spur_get_workflow",
      "mcp__spur__spur_list_sms_conversations",
      "mcp__spur__spur_get_sms_conversation",
      "mcp__spur__spur_get_outreach_report",
      "mcp__spur__spur_list_message_templates",
      "mcp__spur__spur_get_message_template",
      "mcp__spur__spur_preview_message_template",
      "mcp__spur__spur_preview_message_draft",
      "mcp__spur__spur_list_postcard_templates",
      "mcp__spur__spur_get_postcard_template",
      "mcp__spur__spur_preview_postcard_template",
      "mcp__spur__spur_list_return_addresses",
      "mcp__spur__spur_preview_postcard_campaign",
      "mcp__spur__spur_list_qr_codes",
      "mcp__spur__spur_get_qr_code_activity",
      "mcp__spur__spur_list_images",
      "mcp__spur__spur_list_letter_templates",
      "mcp__spur__spur_get_letter_template",
      "mcp__spur__spur_preview_letter_template",
      "mcp__spur__spur_preview_letter_campaign",
      "mcp__spur__spur_get_billing_summary",
      "mcp__spur__spur_list_campaigns",
      "mcp__spur__spur_get_campaign_stats",
      "mcp__spur__spur_get_direct_mail_analytics",
      "mcp__spur__spur_show_billing_options",
      "mcp__spur__spur_list_search_automations",
      "mcp__spur__spur_get_automation_logs",
      "mcp__spur__search",
      "mcp__spur__fetch"
    ],
    "ask": [
      "mcp__spur__spur_save_properties",
      "mcp__spur__spur_create_property_list",
      "mcp__spur__spur_add_properties_to_list",
      "mcp__spur__spur_draft_message",
      "mcp__spur__spur_create_workflow",
      "mcp__spur__spur_set_workflow_step_template",
      "mcp__spur__spur_create_email_template",
      "mcp__spur__spur_update_email_template",
      "mcp__spur__spur_create_sms_template",
      "mcp__spur__spur_update_sms_template",
      "mcp__spur__spur_send_test_email",
      "mcp__spur__spur_create_postcard_template",
      "mcp__spur__spur_update_postcard_template",
      "mcp__spur__spur_add_postcard_qr_code",
      "mcp__spur__spur_create_qr_code",
      "mcp__spur__spur_update_qr_code",
      "mcp__spur__spur_save_image",
      "mcp__spur__spur_upload_image",
      "mcp__spur__spur_save_uploaded_image",
      "mcp__spur__spur_create_letter_template",
      "mcp__spur__spur_update_letter_template",
      "mcp__spur__spur_top_up_wallet",
      "mcp__spur__spur_check_payment",
      "mcp__spur__spur_manage_billing",
      "mcp__spur__spur_create_search_automation"
    ],
    "deny": [
      "mcp__spur__spur_enrich",
      "mcp__spur__spur_set_workflow_active",
      "mcp__spur__spur_enroll_owners_in_workflow",
      "mcp__spur__spur_send_sms",
      "mcp__spur__spur_delete_message_template",
      "mcp__spur__spur_remove_postcard_qr_code",
      "mcp__spur__spur_delete_postcard_template",
      "mcp__spur__spur_send_postcards",
      "mcp__spur__spur_delete_qr_code",
      "mcp__spur__spur_delete_image",
      "mcp__spur__spur_delete_letter_template",
      "mcp__spur__spur_send_letters",
      "mcp__spur__spur_change_plan",
      "mcp__spur__spur_set_auto_recharge",
      "mcp__spur__spur_run_search_automation"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as spur. Review it before you use it.

Capability tags behind 37 rules
  • mcp__spur__spur_search_properties untrusted-input
  • mcp__spur__spur_get_property untrusted-input
  • mcp__spur__spur_find_owners private-data, untrusted-input
  • mcp__spur__spur_get_owner private-data
  • mcp__spur__spur_enrich untrusted-input
  • mcp__spur__spur_draft_message outbound
  • mcp__spur__spur_list_workflows private-data, untrusted-input
  • mcp__spur__spur_get_workflow private-data, untrusted-input
  • mcp__spur__spur_set_workflow_active untrusted-input
  • mcp__spur__spur_enroll_owners_in_workflow untrusted-input
  • mcp__spur__spur_send_sms untrusted-input, outbound
  • mcp__spur__spur_list_sms_conversations private-data, untrusted-input
  • mcp__spur__spur_get_sms_conversation private-data, untrusted-input
  • mcp__spur__spur_list_message_templates private-data, untrusted-input
  • mcp__spur__spur_get_message_template private-data, untrusted-input
  • mcp__spur__spur_preview_message_template private-data, untrusted-input
  • mcp__spur__spur_preview_message_draft private-data, untrusted-input
  • mcp__spur__spur_create_email_template outbound
  • mcp__spur__spur_update_email_template outbound
  • mcp__spur__spur_create_sms_template outbound
  • mcp__spur__spur_update_sms_template outbound
  • mcp__spur__spur_send_test_email untrusted-input, outbound
  • mcp__spur__spur_get_postcard_template untrusted-input
  • mcp__spur__spur_list_return_addresses private-data, untrusted-input
  • mcp__spur__spur_send_postcards untrusted-input, outbound
  • mcp__spur__spur_list_qr_codes untrusted-input
  • mcp__spur__spur_save_image untrusted-input, outbound
  • mcp__spur__spur_get_letter_template untrusted-input
  • mcp__spur__spur_send_letters untrusted-input, outbound
  • mcp__spur__spur_list_campaigns private-data, untrusted-input
  • mcp__spur__spur_get_direct_mail_analytics private-data, untrusted-input
  • mcp__spur__spur_top_up_wallet untrusted-input
  • mcp__spur__spur_change_plan untrusted-input
  • mcp__spur__spur_manage_billing untrusted-input
  • mcp__spur__spur_set_auto_recharge untrusted-input
  • mcp__spur__spur_run_search_automation untrusted-input
  • mcp__spur__search private-data, untrusted-input

Pin

Keep the decision: fail CI when the tools change, follow every change, or show a badge.

Pin in CI

Fail a build when the tools you reviewed are not the tools the server serves today.

curl -s "https://anlyon.dev/api/v1/servers/com.usespur/spur/verify?hash=d0745ca2d2a7f948fbdda153131effe3b98c5d8ba6f5abf9b2bb522cb549662e" | jq -e '.changed == false'

Pinned hash d0745ca2d2a7, from Oct 24, 2026, 19:17 UTC.

Watch

Get told when its tools change: a new tool, a new description, a new class.

https://anlyon.dev/servers/com.usespur/spur/changes.xml

An Atom feed. Works in any feed reader or Slack's RSS app.

Badge

anlyon.dev badge for com.usespur/spur
[![anlyon.dev](https://anlyon.dev/badge/com.usespur/spur.svg)](https://anlyon.dev/servers/com.usespur/spur)

Source: MCP Registry. Synced Oct 24, 2026, 19:17 UTC.