QuestMCP
QuestMCP
An MCP (Model Context Protocol) server that simulates a human-execution-layer marketplace: AI agents can post real-world tasks ("Quests"), get them semantically matched to real people ("Heroes"), and release payment once work is done — all gated by a delegation-based authorization system so an agent can never spend more, or do more, than a human explicitly allowed.
This project was built to mirror this workflow, almost line for line, as described in a job posting for an AI Engineer Intern, Agent Infrastructure role at a startup building exactly this kind of platform. The three things that posting called out as the core of the job are the three things this project is built around:
From the job description | Where it lives here |
"Build and ship MCP server tools" |
|
"Design delegation objects so agents can safely act on a user's behalf" |
|
"Prototype and test end-to-end agent workflows (e.g., an agent posting a quest, matching to a Hero, releasing payment)" |
|
"Comfortable with LLM APIs... exposure to NLP/embeddings" |
|
"Think carefully about safety and authorization design, not just feature velocity" | Every mutating tool routes through |
Why a delegation object, not just an API key
An agent acting for a user needs narrower trust than the user has over
their own account. A Delegation here is not a blanket credential — it is:
Scoped — lists exactly which actions it authorizes (
quest:post,quest:assign,payment:release,quest:cancel). An agent that can post quests can't necessarily release payments.Spend-capped — carries a hard ceiling in cents that the server enforces on every payment release, tracking cumulative spend server-side (never trusting a number the agent sends).
Signed — HMAC-SHA256 over the payload, so a tampered token (e.g. an agent editing its own spend cap client-side) is rejected outright.
Expiring and revocable — time-boxed by default, and a principal can kill it instantly if something looks wrong.
Auditable — every authorization check, allowed or denied, is logged with the actor, action, and reason.
This is the piece most "wrap an LLM in a loop" projects skip, and it's the piece the job explicitly said matters more than shipping features fast.
The workflow
principal (human)
│ issues a scoped, spend-capped delegation
▼
AI agent
│ post_quest() [checked: quest:post scope, budget ≤ cap]
▼
Quest (open)
│ find_heroes() [semantic match, read-only]
▼
assign_hero() [checked: quest:assign scope]
▼
Quest (assigned)
│ submit_deliverable() [Hero-side action]
▼
Quest (submitted)
│ release_payment() [checked: payment:release scope + spend cap +
▼ quest must be in 'submitted' state]
Quest (completed)Project layout
questmcp/
├── app/
│ ├── models.py Quest, Hero, AuditEntry data models
│ ├── delegation.py The authorization layer (Delegation, DelegationStore)
│ ├── matching.py Pluggable embedding-based hero matching
│ ├── store.py In-memory persistence, seeded with demo Heroes
│ ├── server.py MCP server — the actual tool definitions
│ └── demo.py Scripted end-to-end walkthrough + safety demos
├── tests/
│ └── test_flow.py 8 tests: happy path + 6 authorization failure modes
├── requirements.txt
└── README.mdRunning it
pip install -r requirements.txt
# Fastest way to see the whole thing work (no MCP client needed):
python -m app.demo
# Run the test suite (includes deliberate attack/misuse scenarios):
python -m pytest tests/ -v
# Run as an actual MCP server over stdio (connect from Claude Desktop,
# an MCP Inspector, or any MCP client):
python -m app.serverTo connect it to Claude Desktop, add to your MCP config:
{
"mcpServers": {
"questmcp": {
"command": "python",
"args": ["-m", "app.server"],
"cwd": "/path/to/questmcp"
}
}
}The 9 MCP tools
Tool | Purpose | Auth required |
| Issue a scoped, capped delegation to an agent | — |
| Kill a delegation immediately | principal match |
| Create a new task |
|
| Semantic-match a quest to available Heroes | read-only |
| Assign a matched Hero to a quest |
|
| Hero marks work as done | Hero identity match |
| Pay the Hero from escrow |
|
| Check a quest's state | read-only |
| Full trail of allowed/denied checks | read-only |
What's a stand-in vs. what's production-shaped
To keep this runnable with zero external accounts or model downloads:
Matching uses TF-IDF + cosine similarity (
scikit-learn) instead of a real embedding model.app/matching.pydefines anEmbeddingBackendinterface specifically so this is a one-class swap forsentence-transformers, VertexAI Embeddings, or an Anthropic/OpenAI embedding call — the commentedSentenceTransformerBackendclass shows the shape that would take.Storage is in-memory (
app/store.py). Swapping to Postgres/PGVector behind the same interface wouldn't touch any tool logic inserver.py.Signing uses a single server-side HMAC secret rather than per-principal keys in a KMS — the verification logic (signature check, expiry, scope, spend cap, revocation) is the real design; the key management around it is simplified for a demo.
Possible next steps
Real embedding backend + PGVector for hero search at scale
LLM-assisted moderation pass on quest descriptions before they go live (the job's secondary track — UGC moderation / trust-tier review)
Multi-hero bidding instead of top-1 auto-assign
Dispute/refund flow when a submitted deliverable is rejected