Free MCP + REST · no sign-up

Job boards,
watched for AI.

Tech job monitoring for AI agents. Say what you are looking for once and get only the new postings that match, from the job boards of tech companies and startups, as structured JSON.

Take the quiz

4 quick questions, then a prompt to paste into your agent

Paste into your agentTake the quiz ↓
Use watchtower.lat (https://watchtower.lat/llms.txt) to watch for iOS roles in Austin, TX paying at least $150k a year with at most 6 years of experience, and tell me about new postings as they appear.
agent↵ Run
watch_jobs({
  query: "iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience"
})

// a week later
get_changes()Agent
3 new jobs since the last callJOB_ADDED
Senior iOS Engineer$165k–$210k5 yrsAcme · Austin, TX · Greenhouse
iOS Engineer, Payments$150k–$185k3 yrsNorthwind · Austin, TX · Lever
Staff Mobile Engineer (iOS)$190k–$240k6 yrsGlobex · Austin, TX · Ashby

Careers pages weren't built for agents.

Watchtower reads every board as structured jobs.

Your agent hears only what's new.Example data. Companies are fictional.

Take the quiz · 4 questions

Four questions. One prompt.

Answer a few questions and get a prompt to paste into your agent. It does the watching from there.

Your prompt is ready.

Tap a colour to change an answer.

Use watchtower.lat to watch for roles in paying at least a year with at most of experience.

your agent
Use watchtower.lat (https://watchtower.lat/llms.txt) to watch for iOS roles in Austin, TX paying at least $150k a year with at most 6 years of experience, and tell me about new postings as they appear.
On it. I'm watching tech company job boards for iOS roles in Austin, TX (paying $150k+, asking for 6 years or less). Here's what's open now, and I'll only tell you when something new is posted.

Works with any agent that can browse the web or call an API. Or install the MCP server.

Ask once. Hear only what's new.

Watchtower remembers which jobs were open, so your agent doesn't have to.

Choose a task
Watchtoweragent
watch_jobs({ query: "iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience" })
// later, and every time after
get_changes()

→ 2 changes · JOB_ADDED Senior iOS Engineer (Acme), JOB_ADDED iOS Engineer, Payments (Northwind)

Watchtower

One call

Only new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.

Browser agent
  • Searching the web for iOS jobs in Austin…
  • Opening each company's careers page…
  • Reading every posting, including yesterday's…
  • Comparing against what it remembers

Re-searching

Every page, every time

Starts from scratch on every check, with pages instead of data, and some boards block it.

Watchtoweragent
watch_jobs({ url: "https://boards.greenhouse.io/acme" })
// later
get_changes()

→ 1 change · JOB_REMOVED Data Engineer (New York)

Watchtower

One call

Only new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.

Browser agent
  • Opening boards.greenhouse.io/acme…
  • Scrolling the full list of openings…
  • Reading each posting page…
  • Working out what was added or removed

Re-searching

Every page, every time

Starts from scratch on every check, with pages instead of data, and some boards block it.

Watchtoweragent
watch_jobs({
  urls: ["https://jobs.lever.co/northwind", "https://jobs.ashbyhq.com/globex"],
  seniority: ["senior", "staff"], remote_only: true
})
get_changes()

→ [] · nothing new since the last call

Watchtower

One call

Only new, removed or updated jobs, as structured JSON. The watch keeps checking while your agent is off.

Browser agent
  • Opening two job boards…
  • Filtering by title and location by hand…
  • Reading every remote posting again…
  • Reporting the same jobs as last time

Re-searching

Every page, every time

Starts from scratch on every check, with pages instead of data, and some boards block it.

Every board.
One watch.

Six MCP tools, the same operations over REST. Watch Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Workday, iCIMS, Oracle Recruiting, Eightfold, SuccessFactors, Apple, Google, Amazon, Microsoft boards, or any careers page with schema.org JobPosting, and filters live on the watch, so get_changes only returns what matters.

Wwatch_jobscore
  • query
  • url / urls
  • filters
  • webhook_url
  • interval_minutes
  • label
GGreenhouseATS

boards.greenhouse.io/acme

Cget_changescore
  • since
  • limit
  • peek
  • watch_id
LLeverATS

jobs.lever.co/acme

FFilters8
  • keywords
  • all_keywords
  • exclude_keywords
  • locations
  • seniority
  • remote_only
  • min_salary
  • max_experience_years
AAshbyATS

jobs.ashbyhq.com/acme

WWorkableATS

apply.workable.com/acme

ΔChanges3
  • JOB_ADDED
  • JOB_REMOVED
  • JOB_UPDATED
SSmartRecruitersATS

jobs.smartrecruiters.com/Acme

Kack_changescore

Acknowledge a cursor after get_changes(peek=true), for at-least-once processing.

RRecruiteeATS

acme.recruitee.com

WWorkdayATS

acme.wd5.myworkdayjobs.com/Careers. Boards over 200 postings report the newest 200.

≡list_watches · get_watch · delete_watch
  • health and pending counts
  • jobs open now that match
  • free a watch slot
iiCIMSATS

careers-acme.icims.com

{}Any careers pageJSON-LD

Read from schema.org JobPosting markup. Pages without it are rejected up front with NO_JOB_DATA.

↗Delivery
  • poll get_changes
  • signed webhook_url
  • ETag / Last-Modified honored

Install for free

Assistants In your code
✳·····W

Connect to Claude Code

  1. Run this in a terminal
  2. Ask Claude to watch jobs for you
Command
claude mcp add --transport http watchtower https://watchtower.lat/mcp?ref=claude-code
✳·····W

Connect to Claude

  1. Open Settings → Connectors
  2. Choose Add custom connector and paste this URL
  3. No account needed: Watchtower uses an anonymous client
Server address
https://watchtower.lat/mcp
C·····W

Connect to Cursor

  1. Click the button: Cursor opens with the server filled in
  2. Confirm, then ask the agent to watch jobs

Add to Cursor

Server address
https://watchtower.lat/mcp
V·····W

Connect to VS Code

  1. Click the button: VS Code opens with the server filled in
  2. Confirm, then ask Copilot to watch jobs

Add to VS Code

Server address
https://watchtower.lat/mcp
…·····W

Connect any MCP client

  1. Add this to the client's MCP config (Streamable HTTP)
  2. Clients with OAuth connect in one click (add ?auth=required to the URL if yours only signs in when asked). Otherwise send Authorization: Bearer <token> with a token from POST /v1/clients
MCP config
{
  "mcpServers": {
    "watchtower": {
      "type": "http",
      "url": "https://watchtower.lat/mcp"
    }
  }
}
$·····W

Three calls over HTTP

TOKEN=$(curl -s -X POST https://watchtower.lat/v1/clients | jq -r .token)

# every new matching job, on any monitored board
curl -s -X POST https://watchtower.lat/v1/watches \
  -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"query":"iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience"}'

# or specific companies' boards
curl -s -X POST https://watchtower.lat/v1/watches \
  -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"urls":["https://boards.greenhouse.io/acme","https://jobs.lever.co/acme"],"keywords":["iOS"],"seniority":["senior","staff"],"remote_only":true}'

curl -s https://watchtower.lat/v1/changes -H "Authorization: Bearer $TOKEN"
Base URL
https://watchtower.lat/v1
{}·····W

What a change looks like

{
  "id": 1842,
  "type": "JOB_ADDED",
  "summary": "New job: Senior iOS Engineer (Austin, TX)",
  "data": { "job": { "title": "Senior iOS Engineer", "company": "Acme", "location": "Austin, TX", "remote": false, "seniority": "senior",
                     "salary": { "min": 165000, "max": 210000, "currency": "USD", "period": "year", "annual_min": 165000, "annual_max": 210000 },
                     "experience_years": 5, "url": "https://..." } }
}

Types: JOB_ADDED, JOB_REMOVED, JOB_UPDATED. JOB_UPDATED adds before and changed_fields.

No account or API key. Full reference in the docs.Prefer to run it yourself? It's MIT on GitHub.

Polite by design.

Free and anonymous, with limits that keep it that way for everyone.

How Watchtower fetches

Public job boards only, read the way each one publishes its jobs.

0150 watches per client

One per board. Checks at most every 5 minutes. Watches nobody reads for 30 days expire.

02One request per site

At most one request at a time per website, spaced out, with ETag / Last-Modified honored.

03Shared fetching

Many agents watching the same board cost one request.

04Respects robots.txt

No CAPTCHA, login, paywall or anti-bot bypassing. Private and internal network addresses are refused.

Fair questions.

More in the docs, or open an issue.

Is this a crawler or a scraper?

Neither in the usual sense. Supported platforms are read through their own public job-board endpoints, and other careers pages through the schema.org JobPosting markup they publish. Watchtower respects robots.txt and never bypasses CAPTCHAs, logins, paywalls or anti-bot systems.

Which agents does it work in?

Any MCP client (Claude Code, Claude.ai, Claude Desktop, Cursor, VS Code and the rest) over Streamable HTTP, or anything that can make HTTP requests through the REST API.

What does it cost?

Nothing. Watchtower is free and anonymous: no sign-up, no email, no API key to request. Connecting creates an anonymous client in one click.

Which companies are covered?

A built-in directory of tech company and startup boards, from large public companies to seed-stage startups, plus every board anyone watches by URL. Every role they post is covered, not only engineering. See the full list of companies. To add a missing company, watch its board URL (or its careers page); it then stays covered for everyone.

What if a posting does not state pay or experience?

Pay and experience come from what each posting states. Postings that state neither are still reported, without those fields, unless you pass include_unknown: false.

What if my query is read wrong?

The response shows how it was read (interpreted) and the matching jobs open right now. Pass explicit filters to correct it; they override the query.

Can it run on a schedule, unattended?

Yes: that is the point. Watches are checked on a schedule whether or not your agent is running. Add a webhook_url for a signed POST on every matching change, or use get_changes(peek=true) then ack_changes(cursor) for at-least-once processing.

What do you store?

Your watches, a hash of your token and request counts for rate limiting. No accounts, no ads, nothing sold. The privacy page has the details and retention periods.