Skip to main content
Glama

Todokit MCP Server

npm version License: MIT Node.js TypeScript MCP SDK

Install in VS Code Install in VS Code Insiders Install in Claude Desktop Install in Cursor

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://list resource with change notifications

Tech Stack

Component

Technology

Runtime

Node.js ≥ 24

Language

TypeScript 5.9+

MCP SDK

@modelcontextprotocol/sdk ^1.26.0

Schema

Zod ^4.3.6 (z.strictObject())

Transport

stdio (JSON-RPC over stdin/stdout)

Package Manager

npm

Architecture

  1. CLI Entrypoint (src/index.ts) — Parses CLI args, wires the McpServer to a StdioServerTransport, registers signal handlers for graceful shutdown.

  2. Tool Layer (src/tools.ts) — Registers 7 tools with timeout/abort/diagnostics wrappers and cursor-based pagination.

  3. Storage Layer (src/storage.ts) — Port/Adapter pattern (FileSystemPort, LockPort) for atomic JSON file reads/writes with in-memory caching and mtime-based invalidation.

  4. Schema Layer (src/schema.ts) — Zod strict schemas for all tool inputs and outputs.

  5. Diagnostics (src/diagnostics.ts) — Publishes events on todokit:tool, todokit:storage, and todokit:lifecycle channels.

  6. 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.mjs

Requirements

  • Node.js ≥ 24

  • npm (included with Node.js)

Quickstart

Run with npx — no installation needed:

npx -y @j0hanz/todokit-mcp@latest

Add to your MCP client configuration:

{ "mcpServers": { "todokit": { "command": "npx", "args": ["-y", "@j0hanz/todokit-mcp@latest"] } } }

Installation

npx -y @j0hanz/todokit-mcp@latest

Global Install

npm install -g @j0hanz/todokit-mcp todokit-mcp

From Source

git clone https://github.com/j0hanz/todokit-mcp-server.git cd todokit-mcp-server npm ci npm run build node dist/index.js

Configuration

CLI Arguments

Flag

Short

Type

Default

Description

--todo-file

-f

string

Path to the todo JSON file

--diagnostics

-d

boolean

false

Enable diagnostics logging to stderr

--log-level

-l

string

info

Log level: error, warn, info, or debug

Environment Variables

Variable

Default

Description

TODOKIT_TODO_FILE

./todos.json

Path to the JSON storage file

TODOKIT_TOOL_TIMEOUT_MS

60000

Tool execution timeout in ms (0 to disable)

TODOKIT_LOCK_TIMEOUT_MS

5000

File lock acquisition timeout in ms

TODOKIT_MAX_TODO_FILE_BYTES

5242880 (5 MB)

Maximum allowed size of the todo file

TODOKIT_JSON_PRETTY

false

Pretty-print the JSON storage file (true/1/yes)

TODOKIT_ALLOW_OUTSIDE_CWD

Allow todo file outside the current working directory

TODOKIT_STRICT_PROTOCOL_VERSION

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 debug

MCP Surface

Tools

add_todo

Create a single task. For multiple items, prefer add_todos.

Parameter

Type

Required

Default

Description

description

string

Yes

Description of the todo (1–2000 chars)

priority

string

Yes

Task priority: low, medium, or high

category

string

Yes

Task category (1–50 chars, e.g. work, bug, testing, docs)

dueAt

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

items

array

Yes

Array of todo objects (same shape as add_todo parameters)

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

status

string

No

pending

Filter: pending, completed, or all

limit

number

No

50

Max items to return (1–100)

cursor

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

query

string

Yes

Search query (1–100 chars)

status

string

No

pending

Filter: pending, completed, or all

limit

number

No

50

Max items to return (1–100)

cursor

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

id

string

Yes

ID of the todo to update (1–100 chars)

description

string

No

New description (1–2000 chars)

priority

string

No

New priority: low, medium, or high

category

string

No

New category (1–50 chars)

dueAt

string

No

New due date/time as ISO 8601 with offset

At least one field besides id must 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

id

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

id

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

internal://instructions

text/markdown

Server usage instructions

todo://list

application/json

Live list of active (pending) todos. Supports subscriptions for change notifications.

Prompts

Name

Description

get-help

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_CWD to override. Symlink resolution is performed to prevent escaping via symlinks.

  • File locking — Concurrent access is protected by file-based locks with exponential backoff and timingSafeEqual ownership 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 ci

Scripts

Script

Command

Purpose

npm run dev

tsc --watch --preserveWatchOutput

Watch mode compilation

npm run dev:run

node --env-file=.env --watch dist/index.js

Run server with auto-reload

npm run build

Clean + compile + validate + copy assets

Production build

npm start

node dist/index.js

Run compiled server

npm run format

prettier --write .

Format code

npm run lint

eslint .

Lint code

npm run lint:fix

eslint . --fix

Auto-fix lint issues

npm run type-check

tsc --noEmit

Type-check without emitting

npm test

Build + node --test with tsx

Run tests

npm run test:coverage

Build + test with --experimental-test-coverage

Run tests with coverage

npm run dup-check

jscpd --config .jscpd.json

Check for code duplication

npm run knip

knip

Detect dead/unused code

npm run inspector

npx @modelcontextprotocol/inspector

Launch MCP Inspector

Full Validation

npm run format && npm run lint && npm run type-check && npm run build && npm test

Build and Release

The project uses GitHub Actions for CI/CD. On a GitHub Release event:

  1. Checks out the repository

  2. Sets up Node.js 24 with the npm registry

  3. Installs dependencies (npm ci)

  4. Runs lint, type-check, tests, coverage, and duplication checks

  5. Builds the package

  6. Publishes to npm using Trusted Publishing (OIDC — no NODE_AUTH_TOKEN needed)

Published package: @j0hanz/todokit-mcp

Troubleshooting

Inspect the Server

Use the MCP Inspector to interactively test tools:

npx @modelcontextprotocol/inspector node dist/index.js

Or if installed from npm:

npx @modelcontextprotocol/inspector npx -y @j0hanz/todokit-mcp@latest

Common Issues

Issue

Solution

Server not responding

Ensure nothing else is reading/writing to stdout in the process

E_NOT_FOUND

Call list_todos first to verify the todo ID exists

E_STORAGE_CONFLICT

Retry the operation — another process may be holding the file lock

E_STORAGE_TOO_LARGE

Delete completed items or increase TODOKIT_MAX_TODO_FILE_BYTES

E_BAD_REQUEST

Ensure at least one field is provided when calling update_todo

E_INVALID_PARAMS

Check enum values (priority, status) and ISO 8601 date formats

File outside CWD error

Set TODOKIT_ALLOW_OUTSIDE_CWD=true or use a path within CWD

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 debug

This 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

License

MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/j0hanz/todokit-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server