Agent rules

Copy-paste system-prompt language plus the patterns we recommend so Claude, Cursor, and any other agent uses ShipMCP tools effectively (and doesn't shoot itself in the foot).

Drop-in system-prompt block

Paste the block below into your Claude.ai system prompt, your Cursor rules file, your CLAUDE.md, or any equivalent. It teaches an agent the read/write/ingest patterns that make ShipMCP feel native instead of clunky.

# Using ShipMCP tools

This MCP server is a ShipMCP-managed endpoint. Your tool catalog includes
read tools (list_*, get_*_by_id, search_*, filter_*, count_*_by_*,
get_*_for_*) and, on write-enabled endpoints, insert_*, update_*_by_id,
delete_*_by_id, plus four ingest tools (ingest_url, ingest_file,
request_upload_url, ingest_uploaded_file) and one polling tool
(get_write_job_by_id).

Read patterns:
- Use list_<table> when you need recent rows or pagination.
- Use search_<table> for ILIKE-style fuzzy text matches across all text
  columns ("anything mentioning X").
- Use filter_<table> for structured queries with exact / range /
  date-window predicates ("status = open AND created_at > ...").
- Use get_<table>_by_id when you already have an id from another tool
  (don't search for an id you already know).
- Use count_<table>_by_<col> for "how many X by category" questions
  rather than fetching all rows and counting.
- Use get_<children>_for_<parent_singular> for FK-aware joins instead
  of pulling a full table and filtering client-side.

File access:
- Prefer the MCP resources/* methods (resources/list, resources/read)
  for file content if your client supports them. They return inline
  base64 for files <= 4 MB.
- Fall back to the get_documents_file tool. It returns a 120-second
  signed URL; follow it with a plain GET (no Authorization header).

Async writes (only on Pro+ writeable endpoints with mcp:write scope):
- All write tools (insert_*, update_*_by_id, delete_*_by_id) and all
  ingest tools return {"status": "queued", "job_id": "..."} immediately.
  They do NOT confirm the change happened.
- After every write/ingest call, IF the user is depending on the result,
  call get_write_job_by_id with the returned job_id. Poll until status
  is "succeeded" or "failed". Don't claim success based on the queued
  response alone.
- Failures don't lock the endpoint. A failed write_jobs row with
  result.error is the correct surface to report back.

Ingest:
- ingest_url is preferred for any web source. format="markdown" for
  articles/docs; format="crawl" for site-graphs (set max_depth and
  max_pages to keep it bounded); format="json" with a table_name to
  extract structured rows.
- ingest_file is fine for small files (<= 5 MB) you have as bytes.
- For larger files, use request_upload_url (returns a signed PUT URL),
  PUT the bytes there with a plain HTTP client (no auth header), then
  call ingest_uploaded_file with the returned r2_key.

What NOT to do:
- Don't try to ingest a URL you can't trust. The fetcher uses a real
  headless browser; pages it lands on can run JavaScript.
- Don't insert rows into pdf_metadata, audio_metadata, image_metadata,
  office_metadata, or web_metadata directly. Those are populated by
  the ingest pipeline. Write the parent document via insert_documents
  and the metadata fills in.
- Don't assume tools/list is current after the user enables a feature
  on shipmcp.io. The user may need to click "Rebuild" on the dashboard
  Tools card. If a tool you expect is missing, surface that.

Patterns we recommend

Start read-only. Add writes when you genuinely need them.

The default mcp scope is enough for the majority of agent workflows: search, filter, summarize, link to sources. mcp:write opens up a real-mutation surface that requires more trust in the agent's judgment. Don't enable it preemptively.

One-table-per-endpoint when scope discipline matters

ShipMCP's writes toggle is per-endpoint, not per-table. If you want an agent that can write to notes but absolutely not to customers, provision two endpoints — one read-only (with all the data the agent needs to consult) and one write-enabled (just notes). Connect each to the agent under separate consent grants. The agent's tools list makes the boundary obvious.

Treat the audit log as the source of truth

Tool responses can lie — an agent that miscounts what it did will report wrong numbers back. The dashboard's Agent writes & ingest card shows real write_jobs rows with succeeded/failed status, and the audit_log table records every mcp_write action with the row id and the OAuth client. If you want to know what an agent did, query that, don't trust the agent's summary.

Use OAuth scope as the trust boundary, not application logic

Don't write your own "is this agent allowed to write?" check inside the agent's prompt or wrapper code. The ShipMCP server enforces it server-side via the mcp:write scope claim on the bearer token. If the agent has the scope, it can write. If you don't want it to write, don't grant the scope at consent time. Revoke the token from the dashboard if you change your mind.

Poll, don't fire-and-forget

Async write/ingest tools return a job_id immediately. An agent that doesn't poll get_write_job_by_id after a write doesn't know whether the write actually landed. For workflows where downstream steps depend on the write, polling is mandatory. For pure "log this and move on" flows, fire-and-forget is fine — but tell the agent that's the intended pattern.

Future: a downloadable Claude Skill

We're working on packaging the system-prompt block above as an installable Claude Skill (and equivalents for Cursor, OpenClaw, etc.) so users don't have to copy-paste it. Watch the changelog for that.