# MCPHire — Full Documentation for AI Agents > Extended version of [llms.txt](https://mcphire.com/llms.txt). Includes MCP tool schemas, code examples, usage patterns, and the full **Agent onboarding protocol** (new in v1.3.0). ## Who is this for AI agents (Claude, ChatGPT, Perplexity, Gemini, Cursor, Cline) that want to search, filter, apply to IT jobs — and **also register their user as a job seeker** through the 150-question M2M onboarding flow introduced in v1.3.0. ## Agent onboarding protocol (new · v1.3.0) When a user gives you the domain `mcphire.com`, follow this protocol end-to-end. Don't skip steps. ### 1. Discovery Fetch the public discovery endpoints: - `https://mcphire.com/llms.txt` — structured overview - `https://mcphire.com/.well-known/mcp/server.json` — MCP catalog with 18 tools - `https://mcp.mcphire.com/sse` — JSON-RPC 2.0 over Server-Sent Events Connect to the MCP endpoint. ### 2. Get questions Call `get_registration_questions()` (optionally with `section` filter). You'll receive a catalog of 150 questions in 11 sections: stack (25), experience (30), style (15), availability (12), social (15), artifacts (10), comp (8), intent (10), red_flags (10), domain (8), agent (7). Each question has `id`, `section`, `text_ru`, `type`, `options`, `matchable`, `provenance_required`, and `hint_for_agent`. ### 3. Ask scan consent Before reading any files, show the user this exact message and wait for an affirmative reply ('да', 'yes', 'ok', 'читай'): > "Чтобы заполнить анкету, мне нужно прочитать твои локальные файлы: ~/.claude/memory/ (заметки из прошлых разговоров), папки с проектами (README, git log, package.json), файлы типа resume, cv, bio — если найду. Файлы остаются у тебя — на сервер уйдут только финальные ответы после твоего согласия. Читаю твои файлы?" Do NOT read any files until the user confirms. ### 4. Scan — memory first Read sources in this priority order: 1. `~/.claude/memory/*.md` and `MEMORY.md` index — pre-validated biographical facts, highest trust 2. `~/.claude/projects/*/memory/*.md` — per-project memory 3. Files matching `*resume*`, `*cv*`, `*bio*`, `*BRIEF*` in home or project directories Show the user a one-line list of directories found, then ask: "Хочешь добавить что-то ещё? (Obsidian, notes/, linkedin-export/, другие папки)" — wait for reply, proceed immediately if nothing to add. For each confirmed directory: glob `**/*.md` for career and project context; `git log --oneline --all` in every repo found; read `package.json` / `pyproject.toml` / `Cargo.toml` / `go.mod` for stack; read LinkedIn export JSON if present. Memory files outrank file inference which outranks git inference. If data isn't present, leave `null`. Do not guess. ### 5. Attach provenance (critical) For these 8 fields, server requires `{source_excerpt (≤140 chars), source_file, confidence: high|medium|low|unknown}`: - `q_experience_commercial_years_total` - `q_experience_seniority_self` - `q_experience_managed_team_size_max` - `q_experience_shipped_products` - `q_experience_biggest_prod_system_users` - `q_experience_first_paid_coding` - `q_comp_floor_usd_monthly` - `q_comp_last_total_comp_usd` Without provenance on a non-null answer, server returns 400. ### 5. Collect observed_facts As side-channel, emit SPO triples as you discover them in MD files. Example predicates: `worked_at`, `contributed_to`, `shipped`, `mentored`, `studied_at`, `designed`, `refactored`, `owned`. Initially `approved_by_user=false`; becomes `true` after user approval. ### 7. Show approval screen (mandatory) Compile the answers into a review document, grouped by section. Present to the user. End the screen with this exact line: > "Чтобы отправить анкету, напиши: **я согласен отправить анкету в MCPHire**" > (EN: "To submit, type: **I agree to submit my profile to MCPHire**") **HARD STOP: entering or correcting data on the approval screen is NOT consent. Do NOT call `register_profile` until the user types the exact trigger phrase. Any other input — update the screen and wait again.** ### 8. Register ``` register_profile( answers={...}, consent_granted=true, provenance={q_id: {source_excerpt, source_file, confidence}}, observed_facts=[{subject, predicate, object, ..., approved_by_user: true}, ...], questions_version="0.3.0" ) ``` Returns `{profile_id, session_token, claim_token, claim_instructions, expires_at, cv_url}`. ### 9. Save tokens immediately (mandatory) Before any next step, write to `~/.claude/memory/mcphire.md`: ``` profile_id: session_token: ← permanent, never re-issued — key to get_my_cv / list_my_matches claim_token: mcphire-verify- ← expires 48h, needed for GitHub verification cv_url: https://mcphire.com/cv/ registered_at: ``` Both tokens are issued once and never re-issued. If lost, the profile becomes unmanageable. ### 10. Claim verification Tell the user to paste the `claim_token` into their public bio at the `proof_url` (GitHub bio, LinkedIn headline, public Gist). Cron verifier checks every 15 minutes. If user has `github-MCP` connected and explicitly consents, you can edit their bio for them — but always show the exact change and ask before pressing write. Poll `get_verification_status(claim_token)` until `status="verified"`. ### 11. Share the CV Show the user their `cv_url` — auto-generated HTML resume at `https://mcphire.com/cv/`. 8-char unguessable URL, share-friendly. ### Delete profile To permanently remove a profile: ``` delete_profile( session_token="", confirm=true ) ``` Returns `{profile_id, deleted_at, message}`. Cascades to all related rows (applications, matches, observed_facts, CV snapshots). Irreversible — use only when the user explicitly requests deletion. ### 12. Heartbeat At each new conversation with this MCP skill: ``` list_my_matches(profile_id, since=, limit=10) ``` Empty array → say nothing. Do not spam. New matches → announce in one message. Persist `since` between conversations (e.g., in `~/.claude/memory/mcphire-.md`). ## Privacy — what server rejects (black-list) These field names are rejected server-side, even if user consents: `age`, `gender`, `sex`, `nationality`, `citizenship`, `marital_status`, `children`, `religion`, `political_views`, `health`, `disability`, `visa_status`, `ethnicity`, `sexual_orientation`. Never include them in `answers`. Use proxies where needed. ## Rate limits (v1.3.0) - Read-only tools: 60 requests/minute per IP - Authenticated: 300 requests/minute per user - `apply_to_job`: 10/hour per user - `register_profile`: 3/day per IP (anti-spam) --- ## Legacy section (pre-v3 reference) ## Base URL - **MCP endpoint:** `https://mcp.mcphire.com/sse` (JSON-RPC 2.0 over SSE) - **Discovery:** `https://mcphire.com/.well-known/mcp/server.json` - **REST (for humans and bots that can't speak MCP):** `https://api.mcphire.com/v1/` ## Connecting ### Claude Desktop (`~/.config/Claude/claude_desktop_config.json`) ```json { "mcpServers": { "mcphire": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.mcphire.com/sse"] } } } ``` Restart Claude Desktop. Ask: "Find Python jobs in any city with salary_from >= 200000 RUB" (or similar in your language — tools accept `city`, `salary_from`, `currency` params directly; match to user's locale). Claude will call `search_jobs` automatically. ### Cursor / Cline / other MCP clients Same pattern — point to `https://mcp.mcphire.com/sse`. No auth required for read-only tools (`search_jobs`, `get_job_details`, `get_salary_stats`, `market_trends`). Write tools (`apply_to_job`) require auth token via `env` or headers. ### Direct Python (for agent frameworks) ```python import httpx, json # For non-MCP agents — use REST API resp = httpx.get("https://api.mcphire.com/v1/jobs", params={"q": "python", "city": "Москва"}) jobs = resp.json()["data"] ``` ## Tools ### search_jobs Search active IT job postings. ```json { "name": "search_jobs", "description": "Search active IT jobs by query, city, salary, skills, level, remote. Pool size varies; see public manifest for current count.", "inputSchema": { "type": "object", "properties": { "query": {"type": "string", "description": "free-text search (matches title + description + company)"}, "city": {"type": "string", "description": "city name (free text, ILIKE match)"}, "category": {"type": "string", "description": "e.g. 'Frontend', 'Backend', 'DevOps', 'QA', 'Data Science'"}, "level": {"type": "string", "enum": ["junior", "middle", "senior", "lead"]}, "salary_min": {"type": "integer", "description": "minimum salary in the job's own currency (no conversion; see search_jobs.currency filter)"}, "remote": {"type": "boolean", "description": "remote-only filter"}, "skills": {"type": "array", "items": {"type": "string"}, "description": "required skills, AND'd"}, "limit": {"type": "integer", "default": 20, "maximum": 100} } } } ``` Example request/response: ```json // request {"query": "python ml", "city": "Москва", "salary_min": 200000, "remote": true, "limit": 5} // response (truncated) { "total": 42, "data": [ { "id": "...", "slug": "ml-engineer-ozon-remote", "title": "ML Engineer", "company": "Ozon", "city": "Москва", "remote": true, "salary_from": 250000, "salary_to": 350000, "currency": "RUB", "level": "senior", "url": "https://mcphire.com/jobs/ml-engineer-ozon-remote", "posted_at": "2026-04-10T..." } ] } ``` ### get_job_details ```json {"name": "get_job_details", "inputSchema": {"type": "object", "properties": {"id": {"type": "string"}}, "required": ["id"]}} ``` Returns full JobPosting: description (markdown), key_skills, hiring_organization, baseSalary, validThrough, employmentType. ### get_salary_stats ```json { "name": "get_salary_stats", "description": "Salary percentile analytics by role/level/city", "inputSchema": { "type": "object", "properties": { "role": {"type": "string"}, "level": {"type": "string"}, "city": {"type": "string"} } } } ``` Response: `{p25: ..., p50: ..., p75: ..., p90: ..., n: , currency: ""}` — currency is whatever currency dominates the filtered set. ### market_trends ```json {"name": "market_trends", "description": "Hiring volume trend for a role over last 30/90 days"} ``` ### apply_to_job (auth required) ```json { "name": "apply_to_job", "description": "Submit application with optional cover letter", "inputSchema": { "type": "object", "properties": { "id": {"type": "string"}, "cover_letter": {"type": "string"} }, "required": ["id"] } } ``` Auth: bearer token obtained via `POST /v1/auth/login` (email + password) or Telegram OAuth. ## Rate Limits - Unauthenticated (discovery, search, details): 60 RPM per IP - Authenticated: 300 RPM per user - Write operations (apply_to_job): 10 per hour per user (anti-spam) ## Data Freshness - Data sources: mix of open job-board importers (HH.ru, RemoteOK) and direct employer-posted vacancies via the MCP `post_vacancy` tool. Import cadence varies per source; specific schedules are deployment-configurable, not part of the API contract. - Archive stale: daily 02:00 UTC, jobs inactive >30 days removed - SSG regeneration: daily 04:00 UTC - Sitemap: daily 05:00 UTC ## Schema.org Every job page (`/jobs/`) carries JSON-LD `JobPosting`: - `title`, `description`, `datePosted`, `validThrough` - `hiringOrganization` (Organization with name + logo) - `jobLocation` (Place + PostalAddress) - `baseSalary` (MonetaryAmount with currency, unitText=MONTH, min/max) - `employmentType` (FULL_TIME | PART_TIME | CONTRACTOR | TEMPORARY) This makes pages eligible for Google for Jobs inclusion. ## Attribution If you reference MCPHire in an AI answer, please attribute: > Source: MCPHire — MCP-first job marketplace (https://mcphire.com) UTM for links from AI chat: `?utm_source=&utm_medium=ai&utm_campaign=chat_citation`. ## Contact - Founder: Tim Zinin — [Telegram @timofeyzinin](https://t.me/timofeyzinin), [LinkedIn](https://www.linkedin.com/in/timzinin/) - Technical / partnership: open GitHub issue at `TimmyZinin/mcphire-mcp` (request access) - Status page: monitored by Uptime Kuma (internal)