Repovive MCP Server
<div align="center">
<img src="docs/assets/repovive-logo.png" alt="Repovive" width="96" height="96" />
<h1>Repovive MCP Server</h1>
<p><strong>The competitive-programming platform, wired into your AI.</strong></p>
<p>
<a href="https://www.python.org"><img alt="Python 3.10+" src="https://img.shields.io/badge/Python-3.10%2B-3776AB?style=flat-square&labelColor=1F1B45&logo=python&logoColor=white"></a>
<a href="https://github.com/jlowin/fastmcp"><img alt="FastMCP v3" src="https://img.shields.io/badge/FastMCP-v3-6C5CE7?style=flat-square&labelColor=1F1B45"></a>
<a href="https://modelcontextprotocol.io"><img alt="MCP server" src="https://img.shields.io/badge/MCP-server-20E3B2?style=flat-square&labelColor=1F1B45"></a>
<img alt="httpx async" src="https://img.shields.io/badge/httpx-async-8B7CF6?style=flat-square&labelColor=1F1B45">
<a href="docs/DEPLOYMENT.md"><img alt="Docker ready" src="https://img.shields.io/badge/Docker-ready-2496ED?style=flat-square&labelColor=1F1B45&logo=docker&logoColor=white"></a>
<a href="deploy/kubernetes"><img alt="Kubernetes ready" src="https://img.shields.io/badge/Kubernetes-ready-326CE5?style=flat-square&labelColor=1F1B45&logo=kubernetes&logoColor=white"></a>
</p>
<p>
<a href="docs/TOOLS.md"><img alt="102 tools" src="https://img.shields.io/badge/tools-102-6C5CE7?style=flat-square&labelColor=1F1B45"></a>
<img alt="11 resources" src="https://img.shields.io/badge/resources-11-20E3B2?style=flat-square&labelColor=1F1B45">
<img alt="8 prompts" src="https://img.shields.io/badge/prompts-8-8B7CF6?style=flat-square&labelColor=1F1B45">
<img alt="End-to-end verified" src="https://img.shields.io/badge/tests-e2e_verified-00B894?style=flat-square&labelColor=1F1B45">
<a href="docs/SECURITY.md"><img alt="Scoped bearer auth" src="https://img.shields.io/badge/auth-scoped_bearer-E17055?style=flat-square&labelColor=1F1B45"></a>
<a href="docs/HISTORY.md"><img alt="Built-in revisions" src="https://img.shields.io/badge/revisions-built--in-00A8E8?style=flat-square&labelColor=1F1B45"></a>
<a href="CONTRIBUTING.md"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-F1B24A?style=flat-square&labelColor=1F1B45"></a>
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-3FB950?style=flat-square&labelColor=1F1B45">
</p>
<img src="docs/assets/hero.svg" alt="Repovive MCP — an AI assistant connected through MCP to problems, contests, a code judge and ratings" width="100%" />
</div>
An [MCP](https://modelcontextprotocol.io) server that exposes the
[Repovive](https://repovive.com) competitive-programming platform to any MCP client
(Claude Desktop, Claude Code, IDE extensions, …). Built with **FastMCP v3** and **httpx**.
It provides **102 tools**, **11 resources** (1 templated), and **8 prompts** covering
problems, contests, ratings, courses, blog posts, direct messages, notifications,
mock-interview info, Vive points, account/profile management, **real code submission**,
**contest standings**, **production problem/contest authoring** in Repovive's build editor,
and a **built-in local judge** — with **built-in version control** over everything it edits,
all behind **scoped bearer authentication** when served over HTTP.
Every tool has been tested end-to-end — read/write tools against the live Repovive API,
submission verified with a real `Accepted` verdict, and the authoring/judge tools by
generating full contests and running every reference solution to `Accepted`.
<table>
<tr>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-authoring.svg" alt="Author problems: statement, test cases, model solution" width="100%" /><br/>
<b>Author & problemset</b><br/>
<sub>Draft a whole problem — statement, tests, model solution, editorial, validator — in Repovive's build editor, with every edit versioned.</sub>
</td>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-judge.svg" alt="Local judge running test cases to green" width="100%" /><br/>
<b>Local judge</b><br/>
<sub>Judge solutions offline (py/c/c++/java/js) before you submit. Generated problems are correct by construction.</sub>
</td>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-contests.svg" alt="Contest podium, rating curve and standings" width="100%" /><br/>
<b>Contests & ratings</b><br/>
<sub>Browse contests, submit for a real verdict, and read standings, results and announcements.</sub>
</td>
</tr>
<tr>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-submit.svg" alt="Submit a solution and get an Accepted verdict" width="100%" /><br/>
<b>Submit & get AC</b><br/>
<sub>Submit for a real verdict and poll to <code>Accepted</code> — verified with a genuine 18/18 pass.</sub>
</td>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-deploy.svg" alt="Deploy anywhere: Docker, Kubernetes, Helm, OpenTofu, Ansible, Vagrant" width="100%" /><br/>
<b>Deploy anywhere</b><br/>
<sub>stdio or HTTP behind scoped bearer auth, with Docker, Compose, Kubernetes, Helm, OpenTofu, Ansible and Vagrant paths.</sub>
</td>
<td width="33%" align="center" valign="top">
<img src="docs/assets/feature-community.svg" alt="Community: direct messages, notifications, blocks" width="100%" /><br/>
<b>Community</b><br/>
<sub>Read and send direct messages, triage notifications, and manage conversations and blocks.</sub>
</td>
</tr>
</table>
---
## Contents
- [How it works](#how-it-works)
- [What you can do](#what-you-can-do)
- [Submitting code](#submitting-code)
- [Quick start](#quick-start)
- [Install](#install)
- [Access control](#access-control)
- [Configure your MCP client](#configure-your-mcp-client)
- [Tool reference](#tool-reference)
- [Authoring & local judge](#authoring--local-judge)
- [History & rollback](#history--rollback)
- [Repovive house style](#repovive-house-style)
- [Resources & prompts](#resources--prompts)
- [Example agent session](#example-agent-session)
- [The two authentications](#the-two-authentications)
- [Deployment](#deployment)
- [Project layout](#project-layout)
- [Documentation](#documentation)
- [Development & tests](#development--tests)
- [Security notes](#security-notes)
---
## How it works
<div align="center">
<img src="docs/assets/workflow.svg" alt="How it works: connect over MCP, read and author, judge locally, then submit or publish" width="100%" />
</div>
1. **Connect** your MCP client (Claude Desktop, Claude Code, an IDE) to the server over
stdio or HTTP.
2. **Read & author** — browse problems and contests, or generate and draft new ones in
Repovive's build editor.
3. **Judge locally** — verify a solution against its tests with the built-in judge before
anything leaves your machine.
4. **Submit / publish** — submit for a real verdict, or (with approval) publish a draft to
a contest.
## What you can do
- **Browse & read problems** — list a contest's problems with full statements,
constraints, I/O formats, time/memory limits, tags, and **sample test cases**.
- **Explore contests** — list upcoming/ongoing/past contests, view details, check and
manage your registrations, get invite links.
- **Submit & track** — submit a solution for a **real verdict**, read your submission
history, and pull a contest's **ranking, results and announcements**.
- **Ratings** — page and filter the global leaderboard by country / name / tier.
- **Courses & blog** — list courses and posts; manage course editors/metadata (with the
right permissions).
- **Community** — read/send direct messages, manage conversations and blocks, read and
mark notifications.
- **Interviews & Vive** — read mock-interview pricing/capacity/sessions; view Vive earn
methods and create a Vive checkout link.
- **Account** — who am I, profile, update country, search users, sign out.
- **Scoped access** — hand out keys that can read but not submit, author but not publish,
or call the platform but not run code on your host.
- **Undo your edits** — every change to a draft, contest, course or profile is versioned
automatically, with a diff and a one-call rollback.
- **Author for production** — create problem drafts in Repovive's editor and fill in
statement, tests, model solution, editorial and validator; generate and verify whole
rounds; judge solutions locally — see [Authoring](#authoring--local-judge).

## Submitting code
`repovive_submit_solution` submits to `POST /api/code/submit` and polls until the verdict
is final — a **real submission** recorded on your account. Verify locally first with
`repovive_judge_solution`; Repovive rate-limits submissions to roughly 10 per minute.
```text
repovive_submit_solution(contest_id="<24-hex>", problem_slug="remainder-count",
source=..., language="pypy")
# -> {"submissionId": "...", "status": "Accepted", "passed": 18, "total": 18}
```
Language ids for submission follow the Judge0 set (`python` 71, `pypy` 220, `cpp` 54,
`java` 62, …), which differs from the problem editor's own ids — the tool maps names for
you. `repovive_list_my_submissions` lists your submission history.

> **Notes.** The curated **problem sets** (Classics / FAANG / Quant / Math) are premium
> content served only through the website, so their problem lists are not available via the
> API — `repovive_list_problem_sets` returns their metadata and website URLs; for
> API-readable problems use contests (`repovive_list_contest_problems`). A problem
> **like/dislike vote** endpoint exists but keys on browser-URL identifiers that can't be
> resolved reliably from the public API, so it is intentionally not exposed.
---
## Quick start
```bash
pip install repovive-mcp # or, from a clone: pip install -e .
export REPOVIVE_EMAIL="you@example.com"
export REPOVIVE_PASSWORD="your-password"
python -m repovive_mcp # stdio transport (or: repovive-mcp)
```
Then point your MCP client at it (see [below](#configure-your-mcp-client)) and try
`repovive_whoami` or `repovive_list_contests`.
Serving it over HTTP instead? You also need an access token, because the port would
otherwise let anyone act as your Repovive account — see [Access control](#access-control).
```bash
export REPOVIVE_MCP_AUTH_TOKEN="$(make auth-token)"
make run-http # or: docker compose up --build
```
## Install
Requires Python ≥ 3.10.
```bash
pip install repovive-mcp
```
Or from a clone, for development:
```bash
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # fastmcp>=3, httpx, pytest, ruff
```
Prefer a container? Images are published multi-arch, signed, and carry an SBOM:
```bash
docker pull ghcr.io/dwin-gharibi/repovive-mcp:latest
```
Run it directly (stdio transport):
```bash
export REPOVIVE_EMAIL="you@example.com"
export REPOVIVE_PASSWORD="your-password"
python -m repovive_mcp # or: repovive-mcp
```
## Access control
Two different things are being authenticated, and it is worth keeping them apart:
| | What it is | Configured with |
|---|---|---|
| **Repovive account** | who the server acts as *on the platform* | `REPOVIVE_EMAIL` + `REPOVIVE_PASSWORD`, or `REPOVIVE_TOKEN` |
| **MCP access** | who may *call this server* | `REPOVIVE_MCP_AUTH_TOKEN` (or `..._TOKENS`, or JWT settings) |
Over **stdio** your MCP client spawns the process, so the process boundary is the trust
boundary and there is nothing to configure. Over **HTTP** the server refuses to start
without an access token — an open port there is an open door to your account: submitting
code, sending direct messages, deleting contests.
```bash
export REPOVIVE_MCP_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
```
Callers then send `Authorization: Bearer <token>`. You can store a `sha256:<hex>` digest
instead of the secret itself, hand out several keys with different privileges, or verify
JWTs from your own issuer.
**Scopes.** Every tool declares what it needs, and a caller without that scope doesn't get
an error — the tool is simply absent from `tools/list`, so a model never sees a capability
it can't use.
| Scope | Grants |
|---|---|
| `repovive:read` | Problems, contests, standings, leaderboard, posts, courses, inbox. |
| `repovive:write` | Mutating your account: DMs, blocks, notifications, profile, registrations, Vive checkout. |
| `repovive:submit` | Real submissions recorded against your account. |
| `repovive:author` | Creating and editing problem drafts. |
| `repovive:admin` | Contest and course administration; deletions. |
| `repovive:execute` | Running code on the server host (local judge, generators). |
| `repovive:history` | Reading the action log and revision history, and rolling a change back. |
```bash
# a read-only key for a dashboard, and a full key for your own agent
export REPOVIVE_MCP_AUTH_TOKENS='{
"sha256:<hex>": {"client_id": "dashboard", "scopes": ["repovive:read"]},
"sha256:<hex>": {"client_id": "agent"}
}'
```
Full details — digests, expiry, JWT settings, and the `REPOVIVE_MCP_ALLOW_ANONYMOUS`
escape hatch for a port already behind an authenticating proxy — in
[docs/SECURITY.md](docs/SECURITY.md).
## Configure your MCP client
Add a server entry. Example (Claude Desktop `claude_desktop_config.json` /
Claude Code `mcp` config):
```json
{
"mcpServers": {
"repovive": {
"command": "python",
"args": ["-m", "repovive_mcp"],
"env": {
"REPOVIVE_EMAIL": "you@example.com",
"REPOVIVE_PASSWORD": "your-password"
}
}
}
}
```
If you installed into a virtualenv, point `command` at that interpreter (e.g.
`/path/to/.venv/bin/python`) or use the `repovive-mcp` console script.
For a server you're running over HTTP, point the client at the endpoint and pass the
access token:
```json
{
"mcpServers": {
"repovive": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }
}
}
}
```
---
## Tool reference
All tools are prefixed `repovive_`. Read tools accept `response_format` (`markdown`
default, or `json`) where a summary view is useful. Each carries the access scope it needs
(see [Access control](#access-control)). The list below is grouped by area; the
always-current, auto-generated reference — with per-tool scopes and full descriptions — is
[docs/TOOLS.md](docs/TOOLS.md).

### Account & profile (7)
| Tool | Description |
|---|---|
| `repovive_whoami` | Current account (id, role, premium, Vive, streaks). |
| `repovive_get_my_profile` | Profile document (job role, org, socials, location). |
| `repovive_update_my_location` | Update profile country (idempotent). |
| `repovive_search_users` | Find users by name (for DMs). |
| `repovive_list_my_documents` | Your uploaded documents. |
| `repovive_build_version` | Deployed build/release info (no auth). |
| `repovive_logout` | Invalidate session (auto re-auth next call). |
### Problems (4)
| Tool | Description |
|---|---|
| `repovive_list_problem_sets` | Curated sets (Classics/FAANG/Quant/Math) + URLs. |
| `repovive_list_contest_problems` | All problems in a contest (summaries or full). |
| `repovive_get_problem` | One problem: statement, constraints, limits, samples. |
| `repovive_get_problem_workspace_url` | Browser URL to solve/submit a problem. |
### Contests & ratings (12)
| Tool | Description |
|---|---|
| `repovive_list_contests` | List contests, filter by upcoming/ongoing/past. |
| `repovive_get_contest` | One contest by number or id. |
| `repovive_get_contest_registrations` | Your registrations & permissions. |
| `repovive_register_for_contest` | Register (normal or virtual). |
| `repovive_get_contest_invite_link` | Shareable invite link. |
| `repovive_check_invite_eligibility` | Invite eligibility. |
| `repovive_get_contest_permissions` | List collaborators *(admin)*. |
| `repovive_set_contest_permission` | Grant a role *(admin)*. |
| `repovive_remove_contest_permission` | Revoke a role *(admin)*. |
| `repovive_update_contest` | Edit contest settings *(admin)*. |
| `repovive_delete_contest` | Delete a contest *(admin, destructive)*. |
| `repovive_get_leaderboard` | Global ratings leaderboard (paged/filtered). |
### Standings & results (4)
| Tool | Description |
|---|---|
| `repovive_get_contest_ranking` | Final standings for a contest. |
| `repovive_get_contest_results` | Your per-problem results in a contest. |
| `repovive_get_contest_announcements` | Contest announcements/clarifications. |
| `repovive_get_problem_submissions` | Submissions for one contest problem. |
### Submissions (3)
| Tool | Description |
|---|---|
| `repovive_submit_solution` | Submit a solution and await the verdict *(real submission)*. |
| `repovive_list_my_submissions` | Your submission history. |
| `repovive_get_submission` | Read a submission's status/verdict by id. |
### Content — courses & blog (8)
| Tool | Description |
|---|---|
| `repovive_list_posts` | Blog posts (paged). |
| `repovive_get_post_categories` | Blog categories. |
| `repovive_list_courses` | Courses with your enrollment. |
| `repovive_get_course_editors` | List course editors. |
| `repovive_add_course_editor` | Add an editor. |
| `repovive_remove_course_editor` | Remove an editor *(destructive)*. |
| `repovive_update_course_details` | Update title/description/tags. |
| `repovive_set_course_visibility` | Public/private *(admin)*. |
### Community — notifications & DMs (14)
| Tool | Description |
|---|---|
| `repovive_list_notifications` | In-app notifications. |
| `repovive_get_unread_notifications_count` | Unread count. |
| `repovive_mark_notifications_read` | Mark notifications read. |
| `repovive_list_conversations` | DM conversations. |
| `repovive_get_conversation_messages` | Messages in a conversation. |
| `repovive_send_direct_message` | Send a message. |
| `repovive_start_conversation` | Start a conversation. |
| `repovive_mark_conversation_read` | Mark a conversation read. |
| `repovive_delete_conversation` | Delete a conversation *(destructive)*. |
| `repovive_delete_direct_message` | Delete a message *(destructive)*. |
| `repovive_get_unread_dm_count` | Total unread DMs. |
| `repovive_list_blocked_users` | Blocked users. |
| `repovive_block_user` | Block a user. |
| `repovive_unblock_user` | Unblock a user *(destructive)*. |
### Interviews & Vive (5)
| Tool | Description |
|---|---|
| `repovive_get_interview_prices` | Mock-interview prices. |
| `repovive_check_interview_capacity` | Interview capacity. |
| `repovive_list_interview_sessions` | Your interview sessions. |
| `repovive_get_vive_earn_methods` | Ways to earn Vive. |
| `repovive_create_vive_checkout` | Create a Vive purchase link (no charge). |
### Authoring & judge — local (11)
| Tool | Description |
|---|---|
| `repovive_list_problem_templates` | Built-in problem generators. |
| `repovive_generate_problem` | Generate a complete, self-consistent problem. |
| `repovive_new_problem_template` | Empty problem skeleton + field reference. |
| `repovive_validate_problem` | Validate a problem against the schema. |
| `repovive_judge_solution` | Run a solution against tests (local judge). |
| `repovive_available_judge_languages` | Languages the host can run. |
| `repovive_build_contest` | Generate + validate + judge a whole contest. |
| `repovive_list_house_templates` | Generators that match Repovive's published style. |
| `repovive_generate_house_problem` | Generate a house-style problem. |
| `repovive_check_house_style` | Check a problem against house conventions. |
| `repovive_build_house_round` | Assemble & verify a full house-style round. |
### Problem editor — build sessions (25)
| Tool | Description |
|---|---|
| `repovive_build_list_sessions` / `repovive_build_create_session` | List / create problem drafts. |
| `repovive_build_update_problem_info` | Slug, difficulty, limits, interactive flag. |
| `repovive_build_update_statement` | Statement, I/O format, constraints. |
| `repovive_build_add_testcases` / `list_testcases` / `clear_testcases` / `delete_testcase` | Manage draft test cases. |
| `repovive_build_set_solutions` / `get_solutions` | Model & alternative solutions (language→judgeId). |
| `repovive_build_set_learn_pages` | Editorial / learn pages. |
| `repovive_build_set_validator` / `set_custom_checker` | Input validator, custom checker. |
| `repovive_build_set_generator` / `set_gen_data` / `delete_generator` / `update_sources` | Generators, gen-data, sources. |
| `repovive_build_prepare_judge_target` / `run_status` / `cancel_run` | Generate & verify tests. |
| `repovive_build_push_problem` | Push a whole generated problem into a draft. |
| `repovive_build_author_complete_problem` | Metadata+statement+tests+solution+editorial+validator in one call. |
| `repovive_build_delete_session` | Delete a problem draft *(destructive)*. |
| `repovive_build_list_admin_contests` / `repovive_build_add_to_contest` | Publish step (explicit). |
### History & revisions (9)
| Tool | Description |
|---|---|
| `repovive_list_history` | Browse the local log of state-changing calls. |
| `repovive_get_history_entry` | One entry in full, with its (redacted) arguments. |
| `repovive_history_status` | Where the database lives, what it holds, retention limits. |
| `repovive_list_revisions` | An entity's saved versions, newest first. |
| `repovive_get_revision` | One revision including its full snapshot. |
| `repovive_diff_revisions` | What changed between two revisions, field by field. |
| `repovive_restore_revision` | Roll back to a revision (or into a different entity). |
| `repovive_undo_last_change` | Step one change back. |
| `repovive_purge_history` | Delete history entries *(destructive)*. |
Drafts are not visible on the platform until reviewed; publishing is the separate
`repovive_build_add_to_contest` call. Details in [docs/AUTHORING.md](docs/AUTHORING.md).
Every edit above is versioned automatically — see [History & rollback](#history--rollback).
## Authoring & local judge
The server can **generate complete problems, build full contests, and evaluate them with a
local judge** — offline, with no writes to the live platform. Every generated problem's
expected outputs are computed by running its reference solution, so it is correct by
construction; `repovive_build_contest(..., verify=True)` judges every reference solution
and only reports success when all are `Accepted`.
```text
repovive_build_house_round(title="Repovive Starter Round 8")
-> {round, verification: {all_passed: true, ...}} # 7 problems, house-style, all AC
```
When you're ready to put a draft into Repovive's editor, the build-session tools write
everything and leave publishing to you:

Verified example artifacts live in [`examples/`](examples/) (12 problems, 4 contests). Full
details in [docs/AUTHORING.md](docs/AUTHORING.md). A ready-to-use agent skill is in
[`skills/repovive-contest-dev/`](skills/repovive-contest-dev/SKILL.md).
## History & rollback
Repovive has no version control for problem drafts, so the server keeps its own. Every
state-changing call is logged, and every change to a **problem draft, contest, course or
your profile** is snapshotted automatically — you don't opt in, and you don't call anything
to save a version.
```text
repovive_list_revisions(target_kind="build_session", target_id="<session id>")
# seq 4 auto Updated the draft statement <- the mistake
# seq 3 auto Added draft test cases
# seq 2 auto Updated the draft statement
# seq 1 baseline before the first tracked change
repovive_diff_revisions(from_revision_id=…, to_revision_id=…)
# statement.title: 'Array Sum' -> 'OOPS wrong title'
# statement.description: 'Sum the array.' -> 'Broken.'
repovive_undo_last_change(target_kind="build_session", target_id="<session id>")
# -> statement restored, test cases untouched, undo recorded as a new revision
```
- **Nothing is destroyed.** A restore re-applies an old snapshot through the normal API and
is recorded as a new revision, so you can undo the undo.
- **Deleting a draft doesn't delete its history.** Create a fresh build session and pass
`into_target_id` to rebuild it there.
- **`dry_run=True`** reports exactly which sections would be written before anything changes.
- **Honest about coverage.** Repovive exposes no read endpoint for a draft's statement or
generators, so those sections are reconstructed from what this server wrote; test cases and
solutions are read back and always authoritative. Each revision names the sections it
actually knows instead of pretending to more.
- **Irreversible things stay irreversible.** A sent direct message, a recorded submission and
a Vive checkout are logged, never claimed as undoable.
The log doubles as an audit trail — filter it by actor to see what a given access token did,
or by tool to see who ran code on the host:
```text
repovive_list_history(status="error", days=7)
repovive_list_history(tool="repovive_judge_solution")
```
Everything lives in one local SQLite file (mode `0600`), holds no secrets — argument keys
that look like credentials are redacted before writing — and is bounded by retention limits.
Reading needs `repovive:history`; restoring additionally needs the write scope of whatever is
being restored — so a `repovive:history` token alone is a genuine read-only audit key, and the
restore tools are not even listed for it. Full details in [docs/HISTORY.md](docs/HISTORY.md).
## Repovive house style
The generators and the skill follow Repovive's **measured** conventions — read from all 98
published problems and 23 contests, and exposed as the `repovive://house-style` resource:
- **Problems** are multi-test (every problem starts with `t`), use a braced-array input
format, a markdown-bullet constraints list, exactly one sample holding several sub-cases,
and one explanation paragraph per sub-case. Memory limit 256 MB; time limits 1–2 s.
- **Rounds** are 7 problems (A–G) on the `500…3500` points ladder with the difficulty curve
*easy, easy, medium, medium, medium, hard, hard*, 120 minutes, tags drawn from a fixed
12-word vocabulary.
`repovive_check_house_style` validates a problem against these rules, and
`repovive_build_house_round` assembles a whole conforming round and verifies every problem.
## Resources & prompts
**Resources** (read via URI) — 11, one templated:
`repovive://me`, `repovive://profile`, `repovive://contests`,
`repovive://contests/{contest_id}/problems` *(templated)*, `repovive://problem-sets`,
`repovive://leaderboard`, `repovive://posts`, `repovive://courses`,
`repovive://notifications`, `repovive://house-style`, `repovive://auth-scopes`.
**Prompts** (parameterised workflows) — 8:
`solve_problem`, `prepare_for_contest`, `study_plan`, `analyze_leaderboard`,
`inbox_triage`, `build_repovive_round`, `problemset_contest`, `author_and_verify_problem`.
## Example agent session
A typical "solve a real problem" loop chains a handful of tools:
```text
1. repovive_list_contests(status="ongoing") # find a contest id
2. repovive_list_contest_problems(contest_id=…) # pick a problem slug
3. repovive_get_problem(contest_id=…, problem_slug=…) # statement + samples
4. …write a solution…
5. repovive_judge_solution(problem=…, source=…) # local check → Accepted
6. repovive_submit_solution(contest_id=…, problem_slug=…, source=…, language="pypy")
# -> {"status": "Accepted", "passed": 18, "total": 18}
7. repovive_get_contest_ranking(contest_id=…) # see where you land
```

---
## The two authentications
**Inbound — who may call this server.** Nothing to configure over stdio; over HTTP a bearer
token is required and the server refuses to start without one. Tokens are held as SHA-256
digests and carry scopes that decide which tools a caller can even see. See
[Access control](#access-control) and [docs/SECURITY.md](docs/SECURITY.md).
**Outbound — who this server is on Repovive.**
- With `REPOVIVE_EMAIL` + `REPOVIVE_PASSWORD`, the server logs in on first use, keeping
both the JWT bearer token **and** the `auth_token` session cookie (some routes need the
cookie). It re-authenticates automatically on a 401 — and a concurrent caller reuses a
token another has already refreshed rather than logging in again — and caches the token
(`REPOVIVE_TOKEN_CACHE`, mode `0600`, written atomically) to avoid login rate limits.
- With `REPOVIVE_TOKEN` only, it uses the bearer token (cookie-gated routes may not work).
- A `429` from Repovive surfaces as a typed rate-limit error carrying `Retry-After` rather
than being retried indefinitely.
- The server sends a descriptive `User-Agent` and standard `Origin` header, exactly like
any first-party API client.

## Deployment
Runs over **stdio** (local) or **HTTP** (`REPOVIVE_MCP_TRANSPORT=http`, endpoint `/mcp`).
Docker, Docker Compose, Kubernetes (kustomize), Helm, OpenTofu/Terraform, Ansible, and
Vagrant paths are all provided under [`deploy/`](deploy/) and the root Docker/Vagrant files.
```bash
docker compose up --build # HTTP on :8000 (reads .env, incl. REPOVIVE_MCP_AUTH_TOKEN)
# or: helm install rv deploy/helm/repovive-mcp \
# --set credentials.email=... --set credentials.password=... --set access.token=...
# or: kubectl apply -k deploy/kubernetes (after creating the secret)
```
Every path carries an access token, and the Helm chart refuses to render without one.

Full guide: [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md). Handy targets in the `Makefile`
(`make help`) and a [`Taskfile.yml`](Taskfile.yml) for [go-task](https://taskfile.dev)
(`task --list`).
## Project layout
```
repovive-mcp/
├── repovive_mcp/ the server package
│ ├── app.py shared FastMCP instance, RepoviveClient, auth provider, lifespan
│ ├── auth.py access control for the server itself (tokens, JWT, scope guard)
│ ├── scopes.py the scope vocabulary
│ ├── client.py async httpx client (login, re-auth, rate limits, token cache)
│ ├── history.py local SQLite action log + revision store
│ ├── tracking.py which tools change what; the middleware that records it
│ ├── revisions.py per-entity snapshot capture and restore
│ ├── tools_*.py tool groups (account, contests, submit, build, …)
│ ├── resources.py MCP resources prompts.py MCP prompts
│ ├── authoring.py housestyle.py templates_house.py production.py local authoring
│ ├── localjudge.py Judge0-style subprocess judge
│ └── server.py registers everything; stdio or HTTP (refusing an open port)
├── scripts/gen_tools_doc.py regenerates docs/TOOLS.md from the live server
├── scripts/release.py one-source version management + changelog rolling
├── .github/workflows/ ci.yml (lint, tests, auth gate) and release.yml
├── docs/ architecture, tools, authoring, deployment, api map, security
├── deploy/ docker, kubernetes, helm, opentofu, ansible
├── examples/ verified problems & contests
├── skills/ repovive-contest-dev agent skill
└── tests/ smoke, offline authoring, and live e2e tests
```
## Documentation
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — components + diagrams
- [docs/TOOLS.md](docs/TOOLS.md) — full tool reference (auto-generated)
- [docs/AUTHORING.md](docs/AUTHORING.md) — problem/contest generation + local judge
- [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) — Docker/K8s/Helm/OpenTofu/Ansible/Vagrant
- [docs/API_MAP.md](docs/API_MAP.md) — the Repovive endpoints the tools use
- [docs/HISTORY.md](docs/HISTORY.md) — the action log, automatic revisions, and rollback
- [docs/RELEASING.md](docs/RELEASING.md) — how a version reaches PyPI, GHCR and the Releases tab
- [docs/SECURITY.md](docs/SECURITY.md) — access tokens, scopes, credentials, boundaries, judge sandboxing
- [skills/repovive-contest-dev/](skills/repovive-contest-dev/SKILL.md) — production contest-development skill
- [CONTRIBUTING.md](CONTRIBUTING.md) · [CHANGELOG.md](CHANGELOG.md)
## Development & tests
```bash
pip install -e ".[dev]"
# Live tests require real credentials and are skipped without them:
REPOVIVE_EMAIL=... REPOVIVE_PASSWORD=... pytest -q
make check # lint + offline tests + docs freshness (no credentials needed)
make test-offline # or: task test:offline
make docs # regenerate docs/TOOLS.md from the live server
```
`tests/test_smoke.py` boots the server in-memory (`fastmcp.Client(mcp)`), lists
tools/resources/prompts, and exercises representative read tools plus error handling.
`tests/test_auth.py` covers token parsing and verification, the scope guard, and the
fail-closed HTTP start; `tests/test_client_behaviour.py` drives the HTTP client through a
mock transport (re-login, rate limits, token-cache permissions); `tests/test_history.py`
runs the whole edit → snapshot → diff → undo loop.
`docs/TOOLS.md` is generated by `scripts/gen_tools_doc.py` (CI enforces freshness with
`--check`).
## Security notes
- **The HTTP transport will not serve without an access token.** Every caller acts as your
Repovive account, so that port is the boundary that matters.
- Credentials come only from environment variables — never hard-code them.
- Treat the JWT/cookie as secrets; they grant access to your account. The token cache lives
outside the repo (`REPOVIVE_TOKEN_CACHE`, default
`$XDG_CACHE_HOME/repovive-mcp/token.json`, mode `0600`).
- Write tools (submission, DMs, registration, deletes, course/contest admin) perform real
actions; their annotations (`destructiveHint`, etc.) let clients gate them, and scopes let
you withhold them entirely.
- The local judge runs the code you give it. `repovive:execute` is a separate scope for
exactly that reason.
- The history database holds your statements, tests and solution source. It is written
`0600`, never leaves the host, redacts credential-shaped arguments, and can be turned off
with `REPOVIVE_HISTORY=off`.
- Authoring writes **drafts**; publishing a draft to a live contest is a separate, explicit
call. See [docs/SECURITY.md](docs/SECURITY.md).
---
<div align="center">
<img src="docs/assets/social-card.svg" alt="Repovive MCP — 102 tools, 11 resources, 8 prompts, a local judge, built-in revisions and real submissions" width="100%" />
</div>
TDQS
Scored across 102 tools
Most tools are clearly separated by resource and action, and descriptions explicitly distinguish near-twins like get_my_profile vs whoami and push_problem vs author_complete_problem. However, with 102 tools there are several clusters (history vs revisions, contest ranking vs leaderboard, build status vs build actions) where an agent could still misselect without careful reading.
The overwhelming majority of tools follow a consistent repovive_verb_noun snake_case pattern, which makes the set predictable. Minor deviations like whoami, new_problem_template, available_judge_languages, and build_run_status keep it from being a perfect 5.
102 tools is far beyond the 50+ threshold for an extreme mismatch. Even if each tool is individually useful, the surface is too large for an agent to navigate efficiently and for a user to audit coherently.
The server covers many domains thoroughly: contest problems, draft building, submissions, DMs, notifications, and revision history. Notable gaps remain, however, including no contest creation, no contest unregistration, no mock-interview booking/cancellation, and no course creation or content management.