{
  "name": "de.nomado24/jobs",
  "title": "Nomado24 remote jobs",
  "description": "Read-only Model Context Protocol server over the nomado24 index of remote and hybrid jobs in Germany and the EU. No account, no API key, free to use with an attribution link back to nomado24.de.",
  "version": "1.0.0",
  "websiteUrl": "https://www.nomado24.de",
  "documentationUrl": "https://www.nomado24.de/de/developers",
  "aiInterfacesUrl": "https://www.nomado24.de/de/developers/ai",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://api.nomado24.de/api/public/v1/mcp",
      "methods": [
        "POST"
      ],
      "session": "stateless",
      "streaming": false,
      "requiredHeaders": {
        "Content-Type": "application/json",
        "Accept": "application/json, text/event-stream"
      },
      "authentication": {
        "type": "none"
      },
      "rateLimit": {
        "requests": 120,
        "windowSeconds": 900,
        "scope": "ip"
      }
    }
  ],
  "capabilities": {
    "tools": true,
    "resources": false,
    "prompts": false
  },
  "tools": [
    {
      "name": "search_jobs",
      "description": "Search nomado24's remote/hybrid job board. Read-only, free, attribution required (see structuredContent.attribution). Two contracts, chosen by the arguments: q, language, page and per_page alone return the legacy v1 result shape with page-based paging; any structured filter or a cursor returns the v2 contract with per-posting provenance (salaryOrigin, firstSeenAt, lastVerifiedAt, verification.method, updatedAt), a corpus changeWatermark, a snapshotId and keyset paging via pagination.nextCursor. page together with a structured filter is refused. Structured results omit the posting body and the per-field dataOrigin; call get_job for those. A filter nomado24 cannot answer honestly is refused with the reason, never answered with the unfiltered corpus, and pagination.total is null whenever a post-projection filter (skills, seniority, salary bounds, employment_type=unknown) is active.",
      "readOnly": true,
      "parameters": [
        {
          "name": "q",
          "type": "string",
          "required": false,
          "maxLength": 200,
          "description": "Free-text search over job title/company/tags"
        },
        {
          "name": "language",
          "type": "string",
          "required": false,
          "enum": [
            "de",
            "en",
            "fr"
          ],
          "description": "Filter by job content language"
        },
        {
          "name": "page",
          "type": "integer",
          "required": false,
          "minimum": 1,
          "maximum": 1000,
          "description": "1-based page number, default 1. Legacy contract only, refused together with a structured filter"
        },
        {
          "name": "per_page",
          "type": "integer",
          "required": false,
          "minimum": 1,
          "maximum": 25,
          "description": "Results per page, 1-25, default 20"
        },
        {
          "name": "country",
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 8
          },
          "maxItems": 20,
          "required": false,
          "description": "Where the ROLE sits, ISO 3166-1 alpha-2, uppercase (DE, US)"
        },
        {
          "name": "applicant_region",
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 16
          },
          "maxItems": 20,
          "required": false,
          "description": "Where a CANDIDATE may be: WORLDWIDE, EU or an ISO 3166-1 alpha-2, uppercase (DE, US) code. EEA, DACH and EMEA are refused, nomado24 does not classify them"
        },
        {
          "name": "work_arrangement",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "remote",
              "hybrid"
            ]
          },
          "maxItems": 2,
          "required": false,
          "description": "Work arrangement. The board serves remote and hybrid postings only, so these are the only two values"
        },
        {
          "name": "employment_type",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "full_time",
              "part_time",
              "contract",
              "freelance",
              "temporary",
              "internship",
              "working_student",
              "apprenticeship",
              "minijob",
              "volunteer",
              "other",
              "unknown"
            ]
          },
          "maxItems": 12,
          "required": false,
          "description": "Employment type. 'unknown' means the field is absent in the response, not a stored value"
        },
        {
          "name": "seniority",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "student",
              "entry",
              "junior",
              "mid",
              "senior",
              "lead",
              "manager",
              "director",
              "executive",
              "unknown"
            ]
          },
          "maxItems": 10,
          "required": false,
          "description": "Seniority. 'unknown' means the field is absent in the response, not a stored value"
        },
        {
          "name": "skills",
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 64
          },
          "maxItems": 20,
          "required": false,
          "description": "Skill slugs, lowercase kebab-case (react, node-js)"
        },
        {
          "name": "skills_match",
          "type": "string",
          "required": false,
          "enum": [
            "any",
            "all"
          ],
          "description": "How to combine skills. Requires skills"
        },
        {
          "name": "salary_min",
          "type": "number",
          "required": false,
          "minimum": 0,
          "description": "Lower bound in normalized ANNUAL EUR (gross). Matches jobs whose salary interval overlaps it"
        },
        {
          "name": "salary_max",
          "type": "number",
          "required": false,
          "minimum": 0,
          "description": "Upper bound in normalized ANNUAL EUR (gross)"
        },
        {
          "name": "salary_currency",
          "type": "string",
          "required": false,
          "maxLength": 8,
          "description": "ISO 4217. Only EUR: every salary is normalized to EUR at ingest and no conversion is performed"
        },
        {
          "name": "published_after",
          "type": "string",
          "required": false,
          "maxLength": 64,
          "description": "RFC 3339 date-time, e.g. 2026-08-01T00:00:00Z"
        },
        {
          "name": "verified_after",
          "type": "string",
          "required": false,
          "maxLength": 64,
          "description": "RFC 3339 date-time. Compares against the SAME value the response reports as lastVerifiedAt"
        },
        {
          "name": "source",
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 64
          },
          "maxItems": 20,
          "required": false,
          "description": "Feed/source ids, lowercase kebab-case"
        },
        {
          "name": "company",
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 128
          },
          "maxItems": 10,
          "required": false,
          "description": "Company name, exact match, case-insensitive. Aggregated postings carry no verified employer identity"
        },
        {
          "name": "sort",
          "type": "string",
          "required": false,
          "maxLength": 32,
          "description": "One of published_desc, verified_desc, salary_asc, salary_desc. Default published_desc"
        },
        {
          "name": "include_total",
          "type": "string",
          "required": false,
          "enum": [
            "none",
            "estimated",
            "exact"
          ],
          "description": "Whether to compute a total. 'exact' returns a number only when the database saw the whole predicate; with a post-projection filter active the total is withheld (null, totalRelation 'not_computed')"
        },
        {
          "name": "cursor",
          "type": "string",
          "required": false,
          "maxLength": 4096,
          "description": "Continuation cursor from pagination.nextCursor. Send it ALONE (with per_page at most), never alongside filters: the cursor already carries the filter set it traverses"
        }
      ]
    },
    {
      "name": "get_job_statistics",
      "description": "Get aggregate statistics (active jobs, new-this-week/month, top sources, salary ranges) for nomado24's remote-jobs board. No input required.",
      "readOnly": true,
      "parameters": []
    },
    {
      "name": "get_job",
      "description": "Fetch ONE nomado24 job posting by id, with the complete v2 payload: the posting body where the source permits redistribution, per-field provenance (dataOrigin: who asserted each field, by which method, when), salaryOrigin, firstSeenAt, lastVerifiedAt with its verification method, and updatedAt (the last genuine content change). Returns an error result for an id that is not a live posting; expired and withdrawn postings are not served. Read-only, free, attribution required (see structuredContent.attribution).",
      "readOnly": true,
      "parameters": [
        {
          "name": "id",
          "type": "string",
          "required": true,
          "minLength": 1,
          "maxLength": 200,
          "description": "Job id as returned by search_jobs ('job_<slug>'). A bare slug is also accepted"
        }
      ]
    }
  ],
  "license": "Free to use with an attribution link to https://nomado24.de",
  "attribution": {
    "license": "Free to use with an attribution link to https://nomado24.de",
    "requiredLinkUrl": "https://www.nomado24.de",
    "docsUrl": "https://www.nomado24.de/de/developers"
  },
  "alsoAvailable": {
    "restApi": "https://api.nomado24.de/api/public/v1/jobs",
    "restApiV2": "https://api.nomado24.de/api/public/v2/jobs",
    "openapi": "https://www.nomado24.de/openapi.yaml",
    "llmsTxt": "https://www.nomado24.de/llms.txt",
    "jobsFeed": "https://www.nomado24.de/jobs.xml",
    "statisticsDataset": "https://www.nomado24.de/remote-jobs-statistik.json"
  }
}
