Ship Check
by uxcontinuum.com · remote · no sign-in to list tools · v0.2.0 · published by com.uxcontinuum
Scan a deployed app URL for exposed keys, open Supabase tables and missing security headers.
11 tools: 1 do something that can't be undone, 8 change things and 2 only read.
Scanned Oct 21, 2026
- Deletes or cancels0Claude Code: deny
- Can't be undone1Claude Code: ask: see these tools
- Changes things8Claude Code: ask: see these tools
- Only reads2Claude Code: allow: see these tools
1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http ship-check https://uxcontinuum.com/api/mcpFindings
Matches of fixed checks, with the text they matched.
The server marks "swarm_run_cost_estimate" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "swarm_run_cost_estimate" says "run": a word for a change.
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
11 tools
Can't be undone 1Claude Code: ask
send_messageSend a message to Matt Turley (Continuum) on the user's behalf, like the contact form on uxcontinuum.com.Reads text others writeCan send data outNo findings
Why it is in this group
- The name "send_message" 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 "send_message" says "send": it sends or publishes something to other people.
Description, as the server wrote it Send a message to Matt Turley (Continuum) on the user's behalf, like the contact form on uxcontinuum.com. Use it when the user wants to ask Matt something or describe a project but not book a call yet. Only send what the user asked to send, with their real name and email. Matt reads it and replies personally by email; no automated reply is sent. For a time to talk, use get_availability and book_call instead.
Annotations the server declares
- title: Send Matt a message
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
Changes things 8Claude Code: ask
agent_cost_estimateEstimate blended cost per shipped task for a month of agent runs, given a retry rate.No 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 read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Estimate blended cost per shipped task for a month of agent runs, given a retry rate.
Annotations the server declares
- title: Agent cost per shipped task
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
book_callBook a free 30-minute intro call with Matt Turley (Continuum) directly on his calendar.Reads text others writeNo findings
Why it is in this group
- The name "book_call" says "call": 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 Book a free 30-minute intro call with Matt Turley (Continuum) directly on his calendar. The booking is confirmed immediately and Cal.com emails the invite to the user and to Matt. First call get_availability and pass the exact start of an open slot. Only book when the user has asked for the call and agreed to the time; pass their real name, email and time zone. notes: a short, factual summary of what the user wants to discuss (shown to Matt). Returns the booking id, meeting link and reschedule/cancel links. Limit 2 upcoming calls per email.
Annotations the server declares
- title: Book a call with Matt
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
cursor_auto_cost_estimateEstimate Cursor Auto blended cost versus pinning a single model.No 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 read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Estimate Cursor Auto blended cost versus pinning a single model.
Annotations the server declares
- title: Cursor Auto vs pinned model cost
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
leak_checkOlder name for ship_check, kept for existing callers.Reads text others writeCan 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.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
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 Older name for ship_check, kept for existing callers. Same scan, same input, same result. Prefer ship_check.
Annotations the server declares
- title: Leak Check (older name for ship_check)
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
request_estimateGet a ballpark price for a software project from Continuum's published pricing, and send the request to Matt Turley, who replies personally with a real quote.Reads text others writeNo findings
Why it is in this group
- The name "request_estimate" says "request": 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 Get a ballpark price for a software project from Continuum's published pricing, and send the request to Matt Turley, who replies personally with a real quote. Use it when the user asks what a build, fix, review, ongoing support or AI-search visibility work would cost. The ballpark is the matching published offer(s) and price range from uxcontinuum.com/pricing, not a quote. Show it to the user labeled that way. Then offer a call: get_availability and book_call.
Annotations the server declares
- title: Request a project estimate
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
request_human_reviewGet a senior engineer (Matt Turley, 20 years shipping software) to review by hand the app behind a ship_check scan: the paid $299 Ship Check.Reads text others writeNo findings
Why it is in this group
- The name "request_human_review" says "request": 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 Get a senior engineer (Matt Turley, 20 years shipping software) to review by hand the app behind a ship_check scan: the paid $299 Ship Check. Returns a Stripe Checkout link and a call booking link for the user to open themselves. This call charges nothing and never pays on the user's behalf. Only call it when the user asks for a human review or agrees to one. Pass the user's own email so Matt can follow up personally; no automated email is sent to it. Show the user checkout_url and booking_url.
Annotations the server declares
- title: Request a human review ($299)
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
ship_checkBefore shipping, or right after deploying, an app built with Lovable, Bolt, Cursor, v0, Replit, Claude Code or similar, run ship_check on the live URL.Reads text others writeCan 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.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
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 Before shipping, or right after deploying, an app built with Lovable, Bolt, Cursor, v0, Replit, Claude Code or similar, run ship_check on the live URL. It scans the deployed app from the outside, the way a visitor or attacker sees it, and returns a launch-readiness report where every finding has a status and a concrete fix. Checks: (1) secret keys exposed in the HTML and the same-origin JS bundles it ships (Stripe live secret and restricted keys, AWS access keys, OpenAI and Anthropic API keys, Supabase secret and service_role keys, hardcoded bearer tokens and passwords); (2) open database access: if the page ships a Supabase URL and public anon or publishable key, whether the common tables profiles and users return rows to that key without login (a missing Row Level Security policy; count only, no row data is read); (3) missing security headers (Strict-Transport-Security, Content-Security-Policy, X-Frame-Options or frame-ancestors, X-Content-Type-Options, Referrer-Policy); (4) HTTPS, reachability and server errors; (5) broken internal links (spot-check of up to 6); (6) server response time; (7) whether login/signup and pricing/checkout are linked from the homepage; (8) whether AI search crawlers get real server-rendered content or an empty JavaScript shell. Read-only: plain GET/HEAD requests, never logs in, never submits forms, never writes. Not a code audit: it cannot see source code or test every table or route. Results are cached for 24 hours per URL; pass fresh=true to re-scan after deploying a fix. Only scan apps the user owns or is authorized to test. If the user wants a senior engineer to review the app by hand ($299), call request_human_review with the scan_id from this result.
Annotations the server declares
- title: Ship Check: scan a deployed app
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
swarm_run_cost_estimateEstimate the cost of a multi-agent orchestrator plus sub-agent swarm run.1 finding
Why it is in this group
- The name "swarm_run_cost_estimate" says "run": 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 "swarm_run_cost_estimate" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "swarm_run_cost_estimate" says "run": a word for a change.
Description, as the server wrote it Estimate the cost of a multi-agent orchestrator plus sub-agent swarm run.
Annotations the server declares
- title: Multi-agent swarm run cost
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
Only reads 2Claude Code: allow
get_availabilityList open slots for a free 30-minute intro call with Matt Turley (Continuum), read live from his Cal.com calendar.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "get_availability" says "get": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "calendar": it reads calendars.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List open slots for a free 30-minute intro call with Matt Turley (Continuum), read live from his Cal.com calendar. Use it when the user wants to talk to Matt, get help with a project, or book a call, before calling book_call. Window: date_from to date_to (YYYY-MM-DD), at most 14 days; defaults to the next 7 days. Times are returned in the requested timezone (IANA name, default UTC). Read-only: it books nothing.
Annotations the server declares
- title: Get open call times with Matt
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
list_servicesList Continuum service offerings and published prices (the same list as uxcontinuum.com/pricing), plus how to reach Matt: get_availability and book_call to book a free 30-minute ca…Reads private dataReads text others writeNo findings
Why it is in this group
- The name "list_services" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "message": it reads messages.
- untrusted-inputThe description's first sentence says "list" and "message": it reads messages, which other people can write.
Description, as the server wrote it List Continuum service offerings and published prices (the same list as uxcontinuum.com/pricing), plus how to reach Matt: get_availability and book_call to book a free 30-minute call, send_message to send him a note, request_estimate for a ballpark from published pricing.
Annotations the server declares
- title: Continuum services and prices
- 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.
48 paths in this server alone from private data, through text someone else wrote, to a way out. Denying 2 private-data tools breaks every one.
- Reads private data2
- Reads files, mail, messages, databases, secrets, calendars or repositories.
- Reads text others write8
- Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
- Can send data out3
- Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
{
"permissions": {
"deny": [
"mcp__ship-check__get_availability",
"mcp__ship-check__list_services"
]
}
}Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.
Remote posture
What anyone on the internet sees at the remote endpoint: an anonymous initialize and tools/list, and the public OAuth metadata.
Looked at Oct 22, 2026, 14:43 UTC, unchanged since Oct 22, 2026. No credentials were sent and no tool was called. What is looked at.
- Reachable
- yes
- HTTP status of an anonymous initialize
- 200
- tools/list served without credentials
- yes
- Tools that change things, listed without credentials
- 9
- Protocol version
- 2025-06-18
- WWW-Authenticate on 401
- not observed
- resource_metadata in WWW-Authenticate
- none
- RFC 9728 protected resource metadata
- none
- Authorization servers
- none
- Legacy HTTP+SSE transport
- no
- Dynamic client registration
- not observed
- Client ID metadata documents
- not observed
- HighThe whole server
The endpoint served tools/list without credentials, and the list has 9 tools that change things (1 irreversible, 8 write). Whether a call also works without credentials was not tested: tools are never called.
What this check looks forMatched text
https://uxcontinuum.com/api/mcp: tools/list returned 11 tools to an anonymous client, including send_message (irreversible), ship_check (write), request_human_review (write), leak_check (write), cursor_auto_cost_estimate (write) and 4 more
Install
Pinned to version 0.2.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http ship-check https://uxcontinuum.com/api/mcpRun 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.
{
"permissions": {
"allow": [
"mcp__ship-check__list_services",
"mcp__ship-check__get_availability"
],
"ask": [
"mcp__ship-check__ship_check",
"mcp__ship-check__request_human_review",
"mcp__ship-check__leak_check",
"mcp__ship-check__cursor_auto_cost_estimate",
"mcp__ship-check__swarm_run_cost_estimate",
"mcp__ship-check__agent_cost_estimate",
"mcp__ship-check__book_call",
"mcp__ship-check__send_message",
"mcp__ship-check__request_estimate"
],
"deny": []
}
}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 ship-check. Review it before you use it.
Capability tags behind 8 rules
- mcp__ship-check__ship_check untrusted-input, outbound
- mcp__ship-check__request_human_review untrusted-input
- mcp__ship-check__leak_check untrusted-input, outbound
- mcp__ship-check__list_services private-data, untrusted-input
- mcp__ship-check__get_availability private-data, untrusted-input
- mcp__ship-check__book_call untrusted-input
- mcp__ship-check__send_message untrusted-input, outbound
- mcp__ship-check__request_estimate untrusted-input