# PasteApply

> Honest resume/cover tailor for agents. Free generate; Stripe unlock for downloads. Streamable HTTP.

- name: com.pasteapply/mcp
- version: 1.0.0
- connection class: R0 (autonomous)
- trust: 80/100 flags: no-repository
- quality: 67/100 (needs work)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/com.pasteapply%2Fmcp
- tools: https://api.protogrid.dev/v1/servers/com.pasteapply%2Fmcp/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "pasteapply": {
      "type": "http",
      "url": "https://pasteapply.com/mcp"
    }
  }
}
```


## Trust

- hygiene: 80
- liveness: 100
- freshness: 85
- provenance: 55
- drivers: +dns-namespace +website +reachable +uptime-100% ~updated-43d-ago -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 67/100 (needs work)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 71 (weight 30)

- pass `tools.descriptions`: every tool has a description
- pass `tools.description_length`: descriptions are concise
- pass `tools.schemas`: every tool has an object input schema
- fail `tools.annotations`: no tool declares readOnlyHint or destructiveHint, so clients cannot tell safe calls from risky ones
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: generate (readOnlyHint, destructiveHint, idempotentHint, openWorldHint); status (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)
- pass `tools.token_cost`: about 307 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 25 (weight 15)

- warn `stability.changes`: 13 tool changes in 30 days
- fail `stability.rug_pull`: 2 tools kept their name but changed most of their description in 30 days; review before trusting them

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 2, about 307 tokens to load them all
- tool set hash: 6e03f4b48fd60d3da53b075ce41803b4
- tools last changed: 2026-10-09T06:34:57.155Z
- badge: [![protogrid quality](https://protogrid.dev/badge/com.pasteapply/mcp.svg)](https://protogrid.dev/servers/com.pasteapply/mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-09 `get_generation` removed
  - Happy path after pay: poll until paid:true (webhook persists the unlock). Poll a generation including paid/unlocked after the human pays. Pass id or generationId (same uuid from generate). When paid:true: full coverLetter, resume, and files.ready/files.pdf/files.docx/files.coverPdf/files.expiresAt/files.coverLetter/files.resume (pdf/docx/coverPdf ?dl= URLs last the UTC billing month; refresh via get_generation anytime in-month). On file GET 403, re-call get_generation for a fresh token. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-10-09 `store_resume` removed
  - Store resume text in the vault and get a resumeId (rs_1.<uuid>) to reuse on generate. Prefer resumeId on later generate over re-pasting the full resume. Pass resume text here. For PDF/DOCX/DOC/TXT/MD files, use HTTP POST /api/resumes multipart field "file" (max ~8MB) — this MCP tool is text-only. Stored text is used as-is (honesty lock; never invent employers). TTL ~30 days. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-10-09 `confirm_payment` removed
  - Fallback unlock when get_generation still shows paid:false after the human paid (slow webhook). Pass the cs_ session id from the success URL. Happy path: poll get_generation until paid:true — no cs_ required. When paid, returns full coverLetter, structured resume, files.pdf/docx/coverPdf absolute URLs (?dl= token lasts UTC billing month), and apiKey (Authorization Bearer pa_… for later status/generate). Or POST /api/agent-key {sessionId, claimToken}. Pass claimToken from unlock_link: without it (and without the paying Google session) only the draft status comes back — no plan link, no apiKey. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human.
- 2026-10-09 `unlock_link` removed
  - PURCHASES MAY BE PAUSED: while file storage is unavailable this tool returns an error with code purchases_paused (HTTP 503 + retryAfter, nothing charged, no Checkout created). Check status first (purchasesPaused / pricesAvailable) and do not retry in a loop. Otherwise: create a Stripe Checkout URL so a HUMAN can pay $5/mo Export (5 unlocks, default), $3/mo (1 unlock), $10/mo Pro (50 unlocks + extras), or $20/mo (up to 200 unlocks within 2,350 signed-in requests a month + Pro extras). After the human pays, poll get_generation until paid:true for paid files fields (files.ready, files.pdf, files.docx, files.coverPdf, files.expiresAt, files.coverLetter, files.resume). confirm_payment only if the poll stays unpaid (also returns apiKey pa_…): keep the claimToken from this reply and pass it to confirm_payment — only the Checkout's starter can link the plan or get the key. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-10-09 `generate` changed (title, description, inputSchema) **meaning changed**
  - before: Tailor a resume and cover letter to one job posting. Pass jobPosting text and/or jobUrl (public http(s); we fetch+strip HTML; prefer pasted jobPosting if both). Pass resume text and/or resumeId from store_resume / POST /api/resumes (prefer resumeId over re-pasting; pasted resume still wins if both). Resume or resumeId required unless useSample. Unpaid generate returns a teaser only (coverage, fit.recommend skip|weak|apply with mustHavesMissing/impliedOnly and fit.gap naming any missing must-have (exactly one missing must-have ⇒ weak; two or more ⇒ skip; interview % bands follow the verdict: apply 70–95, weak 45–69, skip 0–44), recommendUnlock false when skip / true when weak|apply with optional unlockAdvice, proof, short what-changed, redacted sample). Check recommendUnlock / fit.recommend before unlock_link — do not unlock when skip. Full letter and resume require unlock_link or a paid Bearer pa_… key with unlocks remaining. Free daily cap → HTTP 429 code free_cap + retryAfter; paid month unlock cap → HTTP 402 code unlock_quota (not retry-later). Optional BYOK: modelProvider openai|anthropic as a tool arg; send the provider key only in connection header X-PasteApply-BYOK-Key (env-var placeholder — never a literal key in tool args or chat). Hosted is default. Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=up to 200 (within 2,350 signed-in requests a month). Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics. If the posting wants something not on the source resume, omit it.
  - after: Free fixed sample only: call with useSample:true to see what a tailored resume and cover letter look like (a fixed example, not the user's resume; no AI runs; nothing charged). Free on PasteApply is a fixed sample right now: it shows what a tailored resume and cover letter look like, and no AI runs on free requests. Tailoring your own resume needs a plan. Any other call answers HTTP 402 code free_samples_only with nothing charged. A human tailors their own resume on https://pasteapply.com after signing in with Google and choosing a plan; agent keys, the resume vault, unlock links and saved drafts are temporarily off. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-10-09 `status` changed (description) **meaning changed**
  - before: Read PasteApply readiness (openaiConfigured, stripeConfigured, prices, plan/unlocks when Bearer pa_). Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=up to 200 (within 2,350 signed-in requests a month). Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
  - after: Read PasteApply status: freeMode "samples_only", purchasesOpen, prices (empty while purchases are paused), storage "off" and which features are temporarily off. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-10-01 `unlock_link` changed (description)
  - before: Create a Stripe Checkout URL so a HUMAN can pay $5/mo Export (5 unlocks, default), $3/mo (1 unlock), $10/mo Pro (50 unlocks + extras), or $20/mo (up to 200 unlocks within 2,350 signed-in requests a month + Pro extras). After the human pays, poll get_generation until paid:true for paid files fields (files.ready, files.pdf, files.docx, files.coverPdf, files.expiresAt, files.coverLetter, files.resume). confirm_payment only if the poll stays unpaid (also returns apiKey pa_…): keep the claimToken from this reply and pass it to confirm_payment — only the Checkout's starter can link the plan or get the key. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
  - after: PURCHASES MAY BE PAUSED: while file storage is unavailable this tool returns an error with code purchases_paused (HTTP 503 + retryAfter, nothing charged, no Checkout created). Check status first (purchasesPaused / pricesAvailable) and do not retry in a loop. Otherwise: create a Stripe Checkout URL so a HUMAN can pay $5/mo Export (5 unlocks, default), $3/mo (1 unlock), $10/mo Pro (50 unlocks + extras), or $20/mo (up to 200 unlocks within 2,350 signed-in requests a month + Pro extras). After the human pays, poll get_generation until paid:true for paid files fields (files.ready, files.pdf, files.docx, files.coverPdf, files.expiresAt, files.coverLetter, files.resume). confirm_payment only if the poll stays unpaid (also returns apiKey pa_…): keep the claimToken from this reply and pass it to confirm_payment — only the Checkout's starter can link the plan or get the key. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-09-30 `unlock_link` changed (description)
  - before: Create a Stripe Checkout URL so a HUMAN can pay $5/mo Export (5 unlocks, default), $3/mo (1 unlock), $10/mo Pro (50 unlocks + extras), or $20/mo (200 unlocks + Pro extras). After the human pays, poll get_generation until paid:true for paid files fields (files.ready, files.pdf, files.docx, files.coverPdf, files.expiresAt, files.coverLetter, files.resume). confirm_payment only if the poll stays unpaid (also returns apiKey pa_…): keep the claimToken from this reply and pass it to confirm_payment — only the Checkout's starter can link the plan or get the key. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
  - after: Create a Stripe Checkout URL so a HUMAN can pay $5/mo Export (5 unlocks, default), $3/mo (1 unlock), $10/mo Pro (50 unlocks + extras), or $20/mo (up to 200 unlocks within 2,350 signed-in requests a month + Pro extras). After the human pays, poll get_generation until paid:true for paid files fields (files.ready, files.pdf, files.docx, files.coverPdf, files.expiresAt, files.coverLetter, files.resume). confirm_payment only if the poll stays unpaid (also returns apiKey pa_…): keep the claimToken from this reply and pass it to confirm_payment — only the Checkout's starter can link the plan or get the key. Never scrape card UI. Never complete Stripe Checkout as the user. Hand the Checkout URL to a human. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- 2026-09-30 `generate` changed (description)
  - before: Tailor a resume and cover letter to one job posting. Pass jobPosting text and/or jobUrl (public http(s); we fetch+strip HTML; prefer pasted jobPosting if both). Pass resume text and/or resumeId from store_resume / POST /api/resumes (prefer resumeId over re-pasting; pasted resume still wins if both). Resume or resumeId required unless useSample. Unpaid generate returns a teaser only (coverage, fit.recommend skip|weak|apply with mustHavesMissing/impliedOnly and fit.gap naming any missing must-have (exactly one missing must-have ⇒ weak; two or more ⇒ skip; interview % bands follow the verdict: apply 70–95, weak 45–69, skip 0–44), recommendUnlock false when skip / true when weak|apply with optional unlockAdvice, proof, short what-changed, redacted sample). Check recommendUnlock / fit.recommend before unlock_link — do not unlock when skip. Full letter and resume require unlock_link or a paid Bearer pa_… key with unlocks remaining. Free daily cap → HTTP 429 code free_cap + retryAfter; paid month unlock cap → HTTP 402 code unlock_quota (not retry-later). Optional BYOK: modelProvider openai|anthropic as a tool arg; send the provider key only in connection header X-PasteApply-BYOK-Key (env-var placeholder — never a literal key in tool args or chat). Hosted is default. Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=200. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics. If the posting wants something not on the source resume, omit it.
  - after: Tailor a resume and cover letter to one job posting. Pass jobPosting text and/or jobUrl (public http(s); we fetch+strip HTML; prefer pasted jobPosting if both). Pass resume text and/or resumeId from store_resume / POST /api/resumes (prefer resumeId over re-pasting; pasted resume still wins if both). Resume or resumeId required unless useSample. Unpaid generate returns a teaser only (coverage, fit.recommend skip|weak|apply with mustHavesMissing/impliedOnly and fit.gap naming any missing must-have (exactly one missing must-have ⇒ weak; two or more ⇒ skip; interview % bands follow the verdict: apply 70–95, weak 45–69, skip 0–44), recommendUnlock false when skip / true when weak|apply with optional unlockAdvice, proof, short what-changed, redacted sample). Check recommendUnlock / fit.recommend before unlock_link — do not unlock when skip. Full letter and resume require unlock_link or a paid Bearer pa_… key with unlocks remaining. Free daily cap → HTTP 429 code free_cap + retryAfter; paid month unlock cap → HTTP 402 code unlock_quota (not retry-later). Optional BYOK: modelProvider openai|anthropic as a tool arg; send the provider key only in connection header X-PasteApply-BYOK-Key (env-var placeholder — never a literal key in tool args or chat). Hosted is default. Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=up to 200 (within 2,350 signed-in requests a month). Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics. If the posting wants something not on the source resume, omit it.
- 2026-09-30 `status` changed (description)
  - before: Read PasteApply readiness (openaiConfigured, stripeConfigured, prices, plan/unlocks when Bearer pa_). Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=200. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
  - after: Read PasteApply readiness (openaiConfigured, stripeConfigured, prices, plan/unlocks when Bearer pa_). Paid bots: Authorization Bearer pa_… from confirm_payment or POST /api/agent-key. Ladder $3=1/$5=5/$10=50/$20=up to 200 (within 2,350 signed-in requests a month). Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.

Full history: https://api.protogrid.dev/v1/servers/com.pasteapply%2Fmcp/changes

## Remotes

- https://pasteapply.com/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (2)

- `generate`: Free fixed sample only: call with useSample:true to see what a tailored resume and cover letter look like (a fixed example, not the user's resume; no AI runs; nothing charged). Free on PasteApply is a fixed sample right now: it shows what a tailored resume and cover letter look like, and no AI runs on free requests. Tailoring your own resume needs a plan. Any other call answers HTTP 402 code free_samples_only with nothing charged. A human tailors their own resume on https://pasteapply.com after signing in with Google and choosing a plan; agent keys, the resume vault, unlock links and saved drafts are temporarily off. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
- `status`: Read PasteApply status: freeMode "samples_only", purchasesOpen, prices (empty while purchases are paused), storage "off" and which features are temporarily off. Honesty lock: we only rearrange what is already true. Never invent employers, dates, skills, or metrics.
