MCP server
How do I connect an AI agent to BetterJobs over MCP, and what does each tool cost?
BetterJobs runs a remote MCP server. An agent connected to it can search jobs, check whether a company is hiring and watch companies, at the same credit prices as the REST API.
| Setting | Value |
|---|---|
| URL | https://mcp.betterjobs.cc/mcp |
| Transport | Streamable HTTP |
| Auth | Bearer API key |
| Plan | Growth and above |
Use a bj_live_ key. See Authentication.
Connect a client
Section titled “Connect a client”Run once in your terminal. It adds the server to your Claude Code config.
claude mcp add --transport http betterjobs https://mcp.betterjobs.cc/mcp \ --header "Authorization: Bearer $BETTERJOBS_API_KEY"Check it with claude mcp list.
Add this to claude_desktop_config.json and restart Claude Desktop. The mcp-remote bridge connects the desktop app to a remote server.
{ "mcpServers": { "betterjobs": { "command": "npx", "args": [ "-y", "mcp-remote", "https://mcp.betterjobs.cc/mcp", "--header", "Authorization:${BETTERJOBS_AUTH}" ], "env": { "BETTERJOBS_AUTH": "Bearer bj_live_..." } } }}Add this to .cursor/mcp.json in your project, or ~/.cursor/mcp.json for all projects. Cursor reads the key from your environment.
{ "mcpServers": { "betterjobs": { "url": "https://mcp.betterjobs.cc/mcp", "headers": { "Authorization": "Bearer ${env:BETTERJOBS_API_KEY}" } } }}Each tool maps to one REST endpoint and costs the same. Tool descriptions are written for the agent: when to call, what to pass, and what cheaper or lighter tool to try first.
| Tool | Call it when | Inputs | Cost | Ask the user first? | Cheaper or lighter sibling | REST |
|---|---|---|---|---|---|---|
search_jobs | Find jobs matching filters. Call estimate_search first if it may cost more than 50 credits, and ask the user. | Same body as POST /v1/jobs/search: filters (required), waterfall, limit (1 to 100), cursor. | 1 credit per unique job | Ask above 50 credits (estimate first) | estimate_search (free) to price it first | POST /v1/jobs/search |
estimate_search | Before any large search. Returns expected jobs, providers and credit range. | filters (required), waterfall, limit. | Free | No | None. It is free. | POST /v1/jobs/search with dry_run: true |
get_job | Fetch one job by id. | id: a canonical job id (job_...). | Free if already paid, else 1 credit | No | None. Free for jobs you already paid for. | GET /v1/jobs/{id} |
company_hiring | Full hiring profile for a company domain. | domain: company domain, no scheme or path. | 1 credit, every call | Ask before looping over many domains (1 credit each) | is_hiring returns the same profile call. Call one, not both; each call is charged. | GET /v1/companies/{domain} |
is_hiring | Yes / no / unknown answer for one company. | domain: company domain, no scheme or path. | 1 credit, every call | Ask before looping over many domains (1 credit each) | company_hiring hits the same endpoint. Call one, not both; each call is charged. | GET /v1/companies/{domain} |
watch_company | Get told when a company opens jobs or starts or stops hiring. Needs webhooks (Pro and above); otherwise returns plan_required. | domain, webhook_url, events (optional; defaults to all job and company events). | Free to create; 1 credit per job.opened delivered (free if already paid) | Always ask: ongoing charge with no cap | is_hiring for a one-off check | POST /v1/watches |
list_events | Read the event feed for watches and async searches. | since (cursor from the last next_cursor), limit (1 to 100). | Free | No | None. It is free. | GET /v1/events |
search_docs | Answer questions about the API from these docs. | query: a question in plain English. | Free | No | None. It is free. | — |
search_jobs takes exactly the POST /v1/jobs/search body, so the Filters page applies as-is. The Query Builder prints a ready search_jobs call.
The consent rule
Section titled “The consent rule”Agents spend your credits. The server enforces your plan and your max_credits. The rest is a rule the agent should follow:
- Before any search that may cost more than 50 credits, call
estimate_search. It is free. - Show the user
credits_rangeandproviders_plannedand ask before running it. - Run
search_jobswithwaterfall.max_creditsset to what the user approved. - Keep the canonical job
idvalues.get_jobon a job you already paid for is free, so never search again just to re-read a job. - Never call
watch_companywithout asking. Eachjob.openedit delivers costs 1 credit, and a watch has no credit cap. is_hiringandcompany_hiringcall the same endpoint and each call costs 1 credit. Call one, not both, and ask before looping over many domains.
Put the rule in your system prompt or project instructions:
When using the BetterJobs MCP server: before any search_jobs call that may cost morethan 50 credits, call estimate_search, show me credits_range and providers_planned,and wait for my approval. Always set waterfall.max_credits. Never call watch_companywithout asking: each job.opened it delivers costs 1 credit, with no cap. Treatis_hiring.value null as unknown, never as false.Errors
Section titled “Errors”Tools return the same error codes as the REST API, with the same fields. The ones agents hit most:
| Code | What the agent should do |
|---|---|
insufficient_credits |
Stop. Tell the user credits_needed and the upgrade_url. |
plan_required |
Tell the user the required_plan. Do not retry. |
unknown_filter |
Fix the field named in param. The message suggests the right name. |
rate_limited |
Wait Retry-After seconds, then retry once. |
Full list: Errors.