LeetCode MCP
by akshaya-cp
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. |
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues