upwork-mcp
Enables searching for jobs, analyzing opportunities with a custom scoring engine, submitting proposals, managing client communications, and monitoring freelancer profile statistics.
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., "@upwork-mcp search for n8n automation jobs and analyze the top 3 matches"
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.
upwork-mcp
A Model Context Protocol (MCP) server that connects Claude to Upwork — enabling AI agents to search jobs, analyze opportunities, submit proposals, and manage client communications autonomously.
Works for any freelance niche: development, design, writing, marketing, automation, and more.
Features
Tool | Description |
| Search Upwork jobs by keyword, type, budget, experience level |
| Fetch full job description, screening questions, and client history |
| Score a job 0–100 across niche fit, client quality, budget, competition, and clarity |
| Automatically write and submit a proposal with custom cover letter and bid |
| List submitted proposals and their current status |
| Read conversations and check for unread messages |
| Reply to clients in ongoing conversations |
| View your freelancer profile, JSS score, and connects balance |
| Update your freelancer profile title, overview, and skills |
| Capture session cookies from an already-logged-in Chrome tab |
Related MCP server: offer-quest mcp
Architecture
Claude Agent
│
▼
MCP Gateway (stdio, never restarts)
│ HTTP POST /tool
▼
Worker Server (port 47821, hot-reloads on code changes)
│
▼
CDP Proxy (port 9223, rewrites Host headers)
│
▼
Chrome on host (port 9222, Playwright CDP connection)
│
▼
Upwork Web UIThe gateway/worker split means you can update tool logic without restarting Claude or your MCP client.
Prerequisites
Node.js 20+
Docker + Docker Compose
Google Chrome installed
An Upwork freelancer account
Quick Start (Docker)
1. Clone and configure
git clone https://github.com/zcrossoverz/upwork-mcp.git
cd upwork-mcp
cp .env.example .envEdit .env:
UPWORK_EMAIL=your@email.com
UPWORK_PASSWORD=yourpassword
FREELANCER_NAME=Your Name
FREELANCER_TITLE=Your Professional Title
FREELANCER_NICHE=your,skills,here
BID_RATE_DEFAULT=40
BID_RATE_MIN=25
BID_RATE_MAX=1002. Start Chrome with CDP
connect-chrome-docker.batThis launches Chrome with remote debugging + a CDP proxy that allows Docker to connect.
3. Start the worker
docker compose up -d4. Capture your session
In Claude, call manual_login — it extracts cookies from your logged-in Chrome tab and saves the session. You only need to do this once (or after your session expires).
Connect to Claude Code
Add to your MCP config (~/.claude/claude_desktop_config.json):
{
"mcpServers": {
"upwork": {
"command": "node",
"args": ["/absolute/path/to/upwork-mcp/dist/gateway.js"],
"env": {
"WORKER_PORT": "47821"
}
}
}
}Or via CLI:
claude mcp add upwork node /absolute/path/to/upwork-mcp/dist/gateway.jsLocal Development (Hot Reload)
npm install
npm run worker # starts tsc --watch + nodemon on dist/worker.jsThe gateway (dist/gateway.js) runs separately and proxies to the local worker — changes to any tool file reload the worker instantly without restarting Claude.
Recommended Agent Workflow
1. manual_login → Capture session (first time / session expired)
2. get_profile → Check connects balance before bidding
3. search_jobs → Find relevant jobs by keyword
4. get_job_details → Get full description + screening questions
5. analyze_job → Score the opportunity (skip grade D or F)
6. submit_proposal → Auto-bid with personalized cover letter
7. get_messages → Check for client responses
8. send_message → Reply to clients
9. get_proposals → Track active proposalsExample agent prompt
Search for freelance jobs matching my skills posted in the last 3 days.
For each job with grade A or B:
1. Get full job details
2. Analyze the opportunity
3. Write a personalized proposal highlighting my relevant experience
4. Submit at the recommended bid rateJob Analysis Scoring
The analyze_job tool scores each job across 5 dimensions:
Dimension | Max Points | What It Measures |
Niche Fit | 30 | Keyword match between job and your |
Client Quality | 25 | Rating, total spend, hire rate, payment verified |
Budget Fit | 20 | Budget vs your target rate, estimated project value |
Competition | 10 | Number of existing proposals (fewer = better) |
Project Clarity | 10 | Description detail, skills listed, budget specified |
Red Flags | -5 each | Vague scope, low-budget signals, no client history |
Grades:
Grade | Score | Action |
A+ | 90–100 | APPLY NOW — high priority |
A | 75–89 | APPLY — strong opportunity |
B | 60–74 | APPLY — worth pursuing |
C | 45–59 | CONSIDER — marginal fit |
D | 30–44 | SKIP |
F | <30 | AVOID |
Project Structure
upwork-mcp/
├── src/
│ ├── gateway.ts # MCP stdio gateway (thin proxy, never restarts)
│ ├── worker.ts # HTTP tool server (hot-reloads via nodemon)
│ ├── config.ts # Environment configuration
│ ├── browser/
│ │ ├── browser-manager.ts # Playwright CDP connection manager
│ │ └── upwork-auth.ts # Session management
│ └── tools/
│ ├── search-jobs.ts
│ ├── get-job-details.ts
│ ├── analyze-job.ts # Scoring engine
│ ├── submit-proposal.ts
│ ├── get-proposals.ts
│ ├── get-messages.ts
│ ├── send-message.ts
│ ├── get-profile.ts
│ ├── update-profile.ts
│ └── manual-login.ts # CDP cookie extractor
├── cdp-proxy.cjs # Host-side proxy: Docker → Chrome (fixes Host header)
├── connect-chrome-docker.bat # Launch Chrome + CDP proxy (for Docker use)
├── connect-chrome.bat # Launch Chrome only (for local use)
├── Dockerfile
├── docker-compose.yml
└── .env.exampleNotes
Session Management
Login is handled manually via manual_login. Open Chrome, log in to Upwork normally (including any 2FA), then call manual_login — it captures all cookies and saves them for Playwright to reuse.
Bot Detection
Upwork may detect unusual activity. Use reasonable request intervals and do not run the agent continuously. The server connects to your real Chrome profile via CDP, which behaves more like a real browser than headless automation.
Selector Stability
Upwork's UI changes periodically. Browser-based selectors in src/tools/ may need updating if the UI is redesigned.
Ethical Use
Only automate your own account
Comply with Upwork's Terms of Service
Review proposals before submission in production use
License
MIT
Available Tools
11 toolsanalyze_jobA
Analyze a job opportunity and score it across 5 dimensions to decide whether to apply.
Scoring breakdown (100 pts max):
Niche Fit (30pts): How well the job matches n8n/automation keywords
Client Quality (25pts): Rating, total spent, hire rate, location
Budget Fit (20pts): Budget vs your target rate, estimated total project value
Competition (10pts): Number of existing proposals (fewer = better)
Project Clarity (10pts): How well-defined the scope is
Red Flag Penalty (-5pts each): Vague scope, low budget signals, no client history
Returns: grade (A+/A/B/C/D/F), recommendation (APPLY NOW/APPLY/CONSIDER/SKIP/AVOID), suggested bid, estimated project value, key selling points, and proposal tips.
RECOMMENDED WORKFLOW:
search_jobs → find candidates
get_job_details → get full info
analyze_job → score and decide
submit_proposal → if grade A or B
Inputs: job (required), my_rate.
get_job_detailsA
Get full details of a specific Upwork job posting. Returns complete description, all screening questions, client history (jobs posted, hire rate, spend), required skills, budget, and proposal stats. ALWAYS call this before submitting a proposal to get screening questions and understand client context.
Inputs: job_url (required).
get_messagesA
Read Upwork messages.
Without room_id: lists all conversations with unread status and last message preview
With room_id: reads the full message history of that conversation
Use this to check for client responses, new invitations, and ongoing contract discussions.
Inputs: room_id, limit, unread_only.
get_profileA
Get your Upwork freelancer profile, stats, and connects balance. Returns: name, title, skills, hourly rate, JSS score, Top Rated status, total earnings, connects balance. Use this to understand your current standing and available connects before bidding.
Inputs: include_stats.
get_proposalsA
Get list of your submitted proposals on Upwork. Shows status, bid rate, submission date, and whether the client is interviewing you. Use this to track which proposals need follow-up.
Inputs: status, limit.
manual_loginA
Step 1: Open a visible browser window at Upwork login page. Returns immediately — you then login manually in the browser (solve CAPTCHA, enter credentials, handle 2FA). After login is complete, call save_session to persist the session.
Inputs: no named parameters.
save_sessionA
Step 2: After manually logging in via manual_login, call this to save the browser session. Checks if login was successful and saves cookies/storage for future headless use. Must be called AFTER you have fully logged in to Upwork in the browser window.
Inputs: no named parameters.
search_jobsB
Search for jobs on Upwork. Optimized for n8n workflow automation niche. Returns a list of jobs with title, budget, description snippet, required skills, client info, and proposal count. Use this to find potential clients and opportunities.
Inputs: query (required), job_type, experience_level, budget_min, +3 more.
send_messageA
Send a message in an Upwork conversation. Use this to:
Reply to client questions about your proposal
Follow up on submitted proposals (after 3-5 days)
Clarify project requirements
Communicate during an active contract
Keep messages professional, specific to the project, and value-adding.
Inputs: room_id (required), message (required).
submit_proposalA
Submit a proposal/bid for an Upwork job. Before calling this:
Call get_job_details to get screening questions
Craft a personalized cover letter that:
Opens with the client's specific problem (not "I am an expert in...")
Shows concrete n8n examples relevant to their use case
Mentions specific workflow patterns (HTTP Request, Webhook, Code node, etc.)
Ends with a clear CTA
Answer ALL screening questions thoughtfully
The agent will automatically type and submit the proposal.
Inputs: job_url (required), cover_letter (required), bid_rate, screening_answers, +1 more.
update_profileA
Update your Upwork freelancer profile fields. Can update: title, description/bio, hourly_rate, skills. Each field is optional — only provide what you want to change. Uses the edit buttons on your profile page (requires browser via connect-chrome.bat).
Inputs: title, description, hourly_rate, skills.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Each tool targets a distinct action and resource: job analysis, details retrieval, messaging, profile, proposals, login, search, sending messages, proposal submission, and profile updates. No two tools overlap in purpose.
All tool names follow a clear verb_noun pattern with underscores (e.g., analyze_job, get_job_details, submit_proposal). The naming is uniform and predictable across the entire set.
With 11 tools, the server is well-scoped for its purpose of automating Upwork freelancer operations. Each tool serves a necessary function without redundancy or unnecessary bloat.
The tool set covers the full workflow from job search to proposal submission, messaging, and profile management. A minor gap is the lack of tools for withdrawing proposals or managing contracts, but the core operations are complete.
Related MCP Connectors
The official Upwork MCP server, letting AI agents connect to Upwork and act on your behalf.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Free hosted MCP server: new Upwork jobs for your agent and Telegram alerts within a minute.
Hosted Web Crawler MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables seamless interaction with LinkedIn for job applications, profile retrieval, feed browsing, and resume analysis through natural language commands.36-
- AlicenseBqualityCmaintenanceA fast, secure, and LLM-friendly Model Context Protocol (MCP) server that scrapes job listings from major platforms (LinkedIn, Indeed, Google) and converts them into structured Markdown format.11MIT
- AlicenseNot gradedqualityNot gradedmaintenanceAn MCP server for automating Upwork workflows including job search, proposal submission, client communication, and contract management. It provides tools for client vetting, template-based proposals, and session safety with audit logging.MIT
- AlicenseAqualityDmaintenanceMCP server for Upwork via browser automation. Enables Claude Code to search jobs, manage proposals, messages, and contracts on Upwork.1872Apache 2.0