Skip to main content
Glama
landedjobs

Landed MCP Server

Official

License: MIT Model Context Protocol Works with Claude Works with Cursor

Search AI-native jobs, prepare applications, and study for interviews — from any MCP client. A public Model Context Protocol server giving Claude, Cursor, VS Code, and any MCP-capable agent live access to Landed's ranked, fit-scored job corpus.

Maintained by Landed — daily AI-native job matches, agent help with every application, and mock-interview prep.


What is this?

Landed MCP connects your AI assistant to a curated, continuously-updated corpus of AI-native roles (AI Engineer, ML Engineer, RAG Engineer, AI PM, GTM Engineer, and more). Instead of copy-pasting job boards into a chat, your agent can:

  • 🔎 Search jobs — ranked and fit-scored against a structured brief (role, skills, seniority, remote, compensation, industries…), or from a plain-English description.

  • 📝 Prepare applications — pull a job's real application form, grouped into standard / screening / EEO fields, so the agent can auto-fill and draft answers before you apply.

  • 🎓 Study for interviews — fetch free, curated interview-prep, portfolio, and roadmap resources.

It speaks Streamable HTTP and works with any MCP client. Use the hosted server in seconds, or self-host this repo against your own Landed API.

Free to start. Anonymous callers get a shared free budget — no signup, no key. Add an API token for unlimited, personalized results.


Related MCP server: CareerPilot

Quick start (hosted)

The hosted server lives at:

https://mcp.landed.jobs/mcp

Pick your client below. Everything works anonymously out of the box — just omit the Authorization header. Add Authorization: Bearer lnd_live_… (mint one at Landed → Settings → API tokens) for unlimited, brief-personalized search.

Claude Code

The one-liner (CLI):

# Anonymous (free tier)
claude mcp add --transport http landed-jobs https://mcp.landed.jobs/mcp

# Authenticated (unlimited, personalized)
claude mcp add --transport http landed-jobs https://mcp.landed.jobs/mcp \
  --header "Authorization: Bearer lnd_live_your_token_here"

Then in a session: /mcp to confirm it's connected, and try the find_jobs prompt.

Claude Desktop

Open Settings → Developer → Edit Config (this opens claude_desktop_config.json), then add:

{
  "mcpServers": {
    "landed-jobs": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://mcp.landed.jobs/mcp",
        "--header", "Authorization: Bearer lnd_live_your_token_here"
      ]
    }
  }
}

Restart Claude Desktop. Drop the --header line for the free anonymous tier.

Claude Desktop bridges remote HTTP servers through mcp-remote. If your build has native Custom Connectors (Settings → Connectors → Add custom connector), you can instead paste https://mcp.landed.jobs/mcp directly.

Cursor

Create .cursor/mcp.json in your project (or ~/.cursor/mcp.json globally):

{
  "mcpServers": {
    "landed-jobs": {
      "url": "https://mcp.landed.jobs/mcp",
      "headers": { "Authorization": "Bearer lnd_live_your_token_here" }
    }
  }
}

Then enable landed-jobs under Settings → MCP. Omit headers for the free tier.

VS Code (GitHub Copilot / Agent Mode)

Create .vscode/mcp.json:

{
  "servers": {
    "landed-jobs": {
      "type": "http",
      "url": "https://mcp.landed.jobs/mcp",
      "headers": { "Authorization": "Bearer lnd_live_your_token_here" }
    }
  }
}

Open the Chat view → Agent mode → the tools appear under the 🔧 picker.

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "landed-jobs": {
      "serverUrl": "https://mcp.landed.jobs/mcp",
      "headers": { "Authorization": "Bearer lnd_live_your_token_here" }
    }
  }
}

Cline (VS Code extension)

Open Cline → MCP Servers → Configure, or edit cline_mcp_settings.json:

{
  "mcpServers": {
    "landed-jobs": {
      "type": "streamableHttp",
      "url": "https://mcp.landed.jobs/mcp",
      "headers": { "Authorization": "Bearer lnd_live_your_token_here" }
    }
  }
}

Gemini CLI

Edit ~/.gemini/settings.json (or .gemini/settings.json in your project):

{
  "mcpServers": {
    "landed-jobs": {
      "httpUrl": "https://mcp.landed.jobs/mcp",
      "headers": { "Authorization": "Bearer lnd_live_your_token_here" }
    }
  }
}

Restart gemini and run /mcp to see the tools. Omit headers for the free tier.

Any other MCP client

Point it at https://mcp.landed.jobs/mcp using the Streamable HTTP transport. Pass Authorization: Bearer <token> if you have one. Quick sanity check from a terminal:

