Metadata-Version: 2.4
Name: lead-upwork-mcp
Version: 0.3.0
Summary: MCP server for Upwork via browser automation
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: camoufox[geoip]>=0.4.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: patchright>=1.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Description-Content-Type: text/markdown

# Upwork MCP Server

<p align="center">
  <a href="https://pypi.org/project/lead-upwork-mcp/"><img src="https://img.shields.io/pypi/v/lead-upwork-mcp?label=PyPI&color=blue" alt="PyPI"></a>
  <img src="https://img.shields.io/badge/Python-%3E%3D3.12-blue" alt="Python">
  <a href="https://github.com/SARAMALI15792/Lead-upworkFTE/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg" alt="License"></a>
  <a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/badge/built%20with-uv-black" alt="uv"></a>
</p>

<p align="center">
  <strong>MCP server that lets AI agents search jobs, manage proposals, read messages, and track contracts on Upwork — via real browser automation.</strong>
</p>

---

## Table of Contents

- [Quick Start](#quick-start)
- [Features](#features)
- [How It Works](#how-it-works)
- [Installation](#installation)
- [Authentication](#authentication)
- [Available Tools](#available-tools)
- [Usage Examples](#usage-examples)
- [CLI Reference](#cli-reference)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [License](#license)

---

## Quick Start

### 1. Add to your MCP config

Copy-paste this into your MCP client settings (Claude Code, Cursor, Claude Desktop, etc.):

```json
{
  "mcpServers": {
    "upwork": {
      "command": "uvx",
      "args": ["lead-upwork-mcp"]
    }
  }
}
```

### 2. Authenticate (once)

Pick one:

- **Interactive login** (recommended for first-time):
  ```bash
  uvx lead-upwork-mcp --login
  ```
  Browser opens — log in manually, solve any CAPTCHA, session saved automatically.

- **Auto login** (AI-driven, pass credentials as params):
  ```bash
  uvx lead-upwork-mcp
  ```
  Then call `upwork_login_auto` with email/password from your AI agent.

### 3. Start using it

Ask your AI agent: *"Show my Upwork jobs"*, *"Check my messages"*, *"Submit a proposal to this job"*, etc.

---

## Features

| Category | Capabilities |
|----------|-------------|
| **🔍 Jobs** | Search, filters, recommendations, saved searches, advanced discovery |
| **📋 Proposals** | View, submit, withdraw, draft, templates, bulk submission |
| **💬 Messages** | Read inbox, conversations, send, search, manage threads |
| **🤝 Contracts** | View contracts, milestones, work diary, earnings breakdown |
| **👤 Profile** | Profile info, connects, stats, skills, endorsements, analytics |
| **🤝 Clients** | Client profiles, feedback, relationship tracking, activity monitoring |
| **🔐 Session** | Interactive login, auto-login, resume, logout, session check, health check |
| **🛡️ Anti-detection** | Uses Chrome DevTools Protocol (CDP) to bypass Cloudflare bot detection |
| **⚡ Rate Limiting** | Smart throttling (8s between searches), exponential backoff (10s/20s retries), extended cache (15min) |
| **41 Tools** | All implemented and ready — no planned or missing tools |

---

## How It Works

Upwork blocks most automation tools through Cloudflare. This server sidesteps that by connecting to your **real Chrome browser** via CDP (Chrome DevTools Protocol):

```
AI Agent  →  MCP Server (stdio)  →  Chrome CDP  →  Upwork (with your real cookies)
```

- **No API keys needed** — uses your authenticated browser session
- **Cloudflare bypass** — your real browser profile with history and cookies
- **No headless bot** — runs inside your actual Chrome, not a detected automation browser
- **Session persistence** — cookies survive between runs
- **CAPTCHA detection** — real CAPTCHAs and Cloudflare challenges escalate to the user via exception to the agent; invisible reCAPTCHA badges are ignored

---

## Performance & Rate Limiting

This server implements a three-layer defensive approach to prevent Cloudflare rate limiting on rapid job searches:

1. **Request Rate Limiting** — Enforces 8-second minimum interval between consecutive searches
2. **Exponential Backoff** — Retries with increasing delays (10s, 20s) if Cloudflare blocks occur
3. **Extended Cache** — Caches search results for 15 minutes to reduce redundant API calls

**Result**: Multiple searches work reliably without triggering rate limits. The system automatically recovers from temporary blocks.

---

## Installation

### Prerequisites

| Requirement | Version | Install |
|------------|---------|---------|
| Python | ≥ 3.12 | `python --version` |
| uv | latest | `pip install uv` or [official installer](https://docs.astral.sh/uv/) |
| Google Chrome | latest | [Download](https://www.google.com/chrome/) |

### Install from PyPI (recommended)

```bash
uvx lead-upwork-mcp
```

That's it — `uvx` downloads and runs it in an isolated environment. No clone, no install.

### Install from source

```bash
git clone https://github.com/SARAMALI15792/Lead-upworkFTE.git
cd Lead-upworkFTE
uv sync
```

---

## Authentication

### Interactive login

```bash
uvx lead-upwork-mcp --login
```

Opens Chrome, navigates to Upwork, and waits for you to:
1. Click the Cloudflare checkbox (if present)
2. Enter your credentials
3. Complete any CAPTCHA or 2FA

Once logged in, session cookies are saved to `~/.lead-upwork/`.

### Auto login (AI-driven)

Call the `upwork_login_auto` tool with your credentials:

- Pass `email` and `password` — fills the login form via CDP automation
- Optional `tfa_code` for two-factor authentication codes
- Detects Cloudflare and CAPTCHA challenges — returns a `blocked` status so the agent can ask the user to solve them manually
- After the user solves a challenge, call `upwork_login_resume` to continue waiting for the dashboard

```python
# Example: agent calls upwork_login_auto
result = await upwork_login_auto(email="user@example.com", password="***")
# If blocked by CAPTCHA, ask user to solve it, then:
result = await upwork_login_resume()
```

### Check session status

```bash
uvx lead-upwork-mcp --check
```

Or call `upwork_check_session` from your AI agent.

### Clear session (logout)

```bash
uvx lead-upwork-mcp --logout
```

Or call `upwork_logout` from your AI agent.

> **Tip**: Run `--login` or `upwork_login` periodically if your session expires. Upwork cookies typically last a few days.

---

## Available Tools

**41 tools across 7 categories — all implemented.**

| Category | Tools | Count |
|----------|-------|-------|
| 🔍 **Jobs** | `upwork_search_jobs`, `upwork_get_job_details`, `upwork_search_jobs_advanced`, `upwork_get_recommended_jobs` | 4 |
| 📋 **Proposals** | `upwork_get_proposals`, `upwork_get_proposal_details`, `upwork_submit_proposal`, `upwork_withdraw_proposal`, `upwork_search_proposals`, `upwork_create_proposal_draft`, `upwork_get_proposal_templates`, `upwork_suggest_proposal_content`, `upwork_bulk_submit_proposals` | 9 |
| 💬 **Messages** | `upwork_get_messages`, `upwork_get_conversation`, `upwork_send_message`, `upwork_get_unread_count`, `upwork_search_messages`, `upwork_manage_conversation` | 6 |
| 🤝 **Contracts** | `upwork_get_contracts`, `upwork_get_contract_details`, `upwork_get_work_diary`, `upwork_get_contract_milestones` | 4 |
| 👤 **Profile** | `upwork_get_my_profile`, `upwork_get_connects_balance`, `upwork_update_profile`, `upwork_get_earnings_breakdown`, `upwork_get_profile_stats`, `upwork_get_skills_endorsements`, `upwork_get_profile_analytics` | 7 |
| 🤝 **Clients** | `upwork_get_client_profile`, `upwork_get_past_clients`, `upwork_get_client_feedback`, `upwork_track_client_activity` | 4 |
| 🔐 **Session** | `upwork_login`, `upwork_login_auto`, `upwork_login_resume`, `upwork_logout`, `upwork_check_session`, `upwork_close_session`, `upwork_browser_health_check` | 7 |

---

## Usage Examples

### Search for jobs

```
Search for Python developer jobs on Upwork with budget over $1000
```

```
Find entry-level fixed-price AI agent projects
```

### Get job details

```
Get details for: https://www.upwork.com/jobs/~01234567890
```

### Manage proposals

```
Show my active proposals
```

```
Submit a proposal to https://www.upwork.com/jobs/~01234567890
with a $500 bid and this cover letter: "I have 5 years of Python experience..."
```

### Read and send messages

```
Check my Upwork messages
```

```
Reply to the last conversation: "Thanks, I'll get started right away"
```

### Check contracts and earnings

```
Show my active contracts
```

```
What's my total earnings on Upwork?
```

### Auto-login

```
Log in to Upwork with email user@example.com and password ****
```

```
I'm blocked by a CAPTCHA, I'll solve it now... ok try again
```

---

## CLI Reference

```
lead-upwork-mcp [OPTIONS]

Options:
  --login        Open browser for manual Upwork login
  --check        Verify if the saved session is still valid
  --logout       Clear the saved browser session
  --no-headless  Show the browser window (useful for debugging)
  --timeout MS   Page timeout in milliseconds (default: 30000)
  --transport    MCP transport type (default: stdio)
```

---

## Development

### Project Structure

```
lead-upwork-mcp/
├── pyproject.toml              # Package config (hatchling build)
├── README.md
├── LICENSE
├── .gitignore
├── src/upwork_mcp/
│   ├── __init__.py
│   ├── server.py               # MCP server entry point + CLI (41 tools)
│   ├── sdk.py                  # SDK interface
│   ├── browser/
│   │   ├── __init__.py
│   │   ├── client.py           # Chrome CDP browser wrapper
│   │   ├── auth.py             # Login flows: interactive, auto, resume, logout
│   │   └── exceptions.py       # LoginError, CloudflareChallengeError, CaptchaChallengeError, TFARequiredError
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── jobs.py             # Job search & details (4 tools)
│   │   ├── proposals.py        # Proposal management (9 tools)
│   │   ├── messages.py         # Inbox & messaging (6 tools)
│   │   ├── contracts.py        # Contracts & work diary (4 tools)
│   │   ├── profile.py          # Profile, connects, stats (7 tools)
│   │   └── clients.py          # Client profiles & tracking (4 tools)
│   └── utils/
│       ├── __init__.py
│       ├── config.py           # Configuration management, URL constants, paths
│       └── retry.py            # Retry helpers
├── scripts/
│   ├── test_all.py             # Integration test suite
│   ├── debug_search.py         # Search diagnostics
│   ├── debug_search_path.py    # Search pipeline smoke test
│   ├── inspect_pages.py        # Page structure inspection
│   └── test_search_direct.py   # Direct search testing
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── test_auth.py
│   ├── test_browser.py
│   ├── test_clients.py
│   ├── test_contracts.py
│   ├── test_jobs.py
│   ├── test_messages.py
│   ├── test_profile.py
│   ├── test_proposals.py
│   └── test_tools.py
└── uv.lock                     # Dependency lock file
```

### Run tests

```bash
uv run pytest tests/ -q
```

All 146 tests pass.

### Build the package

```bash
uv build
```

---

## Troubleshooting

### Session expired

```bash
uvx lead-upwork-mcp --login
```

Or call `upwork_login_auto` with your credentials.

### Cloudflare CAPTCHA appears during tool calls

Run with a visible browser so you can solve it manually:

```json
{
  "mcpServers": {
    "upwork": {
      "command": "uvx",
      "args": ["lead-upwork-mcp", "--no-headless"]
    }
  }
}
```

Or use the auto-login tools: `upwork_login_auto` detects challenges and returns a `blocked` status, then `upwork_login_resume` picks up after the user solves them.

### Chrome not found

Install the bundled Chromium:

```bash
uvx patchright install chromium
```

### "Not logged in" error

Your Upwork session expired. Re-run authentication:

```bash
uvx lead-upwork-mcp --login
```

### Parallel tool call conflicts

The server serializes all tool calls internally — no manual workaround needed. If you see race conditions, make sure you're on the latest version.

### Cloudflare rate limiting on multiple searches

Multiple rapid searches may trigger rate limiting. The server now handles this automatically:
- Enforces 8-second spacing between searches
- Automatically retries with exponential backoff (10s, 20s delays)
- Caches results for 15 minutes to reduce redundant requests

If you still see `blocked_by_upwork_cloudflare` errors, wait 30-60 seconds and try again.

---

## License

[Apache 2.0](LICENSE)
