Coderift MCP Server
MCP server for managing customer feature requests with role-based approvals, elicitation for high-impact changes, and support for notifications, sampling, and progress tracking. Enables employees to review, prioritize, and approve requests without direct database access.
README
Coderift MCP Project
Overview
Coderift Technologies is a B2B software company. Customers submit feature requests continuously, and internal employees need to review, prioritize, and approve them without touching the production database directly. This project is an MCP server sitting in front of that database, plus a client that talks to it through the protocol instead of raw SQL.
The Problem
Before this system, support agents queried the database directly (or asked an engineer to) whenever a customer asked about a request's status, and a product manager approved requests from a spreadsheet with no audit trail and no check on how many customers a change actually affected. Two things made this risky enough to justify a real protocol-aware server instead of a thin CRUD wrapper:
- Approvals are not all equal. Approving a request that affects 800 customers is a different decision than approving one that affects 40. The naive version either lets any agent approve anything, or hard-codes a blanket rule that ignores context. We wanted a manager to have to explicitly sign off on high-impact approvals, live, not just trust a role field the caller sends us.
- Roles change mid-session. A support agent gets promoted to product manager during their shift (or a manager is filling in). The tool set available to them should change the moment that happens, not after they reconnect.
Those two facts are what justify elicitation and notifications in this system, not a rule bolted on for the assignment. Report generation over the full pending-request backlog is also genuinely slow-ish and benefits from progress feedback instead of a blocking call.
Database & ERD
Engine: SQLite (db/coderift.db, built from db/schema.sql +
db/seed.sql via db/create_db.py).

Tables: customers, employees, feature_requests (FK to customers),
approvals (FK to feature_requests and employees, for a future audit
trail). Seed data covers both roles, all three statuses (Pending,
Approved, Rejected), and both sides of the 500-customer elicitation
threshold (a 40-customer request, a 500-customer boundary case, and an
800-customer request).
Project Structure
coderift-mcp/
├── db/
│ ├── schema.sql
│ ├── seed.sql
│ ├── create_db.py
│ ├── ERD.png
│ └── coderift.db (generated)
├── mcp_server/
│ ├── server.py
│ └── models.py
├── agent/
│ └── client.py
├── requirements.txt
└── README.md
Installation
python -m venv .venv
source .venv/bin/activate # .venv\Scripts\activate on Windows
pip install -r requirements.txt
python db/create_db.py
Running
# server, local development
cd mcp_server
python server.py # stdio (default)
python server.py --transport streamable-http --port 8000 # remote
# agent, in a second terminal
cd agent
python client.py # stdio, spawns server.py itself
python client.py --http http://127.0.0.1:8000/mcp # against a running HTTP server
Set ANTHROPIC_API_KEY before running the agent to have the sampling
callback use a real model; otherwise it uses a labeled stub response so
the demo still runs end to end.
Where each protocol concern lives
| Concern | File / function |
|---|---|
| Capability negotiation | server.py: CoderiftMCP._init_options declares tools.listChanged=True. client.py: run_demo reads init.capabilities.tools.listChanged before assuming notifications will arrive. |
| Notifications | server.py: promote_to_manager calls ctx.session.send_tool_list_changed() after verifying the employee against the employees table. client.py: make_notification_handler reacts to ToolListChangedNotification. |
| Elicitation | server.py: approve_feature_request calls ctx.elicit(...) when affected_customers > 500, gated behind has_capability(ctx, elicitation=True). client.py: elicitation_callback prompts a human and returns accept/decline. |
| Sampling | server.py: generate_feature_analysis calls ctx.session.create_message(...) for the written risk recommendation, gated behind has_capability(ctx, sampling=True). client.py: sampling_callback answers using the client's own model. |
| Resources | server.py: policy://feature-prioritization, policy://approval-guidelines, policy://release-guidelines, fetched via resources/read, never wrapped in a tool. |
| Prompts | server.py: draft_feature_summary, draft_rejection_email, customer_feature_update. |
| Transport | server.py __main__ accepts `--transport stdio |
| Progress tracking | server.py: generate_impact_report calls ctx.report_progress(...) at five real milestones while it scans pending requests. client.py passes a progress_callback to call_tool. |
| Defensive tool design | models.py: every write tool takes a single Pydantic model with extra="forbid", Field(gt=0), and Literal enums. server.py: change_priority and approve_feature_request re-validate server-side and check get_role(ctx) — a role read from server-held session state, never a client-supplied parameter. |
Comparison note
| Tool | Read/Write | Requires elicitation | Notes |
|---|---|---|---|
get_feature_request |
Read | No | |
list_customer_requests |
Read | No | |
search_knowledge_base |
Read | No | BM25 over titles/descriptions |
approve_feature_request |
Write | Conditional — only when affected_customers > 500 |
Falls back to an explanatory error if the client lacks elicitation support, instead of silently approving or hanging |
change_priority |
Write | No | Role-gated only |
generate_impact_report |
Read (long-running) | No | Progress-tracked |
generate_feature_analysis |
Read | No | Uses sampling if available; deterministic rule-based fallback otherwise |
promote_to_manager |
Write (session state) | No | Verified against employees table server-side |
If a client connects without elicitation support, approve_feature_request
refuses to silently approve a high-impact request — it returns a structured
elicitation_unsupported error explaining that a manager needs to approve
it out of band. If a client connects without sampling support,
generate_feature_analysis still returns a usable (if less nuanced)
rule-based risk rating instead of failing.
Transport choice, justified
Development happens over stdio — no server process to manage, easy to
run from the agent script directly, matches how one developer iterates
locally. server.py also runs over Streamable HTTP (--transport streamable-http), which is the right choice once Coderift's own product
managers across multiple offices need to hit the same server concurrently
instead of each spawning their own local process — a single deployed HTTP
endpoint sits behind normal auth/network controls, which stdio can't do.
Both paths share the same tool/resource/prompt code; only the transport
layer changes.
Demonstration Workflow
agent/client.py runs, in order: initialize + capability check, list
tools as a support_agent, an unauthorized change_priority attempt,
promote_to_manager (real employee lookup + real notification), tool list
re-fetch showing the unlocked write tools, generate_impact_report with
live progress, approve_feature_request on an 800-customer request
(elicitation fires) and a 40-customer request (it doesn't), sampling-backed
generate_feature_analysis, change_priority, a resource read, and a
prompt fetch.
Where it stands now
Session role state lives in a process-local dict keyed by session id,
which is fine for the stdio demo and a single-process HTTP deployment but
wouldn't survive a restart or a multi-instance deployment — a production
version would move that to a signed session token or a real auth layer
instead. The approvals table exists in the schema for an audit trail but
isn't written to yet; that'd be the next addition, along with a director
review tier for requests over 1000 affected customers as described in the
approval-guidelines resource.
Technologies Used
Python, MCP Python SDK (mcp), SQLite, Pydantic, rank_bm25.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.