Skip to main content
Glama
README.md
# LeetCode MCP — Learn MCP by Building One

This project is **two things at once**:

1. A gentle, from-scratch tutorial on **what an MCP is and how to build one**.
2. A working **LeetCode MCP** that connects to your LeetCode profile so an AI
   assistant (Cursor / Claude) can tell you whether you've solved a problem and
   recommend new problems by topic and difficulty.

---

## Part 1 — What is an MCP? (the mental model)

**MCP = Model Context Protocol.** It's an open standard that lets an AI model
safely use *external tools and data*. Think of it as a **USB-C port for AI**:
any AI client that "speaks MCP" can plug into any MCP server and instantly gain
new abilities.

Three roles:

| Role         | What it is                                | In our case               |
| ------------ | ----------------------------------------- | ------------------------- |
| **Host**     | The app you chat in                       | Cursor / Claude Desktop   |
| **Client**   | Lives inside the host, speaks MCP         | Built into Cursor         |
| **Server**   | Your program that exposes tools/data      | `server.py` (this repo)   |

An MCP server can expose three kinds of things:

- **Tools** — functions the AI can *call* (e.g. `recommend_questions`). ← we use this
- **Resources** — read-only data the AI can *load* (like files).
- **Prompts** — reusable prompt templates.

**How they talk:** the host launches your server as a subprocess and exchanges
JSON-RPC messages over **stdio** (standard input/output). You don't manage that
plumbing — the SDK does. You just write Python functions and decorate them.

The magic of the SDK: a function's **name**, **docstring**, and **type hints**
are automatically turned into a schema the AI reads to know when/how to call it.
That's why our functions have descriptive names and detailed docstrings.

```python
@mcp.tool()
async def recommend_questions(topic: str, difficulty: str, count: int = 5) -> dict:
    """Recommend LeetCode problems by topic and difficulty..."""
    ...
```

That decorator is 90% of "creating an MCP." Everything else is normal code.

---

## Part 2 — What THIS MCP does

It exposes three tools:

| Tool                 | What it does                                                        |
| -------------------- | ------------------------------------------------------------------- |
| `get_profile`        | Your solved counts (easy/medium/hard) + global ranking.             |
| `check_if_solved`    | "Have I solved *Two Sum*?" → solved / attempted / never tried.      |
| `recommend_questions`| Find new problems by topic + difficulty, **skipping solved ones**.  |

### Where the data comes from

LeetCode has **no official public API**, but its website runs on a GraphQL
endpoint at `https://leetcode.com/graphql`. We query it the same way the site
does (see `leetcode_client.py`).

- **Public data** (problem lists, difficulty, topics) needs no login.
- **Your private "solved" status** requires your browser session cookies so
  LeetCode knows it's you. With those, every problem carries a `status`:
  `"ac"` = solved, `"notac"` = attempted, `null` = never tried.

---

## Part 3 — Setup (5 minutes)

### 1. Install dependencies

```bash
cd /Users/akshayapratapsingh/Desktop/Leetcode-MCP
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

### 2. Configure your identity + cookies

```bash
cp .env.example .env
```

Then edit `.env`:

- `LEETCODE_USERNAME` → your username from `leetcode.com/u/<username>/`.
- `LEETCODE_SESSION` and `LEETCODE_CSRF` (optional but recommended) → these
  unlock personal "solved / not solved" detection.

**How to get the cookies:**

1. Log in to <https://leetcode.com> in Chrome.
2. Open DevTools (`F12` or `Cmd+Option+I`).
3. Go to **Application → Storage → Cookies → https://leetcode.com**.
4. Copy the **Value** of `LEETCODE_SESSION` → paste into `.env`.
5. Copy the **Value** of `csrftoken` → paste as `LEETCODE_CSRF` in `.env`.

> ⚠️ These cookies are like passwords. `.env` is already in `.gitignore` so it
> won't be committed. Never share it. They expire every ~2 weeks; just re-copy
> them when your tools stop seeing your progress.

### 3. (Optional) quick local test without the AI

```bash
source .venv/bin/activate
python smoke_test.py        # prints your profile + a few recommendations
```

---

## Part 4 — Plug it into Cursor

Cursor reads MCP servers from a JSON config. Create/edit
`~/.cursor/mcp.json` (global) **or** `.cursor/mcp.json` in this project, and add:

```json
{
  "mcpServers": {
    "leetcode": {
      "command": "/Users/akshayapratapsingh/Desktop/Leetcode-MCP/.venv/bin/python",
      "args": ["/Users/akshayapratapsingh/Desktop/Leetcode-MCP/server.py"]
    }
  }
}
```

A ready-made copy is in `.cursor/mcp.json` in this repo already.

Then: **Cursor Settings → MCP** → you should see `leetcode` with a green dot and
its 3 tools. Toggle it on. (For Claude Desktop, the same block goes in
`claude_desktop_config.json`.)

### Try it in chat

- "Using leetcode, have I solved *Two Sum*?"
- "Recommend 5 medium dynamic programming problems I haven't solved yet."
- "What's my LeetCode profile summary?"
- "Give me graph problems around difficulty medium, skip ones I've done."

---

## Part 5 — How the code is organized

```
Leetcode-MCP/
├── server.py           # The MCP server: defines the 3 tools (start here)
├── leetcode_client.py  # Talks to LeetCode's GraphQL API
├── smoke_test.py       # Run the tools directly, no AI needed
├── requirements.txt    # Python dependencies
├── .env.example        # Template for your username + cookies
├── .cursor/mcp.json    # Cursor integration config
└── README.md           # This file
```

**Reading order to learn:** `server.py` (the tools + decorator) →
`leetcode_client.py` (the API calls) → `smoke_test.py` (how to call them).

---

## Part 6 — Ideas to extend it (great for upskilling)

- Add `get_daily_challenge` (LeetCode's daily problem).
- Add `get_recent_submissions(username)` to show your latest ACs.
- Add a **Resource** exposing your solved list as a browsable document.
- Cache results so you don't re-hit LeetCode on every call.
- Track a "study plan" and recommend the next problem in a curated list.

---

## Troubleshooting

| Problem | Fix |
| ------- | --- |
| Tools show "solved: null" or note about session | Add valid `LEETCODE_SESSION` + `LEETCODE_CSRF` in `.env`. |
| Cursor shows the server red / not connecting | Use **absolute paths** in `mcp.json`; confirm the venv python path exists. |
| `User not found` | Check `LEETCODE_USERNAME` matches your profile URL exactly. |
| Empty recommendations | Loosen filters (remove topic or difficulty), or set `include_paid=true`. |
| 403 / errors from LeetCode | Cookies expired — re-copy them from the browser. |