curl -s -X POST https://mcp.landed.jobs/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Registries

Landed is listed on the Official MCP Registry as io.github.landedjobs/landed, and on Smithery as landedjobs/landed. Clients that read either registry can discover and install it without any manual configuration.


Tools

Tool

What it does

Anonymous cost

search_jobs

Ranked, fit-scored jobs. Supports physical city/country labels plus canonical remote-eligibility country/region codes; free text is parsed server-side.

1 unit / job returned

get_job_form

Application form for a jobId, grouped standard / screening / eeo for answer prep.

free

get_learning_content

Curated interview-prep, portfolio, and roadmap resources.

free

Prompts (guided workflows)

MCP prompts are reusable, user-invocable skills that teach the agent how to chain the tools and present results as a clean shortlist — never raw JSON. In most clients they show up as slash-commands.

Prompt

Args

What it guides

find_jobs

describe?

Search, then present a ranked, fit-scored shortlist + next steps.

prepare_application

jobId

Fetch the form; auto-fill standard, draft screening, leave EEO to the user.

prep_for_role

role?

Pull learning resources for a role and suggest a study order.

The server also ships always-on instructions (tool overview, presentation rules, freemium behavior) that compliant clients load automatically.

Location parameters

Location eligibility is structured rather than keyword-matched:

  • locations: physical cities/countries, with country included for ambiguous cities, e.g. ["Bengaluru, India"]

  • countryCodes: ISO alpha-2 remote/base eligibility, e.g. ["IN"]

  • regionCodes: apac, emea, or americas

  • workAuthorizationCountryCodes: ISO alpha-2 work-authorization countries

  • remote: work mode (remote, hybrid, or onsite)

The hosted API resolves human city labels to stable place identities. Callers must not invent place IDs. The legacy regions field remains accepted for compatibility.


Auth & pricing

Tier

How

What you get

Anonymous

No header

A free budget of job-units that resets every day at 00:00 UTC. Metered by a hybrid of your IP and an issued X-Landed-Anon token (echoed on every response — resend it to keep your budget across sessions).

Authenticated

Authorization: Bearer lnd_live_…

Unlimited search, personalized to your saved brief + profile. Mint a token at Landed → Settings → API tokens.

Every result carries a freemium block so your agent can see how much budget is left and how to lift the cap.


Architecture

This repository is a thin, self-hostable proxy. It speaks MCP and forwards to the hosted Landed API — it holds no database, no ranking engine, and no job data.

   MCP client                 landed-mcp (this repo)              Landed API
 ┌─────────────┐   HTTP    ┌────────────────────────┐  HTTPS   ┌────────────────────────┐
 │ Claude /    │ ───────▶  │ • MCP protocol + tools │ ──────▶  │ • search engine        │
 │ Cursor /    │  /mcp     │ • forwards caller creds│          │ • job corpus + forms   │
 │ VS Code …   │ ◀───────  │ • local learning list  │ ◀──────  │ • auth · freemium meter│
 └─────────────┘           └────────────────────────┘          └────────────────────────┘

The proxy resolves nothing itself: it forwards the caller's API token (or an anonymous id) to the Landed API, which validates it, runs the search, meters usage, and returns results plus a freemium block the proxy relays verbatim. The get_learning_content catalog is static and lives in this repo (src/mcp/catalog/learning.ts) — that tool works with no backend at all.


Self-host

Run your own proxy against the Landed API (or your own deployment of it).

Prerequisites

  • Node.js ≥ 20

  • pnpm (npm i -g pnpm)

  • A Landed API base URL and its shared internal secret

Run

git clone git@github.com:landedjobs/landed-mcp.git
cd landed-mcp
pnpm install
cp .env.example .env       # then fill in the values below
pnpm dev                   # hot-reload dev server
# → [mcp] listening on :8090 — POST /mcp → https://api.landed.jobs/api/v1

For production: pnpm start.

Stdio and Docker

For clients that start the server as a process, pnpm start:stdio speaks MCP over stdio instead of HTTP. Set LANDED_API_TOKEN to use your own API token; without it you get the anonymous free budget.

docker build -t landed-mcp .
docker run -i --rm landed-mcp

The image runs the stdio server against the hosted API.

Environment variables

Variable

Required

Default

Description

LANDED_API_BASE

✓

http://localhost:8000/api/v1

Hosted Landed API base, including the /api/v1 prefix.

LANDED_INTERNAL_SECRET

✓

—

