The Todokit MCP Server is a task management tool that provides comprehensive CRUD operations for todos with JSON persistence, batch operations, and advanced filtering capabilities.
Core Capabilities:
Create todos - Add single or multiple todo items (up to 50 per batch) with title, description, priority (low/normal/high), tags (up to 50), and due dates (ISO format)
List and filter - Retrieve todos with flexible filtering by status (pending/completed/all), priority, tags, date ranges (dueAfter/dueBefore), and text search across titles, descriptions, and tags
Sorting & pagination - Sort by title, priority, dueDate, or createdAt in ascending/descending order with offset/limit controls (up to 200 results per query, default 50)
Update todos - Modify existing todo fields including title, description, priority, tags, and due dates
Complete todos - Mark tasks as completed or change completion status
Delete todos - Remove individual todos or bulk delete with filters, dry-run preview mode, and safety limits (default 10 items, max 100)
Key Features:
JSON persistence - Configurable storage location via
TODOKIT_TODO_FILEenvironment variable or--todo-fileCLI flag with atomic file writes and automatic cleanup when all todos are completedData validation - Strict input validation using Zod schemas with consistent error response format
Diagnostics - Optional monitoring via
--diagnosticsflag and--log-levelsettings (error/warn/info/debug) with programmatic access through Node.js diagnostics channelsConfiguration options - Customizable JSON formatting (pretty-printed or compact) via
TODOKIT_JSON_PRETTYenvironment variableClient integration - Easy setup for VS Code, Claude Desktop, and Cursor with one-click installation options
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Todokit MCP Serveradd a todo to finish the quarterly report by Friday with high priority"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Todokit MCP Server
A local, persistent task management MCP server with JSON file storage, cursor pagination, and diagnostics.
Overview
Todokit is a Model Context Protocol (MCP) server that gives AI assistants the ability to manage a structured todo list. Tasks are persisted as a JSON file on disk with atomic writes and file-based locking, so data integrity is maintained even under concurrent access. The server communicates over stdio transport and exposes 7 tools, 2 resources, and 1 prompt for complete task lifecycle management.
Key Features
Full task lifecycle — create, list, search, update, complete, and delete todos
Batch operations — add up to 50 tasks in a single call
Cursor-based pagination — efficiently navigate large task lists (up to 100 items per page)
Fuzzy search — find tasks by description or category text
Atomic file writes — data integrity with temp-file-then-rename strategy and file-based locking
Resource subscriptions — live
todo://listresource with change notifications
Tech Stack
Component | Technology |
Runtime | Node.js ≥ 24 |
Language | TypeScript 5.9+ |
MCP SDK |
|
Schema | Zod ^4.3.6 ( |
Transport | stdio (JSON-RPC over stdin/stdout) |
Package Manager | npm |
Architecture
CLI Entrypoint (
src/index.ts) — Parses CLI args, wires theMcpServerto aStdioServerTransport, registers signal handlers for graceful shutdown.Tool Layer (
src/tools.ts) — Registers 7 tools with timeout/abort/diagnostics wrappers and cursor-based pagination.Storage Layer (
src/storage.ts) — Port/Adapter pattern (FileSystemPort,LockPort) for atomic JSON file reads/writes with in-memory caching and mtime-based invalidation.Schema Layer (
src/schema.ts) — Zod strict schemas for all tool inputs and outputs.Diagnostics (
src/diagnostics.ts) — Publishes events ontodokit:tool,todokit:storage, andtodokit:lifecyclechannels.Request Context (
src/requestContext.ts) —AsyncLocalStorage-based correlation of tool calls with storage events.
Repository Structure
├── src/
│ ├── index.ts # CLI entrypoint, server creation, transport wiring
│ ├── tools.ts # Tool registration and handler logic
│ ├── storage.ts # JSON file storage with locking and caching
│ ├── schema.ts # Zod input/output schemas
│ ├── responses.ts # createToolResponse / createErrorResponse helpers
│ ├── diagnostics.ts # node:diagnostics_channel publishers
│ ├── requestContext.ts # AsyncLocalStorage request context
│ ├── constants.ts # Error name/code constants
│ └── instructions.md # Server instructions resource
├── tests/ # node:test test files
├── scripts/
│ └── tasks.mjs # Build orchestration
├── assets/
│ └── logo.svg # Server icon
├── .github/
│ └── workflows/
│ └── publish.yml # CI/CD: npm publish on release
├── package.json
├── tsconfig.json
└── eslint.config.mjsRequirements
Node.js ≥ 24
npm (included with Node.js)
Quickstart
Run with npx — no installation needed:
npx -y @j0hanz/todokit-mcp@latestAdd to your MCP client configuration:
{
"mcpServers": {
"todokit": {
"command": "npx",
"args": ["-y", "@j0hanz/todokit-mcp@latest"]
}
}
}Installation
NPX (recommended)
npx -y @j0hanz/todokit-mcp@latestGlobal Install
npm install -g @j0hanz/todokit-mcp
todokit-mcpFrom Source
git clone https://github.com/j0hanz/todokit-mcp-server.git
cd todokit-mcp-server
npm ci
npm run build
node dist/index.jsConfiguration
CLI Arguments
Flag | Short | Type | Default | Description |
|
| string | — | Path to the todo JSON file |
|
| boolean |
| Enable diagnostics logging to stderr |
|
| string |
| Log level: |
Environment Variables
Variable | Default | Description |
|
| Path to the JSON storage file |
|
| Tool execution timeout in ms ( |
|
| File lock acquisition timeout in ms |
|
| Maximum allowed size of the todo file |
|
| Pretty-print the JSON storage file ( |
| — | Allow todo file outside the current working directory |
| — | Reject unsupported MCP protocol versions |
Usage
Todokit uses stdio transport. Start the server and communicate via JSON-RPC over stdin/stdout:
# With npx
npx -y @j0hanz/todokit-mcp@latest
# With custom todo file
npx -y @j0hanz/todokit-mcp@latest --todo-file ./my-tasks.json
# With diagnostics enabled
npx -y @j0hanz/todokit-mcp@latest --diagnostics --log-level debugMCP Surface
Tools
add_todo
Create a single task. For multiple items, prefer add_todos.
Parameter | Type | Required | Default | Description |
| string | Yes | — | Description of the todo (1–2000 chars) |
| string | Yes | — | Task priority: |
| string | Yes | — | Task category (1–50 chars, e.g. work, bug, testing, docs) |
| string | No | — | Due date/time as ISO 8601 with offset |
Returns: The created todo item with id, timestamps, and suggested next actions.
{
"ok": true,
"result": {
"item": {
"id": "a1b2c3",
"description": "Review PR #42",
"completed": false,
"priority": "high",
"category": "work",
"createdAt": "2026-02-10T12:00:00.000Z"
},
"summary": "Added todo",
"nextActions": ["list_todos", "update_todo", "complete_todo"]
}
}add_todos
Create multiple tasks in one batch call (1–50 items).
Parameter | Type | Required | Default | Description |
| array | Yes | — | Array of todo objects (same shape as |
Returns: Count of created items, their IDs, and suggested next actions.
{
"ok": true,
"result": {
"count": 3,
"ids": ["id1", "id2", "id3"],
"summary": "Added 3 todos",
"nextActions": ["list_todos", "update_todo"]
}
}list_todos
List todos with optional status filtering and cursor-based pagination.
Parameter | Type | Required | Default | Description |
| string | No |
| Filter: |
| number | No |
| Max items to return (1–100) |
| string | No | — | Opaque pagination cursor from a previous response |
Returns: Filtered todo items with counts, pagination info, and hints.
{
"ok": true,
"result": {
"items": [],
"summary": "Showing 5 pending todos (Found 10 todos (5 pending, 5 completed))",
"counts": { "total": 10, "pending": 5, "completed": 5 },
"filteredCounts": { "total": 5, "pending": 5, "completed": 0 },
"status": "pending",
"returned": 5,
"truncated": false,
"remaining": 0,
"hint": "Tip: when all todos are completed, the storage file is automatically deleted.",
"limit": 50,
"hasMore": false
}
}search_todos
Search todos by description or category text with status filtering and pagination.
Parameter | Type | Required | Default | Description |
| string | Yes | — | Search query (1–100 chars) |
| string | No |
| Filter: |
| number | No |
| Max items to return (1–100) |
| string | No | — | Opaque pagination cursor from a previous response |
Returns: Matching items with match count, pagination info, and suggested next actions.
{
"ok": true,
"result": {
"items": [],
"query": "review",
"status": "pending",
"summary": "Found 2 matches for \"review\" (pending)",
"returned": 2,
"totalMatches": 2,
"remaining": 0,
"limit": 50,
"hasMore": false,
"nextActions": ["update_todo", "complete_todo"]
}
}update_todo
Update one or more fields on an existing todo.
Parameter | Type | Required | Default | Description |
| string | Yes | — | ID of the todo to update (1–100 chars) |
| string | No | — | New description (1–2000 chars) |
| string | No | — | New priority: |
| string | No | — | New category (1–50 chars) |
| string | No | — | New due date/time as ISO 8601 with offset |
At least one field besides
idmust be provided.
Returns: The updated todo item and suggested next actions.
{
"ok": true,
"result": {
"item": {
"id": "a1b2c3",
"description": "Updated task",
"completed": false,
"priority": "medium",
"category": "work",
"createdAt": "...",
"updatedAt": "..."
},
"summary": "Updated todo",
"nextActions": ["list_todos", "complete_todo"]
}
}complete_todo
Mark a todo as completed. Idempotent — completing an already-completed todo returns success with an informational summary.
Parameter | Type | Required | Default | Description |
| string | Yes | — | ID of the todo (1–100 chars) |
Returns: The completed todo item with completedAt timestamp.
{
"ok": true,
"result": {
"item": {
"id": "a1b2c3",
"completed": true,
"completedAt": "2026-02-10T14:00:00.000Z"
},
"summary": "Completed todo",
"nextActions": ["list_todos"]
}
}delete_todo
Permanently delete a todo by ID. Destructive — cannot be undone.
Parameter | Type | Required | Default | Description |
| string | Yes | — | ID of the todo (1–100 chars) |
Returns: The deleted todo's ID and suggested next actions.
{
"ok": true,
"result": {
"deletedIds": ["a1b2c3"],
"summary": "Deleted todo",
"nextActions": ["list_todos"]
}
}Resources
URI | MIME Type | Description |
|
| Server usage instructions |
|
| Live list of active (pending) todos. Supports subscriptions for change notifications. |
Prompts
Name | Description |
| Returns concise usage instructions and best-practice workflows for Todokit tools. |
Client Configuration Examples
Add to your VS Code settings (settings.json) or use the one-click install buttons above:
{
"mcp": {
"servers": {
"todokit": {
"command": "npx",
"args": ["-y", "@j0hanz/todokit-mcp@latest"]
}
}
}
}Add to your Claude Desktop config file (claude_desktop_config.json):
{
"mcpServers": {
"todokit": {
"command": "npx",
"args": ["-y", "@j0hanz/todokit-mcp@latest"]
}
}
}Add to your Cursor MCP config (.cursor/mcp.json), or use the one-click install button above:
{
"mcpServers": {
"todokit": {
"command": "npx",
"args": ["-y", "@j0hanz/todokit-mcp@latest"]
}
}
}Add to your Windsurf MCP config (~/.windsurf/mcp.json):
{
"mcpServers": {
"todokit": {
"command": "npx",
"args": ["-y", "@j0hanz/todokit-mcp@latest"]
}
}
}Security
stdout safety — The server never writes non-MCP output to stdout. All logging goes to stderr via
console.error(), preserving JSON-RPC transport integrity.Path traversal protection — The todo file must reside within the current working directory by default. Set
TODOKIT_ALLOW_OUTSIDE_CWDto override. Symlink resolution is performed to prevent escaping via symlinks.File locking — Concurrent access is protected by file-based locks with exponential backoff and
timingSafeEqualownership verification.Atomic writes — Data is written to a temporary file first, then atomically renamed to prevent corruption on partial writes.
Size limits — The todo file is capped at 5 MB by default (
TODOKIT_MAX_TODO_FILE_BYTES) to prevent unbounded growth.
Development Workflow
Install Dependencies
npm ciScripts
Script | Command | Purpose |
|
| Watch mode compilation |
|
| Run server with auto-reload |
| Clean + compile + validate + copy assets | Production build |
|
| Run compiled server |
|
| Format code |
|
| Lint code |
|
| Auto-fix lint issues |
|
| Type-check without emitting |
| Build + | Run tests |
| Build + test with | Run tests with coverage |
|
| Check for code duplication |
|
| Detect dead/unused code |
|
| Launch MCP Inspector |
Full Validation
npm run format && npm run lint && npm run type-check && npm run build && npm testBuild and Release
The project uses GitHub Actions for CI/CD. On a GitHub Release event:
Checks out the repository
Sets up Node.js 24 with the npm registry
Installs dependencies (
npm ci)Runs lint, type-check, tests, coverage, and duplication checks
Builds the package
Publishes to npm using Trusted Publishing (OIDC — no
NODE_AUTH_TOKENneeded)
Published package: @j0hanz/todokit-mcp
Troubleshooting
Inspect the Server
Use the MCP Inspector to interactively test tools:
npx @modelcontextprotocol/inspector node dist/index.jsOr if installed from npm:
npx @modelcontextprotocol/inspector npx -y @j0hanz/todokit-mcp@latestCommon Issues
Issue | Solution |
Server not responding | Ensure nothing else is reading/writing to stdout in the process |
| Call |
| Retry the operation — another process may be holding the file lock |
| Delete completed items or increase |
| Ensure at least one field is provided when calling |
| Check enum values ( |
File outside CWD error | Set |
Storage file auto-deleted | This is expected — the file is removed when all todos are completed |
Diagnostics
Enable detailed logging to stderr:
npx -y @j0hanz/todokit-mcp@latest --diagnostics --log-level debugThis publishes events on node:diagnostics_channel channels: todokit:tool, todokit:storage, todokit:lifecycle.
Contributing
Contributions are welcome! Please ensure all changes pass the full validation sequence:
npm run format && npm run lint && npm run type-check && npm run build && npm test