Skip to main content

Salary MCP Server (salary-mcp)

CI PyPI Python Version License: MIT

A Model Context Protocol (MCP) server providing LLMs with direct, programmatic access to actual public IT market salary benchmarks from Djinni (djinni.co) and DOU (jobs.dou.ua/salaries/).


⚡ Quick Start (Published PyPI Package)

salary-mcp is published on PyPI and can be run instantly without manual repository cloning.

1. Run over Stdio (Default)

Standard input/output communication for desktop AI clients (Claude Desktop, Cursor, Antigravity, Zed):

# Instant run with uvx (no installation needed)
uvx salary-mcp

# Or with pipx
pipx run salary-mcp

# Or install via pip
pip install salary-mcp
salary-mcp

2. Run over HTTP / SSE (Remote Server)

Server-Sent Events (SSE) mode for remote deployments, containers, and web clients:

# Start SSE HTTP server on port 8000
uvx salary-mcp --transport sse --host 0.0.0.0 --port 8000

Your MCP client can connect to: http://localhost:8000/sse


🔌 MCP Client Configurations

Claude Desktop (claude_desktop_config.json)

Stdio Mode (Recommended):

{
  "mcpServers": {
    "salary-mcp": {
      "command": "uvx",
      "args": ["salary-mcp"]
    }
  }
}

HTTP / SSE Mode:

{
  "mcpServers": {
    "salary-mcp": {
      "url": "http://localhost:8000/sse"
    }
  }
}

Cursor (~/.cursor/mcp.json)

{
  "mcpServers": {
    "salary-mcp": {
      "command": "uvx",
      "args": ["salary-mcp"]
    }
  }
}

🌐 Data Sources & Extraction Architecture

The server fetches data exclusively from the live official web portals of Djinni and DOU:

1. Djinni (https://djinni.co/salaries/)

  • Endpoint Format: https://djinni.co/salaries/?category={category}&exp={exp}&english_level={level}
  • Extraction Method: Live on-demand scraping of Djinni's rolling 30-day platform hiring metrics.
  • Extracted Data:
    • Candidate Expectations: 25th–75th percentile salary expectations and calculated median.
    • Company Vacancies: Active job posting salary offer ranges.
    • Market Activity: Real-time counters of active candidates online and open vacancies.
    • Salary Distribution: Full salary bin histogram parsed directly from embedded chart data.

2. DOU (https://jobs.dou.ua/salaries/)

  • Endpoint Source: Master widget dataset loaded directly by https://jobs.dou.ua/salaries/ (https://s.dou.ua/files/lenta/salary-widget_jun_2026_v3/data/swd-medians.csv).
  • Extraction Method: Slices official statistical quartiles ($q1$, $median$, $q3$), respondent sample sizes ($count$), and seniority title levels ($title$).
  • Historical Support: Supports querying specific historical survey waves via the as_of_date parameter (e.g. '2025-12', '2026-06'), defaulting to the latest available wave.

❓ Why DOU Provider Data May Differ from Website UI Views

When querying DOU via salary-mcp, you might occasionally notice subtle differences between the returned statistics and what is rendered in the interactive UI of jobs.dou.ua/salaries/:

  1. Frontend Sample Size Thresholds:
    • On the public website, DOU's charting scripts often apply a minimum sample size threshold (typically $\ge 15-20$ respondents).
    • When a specific experience bracket has fewer respondents (e.g. $11$ respondents for 9 years of experience in Data Science), the website chart suppresses or greys out the bar as "Недостатньо анкет" (Insufficient data).
    • The underlying DOU analytics dataset preserves the exact calculated median for those respondents, which salary-mcp returns accurately.
  2. Category Aggregations vs. Specific Title Filtering:
    • Selecting a broad category (e.g. "Data & Analytics" or "Management") on the web interface aggregates all sub-roles together.
    • Specific title queries (e.g. Middle Data Scientist or Junior HR Specialist) match the specific title tier within the dataset.
  3. Survey Wave Releases:
    • By default, salary-mcp always selects the most recent official survey wave (e.g. 2026-06). If the website user interface is displaying an earlier wave or a different article, specifying as_of_date ensures identical alignment.

🛠️ MCP Tools Reference

get_djinni_salaries

Fetch real-time candidate salary expectations and vacancy offer distributions from Djinni.

  • Arguments:
    • role (string, required): Target job role (e.g. "Software Engineer", "QA", "DevOps", "HR").
    • specialization (string, optional): Technology or domain (e.g. "Python", "React", "HR").
    • experience_years (integer, optional): Years of experience (e.g. 0, 2, 5).
    • english_level (string, optional): English proficiency (e.g. "intermediate", "advanced").

get_dou_salaries

Fetch official salary survey benchmarks and percentiles from DOU.

  • Arguments:
    • role (string, required): Job role or category (e.g. "Software Engineer", "Data Science").
    • specialization (string, optional): Language or sub-role (e.g. "Python", "Data Scientist").
    • experience_years (integer, optional): Years of professional experience.
    • seniority (string, optional): Seniority tier ("Junior", "Middle", "Senior", "Lead", "Architect").
    • city (string, optional): Location filter (e.g. "Kyiv", "Lviv", "Remote").
    • as_of_date (string, optional): Survey date in YYYY-MM format (e.g. "2025-12", "2026-06"). Defaults to latest.

compare_salaries

Compare salary benchmarks between Djinni and DOU side-by-side with differential analysis.

  • Arguments:
    • role (string, required): Target job role.
    • specialization (string, optional): Technology or specialization.
    • experience_years (integer, optional): Years of experience.
    • seniority (string, optional): Seniority level for DOU matching.
    • as_of_date (string, optional): Target survey date for DOU comparison.

list_specializations

List available roles, technologies, seniorities, locations, and historical survey dates.

  • Arguments:
    • provider (string, optional): Scope of choices ("all", "djinni", "dou"). Defaults to "all".

🛠️ Local Development

# Clone and install dependencies
git clone https://github.com/propsi4/salary-mcp.git
cd salary-mcp
poetry install

# Run test suite
poetry run pytest

# Run linter and type checks
poetry run ruff check . --fix
poetry run ruff format .
poetry run mypy src tests

📄 License

MIT License. See LICENSE for details.

Release files for salary-mcp 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for salary-mcp 0.1.1
File Size Uploaded
salary_mcp-0.1.1.tar.gz 20.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for salary-mcp 0.1.1
File Interpreter ABI Platform
salary_mcp-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 44.3 kB

Release files / salary_mcp-0.1.1.tar.gz

Download URL salary_mcp-0.1.1.tar.gz
Size 20.7 kB
Tags Source
SHA-256 checksum
How to use checksums
6d2a3f8f1d0aa3d46b9d1f2df5d1e83cd9112f7a6ca73c98777b8bff5c3bd12f
BLAKE2b-256 checksum
How to use checksums
95ea67c8cf649fea321c871cd37b3416e9ddb37e5e6320fefee10e7492ef7ac7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.2 CPython/3.13.2 Linux/6.14.0-37-generic

Release files / salary_mcp-0.1.1-py3-none-any.whl

Download URL salary_mcp-0.1.1-py3-none-any.whl
Size 23.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a7ce494efa78fe7b647a610e1fd5698ffbace3ca3ff9ab18743757f9b28ad88
BLAKE2b-256 checksum
How to use checksums
ac2493f29ea5b1de4174578174f290fc167beb7bcf9fcf59b3d308a5f0237707
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.2 CPython/3.13.2 Linux/6.14.0-37-generic

Release history Release notifications | RSS feed

0.1.2

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page