Shared secret authenticating this proxy to the API (must match the server's INTERNAL_SERVICE_SECRET).

PORT

8090

HTTP port to listen on.

CORS_ORIGINS

*

Comma-separated allowlist of origins, or *.

RATE_LIMIT_PER_MIN

60

Per-IP first-line request cap. The API's freemium meter is the real economic cap.

Endpoints

Method

Path

Purpose

POST

/mcp

MCP Streamable HTTP endpoint (stateless).

GET

/healthz

Liveness probe ({ "ok": true }).


Development

pnpm dev           # watch + reload
pnpm check-types   # tsc --noEmit
pnpm test          # deterministic input-contract tests
pnpm start         # run once

The repository includes official MCP Registry metadata in server.json. It describes the public Streamable HTTP endpoint but does not imply that the server has been submitted to or accepted by any external registry.

Project layout

src/
├── index.ts                 # bootstrap: start the HTTP server
├── config/                  # env → typed config
├── http/                    # express shell + per-IP rate limiter
├── services/api-client.ts   # typed fetch client → Landed API
├── types.ts                 # the API response contract (owned here)
└── mcp/
    ├── server.ts            # instructions + tool/prompt registration
    ├── prompts.ts           # find_jobs / prepare_application / prep_for_role
    ├── catalog/learning.ts  # static, public learning resources
    └── tools/               # search_jobs · get_job_form · get_learning_content

Stack: TypeScript · Express · @modelcontextprotocol/sdk · Zod. No database, no build step (runs on tsx).


Contributing

Issues and PRs welcome — bug fixes, new client setup guides, and learning-catalog additions especially. Please run pnpm check-types and pnpm test before opening a PR. For private vulnerability reports, follow SECURITY.md.

License

MIT © Landed

Available Tools

3 tools
get_job_formGet job application formAInspect

Get the application form for a job (by the jobId returned from search_jobs), so you can prepare answers before the user applies. Fields are grouped: "standard" (auto-fillable from a candidate profile via mapsTo), "screening" (free-text questions to draft from the résumé/experience), and "eeo" (leave to the user). Always free — a job's form is only reachable once you've already found the job via search_jobs.

NameRequiredDescriptionDefault
jobIdYesThe jobId from a search_jobs result.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description must carry the burden. It explains the grouping of fields ('standard', 'screening', 'eeo') and notes the form is 'Always free'. This adds useful behavioral context beyond the raw input schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (three sentences) with no fluff. It front-loads the purpose and then adds necessary details about field groups and prerequisites. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple parameter set and no output schema, the description covers the essential aspects: purpose, prerequisites, and structure of the form. It is sufficiently complete for an agent to use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter jobId, with a clear description. The tool description adds only the context that jobId comes from search_jobs, which is helpful but not significantly beyond the schema. Baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get the application form for a job (by the jobId returned from search_jobs)'. It specifies the verb and resource, and distinguishes from sibling tools like search_jobs and get_learning_content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when to use the tool: 'so you can prepare answers before the user applies' and notes prerequisites ('only reachable once you've already found the job via search_jobs'). It does not explicitly mention alternatives, but the guidance is clear enough for a focused tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_learning_contentGet learning contentAInspect

Get Landed's free learning content to help the user prepare — curated interview-prep repos (real questions, company guides, worked system designs), portfolio-project catalogs, and role roadmaps from the landedjobs GitHub org. Filter by topic, role, and/or category. Always free, for any caller.

NameRequiredDescriptionDefault
roleNoTarget role, e.g. "AI Engineer", "AI PM", "GTM Engineer".
topicNoFree-text topic, e.g. "RAG", "system design", "evals".
categoryNoRestrict to one category of content.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must bear disclosure burden. It notes 'Always free, for any caller' suggesting no restrictions, but does not explicitly confirm read-only, side effects, auth needs, or rate limits. Adds 'curated' but lacks complete behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with front-loaded content types and filter guidance. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description should clarify return format (list vs. single) and pagination. It implies multiple items ('repos, catalogs, roadmaps') but not explicit. Lacks details on ordering, limits, or error handling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% parameter description coverage; description adds 'Filter by topic, role, and/or category' which mirrors schema info without additional semantics like combination behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states tool returns 'Landed's free learning content' including specific types (interview-prep repos, portfolio-project catalogs, role roadmaps) from the landedjobs GitHub org, distinguishing it from sibling tools for job forms and job search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states filtering by topic, role, and/or category, and implies use for learning content versus job-related siblings. No explicit when-not-to-use or alternatives beyond context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_jobsSearch jobsAInspect

