Skip to content

Watchtower

by watchtower.lat · remote · no sign-in to list tools · v0.1.1 · published by lat.watchtower

Job alerts for AI agents: describe a role once, get only new postings from 1,500+ tech job boards.

Deletes · 1Changes · 3

8 tools: 1 can delete or cancel things, 3 change things and 4 only read.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http watchtower https://watchtower.lat/mcp?ref=registry

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "get_changes" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "get_changes" says "get": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

8 tools

Deletes or cancels 1Claude Code: deny
  • delete_watchStop monitoring.No findings

    Why it is in this group

    • The name "delete_watch" says "delete": a word for removing or ending something.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    Stop monitoring. Frees one of your watch slots. Delete watches you no longer need.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: true
    • idempotentHint: true
    • openWorldHint: false
Changes things 3Claude Code: ask
  • ack_changesMark changes up to a cursor as processed.No findings

    Why it is in this group

    • The description's first verb is "mark": a word for a change.
    Description, as the server wrote it
    Mark changes up to a cursor as processed. Use with get_changes(peek=true) for at-least-once delivery: peek, act on the changes, then ack the cursor get_changes returned. Not needed if you call get_changes without peek (that acknowledges automatically).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
  • get_changesReturn job changes detected since your last get_changes call, across all your watches or one watch.1 finding

    Why it is in this group

    • The name "get_changes" says "get": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "get_changes" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}; The name "get_changes" says "get": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Return job changes detected since your last get_changes call, across all your watches or one watch. This is the cheap replacement for re-browsing careers pages: if it returns an empty list, nothing you care about has changed. By default the cursor advances so each change is delivered once; pass peek=true to look without advancing, or since=<cursor> to replay.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
  • watch_jobsCreate a persistent watch for tech jobs.Reads text others writeCan send data outNo findings

    Why it is in this group

    • The description's first verb is "create": a word for a change.

    What it can reach

    • untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
    • outboundThe input takes a URL (input.url): a request to a URL can carry data to whoever runs it.
    Description, as the server wrote it
    Create a persistent watch for tech jobs. Describe what you want in query ("iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience") and leave url out: the watch then covers every job board Watchtower monitors (tech companies and startups, whatever platform they use) and reports each new matching posting (JOB_ADDED). The response shows how the query was read (interpreted), the jobs open right now that match (current_jobs) and how many boards are covered (coverage); later call get_changes for new ones. Use this INSTEAD OF re-running job searches or re-checking careers pages yourself. To follow one company, or to cover a company the directory is missing, pass url (or urls for several): Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Workday, iCIMS, Oracle Recruiting, Eightfold and SuccessFactors boards, and the Apple, Google, Amazon and Microsoft careers sites, are read through their own endpoints; other careers pages are parsed via schema.org JobPosting JSON-LD. A careers page that only links to a supported board is watched through that board (resolved_from says so); a page with neither is rejected with NO_JOB_DATA. A board you watch stays covered for every search watch. A board watch emits JOB_ADDED / JOB_REMOVED / JOB_UPDATED. Jobs carry title, location, other_locations, department, company, url, posted_at, remote, seniority, and salary / experience_years when the posting states them. Explicit filters override what the query says.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • openWorldHint: true
Only reads 4Claude Code: allow
  • get_watchGet a watch with its status and the jobs currently open that match its filters: on its board, or across every monitored board for a watch created without a url.Reads text others writeNo findings

    Why it is in this group

    • The name "get_watch" says "get": a word for reading.

    What it can reach

    • untrusted-inputThe description's first sentence says "get" and "url": it reads web pages, which anyone can write.
    Description, as the server wrote it
    Get a watch with its status and the jobs currently open that match its filters: on its board, or across every monitored board for a watch created without a url. Use this to answer "what is open right now" without searching or fetching careers pages yourself.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • openWorldHint: false
  • list_companiesList the companies whose job boards Watchtower monitors, i.e.No findings

    Why it is in this group

    • The name "list_companies" says "list": a word for reading.
    Description, as the server wrote it
    List the companies whose job boards Watchtower monitors, i.e. what search_jobs and watch_jobs without a url cover. Pass query to check whether a company is covered ("stripe"). Each entry has name, board_url (pass it to watch_jobs as url to follow only that company), platform and open_jobs. Read-only, no token needed. If a company is missing, watch its board URL or careers page to add it.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • openWorldHint: false
  • list_watchesList all active watches for your client with their health, last check time and number of pending (undelivered) changes.No findings

    Why it is in this group

    • The name "list_watches" says "list": a word for reading.
    Description, as the server wrote it
    List all active watches for your client with their health, last check time and number of pending (undelivered) changes.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • openWorldHint: false
  • search_jobsFind the tech jobs open right now that match a request, across every job board Watchtower monitors (tech companies and startups).No findings

    Why it is in this group

    • The name "search_jobs" says "search": a word for reading.
    Description, as the server wrote it
    Find the tech jobs open right now that match a request, across every job board Watchtower monitors (tech companies and startups). Describe what you want in query ("iOS jobs in Austin with a maximum of 6 years of experience"). Read-only: nothing is saved and no watch is created, and no token is needed. The response shows how the query was read (interpreted), the matching jobs newest first, the total, and next_offset for the next page. Use this for "what is open right now"; to be told about new postings later, use watch_jobs instead. Jobs carry title, location, other_locations, department, company, url, posted_at, remote, seniority, and salary / experience_years when the posting states them. Explicit filters override what the query says.

    Annotations the server declares

    • readOnlyHint: true
    • destructiveHint: false
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Exfil surface

Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.

No private-data, untrusted-input, outbound path in this server alone: no tool is tagged private-data.

Reads private data0
Reads files, mail, messages, databases, secrets, calendars or repositories.
Reads text others write2
Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
Can send data out1
Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.

Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.

Install

Pinned to version 0.1.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http watchtower https://watchtower.lat/mcp?ref=registry

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__watchtower__search_jobs",
      "mcp__watchtower__list_companies",
      "mcp__watchtower__list_watches",
      "mcp__watchtower__get_watch"
    ],
    "ask": [
      "mcp__watchtower__watch_jobs",
      "mcp__watchtower__get_changes",
      "mcp__watchtower__ack_changes"
    ],
    "deny": [
      "mcp__watchtower__delete_watch"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as watchtower. Review it before you use it.

Capability tags behind 2 rules
  • mcp__watchtower__watch_jobs untrusted-input, outbound
  • mcp__watchtower__get_watch untrusted-input