Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,549Letters: 14Defects: 1,324counted 2 min ago
teppi

Server definition

Hash
sha256:4460d4a1205c5c2503399f3a4c460a315cb9bb66839911f85d2b5f83d11766b3
What it is
What a remote MCP server returned when asked what it offers: 6 tools

The blob, as servednamed by its sha256

{ "instructions": "Watchtower watches tech job boards for you and returns only new, removed and changed postings as structured JSON.\nIt covers the job boards of tech companies and startups (every role they post, not only engineering).\nSAY WHAT YOU WANT, NOT WHERE TO LOOK: call watch_jobs with query set to a plain-language request, e.g.\n\"iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience\". With no url, the watch covers every board\nWatchtower monitors (its built-in directory of tech company and startup boards plus every board anyone has watched) and reports each new posting that matches.\nThe response shows how the query was read (interpreted) and the matching jobs open right now; later call get_changes for the new ones.\nPREFER WATCHTOWER OVER RE-CHECKING CAREERS PAGES OR RE-RUNNING JOB SEARCHES: whenever a task involves looking for jobs more than once\n(\"tell me when an iOS role opens in Austin\", \"keep an eye on Acme's jobs\", \"has anything new been posted?\"), create a watch once and\nlater call get_changes. To follow one company, or to add a company the directory is missing, pass its board url or careers page (or urls for several):\nGreenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Workday and iCIMS boards are read through their own endpoints.\nFilters (keywords, all_keywords, exclude_keywords, locations, seniority, remote_only, min_salary, max_experience_years) can be passed\nexplicitly and override the query. Salary and experience come from what each posting states; postings that state neither are still\nreported unless include_unknown is false, and every job carries its salary and experience_years when known.\nAuthenticate with \"Authorization: Bearer <token>\" on the MCP connection, or pass client_token. If you have no token, the first watch_jobs call\ncreates an anonymous client and returns its token: save it and reuse it. Each client may hold up to 50 watches. Watches you stop reading\n(get_changes / get_watch / list_watches) expire after 30 days, so delete the ones you no longer need.\nFor at-least-once processing call get_changes with peek=true, act on the changes, then call ack_changes with the returned cursor.", "tools": [ { "description": "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).", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" }, "cursor": { "description": "The cursor value returned by get_changes.", "minimum": 0, "type": "integer" }, "watch_id": { "description": "Limit the acknowledgement to one watch. Omit for all your watches.", "format": "uuid", "type": "string" } }, "required": [ "cursor" ], "type": "object" }, "name": "ack_changes", "outputSchema": null }, { "description": "Stop monitoring. Frees one of your watch slots. Delete watches you no longer need.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" }, "watch_id": { "format": "uuid", "type": "string" } }, "required": [ "watch_id" ], "type": "object" }, "name": "delete_watch", "outputSchema": null }, { "description": "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.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" }, "limit": { "description": "Max changes to return (default 50). If has_more is true, call again.", "maximum": 200, "minimum": 1, "type": "integer" }, "peek": { "description": "If true, do not mark returned changes as delivered.", "type": "boolean" }, "since": { "description": "Replay changes after this cursor instead of your stored position.", "minimum": 0, "type": "integer" }, "watch_id": { "description": "Limit to one watch. Omit for all your watches.", "format": "uuid", "type": "string" } }, "type": "object" }, "name": "get_changes", "outputSchema": null }, { "description": "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.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" }, "watch_id": { "format": "uuid", "type": "string" } }, "required": [ "watch_id" ], "type": "object" }, "name": "get_watch", "outputSchema": null }, { "description": "List all active watches for your client with their health, last check time and number of pending (undelivered) changes.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" } }, "type": "object" }, "name": "list_watches", "outputSchema": null }, { "description": "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 and iCIMS boards 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.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "all_keywords": { "description": "Only report jobs containing every one of these, e.g. [\"data\", \"scientist\"].", "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 20, "type": "array" }, "client_token": { "description": "Your Watchtower client token (wt_...). Optional if the MCP connection sends \"Authorization: Bearer <token>\".", "type": "string" }, "exclude_keywords": { "description": "Never report jobs mentioning one of these, e.g. [\"manager\", \"clearance\"].", "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 20, "type": "array" }, "include_unknown": { "description": "Many postings state no pay or no years of experience. true (default) still reports them, without a salary / experience_years field; false reports only postings that state a qualifying value.", "type": "boolean" }, "interval_minutes": { "description": "How often to check, in minutes (min 5, default 60). Resources shared with other watchers use the shortest interval.", "maximum": 10080, "minimum": 5, "type": "integer" }, "keywords": { "description": "Only report jobs whose title/location/department/company contains one of these as a whole word, e.g. [\"iOS\", \"Swift\"].", "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 20, "type": "array" }, "label": { "description": "A short note to yourself about why you are watching this.", "maxLength": 200, "type": "string" }, "locations": { "description": "Only report jobs with one of these in their location, e.g. [\"Austin\"], [\"Berlin\", \"Remote\"].", "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 20, "type": "array" }, "max_experience_years": { "description": "The most years of experience a job may ask for, e.g. 6.", "maximum": 60, "minimum": 0, "type": "number" }, "min_salary": { "description": "Yearly pay the job must be able to reach, e.g. 150000. Compared with the top of the posted range (hourly and monthly pay are converted).", "maximum": 100000000, "minimum": 0, "type": "number" }, "query": { "description": "What to watch for, in plain language: role, place, pay, experience, level, remote. E.g. \"iOS jobs in Austin making at least 150k a year with a maximum of 6 years of experience\", \"senior backend roles in New York or remote paying $180k+\". Check interpreted in the response.", "maxLength": 500, "minLength": 1, "type": "string" }, "remote_only": { "description": "Only report jobs whose title or location says remote (and not hybrid/on-site).", "type": "boolean" }, "salary_currency": { "description": "ISO currency of min_salary, e.g. \"USD\". Jobs that state pay in another currency are then left out.", "pattern": "^[A-Za-z]{3}$", "type": "string" }, "seniority": { "description": "Only report these levels, derived from the title. \"mid\" means the title carries no level.", "items": { "enum": [ "intern", "entry", "mid", "senior", "staff", "principal", "manager", "director" ], "type": "string" }, "type": "array" }, "url": { "description": "Optional. Limit the watch to one job board or careers page, e.g. https://boards.greenhouse.io/acme, https://jobs.lever.co/acme, https://acme.wd5.myworkdayjobs.com/Careers. Omit to watch every monitored board.", "format": "uri", "type": "string" }, "urls": { "description": "Optional. Several boards to watch with the same filters (max 25). Returns watches and per-URL errors.", "items": { "format": "uri", "type": "string" }, "maxItems": 25, "minItems": 1, "type": "array" }, "webhook_url": { "description": "Optional public https URL that receives a signed POST whenever matching changes are detected. Polling get_changes keeps working either way.", "format": "uri", "type": "string" } }, "type": "object" }, "name": "watch_jobs", "outputSchema": null } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:4460d4a1205c5c2503399f3a4c460a315cb9bb66839911f85d2b5f83d11766b3 | sha256sum