Roleset — job postings index

Search 690k open jobs from official ATS feeds, and what changed since your last check.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
75%
Naming quality
87%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~1,736Tokens (tool definitions)
~2.2 KBTypical response size
Moderate attention impact (1.36% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "jobs": {
      "url": "https://mcp.roleset.io/mcp"
    }
  }
}

Remote endpoints

https://mcp.roleset.io/mcpstreamable-http

What it can do

Tool inventory

Tools (6)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢search_jobs(q, title, company, location, country, ...)

Search the index of open job postings. Use for a one-off question about the job market: who is hiring for a role, what is open in a city or country, which companies have remote positions. Returns a page of job records plus a `meta.next_cursor` to continue; each record has title, company, structured locations, remote flag, employment type, salary when the board publishes one, and an apply URL. Descriptions are omitted unless `include_description` is set, because they are large. To find what has *changed* since you last looked, use job_changes instead — do not poll this tool in a loop.

Input Schema

{
  "type": "object",
  "properties": {
    "q": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Free text over title and description.",
      "title": "Q"
    },
    "title": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Match on the job title.",
      "title": "Title"
    },
    "company": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Company name, partial match.",
      "title": "Company"
    },
    "location": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "City or region.",
      "title": "Location"
    },
    "country": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "ISO-3166 alpha-2, e.g. US, DE.",
      "title": "Country"
    },
    "remote": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Only remote, or only non-remote.",
      "title": "Remote"
    },
    "department": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Department"
    },
    "employment_type": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "full_time | part_time | contract | intern | temporary | volunteer",
      "title": "Employment Type"
    },
    "ats": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Restrict to one ATS platform.",
      "title": "Ats"
    },
    "posted_after": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "ISO-8601 timestamp.",
      "title": "Posted After"
    },
    "listed_since_after": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "ISO-8601. When the company last put the role on the market — it moves when a posting is reopened, so this is the filter for what is on the market now.",
      "title": "Listed Since After"
    },
    "include_description": {
      "default": false,
      "title": "Include Description",
      "type": "boolean"
    },
    "limit": {
      "default": 25,
      "maximum": 100,
      "minimum": 1,
      "title": "Limit",
      "type": "integer"
    },
    "cursor": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "From a previous meta.next_cursor.",
      "title": "Cursor"
    }
  },
  "title": "search_jobs_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "search_jobs_toolDictOutput"
}
🟢job_changes(since, event, company, ats, department, ...)

What has opened, changed, closed or reopened in the index. This is the tool to poll: pass `since` (ISO-8601) the first time, then keep passing the returned `meta.next_cursor` and you will see each event exactly once, with no gaps or repeats. Filter it the same way you would a search — by department, country, remote, title, company or ATS — to subscribe to one slice of the market. Each event carries the event type, when it happened, a `diff` showing which fields changed and their before/after values, and the job record itself. Use this to track a hiring market over time, to answer 'what's new since yesterday', or to keep a downstream store in sync. Defaults to the last 24 hours.

Input Schema

{
  "type": "object",
  "properties": {
    "since": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "ISO-8601; ignored when cursor is set.",
      "title": "Since"
    },
    "event": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "opened | updated | closed | reopened",
      "title": "Event"
    },
    "company": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Company"
    },
    "ats": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Ats"
    },
    "department": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Department, partial match.",
      "title": "Department"
    },
    "country": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "ISO-3166 alpha-2, e.g. US.",
      "title": "Country"
    },
    "remote": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Only remote, or only non-remote.",
      "title": "Remote"
    },
    "title": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Match on the job title.",
      "title": "Title"
    },
    "include_job": {
      "default": true,
      "title": "Include Job",
      "type": "boolean"
    },
    "limit": {
      "default": 50,
      "maximum": 100,
      "minimum": 1,
      "title": "Limit",
      "type": "integer"
    },
    "cursor": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Cursor"
    }
  },
  "title": "job_changes_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "job_changes_toolDictOutput"
}
🟢get_job(job_id)

Fetch a single posting by its Roleset id, including the full description text and HTML. Use after search_jobs or job_changes when you need the body of a specific posting — for summarising requirements, or checking whether a role matches a candidate's constraints. The id comes from an earlier result.

Input Schema

{
  "type": "object",
  "properties": {
    "job_id": {
      "description": "Roleset job id (UUID) from an earlier result.",
      "title": "Job Id",
      "type": "string"
    }
  },
  "required": [
    "job_id"
  ],
  "title": "get_job_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "get_job_toolDictOutput"
}
🟢company_jobs(identifier, include_description, limit)

Every open posting at one company. Accepts a domain (acme.com), an ATS board slug, or the company name. Use when the company is already known and you want its roles; use search_jobs when you are looking across companies. For whether the company is growing rather than what it has open, use hiring_signal.

Input Schema

{
  "type": "object",
  "properties": {
    "identifier": {
      "description": "Domain, ATS board slug, or company name.",
      "title": "Identifier",
      "type": "string"
    },
    "include_description": {
      "default": false,
      "title": "Include Description",
      "type": "boolean"
    },
    "limit": {
      "default": 50,
      "maximum": 100,
      "minimum": 1,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "identifier"
  ],
  "title": "company_jobs_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "company_jobs_toolDictOutput"
}
⚪hiring_signal(identifier)

Whether a company is hiring, and where. Returns open roles broken down by department plus how many opened and closed over the last 7 and 30 days, and the net change. Use for sales and research questions — 'is this company growing', 'are they building out engineering', 'did they stop hiring' — where counts and trend matter more than the individual postings. One call, not per record.

Input Schema

{
  "type": "object",
  "properties": {
    "identifier": {
      "description": "Domain, ATS board slug, or company name.",
      "title": "Identifier",
      "type": "string"
    }
  },
  "required": [
    "identifier"
  ],
  "title": "hiring_signal_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "hiring_signal_toolDictOutput"
}
🟢stats

Size and freshness of the whole index: companies, boards per ATS, open and total postings, events in the last 24 hours, and when the oldest active board was last crawled. Free. Use to tell a user how much coverage stands behind an answer, or to check the index is current before relying on it.

Input Schema

{
  "type": "object",
  "properties": {},
  "title": "stats_toolArguments"
}

Output Schema

{
  "type": "object",
  "additionalProperties": true,
  "title": "stats_toolDictOutput"
}

Recommended Prompts

search_research
Search for information about [topic] using Roleset — job postings index
Expected tools: search_jobs
find_specific
Find [specific item] using Roleset — job postings index
Expected tools: search_jobs
retrieve_data
Get details about [item] from Roleset — job postings index
Expected tools: get_job
fetch_info
Fetch [information type] using Roleset — job postings index
Expected tools: get_job
research_workflow
Search for [topic], then get detailed information about the top results using Roleset — job postings index
Expected tools: search_jobsget_job

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded6 tools
verifiedversion not recorded6 tools