Search Landed's live job corpus for AI-native roles and get a ranked, fit-scored shortlist. Fill the structured fields (role, skills, work mode, physical locations, remote-eligibility countries/regions, seniority, comp, industries…) from the user's request — they drive the ranking. Physical locations are resolved to stable places; use ISO country codes and canonical region codes when known. You may also pass a free-text "query"; it's parsed into the same filters and used as a semantic nudge. Free tier: up to a shared budget of jobs for anonymous callers (each returned job counts). Authenticated callers (Authorization: Bearer ) get unlimited, brief-personalized results.

NameRequiredDescriptionDefault
roleNoTarget role or title family, e.g. "AI Engineer", "RAG Engineer", "Data Scientist".
avoidNoCompanies or sectors to avoid.
limitNoHow many jobs to return.
queryNoFree-text description of the ideal job, in the user’s own words. Parsed server-side into structured filters; also used as a semantic nudge.
remoteNoWork mode preference.
skillsNoCore skills / technologies the role should involve, e.g. ["RAG", "LangChain", "Python"].
minCompNoMinimum acceptable base compensation (numeric).
regionsNoLegacy human-readable remote eligibility regions/countries, e.g. ["APAC", "India"]. Prefer regionCodes/countryCodes when known.
currencyNoCurrency for minComp, e.g. "USD".
locationsNoPreferred physical cities/countries as exact labels; include country for ambiguous cities, e.g. ["Bengaluru, India", "London, UK"]. Resolved server-side to stable place IDs.
seniorityNoSeniority target, e.g. "junior", "mid", "senior", "staff", "lead".
industriesNoPreferred company industries / sectors.
regionCodesNoCanonical remote eligibility regions.
countryCodesNoISO 3166-1 alpha-2 countries where the job may be based or remotely eligible, e.g. ["IN"].
companyStagesNoPreferred company stages, e.g. ["seed", "series-a", "public"].
workAuthorizationCountryCodesNoISO country codes where the candidate is authorized to work.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses ranking, fit-scoring, free-tier budget limits, and authenticated personalization. However, it does not mention rate limits, error behavior, or confirm read-only nature, which are important for a search tool. Some behavioral context is given but gaps remain.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (~150 words) and front-loaded with the main purpose. Every sentence adds value, including instructions on filling fields and tier differences. Minor redundancy exists but overall efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (16 parameters, no output schema), the description covers key aspects: ranking, fit-scoring, field filling, location resolution, free-text parsing, and tier differences. It adequately supports an AI agent in understanding tool usage, though return format details are omitted but acceptable for a search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (baseline 3). The description adds value by explaining that structured fields drive ranking, physical locations are resolved to stable places, and free-text query is parsed into same filters and used as a semantic nudge. This contextual meaning goes beyond the individual schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches Landed's live job corpus for AI-native roles and returns a ranked, fit-scored shortlist. It uses a specific verb ('Search'), resource ('Landed's live job corpus'), and result type, which distinguishes it from sibling tools like get_job_form and get_learning_content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when a user wants to find AI-native jobs, and mentions filling structured fields and using free-text query. However, it does not explicitly state when not to use this tool or provide alternatives, such as using get_job_form for a specific job's application form. The guidance is clear but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedget_job_form
    • First observedget_learning_content
    • First observedsearch_jobs

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct stage of the job-search workflow: discovery (search_jobs), application preparation (get_job_form), and learning resources (get_learning_content). There is no meaningful overlap, and the dependency between search_jobs and get_job_form is explicitly documented.

Naming Consistency5/5

All three names follow a consistent snake_case verb_noun convention (search_jobs, get_job_form, get_learning_content). The verb variation between search and get maps cleanly to distinct operations rather than inconsistency.

Tool Count4/5

Three tools is on the thin side for a job platform, but each has a clear, non-redundant role within a focused prep-and-discovery scope. It reads as intentionally minimal rather than an incomplete afterthought.

Completeness3/5

The surface covers discovery, form inspection, and learning content, but stops short of core lifecycle operations like actually submitting an application, saving/bookmarking jobs, or managing a candidate profile. These gaps may force agents into dead ends when users want to act rather than just prepare.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    An AI job-hunt copilot that enables searching live job boards, shortlisting openings, tracking application pipelines, and generating tailored resumes and cover letters from any MCP client.
    14
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that exposes job-search and application-management capabilities to compatible AI clients, enabling discovery of vacancies, drafting of tailored application materials, and coordinated human-approved submissions.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Live job postings read straight from 139 employers' own ATS APIs (Greenhouse, Lever, Ashby, Beisen, Moka). Every listing carries the employer's real posting date, days_open and a ghost_score — a board's "posted 2 days ago" is routinely 300 days old underneath. Heavy on AI infra, autonomous driving and embodied AI across the US, EU and China. No account, no signup, no résumé upload.
    13
    1,853 PyPI
    14
    MIT