todo-mcp-demo
A demo MCP server exposing an in-memory todo list via tools (add_task, list_tasks, complete_task), a resource, and a prompt, over both stdio and HTTP transports.
README
Todo MCP Demo
A demo project showing how an AI Agent (MCP Host) uses the Model Context Protocol (MCP) to communicate with Tools, Resources, and Prompts exposed by an MCP Server, over both stdio and HTTP transports.
Live public MCP endpoint: https://todo-mcp-demo.onrender.com/mcp
(Streamable HTTP — no API key required; connect with MCP Inspector by
choosing the "Streamable HTTP" transport. First request after idle may take
~30-60s to wake up the free Render instance.)
Full specification: docs/00_GLOBAL_RULES.md,
docs/01_REQUIREMENTS.md,
docs/02_ARCHITECTURE.md,
docs/03_IMPLEMENTATION_PLAN.md.
Overview
User → Agent (MCP Host) → MCP Tool → Todo Store → Result → Agent → User
- Todo Store (
src/server/todoStore.ts) — in-memory business logic:addTask,listTasks,completeTask. No database, no transport dependency. - MCP Server (
src/server/server.ts) — exposes the Todo Store as:- 3 Tools:
add_task,list_tasks,complete_task - 1 Resource:
todo://list - 1 Prompt:
plan_my_day
- 3 Tools:
- Transports (
src/transports/) —stdio.tsandhttp.tsboth boot the same MCP Server Core; no business logic is duplicated between them. - Agent / MCP Host (
src/agent/) — connects to an MCP Server (stdio or HTTP), discovers Tools dynamically, and dispatches Tool calls. - Skill (
src/skills/plan-my-day/SKILL.md) — a reusable workflow: read the todo list via thelist_tasksTool, filter unfinished tasks, and generate a prioritized plan for the day.
Architecture
User
│
▼
┌──────────────┐
│ Agent │
│ (MCP Host) │
└──────┬───────┘
│
MCP Client Layer
│
┌──────────────────┴──────────────────┐
│ │
▼ ▼
stdio Transport HTTP Transport
│ │
└──────────────────┬──────────────────┘
▼
MCP Server Core
│
┌──────────────┬──────────────┬──────────────┐
▼ ▼ ▼
Tools Resources Prompts
│
▼
Todo Store
Prerequisites
- Node.js >= 22.9
- npm
Installation
npm install
npm run build
Configuration (optional)
No environment variable is required — every value has a working default. To override one locally, copy the example file:
cp .env.example .env
| Variable | Used by | Default |
|---|---|---|
PORT |
npm run server:http / npm start |
3000 |
MCP_TRANSPORT |
npm run agent |
stdio |
MCP_HTTP_URL |
npm run agent (when MCP_TRANSPORT=http) |
http://localhost:3000/mcp |
All npm scripts load .env automatically via Node's built-in
--env-file-if-exists flag (no dotenv dependency needed). .env is
git-ignored; only .env.example is committed. On hosting platforms
(Render/Railway) PORT is injected by the platform itself, so .env is
not used in production.
Available npm Scripts
| Script | Description |
|---|---|
npm run build |
Compile TypeScript to dist/ |
npm run clean |
Remove dist/ |
npm run server:stdio |
Build, then start the MCP Server over stdio |
npm run server:http |
Build, then start the MCP Server over HTTP (port 3000) |
npm run agent |
Build, then run the Agent CLI with a natural-language command |
npm start |
Start the HTTP MCP Server from an already-built dist/ (used by hosting platforms) |
Run the stdio Server
npm run server:stdio
This starts the MCP Server on stdio. Connect with the MCP Inspector:
npx @modelcontextprotocol/inspector node dist/transports/stdio.js
Run the HTTP Server
npm run server:http
Starts an HTTP MCP endpoint at http://localhost:3000/mcp (override the
port with the PORT environment variable). Connect with MCP Inspector by
choosing the "Streamable HTTP" transport and pointing it at that URL.
Run the Agent
The Agent connects to a running MCP Server, discovers its Tools, and dispatches a single natural-language command.
Against the stdio server (default — the Agent spawns the server itself, no need to start it separately):
npm run agent -- "add task Buy milk"
npm run agent -- "list tasks"
npm run agent -- "complete task <task-id>"
Against a running HTTP server (start it first with
npm run server:http in another terminal):
MCP_TRANSPORT=http npm run agent -- "add task Buy milk"
MCP_TRANSPORT=http MCP_HTTP_URL=http://localhost:3000/mcp npm run agent -- "list tasks"
Run the Skill: plan-my-day
See src/skills/plan-my-day/SKILL.md for
the full workflow definition. The Agent recognizes the trigger phrase and
runs the workflow using the existing list_tasks Tool (no direct access to
the Todo Store):
npm run agent -- "plan my day"
# or, against the HTTP server:
MCP_TRANSPORT=http npm run agent -- "plan my day"
Example output:
Today's plan:
1. Buy milk
2. Write report
Demo Walkthrough
npm run agent -- "add task Buy milk"
npm run agent -- "add task Write report"
npm run agent -- "plan my day"
Note: each
npm run agentcall against the stdio transport spawns a fresh server process, so tasks only persist for the lifetime of a single command. To see tasks persist across multiple Agent calls, start the HTTP server once (npm run server:http) and passMCP_TRANSPORT=httpto every Agent call, as shown above.
Deployment
The HTTP MCP Server (src/transports/http.ts) is deployment-ready:
- It reads the port from the
PORTenvironment variable. npm startruns the compiled server directly (node dist/transports/http.js).
Deployed on Render (Free instance type):
- Repository: https://github.com/thienbanho/todo-mcp-demo
- Build command:
npm install && npm run build - Start command:
npm start - No environment variables required — Render sets
PORTautomatically. - Live endpoint:
https://todo-mcp-demo.onrender.com/mcp
To deploy on Railway instead, the steps are equivalent: connect the
repository, set the same build/start commands, and Railway will assign a
public URL and PORT automatically.
Verified with a raw MCP initialize + tools/list handshake against the
live endpoint (see mcp-session-id flow in src/transports/http.ts); you
can also verify interactively with MCP Inspector, using the public /mcp
URL as a Streamable HTTP endpoint.
Out of Scope
Per the project spec: no database, authentication, authorization, user management, frontend, Docker, CI/CD, or multi-user support. All Todo data is in-memory and is lost on server restart — this is intentional for a demo project.
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.
Neon Database
MCP server for interacting with Neon Management API and databases
E2B
Using MCP to run code via e2b.
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.