toyMCP
The toyMCP To-Do List Server is a simple API server implementing a To-Do list with CRUD operations using the Model Context Protocol (MCP) and JSON-RPC over HTTP. It features a natural language interface using AI models and is built on Node.js and PostgreSQL, running in Docker containers.
toyMCP To-Do List Server
This is a simple example server implementing a To-Do list CRUD API using the Model Context Protocol (MCP) concepts, specifically using JSON-RPC 2.0 over HTTP.
It uses Node.js, Express, and PostgreSQL (via Docker) for persistence.
Components
This project consists of two main components:
- MCP Server: A JSON-RPC based API server for managing todo items
- Agent Framework: A natural language interface to the MCP server using AI models
Setup
-
Prerequisites:
- Node.js (LTS version recommended)
- npm (usually comes with Node.js)
- Docker and Docker Compose
-
Clone the repository (if applicable):
# git clone ... # cd toyMCP
-
Install Dependencies:
npm install
-
Start PostgreSQL Database: Make sure Docker Desktop (or the Docker daemon) is running.
docker compose up -d db
This will start a PostgreSQL container named
toymcp_db
in the background and create a persistent volume for its data. -
Run the Server:
npm start
The server will initialize the database schema if necessary and start listening on
http://localhost:3000
(or the port specified by thePORT
environment variable). The JSON-RPC endpoint ishttp://localhost:3000/rpc
. The Swagger API documentation UI is available athttp://localhost:3000/api-docs
.
Clean Server Start
If you need to ensure the server starts with a completely fresh database (e.g., before running manual end-to-end tests or to reset state), you can use the clean_start.sh
script:
- Stop the running server (if any) by pressing
Ctrl+C
in the terminal where it's running. - Ensure the script is executable:
chmod +x clean_start.sh
- Run the script:
This script will stop and remove the database container (./clean_start.sh
docker compose down
), restart it (docker compose up -d db
), and then start the Node.js server (npm start
).
Running Tests
Ensure the PostgreSQL container is running (docker compose up -d db
).
Tests are separated into tests/unit_tests
and tests/integration_tests
. The following command runs all tests:
npm test
Running Coverage Report
npm run coverage
This will output a summary to the terminal and generate a detailed HTML report in the coverage/lcov-report/
directory, reflecting coverage from both unit and integration tests.
Running End-to-End Test Script
The project includes an orchestrator script (run_full_test.sh
) that performs a full sequence of tests using curl
against a live server, including cleaning the database beforehand and providing a summary report. This is the recommended way to perform a manual end-to-end check.
Prerequisites: curl
, jq
chmod +x run_full_test.sh test_server.sh # Ensure scripts are executable
./run_full_test.sh
API Documentation
Interactive API documentation is available via Swagger UI both locally (when the server is running) and deployed via GitHub Pages:
- Local Swagger UI:
http://localhost:3000/api-docs
- GitHub Pages Swagger UI:
https://izaqyos.github.io/toyMCP/swagger-ui/
The documentation is generated automatically from JSDoc comments in src/swagger_definitions.js
using swagger-jsdoc
.
API Usage
Authentication
Most API endpoints require authentication using a JSON Web Token (JWT).
- Login: First, send a POST request to
/auth/login
with your username and password in the JSON body:
Success Response:curl -X POST -H "Content-Type: application/json" \ -d '{"username": "testuser", "password": "password123"}' \ http://localhost:3000/auth/login
{ "message": "Login successful", "user": { "id": 1, "username": "testuser" }, "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
- Use Token: Copy the received
token
value. For subsequent requests to protected endpoints (like/rpc
), include it in theAuthorization
header as a Bearer token:TOKEN="YOUR_JWT_TOKEN_HERE" # Replace with the actual token curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "mcp.discover", "id": 1}' \ http://localhost:3000/rpc
JSON-RPC Endpoint (/rpc
)
Send POST requests to http://localhost:3000/rpc
with Content-Type: application/json
, an Authorization: Bearer <token>
header, and a JSON-RPC 2.0 payload in the body.
Available Methods:
todo.list
: Lists all todo items.todo.add
: Adds a new todo item (params: { "text": "..." }
).todo.remove
: Removes a todo item (params: { "id": ... }
).mcp.discover
: Describes the service and its available methods.
Example Tool: curl
(assuming you have a valid $TOKEN obtained via /auth/login
)
-
Discover Service (
mcp.discover
)curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "mcp.discover", "id": 1}' \ http://localhost:3000/rpc
Success Response (example):
{ "jsonrpc": "2.0", "result": { "mcp_version": "1.0.0", "name": "ToyMCP Todo Service", "description": "A simple To-Do list manager implementing MCP concepts.", "methods": [ {"name": "todo.list", ...}, {"name": "todo.add", ...}, {"name": "todo.remove", ...}, {"name": "mcp.discover", ...} ] }, "id": 1 }
-
Add Item (
todo.add
)curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "todo.add", "params": {"text": "Buy groceries"}, "id": 1}' \ http://localhost:3000/rpc
Success Response:
{ "jsonrpc": "2.0", "result": { "id": 1, "text": "Buy groceries", "created_at": "2025-04-07T16:15:00.123Z" }, "id": 1 }
-
List Items (
todo.list
)curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "todo.list", "id": 2}' \ http://localhost:3000/rpc
Success Response (example):
{ "jsonrpc": "2.0", "result": [ { "id": 1, "text": "Buy groceries", "created_at": "2025-04-07T16:15:00.123Z" } // ... other items ], "id": 2 }
-
Remove Item (
todo.remove
) (Assuming an item with ID 1 exists)curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "todo.remove", "params": {"id": 1}, "id": 3}' \ http://localhost:3000/rpc
Success Response:
{ "jsonrpc": "2.0", "result": { "id": 1, "text": "Buy groceries", "created_at": "2025-04-07T16:15:00.123Z" }, "id": 3 }
-
Error Response Example (Item Not Found)
curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{"jsonrpc": "2.0", "method": "todo.remove", "params": {"id": 999}, "id": 4}' \ http://localhost:3000/rpc
Response:
{ "jsonrpc": "2.0", "error": { "code": 1001, "message": "Todo item with ID 999 not found" }, "id": 4 }
Agent Framework
The repository includes an AI-powered agent framework that provides a natural language interface to the MCP server. The agent uses either local Ollama models or OpenAI's cloud-based models to interpret user instructions and perform the appropriate actions on the todo list.
Architecture
┌───────────────┐ ┌────────────────┐ ┌───────────────┐
│ LLM Provider │◄───┤ Agent Framework├───►│ toyMCP API │
│ (Ollama/Cloud)│ │ │ │ (Todo Server)│
└───────────────┘ └────────────────┘ └───────────────┘
Setup and Usage
The agent framework is located in the agent-framework/
directory. To use it:
-
Set up the environment:
cd agent-framework npm install cp .env-example .env # Configure settings as needed npm run build
-
Use natural language to manage your todo list:
# Add a task node index.js "Add milk to my shopping list" # List all tasks node index.js "What's on my todo list?" # Remove a task node index.js "Remove the shopping task" # Debug mode node index.js --debug "Add a reminder to call mom"
For detailed documentation on the agent framework, refer to:
agent-framework/README.md
: Setup and usage instructionsagent-framework/ARCHITECTURE.md
: Technical design and interaction flowagent-framework/CHANGELOG.md
: Development history and changes