freelancehunt-mcp
# freelancehunt-mcp
[](https://www.npmjs.com/package/freelancehunt-mcp)
[](./LICENSE)
An [MCP](https://modelcontextprotocol.io) server for the [Freelancehunt](https://freelancehunt.com) API 2.0 — the freelance marketplace used across Ukraine and neighbouring markets.
Point Claude, Cursor or any MCP client at it and ask things like *"find PHP projects under 40 bids where the employer actually pays on time"*. 31 tools cover the whole documented API: projects, bids, profiles, reviews, threads and workspaces.
## Why this exists
Freelancehunt's API has no official MCP server. The one adapter that does exist (inside a multi-board aggregator) flattens every project into a generic "job" record — dropping `bid_count` and the employer block, which are exactly the fields that tell you whether a project is worth one of your finite monthly bids.
This server keeps the API's own shapes and adds the filtering the API cannot do:
- **`find_projects`** walks several feed pages and filters locally by keywords, budget floor, bid-count ceiling and employer quality. The API itself offers none of this.
- **`get_reviews`** surfaces the per-axis grades Freelancehunt collects — communication, brief definition, **payment**, scope stability — averaged across reviews. A low payment score predicts a painful project far better than the budget does.
- Every response keeps `bid_count`, the employer's rating, completed-project count and review balance, so an agent can judge competition and counterparty in one call.
## Install
Requires Node.js 18+.
```bash
npx -y freelancehunt-mcp
```
### Get a token
Generate one on the [**Apps and API**](https://freelancehunt.com/my/api2) page of your Freelancehunt profile (`https://freelancehunt.com/my/api2`). The token acts on behalf of your account — treat it like a password, and revoke it on that same page if it leaks.
### Claude Code
```bash
claude mcp add freelancehunt --env FREELANCEHUNT_TOKEN=your_token -- npx -y freelancehunt-mcp
```
### Claude Desktop / Cursor
Add to the MCP config (`claude_desktop_config.json`, or `.cursor/mcp.json`):
```json
{
"mcpServers": {
"freelancehunt": {
"command": "npx",
"args": ["-y", "freelancehunt-mcp"],
"env": {
"FREELANCEHUNT_TOKEN": "your_token",
"FREELANCEHUNT_LANG": "uk"
}
}
}
}
```
### Run from a local checkout
`bin/mcp-stdio.sh` builds nothing and holds no secret: it reads the token from a `.env` file
and execs the built server, so the client config stays free of credentials.
```bash
git clone https://github.com/iliyalazarevwork-art/freelancehunt-mcp.git
cd freelancehunt-mcp
npm install && npm run build
cp .env.example .env # then fill in FREELANCEHUNT_TOKEN
```
Point any client at the wrapper — no `env` block needed:
```json
{
"mcpServers": {
"freelancehunt": {
"command": "/abs/path/to/freelancehunt-mcp/bin/mcp-stdio.sh"
}
}
}
```
For Codex CLI, the same command goes into `~/.codex/config.toml`:
```toml
[mcp_servers.freelancehunt]
command = "/abs/path/to/freelancehunt-mcp/bin/mcp-stdio.sh"
args = []
```
The wrapper takes the token from `FREELANCEHUNT_TOKEN` in the environment, else from
`$FREELANCEHUNT_ENV_FILE`, else from `.env` beside the repository — and accepts `FH_TOKEN`
as an alias, so a `.env` shared with another project works as-is.
### Configuration
| Variable | Default | Meaning |
|---|---|---|
| `FREELANCEHUNT_TOKEN` | — | **Required.** API token. `FH_TOKEN` also works. |
| `FREELANCEHUNT_LANG` | `en` | Response language: `uk`, `ru` or `en`. Affects skill and status names. |
| `FREELANCEHUNT_TIMEOUT_MS` | `30000` | Per-request timeout. |
## Tools
### Projects
| Tool | What it does |
|---|---|
| `find_projects` | Multi-page scan with local filters: keywords, budget range, `max_bids`, employer rating and history. **Start here.** |
| `list_projects` | Raw feed page, 10 projects per page. |
| `get_project` | Full details of one project. |
| `list_my_projects` | Projects you published (employer accounts only). |
| `create_project` · `update_project` · `project_action` | Publish, edit, amend, extend, close, reopen. |
### Bids
| Tool | What it does |
|---|---|
| `list_my_bids` | Your bids with status and winner flag. |
| `list_project_bids` | Bids on a project — sizing up competition. |
| `add_bid` | Place a bid: `days`, `budget {amount, currency}`, `comment`, `safe_type`, `is_hidden`. |
| `bid_action` | `revoke`, `restore`, `reject`, `choose` (pick winner). |
### Profiles and reviews
`get_my_profile` · `get_freelancer` · `get_employer` · `get_reviews` · `list_profiles`
### Messaging
`get_feed` · `mark_feed_read` · `list_threads` · `get_thread` · `send_message` · `thread_action`
### Workspaces
`list_workspaces` · `get_workspace` · `workspace_action` (negotiate conditions, extend, complete, close, review, request arbitration) · `complete_contest_workspace`
### Reference
`list_skills` · `list_locations` · `list_contests` · `get_contest` · `contest_action`
> **Skill ids are the only feed filter the API enforces.** Call `list_skills` first and pass `skill_ids` — `only_my_skills` and `only_for_plus` are documented but silently ignored by the server.
## Endpoint availability (measured, not documented)
The published API documentation lists 57 endpoints. Fewer than half answer for a regular freelancer token. Measured against the live API in September 2026:
| Works | Returns 404 / 400 |
|---|---|
| `/projects`, `/projects/{id}` | `/countries`, `/cities/{id}` |
| `/skills` | `/freelancers`, `/employers` (list form) |
| `/my/profile`, `/my/bids`, `/my/feed` | `/my/reviews`, `/contests`, `/my/contests` |
| `/freelancers/{id}`, `/employers/{id}` | `/my/workspaces/*` |
| `/freelancers/{id}/reviews`, `/employers/{id}/reviews` | `/projects/{id}/bids` (unless you own the project) |
| `/threads` | `/my/projects` → 400 for freelancer-only accounts |
Tools for the unavailable endpoints are still registered — access may differ by account type or Plus status, and a clear API error is more useful than a missing tool.
Two more things the documentation gets wrong:
- **Rate-limit headers do not exist.** The docs promise `X-Ratelimit-Limit` and `X-Ratelimit-Remaining`; no response carries them. Assume an undocumented limit, back off on HTTP 429.
- **Every response carries `deprecation: true`.** There is no successor version — `/v1`, `/v3` and `/v4` all 404, and the docs still describe 2.0 as current. No `Sunset` date is published, so the flag is informational for now, but plan for the API to change.
## Safety
Some tools write to a real account under the token owner's name. The platform's rules on automation are strict, and bids are a finite monthly resource — a wasted bid cannot be recovered.
- `add_bid`, `bid_action`, `send_message`, `thread_action`, `workspace_action`, `create_project`, `project_action` and `contest_action` are annotated as non-read-only, and the destructive ones (`choose` a winner, close a workspace, delete a thread, request arbitration) additionally carry `destructiveHint`. MCP clients surface these as confirmation prompts.
- The server instructions tell the model to confirm with the user before any of them.
- Unsolicited messages to employers who never contacted you are spam under the platform rules. `send_message` says so in its own description.
If you want a strictly read-only deployment, run the server with a token generated for a throwaway account, or fork and drop the write registrations — they are isolated in `src/tools/`.
## Development
```bash
npm install
npm run build
npm run typecheck
# live smoke test against the API — read-only, writes nothing
FREELANCEHUNT_TOKEN=your_token node scripts/smoke.mjs
# interactive tool explorer
npm run inspect
```
Layout: `src/client.ts` is the HTTP layer (query building, error mapping, pagination), `src/tools/*.ts` register tools by domain, `src/index.ts` wires everything to stdio.
Contributions welcome — particularly measurements of endpoint availability from **employer** and **Plus** accounts, which would fill in the gaps in the table above.
## License
MIT © Iliya Lazarev
Not affiliated with or endorsed by Freelancehunt.
TDQS
Scored across 31 tools
Most tools map cleanly to a distinct resource and action, and the generic *_action tools are separated by their target resource. There is minor overlap between workspace_action and complete_contest_workspace, and a few stubbed 404 tools add noise, but the descriptions generally resolve ambiguity.
The set is predominantly snake_case verb_noun: list_*, get_*, create_project, update_project, add_bid, send_message. The *_action batch tools are a recognizable pattern, though they are noun_noun rather than verb_noun, and complete_contest_workspace / mark_feed_read deviate slightly.
With 31 tools the surface is too large for the rubric's 25+ threshold. Several tools are documented but return 404 for normal tokens, so they inflate the count without adding usable capability.
Core lifecycles are well covered: projects support list/find/get/create/update/actions, bids support add/list/action, workspaces have list/get/action, and threads have list/get/send/action. Missing contest creation, working profile search, and the 404 stubs keep it from a perfect score.