mcp-adzuna

mcp-adzuna

MCP server exposing Adzuna's job search and salary analytics APIs as tools, including job search, category listing, salary histograms, top companies, regional data, historical salary data, and API version checking.

Category
访问服务器

README

mcp-adzuna

An MCP (Model Context Protocol) server that exposes Adzuna's job search and salary analytics APIs as tools.

This repo is server-only, by design: it's meant to be pulled into other AI systems/repos as a reusable dependency, not run standalone. The client half of MCP — connecting to a server, listing its tools, and dispatching tool calls from an LLM — is generic and already provided by whatever is hosting your agent (Claude Code, Claude Desktop, or the MCP client library inside your own agent stack). Point that host at this server (see below) rather than writing a bespoke client per project. A minimal demo client is included under example/ purely to show the protocol working end-to-end — not as a reusable client library for production use.

Architecture

MCP defines three roles: a host app that embeds an LLM (Claude Code, Claude Desktop, or your own agent stack), an MCP client living inside that host which speaks the MCP wire protocol (tool discovery, tools/call, JSON-RPC framing), and an MCP server that exposes tools and responds to protocol messages without knowing who's calling it. This repo is only the last one — the host and its MCP client are supplied by whoever consumes this server (see Using from another repo).

Internally, the server is split into two layers with no knowledge of each other's domain:

LLM decides to call a tool
        │
        ▼
Host app (Claude Code / Claude Desktop / your agent stack)
        │  spawns `mcp-adzuna` as a subprocess, speaks MCP over stdio
        ▼
MCP Client (built into the host — see example/ for a minimal standalone one)
        │  tools/call { name: "search_jobs", arguments: {...} }
        ▼
┌─────────────────────────── this repo ───────────────────────────┐
│  MCP Server (server.py: the `mcp` object)                        │
│    - owns the stdio loop, tool registry, JSON schemas            │
│    - dispatches to the matching @mcp.tool() function             │
│           │                                                      │
│           ▼                                                      │
│  search_jobs(country=..., what=...)                              │
│           │  plain Python function call, no protocol involved    │
│           ▼                                                      │
│  AdzunaAPI.search(...)   (client.py)                             │
│    - builds query params, calls httpx, strips __CLASS__ noise    │
└────────────────────────────┼─────────────────────────────────────┘
                              ▼
                    Adzuna's REST API (api.adzuna.com)
  • server.py is the only file that speaks MCP: tool names, docstrings-as-descriptions, type hints-as-JSON-schema.
  • client.py's AdzunaAPI is a plain REST wrapper around Adzuna's HTTP API — it has no knowledge that MCP exists. It's deliberately not named AdzunaClient, to avoid confusion with the "MCP client" role above; it's a client of Adzuna's API in the ordinary SDK sense (like httpx.Client or boto3.client(...)), not an MCP client.

This split means AdzunaAPI is independently testable (tests/test_client.py runs against a mocked HTTP transport with zero MCP runtime involved) and independently reusable (importable in a plain script with no MCP dependency dragged in).

Tools

Tool Adzuna endpoint What it does
search_jobs /jobs/{country}/search/{page} Search job listings by keyword, location, salary, category, etc.
list_categories /jobs/{country}/categories List job category tags (e.g. it-jobs, sales-jobs).
salary_histogram /jobs/{country}/histogram Distribution of salaries for a search as a histogram.
top_companies /jobs/{country}/top_companies Top 5 employers by vacancy count for a search.
regional_data /jobs/{country}/geodata Vacancy counts per sub-region of a location.
historical_salary /jobs/{country}/history Average salary by month, over time.
api_version /version Current Adzuna API version (useful for checking connectivity/auth).

Setup

  1. Get a free app_id/app_key at developer.adzuna.com/signup.

  2. Install the package:

    pip install -e .
    
  3. Set your credentials:

    cp .env.example .env
    # edit .env and fill in ADZUNA_APP_ID / ADZUNA_APP_KEY
    

Running standalone

export ADZUNA_APP_ID=... ADZUNA_APP_KEY=...
mcp-adzuna

This starts the server on stdio, the standard transport for local MCP clients.

Using from another repo

Since this package isn't published to PyPI, other repos can run it straight from GitHub with uv's uvx — no local clone or install step needed in the consuming repo:

{
  "mcpServers": {
    "adzuna": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/fabioba/mcp-adzuna.git", "mcp-adzuna"],
      "env": {
        "ADZUNA_APP_ID": "your-app-id",
        "ADZUNA_APP_KEY": "your-app-key"
      }
    }
  }
}

Or, with Claude Code's CLI:

claude mcp add adzuna --env ADZUNA_APP_ID=your-app-id --env ADZUNA_APP_KEY=your-app-key \
  -- uvx --from git+https://github.com/fabioba/mcp-adzuna.git mcp-adzuna

uv/uvx will fetch and cache the package from the git repo on first run, and re-fetch when the pinned ref changes — pin to a tag or commit (git+https://...@v0.1.0) once you cut a release, so consuming repos don't pick up breaking changes silently.

If a consuming repo already manages its own Python environment, adding mcp-adzuna @ git+https://github.com/fabioba/mcp-adzuna.git to its pyproject.toml/requirements.txt dependencies works the same way, and mcp-adzuna becomes an installed console-script entry point in that environment's mcpServers config instead.

Using locally with Claude Code / Claude Desktop

For local development on this repo itself, add it to your MCP config using the local install (see Setup) instead:

{
  "mcpServers": {
    "adzuna": {
      "command": "mcp-adzuna",
      "env": {
        "ADZUNA_APP_ID": "your-app-id",
        "ADZUNA_APP_KEY": "your-app-key"
      }
    }
  }
}

Example client

example/ contains a minimal MCP client that spawns this server and calls a tool, to see the protocol work end-to-end without setting up a full MCP host first:

pip install -e ".[dev]"
python example/client.py

See example/README.md for what it demonstrates.

Development

pip install -e ".[dev]"
pytest

Tests run against a mocked HTTP transport (httpx.MockTransport) and don't require real Adzuna credentials.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选