An MCP server that filters US job postings by technical fit AND visa sponsorship history for international students (F-1/OPT).
Project description
runwayMCP
An MCP server that helps international students (F-1/OPT) filter US job postings by technical fit AND visa sponsorship history — in a single call.
Quick install
Create a .mcp.json file in the directory where you run Claude Code:
{
"mcpServers": {
"runway-mcp": {
"command": "uvx",
"args": ["runway-mcp"]
}
}
}
That's it. Open Claude Code — uvx downloads and runs the server automatically.
Don't have
uv? Install it:pip install uv(or see uv docs)
Alternative: install from source
git clone https://github.com/satovarb16/runwayMCP
cd runwayMCP
pip install -e ".[dev]"
Then use python -m server instead of uvx runway-mcp in your .mcp.json, and add "cwd": "/path/to/runwayMCP".
First-time setup: ingest your CV
Before scoring job matches, store your CV once:
You: "Set up my profile using my CV at /path/to/resume.pdf"
Supports .pdf and .docx. Claude will ask for sampling approval — this is expected.
Usage
You: "Evaluate this role for me: https://jobs.example.com/swe-123"
Claude:
→ analyze_job(url) — fetches job + checks visa + scores CV match
→ Returns APPLY / CONSIDER / SKIP + reasoning
On first run, the server downloads USCIS H-1B data (~2MB) automatically.
Optional: Playwright for JavaScript-heavy job boards
Some Greenhouse custom domains require a headless browser to parse. Install the optional extra:
pip install -e ".[dev,browser]"
playwright install chromium
Without it, canonical boards.greenhouse.io URLs always work. The server warns you at startup if Playwright is missing.
Note:
setup_profile,analyze_match, andanalyze_jobuse MCP Sampling — Claude Code will ask for your approval the first time these tools make a sampling request. This is expected behavior.
How it works
Claude Code launches this server over stdio and calls its tools when relevant. You don't invoke the tools directly — Claude decides when to call them based on the conversation.
One-call flow (recommended):
You: "Evaluate this role for me: https://jobs.example.com/swe-123"
Claude:
1. analyze_job(url) → job details + visa verdict + match score + APPLY/CONSIDER/SKIP
2. [reasons over the data] → context, red flags, application advice
Or use the individual tools directly:
Claude:
1. fetch_job_posting(url) → job title, company, country, full JD
2. check_visa_sponsorship(company) → H-1B history, approval rate, verdict
3. analyze_match(job) → fit score vs your stored CV
The visa check only runs for US roles — Claude skips it for positions in other countries.
Status
| Tool | Status |
|---|---|
fetch_job_posting |
✅ Working — Greenhouse, Ashby, Lever, generic fallback |
check_visa_sponsorship |
✅ Working — real USCIS FY2024 data, auto-refreshes on startup |
setup_profile |
✅ Working — CV ingestion via MCP Sampling |
update_profile |
✅ Working — update stored CV |
analyze_match |
✅ Working — job-vs-CV scoring |
analyze_job |
✅ Working — one-call orchestrator |
Tools
analyze_job(url: str) -> AnalyzeJobResult
One-call orchestrator. Fetches the job, checks visa sponsorship, and scores the match against your stored CV. Returns a combined envelope:
{
"job": { "title": "...", "company": "...", "url": "..." },
"visa": { "verdict": "GREEN", "filings": 42, "approval_rate": 0.91 },
"match": { "score": 84, "matched_skills": [...], "missing_skills": [...], "summary": "..." },
"recommendation": "APPLY"
}
Recommendation thresholds:
APPLY— visa GREEN and score ≥ 70SKIP— visa RED or score < 40 (SKIP takes precedence)CONSIDER— everything else
Requires a stored profile (run setup_profile first). If no profile exists, returns a clear error.
setup_profile(cv_path: str) -> ProfileSetupResult
Reads a CV file (.pdf or .docx), sends it to Claude for structured extraction, and stores the result at ~/.config/runway-mcp/profile.json. Required before analyze_match or analyze_job.
update_profile(cv_path: str) -> ProfileSetupResult
Same as setup_profile but replaces an existing profile. Use when you update your CV.
analyze_match(job: JobPostingResult) -> MatchResult
Scores a job posting against your stored CV using Claude. Returns a 0–100 score with matched skills, missing skills, and a summary. Requires a stored profile.
check_visa_sponsorship(company: str) -> VisaResult
Looks up a company's H-1B petition history via the USCIS H-1B Employer Data Hub.
Returns: company, total_filings, approval_rate (0–1), verdict (green/yellow/red), source.
Verdict thresholds (calibrated against FY2024 data, ~36k employers):
green— ≥ 5 filings AND approval rate ≥ 80% (active sponsor, top ~10%)yellow— ≥ 1 filing AND approval rate ≥ 50% (has sponsored before)red— no record or rate below threshold
Data is downloaded and cached at ~/.cache/runway-mcp/uscis_h1b.csv on first call (~2MB) and auto-refreshes to the latest FY on every server startup.
fetch_job_posting(url: str) -> JobPostingResult
Fetches and parses a job posting from a URL.
Returns: title, company, country, location, description, posted_date, source_url.
Supported job boards
| ATS | Canonical domain | Company custom domain | Notes |
|---|---|---|---|
| Greenhouse | ✅ boards.greenhouse.io, job-boards.greenhouse.io |
✅ with [browser] extra |
Custom domains require Playwright |
| Ashby | ✅ jobs.ashbyhq.com |
❌ not yet | |
| Lever | ✅ jobs.lever.co, lever.co |
❌ not yet | |
Any board with schema.org/JobPosting markup |
✅ generic fallback | ✅ generic fallback | Quality depends on the site's markup |
| Workday, ADP, others | ⚠️ generic fallback (best-effort) | ⚠️ generic fallback (best-effort) | Works if the page embeds JSON-LD or microdata |
| SmartRecruiters | ❌ not yet | ❌ not yet | Has public API — planned |
| BambooHR | ❌ not yet | ❌ not yet | Has public API — planned |
Known gaps
| Scenario | Behavior | Workaround |
|---|---|---|
| Greenhouse custom domain without Playwright installed | Fails with an actionable error | Install [browser] extra |
| Greenhouse custom domain behind bot protection | Fails — bot protection blocks even headless browsers | Use the canonical boards.greenhouse.io URL |
| Lever custom domain | Unsupported | Find the jobs.lever.co/company/uuid URL directly |
| Any aggregator URL (LinkedIn, Indeed, Handshake) | Unsupported | Use the URL from the "Apply" redirect |
Tool vs. reasoning boundary
These tools only fetch and shape data. Claude handles all reasoning:
- Whether to call
check_visa_sponsorship(only for US roles) - How to interpret the verdict and score in context
- Whether the role is a good fit overall
This is intentional — tools that encode judgment make Claude less useful, not more.
Tests
pytest -m contract # fast contract tests
pytest -m integration # server tool registration
pytest # full suite (214 tests)
Contributing
pip install -e ".[dev]"
pre-commit install # runs ruff lint + format before every commit
Highest-value next features (in priority order):
- Workday parser — dedicated parser for better reliability on Workday boards
- SmartRecruiters — public API, clean integration
- BambooHR — public API, clean integration
- Lever custom domains — same pattern as Greenhouse custom domains
PRs welcome.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file runway_mcp-0.1.0.tar.gz.
File metadata
- Download URL: runway_mcp-0.1.0.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c57ad9d984921ec0fe1ca6170f59488e21286f1179c01a8e5c829e06c874205d
|
|
| MD5 |
795b56091b8d9c80174834a50eb3cbee
|
|
| BLAKE2b-256 |
e3f1c016eefe63a1f3fedc1201af74a29f039c4691f2758c80eeeafa2a1640e3
|
File details
Details for the file runway_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: runway_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc2604ab598d79e29225c03ba8afe471648f4bf881b37f6f8fa70873cf6224d8
|
|
| MD5 |
3108f70737aad8585bfe4d33f76159b8
|
|
| BLAKE2b-256 |
3c655de8a59845b75d1ab2966edc6f90a38504f783dce563f0db1622d1e9f816
|