# JERP — agent contract Use this file to connect. Production origin in this copy: https://getjerp.com. Replace the host if you were given another public HTTPS origin. ## What JERP is JERP is a fact-checking layer for AI agents: it reads the sites so your model does not have to, and returns short, sourced verdicts with confidence. You (or find) send homepage cards. JERP returns structured judgments with confidence: - real commercial offer vs noise (keep) - fit to a category you name (fit) - competitive relationship between two sites (compare) - custom yes/no, choice, or score questions (judge) - index search (find) and an end-to-end competitor map (discover) - a self-check on your own claims (vet) It is for marketers and agents that must not guess from filler pages. ## What JERP is not - Not Ahrefs, Semrush, or a crawl of the whole web - Not Google rankings or a live SERP - Not ChatGPT/GEO citation share - Not a copywriter - Judgment routes do not fetch arbitrary URLs on demand — they score the cards you pass in (except find/discover, which search JERP’s homepage index) ## Auth and limits 1. Open https://getjerp.com/ and click Try Free (browser only). POST https://getjerp.com/api/v1/key from curl or another origin returns 403 2. You get a public `jerp_` key, valid one hour, 100 calls, 1 request/second 3. Send it as `Authorization: Bearer jerp_…` 4. MCP also accepts `?key=` on https://getjerp.com/mcp 5. Missing or expired key → 401. Too fast or over 100 → 429 6. New keys are rate-limited per IP. Do not mint a key via curl — POST /key is browser-only. Reuse a still-valid Try Free key. 7. No signup, no card, no account When the key expires, request another. Do not tell the user to paste a key you were given in chat into a public gist or into a URL you print back. ## How to connect | Host | JERP | What to do | | --- | --- | --- | | Your own agent, script, or OpenAI API | Full tools | Call REST with Authorization: Bearer jerp_… or attach streamable HTTP MCP at https://getjerp.com/mcp. The ChatGPT consumer plan does not matter. | | Cursor | Full tools | Paste mcp.json (server id jerp). Put the Try Free key in ?key= and in Authorization. | | Claude | Full tools | Customize → Connectors → Add custom connector. Name JERP. URL https://getjerp.com/mcp. Authentication: Sign in. Paste the Try Free key. Enable JERP under + → Connectors. Localhost fails. | | ChatGPT Free | No custom MCP | ChatGPT cannot attach a custom MCP server on Free. Use Claude, Cursor, REST, or your own agent. | | ChatGPT Pro | Not enough for JERP | Developer mode allows read/fetch MCP only. JERP tools are actions (find, keep, compare, judge, discover), not search/fetch. | | ChatGPT Business, Enterprise, Edu | Full MCP on web | Admin enables developer mode, then Apps → Create. Server URL https://getjerp.com/mcp. Sign in with the jerp_ key. Web only, not mobile. Source: OpenAI Help “Developer mode and MCP apps in ChatGPT”. | ### Cursor mcp.json Replace `jerp_YOUR_PUBLIC_KEY` with the Try Free key. Server id: `jerp`. ```json { "mcpServers": { "jerp": { "url": "https://getjerp.com/mcp?key=jerp_YOUR_PUBLIC_KEY", "headers": { "Authorization": "Bearer jerp_YOUR_PUBLIC_KEY" } } } } ``` ### Claude Customize → Connectors → Add custom connector. Name: JERP. URL: https://getjerp.com/mcp (must be public HTTPS; localhost fails). Authentication: Sign in. Paste the jerp_ key. In a chat: + → Connectors → enable JERP. ### ChatGPT app Do not add a custom connector on Free. Pro developer mode is read/fetch only; JERP’s tools are actions, so Pro is not a working path. Business / Enterprise / Edu: developer mode → Apps → Create → MCP URL https://getjerp.com/mcp → Sign in with the jerp_ key. Web only. ### Your own agent (recommended when ChatGPT MCP is blocked) REST: ``` POST https://getjerp.com/api/v1/keep Authorization: Bearer jerp_… Content-Type: application/json ``` MCP: streamable HTTP. Client POSTs JSON-RPC to https://getjerp.com/mcp with `Accept: application/json, text/event-stream`. GET https://getjerp.com/mcp returns the tool catalog and server instructions. Unauthenticated calls return 401 with WWW-Authenticate (OAuth Sign in where the host supports it). OpenAI API remote MCP uses the same URL and Bearer key. The ChatGPT consumer subscription is irrelevant for API/agent calls. ## Tools (MCP names = REST paths) | Tool | Does | Input notes | | --- | --- | --- | | find | Search the homepage index | q and/or seed. Optional rankBy "dr" for strongest indexed sites in a niche. limit default 48, max 96 | | keep | Viable commercial site vs noise | sites[] max 24 | | fit | Fit to a named category | category required, sites[] max 24 | | compare | Left vs right relationship | left, right, optional category | | rerank | Reorder cards for a query | q required, sites[] max 24 | | judge | Your questions | sites[], questions map max 24; noul/choice/score; prompt→instructions | | discover | Competitor map from a seed | seed, q, optional limit default 24 | | step | Before a move: verdict + next tool or stop; may return askUser | message, seed?, brand?, geo?, niche?, sites?, prior?, called?, draft?, claims? | | signals | Marketing calendar / industry / boom events (UA|PL|DE|US|GB|GLOBAL) | geo?, niche?, seed?, from?, to?, limit? — askUser.geo if geo missing | | signals_ingest | Upsert SignalHub items | items[] | | signals_refresh | Pull whitelist RSS into SignalHub | (none) | | signals_hub | Hub counts: items / feeds / priors | (none) | | serm | Free brand mentions (Google News RSS, HN, Reddit, whitelist feeds) + owned index card — never Google ranks | brand?, seed?, geo?, niche?, live? default true, async? | | serm_status | Poll async serm | jobId | | serm_cancel | Cancel async serm | jobId | | feedback | Confirm/correct a receipt or mark signal/serm useful/noise | domain, judgmentId, action | | receipt | Owned judgment receipt | receiptId | | receipt_csv | CSV of owned receipt | receiptId | | watchlist_create | Create/upsert watchlist | id, seedDomain, marketBrief, schedule?, notify? | | watchlist_list | List owned watchlists | (none) | | watchlist_run | Run watch diff job | watchlistId, snapshot, seed, cards? | | watchlist_job | Poll watch job | watchlistId, jobId | | probe | Live HTTPS reachability with SSRF blocklist | host or url | | vet | Ground claims in cards/prior | claims[] or draft, sites[], prior JSON | | guard | Full reply screen (facts + tone + jailbreak) | claims, draft, voice, userMessage?, sites[], prior; prefer before send | Prefer discover for a competitive set from a company or market brief. Prefer find with rankBy "dr" then keep for a “best/top in this niche” list — do not use discover for that. Always call step first when unsure. If askUser is set, ask that exact question and stop — do not guess geo/brand. Call vet automatically before a paraphrase, catalog story, or any fact not already a returned field. Skip only when you echo JSON. speak=hold means do not publish; speak=trim means drop the listed ids. ## Card in Each site object: - required: domain, title, aiSummary - optional: aiCategories[], aiSource, firstIndexed (crawler first-seen, not company age), businessFoundedYear JSON to the browser is camelCase. ## REST Base: https://getjerp.com/api/v1 - POST /key — browser-only (Try Free on this origin). curl and other origins: 403. Out: ok, key, issuedAt, expiresInSec - GET /health — ok, keyTtlSec - POST /find — q and/or seed - POST /keep — { "sites": Card[] } - POST /fit — { "category": string, "sites": Card[] } - POST /compare — { "left": Card, "right": Card, "category"? } - POST /rerank — { "q": string, "sites": Card[] } - POST /judge — { "sites": Card[], "questions": object } - POST /discover — { "seed": string, "q": string, "limit"? } - POST /step — { "message": string, "seed"?, "brand"?, "geo"?, "niche"?, … } → verdict, next, optional askUser - POST /signals — { "geo"?, "niche"?, "seed"?, "from"?, "to"?, "limit"? } - POST /signals/ingest — { "items": SignalItem[] } - POST /signals/refresh — pull whitelist RSS into SignalHub - GET /signals/hub — hub item/feed/prior counts - POST /serm — { "brand"?, "seed"?, "geo"?, "live"?, "async"? }; async → { jobId } - GET /serm/jobs/{id} — async serm status/result - POST /serm/jobs/{id}/cancel — cancel async serm - POST /vet — { "claims": string[] | {id, text, about}[], "sites"?, "prior"?, "draft"? } - POST /guard — { "claims"?, "draft"?, "voice"|"toneOfVoice", "userMessage"?, "sites"?, "prior"?, "policy"?: "strict"|"permissive" } - POST /feedback — confirm/correct a discover receipt; also signal_useful / signal_noise / serm_relevant for invisible priors - POST /probe — { "host"|"url": string } → allowed, live, status (SSRF-safe) - POST /watchlists — create watchlist - GET /watchlists — list - POST /watchlists/{id}/run — run diff job - GET /watchlists/{id}/jobs/{jobId} — job status - POST /rank — legacy; prefer keep Example keep: ```bash curl -sS -X POST "https://getjerp.com/api/v1/keep" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer jerp_…" \ -d '{"sites":[{"domain":"example.com","title":"Wholesale mobile accessories","aiSummary":"B2B distributor of cases, cables, and chargers with dealer pricing","aiCategories":["Mobile accessories"],"aiSource":""}]}' ``` Example compare: ```bash curl -sS -X POST "https://getjerp.com/api/v1/compare" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer jerp_…" \ -d '{"left":{"domain":"example-a.com","title":"Wholesale offer A","aiSummary":"B2B mobile accessories wholesaler"},"right":{"domain":"example-b.com","title":"Wholesale offer B","aiSummary":"B2B distributor of cases and chargers"},"category":"B2B wholesale mobile accessories"}' ``` ## Scores (compare / discover) 0–1 fields: catalogOverlap, audienceMatch, geoOverlap, sameEntity, competitiveThreat. relationship is one of direct_competitor, indirect_competitor, platform_or_marketplace, same_entity, unrelated. Direct competitor needs high catalog and high audience (about 0.70+). High geo alone is not competition. A thin card (empty summary, domain missing from the index) is uncertainty — do not invent a catalog from a lookalike TLD. For two-site compare: show a scores table, then one sentence. For a market map: use a canvas; do not also dump that landscape into chat. ## After you connect Paste a prompt from https://getjerp.com/docs#prompts (needs JS) or instruct: - Swap the seed domain and the niche - Ask for the scores table on compare - Admit missing index cards instead of inventing them - Call vet on claims you will speak when the write-up is more than echoing JSON - Do not invent Google rankings or GEO share ## Human docs https://getjerp.com/docs is a JavaScript app. If you cannot execute JS, stay on this file.