Job Board MCP Server
This server provides MCP-compatible job search and lookup capabilities.
search_jobs: Search job listings across multiple platforms (e.g., Lever, Greenhouse, RemoteOK) by keyword/query, with optional location filter (defaults to Remote) and configurable result limit (default 10).
get_job_details: Retrieve detailed information for a specific job posting using its unique job ID (e.g., 'lever-abc123') returned from search results.
Multi-source aggregation: Combines listings from multiple ATS platforms into one interface.
Smart caching: Uses SQLite to reduce redundant API calls and improve performance.
MCP protocol support: Works with any MCP-compatible client like Claude Desktop.
Aggregates job listings from Greenhouse's ATS API, enabling search and retrieval of job postings from Greenhouse alongside other sources.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Job Board MCP Server find me remote software engineering jobs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Job Board MCP Server
π Live Demo: https://job-board-mcp.onrender.com
A Model Context Protocol (MCP) server that aggregates job listings from multiple platforms into a single searchable interface. Built with TypeScript, containerized with Docker, and deployed with a full CI/CD pipeline.
Why I Built This
I wanted a way to search job listings across multiple platforms without hopping between different sites. Most job aggregators either require paid API access or scrape sites in ways that break constantly. So I built one that pulls from public ATS (Applicant Tracking System) APIs, which is both legitimate and reliable.
This also gave me an excuse to build something end-to-end: TypeScript, testing, Docker, CI/CD, the whole stack.
Related MCP server: jobfinder-mcp
Features
Multi-source aggregation β Pulls from Lever, Greenhouse, and RemoteOK simultaneously
Smart caching β SQLite layer reduces redundant API calls by 70%+
Round-robin merging β Results are interleaved so no single source dominates
Parallel fetching β All API calls happen concurrently for faster responses
MCP protocol β Works with any MCP-compatible client (Claude Desktop, etc.)
Containerized β Multi-stage Docker build produces a 197MB production image
Automated CI/CD β Every push runs tests and builds Docker images
Architecture
graph TD
A[MCP Client<br/>Claude Desktop, etc.] -->|MCP Protocol stdio| B[MCP Server<br/>Node.js + TypeScript]
B --> C[Tool Handlers]
B --> D[Cache Layer]
C --> E[Lever API]
C --> F[Greenhouse API]
C --> G[RemoteOK API]
C --> D
D --> H[(SQLite Database)]
style A fill:#4a90e2,stroke:#2c3e50,color:#fff
style B fill:#27ae60,stroke:#1e8449,color:#fff
style H fill:#e67e22,stroke:#a0522d,color:#fffTech Stack
Layer | Tech |
Runtime | Node.js 22 |
Language | TypeScript 5 |
Framework | @modelcontextprotocol/sdk |
HTTP Client | Axios |
Database | SQLite (better-sqlite3) |
Testing | Jest |
Container | Docker (multi-stage build) |
CI/CD | GitHub Actions |
Available Tools
search_jobs
Search for job listings across all connected platforms.
Parameters:
query(required) β Job title or keyword (e.g., "Cloud Engineer")location(optional) β Location filter (default: "Remote")limit(optional) β Max results (default: 10)
get_job_details
Get detailed information for a specific job posting.
Parameters:
jobId(required) β The unique job ID from search results
Quick Start
Prerequisites
Node.js 22 or higher
npm
Local Development
# Clone the repo
git clone https://github.com/Danialesss/job-board-mcp.git
cd job-board-mcp
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run the server
npm startDocker
# Build the image
docker build -t job-board-mcp .
# Run the container
docker run -it job-board-mcp
# Or use docker-compose
docker compose upRunning Tests
# Run all tests
npm test
# Run with coverage report
npm test -- --coverageProject Structure
job-board-mcp/ βββ src/ β βββ index.ts # MCP server entry point β βββ tools/ # MCP tool handlers β β βββ searchJobs.ts β β βββ getJobDetails.ts β βββ datasources/ β β βββ cache.ts # SQLite caching layer β β βββ apis/ # External API integrations β β βββ leverApi.ts β β βββ greenhouseApi.ts β β βββ remoteOkApi.ts βββ tests/ # Jest test suites βββ .github/workflows/ # GitHub Actions CI/CD βββ Dockerfile # Multi-stage container build βββ docker-compose.yml
CI/CD Pipeline
Every push to main triggers two automated workflows:
Run Tests β Installs dependencies, builds TypeScript, runs the full Jest suite with coverage reporting
Build Docker Image β Builds the multi-stage Docker image with layer caching to verify the container ships correctly
Testing
The project has 12 test cases covering the cache layer, tool handlers, and error paths. Coverage sits at around 85% for business logic (excluding server bootstrapping).
Challenges I Ran Into
Native modules in Docker β
better-sqlite3requires Python and build tools to compile. Solved with a multi-stage build that keeps the final image slim.Node version mismatch β
better-sqlite3needed Node 22+, which conflicted with GitHub Actions' default matrix. Simplified to Node 22 only.ESM + Jest β TypeScript ESM support in Jest is famously painful. Solved with
--experimental-vm-modulesflag and a customtsconfig.test.json.Source dominance β Lever was returning first and filling the result limit before Greenhouse/RemoteOK. Fixed by interleaving results round-robin.
CI cache directory β SQLite failed on GitHub Actions because the
data/directory didn't exist. Added a check to create it if missing.
Future Improvements
Add more ATS sources (Ashby, Workable, SmartRecruiters)
Add job filtering by salary range
Add pagination for large result sets
Deploy to Render or Fly.io for public access
Add rate limiting per source
Implement scheduled cache refresh
License
MIT
Author
Tun Danial Adli Bin Tun Ali
GitHub: @Danialesss
Available Tools
2 toolsget_job_detailsA
Get detailed information about a specific job posting using its ID (returned from search_jobs).
Inputs: jobId (required).
search_jobsB
Search for job listings across multiple platforms (Lever, etc.). Returns a list of jobs matching the query and location.
Inputs: query (required), limit, location.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogβ¦
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: one searches for job listings and the other retrieves details for a specific job by ID. There is no overlap or ambiguity between them.
Both tools follow the same verb_noun snake_case pattern: search_jobs and get_job_details. The naming is predictable and consistent.
Two tools feels thin for a job board server. While they cover the basic search-and-detail flow, a typical job board server would likely benefit from additional tools such as listing recent jobs, filtering by platform, or paginating results.
The server covers the core read-only workflow of searching for jobs and viewing details, but it lacks other common operations like browsing all recent jobs without a query, pagination controls, or platform-specific listing. The surface is functional but minimal.
Maintenance
Related MCP Connectors
Public MCP server for discovering open jobs. Search, filter, and get application links.
Job search for Switzerland. Searches current listings on funkyjobs.ch by keyword, place with radius, workload, category and publishing date, and fetches a single listing with employer, location, workload and salary where stated. Read-only, no account needed. Docs: https://www.funkyjobs.ch/mcp-connector
Google Jobs listings billed per result, via the Apify Google Jobs Scraper API, hosted MCP.
Real-time ATS job postings, company career feeds & B2B hiring signals MCP. OAuth or API key.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAggregates job listings from multiple ATS and job board APIs via MCP, enabling unified search and retrieval in a structured format without HTML parsing.1MIT
- FlicenseAqualityDmaintenanceEnables searching job listings, tracking applications, managing resumes, and tailoring resumes to job posts, all locally via MCP.20-
- AlicenseNot gradedqualityBmaintenanceEnables searching and managing job postings across multiple job boards through a unified MCP interface, with deduplication and persistent tracking of application statuses.MIT
- AlicenseNot gradedqualityCmaintenanceEnables aggregated job scraping from LinkedIn, Indeed, Google Jobs, Adzuna, Jooble, Remotive, and Himalayas, with deduplication and retrieval of job postings via MCP tools.1MIT