LunaTask MCP is an unofficial Model Context Protocol server that provides a standardized bridge between AI models and the LunaTask API. It's designed as a lightweight, asynchronous Python application using the FastMCP framework, running as a local subprocess to enable AI tools to interact with LunaTask data.
LunaTask uses end-to-end encryption for sensitive task and note data. As a result:
- Task 
name/notefields and notecontentare not included in API responses - Only non-sensitive metadata and structural information is available
 - This is a security feature of LunaTask and cannot be bypassed
 - The 
name,note, andcontentfields can be included in create requests - LunaTask automatically encrypts these fields client-side before storage
 - Once created, these fields will not be visible in GET responses due to E2E encryption
 - This is normal LunaTask behavior and ensures data privacy
 
- Task IDs are unique identifiers assigned by LunaTask
 - Use the All Tasks resource to discover available task IDs
 - Task IDs remain consistent across API calls
 
- The server implements rate limiting to prevent API abuse
 - If you encounter rate limit errors, wait before retrying
 - Rate limits are per-server instance and reset over time
 
Lunatask MCP Server is managed by uv, so you will need to install it.
# Install dependencies and create the local virtual environment
uv sync
# Optionally verify the package imports correctly
uv run python -c "import lunatask_mcp"The LunaTask MCP server supports flexible configuration through TOML files and command-line arguments. A bearer token is required to authenticate with the LunaTask API.
- Copy the example configuration file to a path you prefer:
 
cp config.example.toml ~/path/to/your/lunatask_mcp_config.toml- Edit the copied configuration file and add your LunaTask API bearer token:
 
lunatask_bearer_token = "your_lunatask_bearer_token_here"- Run the server:
 
uv run lunatask-mcp --config-file /path/to/your/config.tomlNote: To create an access token open LunaTask app, open application settings, head to "Access tokens" section, and create a new access token. Then, click "Copy to clipboard", and paste it in the lunatask_bearer_token field in the config file.
The server supports three configuration methods with the following precedence (highest to lowest):
- Command-line arguments (highest priority)
 - Configuration file (TOML format)
 - Default values (lowest priority)
 
# Basic usage with default config file (./config.toml)
uv run lunatask-mcp
# Specify a custom config file
uv run lunatask-mcp --config-file /path/to/your/config.toml
# Override specific settings (examples)
uv run lunatask-mcp --log-level DEBUG --port 9000
uv run lunatask-mcp --base-url https://api.lunatask.app/v1/
uv run lunatask-mcp --token "$LUNATASK_TOKEN"
uv run lunatask-mcp --rate-limit-rpm 120 --rate-limit-burst 20
# Get help on available options
uv run lunatask-mcp --helpCreate a config.toml file with your settings:
# Required: Your LunaTask API bearer token
lunatask_bearer_token = "your_lunatask_bearer_token_here"
# Optional: API base URL (default: https://api.lunatask.app/v1/)
lunatask_base_url = "https://api.lunatask.app/v1/"
# Optional: Port for future HTTP transport (default: 8080, range: 1-65535)
# Note: Currently unused as server only supports stdio transport
port = 8080
# Optional: Logging level (default: INFO)
# Valid values: DEBUG, INFO, WARNING, ERROR, CRITICAL
log_level = "INFO"
# Optional: Connectivity test during startup (default: false)
test_connectivity_on_startup = false
# Optional: Rate limiting (defaults: rpm=60, burst=10)
rate_limit_rpm = 60
rate_limit_burst = 10
# Optional: HTTP client tuning
# Number of additional retry attempts for transient failures (default: 2)
http_retries = 2
# Initial retry backoff delay in seconds; doubles with each retry (default: 0.25)
http_backoff_start_seconds = 0.25
# Minimum delay before mutating requests (POST/PATCH/DELETE); set to 0.0 to disable (default: 0.0)
http_min_mutation_interval_seconds = 0.0
# Custom User-Agent header advertised to the LunaTask API
http_user_agent = "lunatask-mcp/0.2.0"
# Timeout in seconds for establishing the TLS connection
timeout_connect = 5.0
# Timeout in seconds for reading the response body
timeout_read = 30.0- If 
--config-fileis not specified, the server looks for./config.toml - Missing configuration files are only an error if explicitly specified
 - Default values are used when no configuration file exists
 
The server validates all configuration on startup and fails fast with clear error messages:
- Invalid TOML syntax: Clear parsing error with file location
 - Unknown configuration keys: Rejected with list of unknown keys
 - Invalid values: Port must be 1-65535, URL must be HTTPS, log level must be valid
 - Missing bearer token: Required field, server will not start without it
 
- Bearer tokens are never logged: Automatically redacted in all log output and error messages
 - Effective configuration logging: Server logs the final configuration with secrets redacted
 - Unknown keys rejection: Prevents typos and ensures clean configuration
 - Input validation: All configuration values are validated before server startup
 
The server provides the following tools:
- Ping Tool: A health-check tool that responds with "pong" when called
 - MCP Resources (read-only): Discovery + single task, plus area/global list aliases
 - MCP Tools (write): Create, update, delete tasks; create notes; create journal entries; create, delete people; create person timeline notes; track habit activity
 - MCP Protocol Version: Supports MCP protocol version 
2025-06-18 - Stdio Transport: Communicates over standard input/output streams
 
MCP resources depend on the client UI, and many popular MCP clients still surface tools only. As tracked in issue #14, missing resource support remains the main friction when browsing LunaTask data through MCP clients. The official MCP client matrix lists feature coverage. Clients such as Claude Desktop, Claude Code, Cline, Continue, Roo Code, Sourcegraph Cody, and the VS Code MCP extension expose resources today. Editors like Cursor, Windsurf, OpenSumi, and several others show tools only until they add resource support. Choose a resource-capable client when you need to inspect task lists directly.
create_task: Creates a new task. Requiresnameand the targetarea_id. Optional fields include text content (note), planning data (status,scheduled_on,estimate,progress), prioritisation (priority,motivation,eisenhower), goal context (goal_id) and external source metadata (source,source_id). Returns{ "success": true, "task_id": "..." }with the new identifier.create_note: Creates a new note. Acceptsnotebook_id,name, optionalcontent,date_on, andsource/source_idmetadata to guarantee idempotency. Returns{ "success": true, "note_id": "..." }when created, or{ "success": true, "duplicate": true, "message": "Note already exists for this source/source_id" }when the LunaTask API responds with204 No Contentfor duplicates.create_journal_entry: Creates a journal entry for a specific date. Requiresdate_oninYYYY-MM-DDformat and supports optionalnameandcontent(Markdown). Returns{ "success": true, "journal_entry_id": "..." }when LunaTask returns a wrappedjournal_entry. Responses never includenameorcontentbecause of end-to-end encryption.create_person: Creates a new person/contact. Requiresfirst_nameandlast_name. Optional fields includerelationship_strength(one offamily,intimate-friends,close-friends,casual-friends,acquaintances,business-contacts, oralmost-strangers; defaults tocasual-friends), external source metadata (source,source_id), and contact details (email,birthday,phone). Returns{ "success": true, "person_id": "..." }when created, or{ "success": true, "duplicate": true, "message": "Person already exists for this source/source_id" }when LunaTask responds with204 No Contentfor duplicates. Note: Custom fields for email, birthday, or phone must be defined in the LunaTask app first, otherwise returns a 422 validation error.create_person_timeline_note: Creates a timeline note for an existing person. Requiresperson_idandcontent, accepts an optionaldate(YYYY-MM-DD). Whendateis omitted the LunaTask API stores the note against the current day. Returns{ "success": true, "person_timeline_note_id": "..." }on success. Validation, authentication, subscription, rate limit, timeout, and network errors map to structured error payloads, and invalid ISO dates are rejected client-side before hitting the API.delete_person: Deletes a person/contact from LunaTask. Requiresperson_id. Returns{ "success": true, "person_id": "...", "deleted_at": "...", "message": "Person deleted successfully" }on success. Note: deletion is not idempotent - attempting to delete the same person twice will return a not found error. Validation, authentication, rate limit, timeout, and network errors map to structured error payloads.update_task: Updates an existing task by ID. Supports partial updates—only the fields you pass (same set as create, minus the requiredname) are mutated. Returns{ "success": true, "task": {...} }with the full serialized task payload.delete_task: Permanently deletes a task from LunaTask. Returns{ "success": true, "task_id": "..." }. Deleted tasks cannot be recovered, so invoke with caution.track_habit: Logs habit activity for a specific habit ID and ISO date. Returns{ "ok": true, "message": "Successfully tracked habit <id> on <date>" }when the API confirms the event.
The server also has the following resources:
- Discovery: 
lunatask://tasksandlunatask://tasks/discovery - Single Task: 
lunatask://tasks/{task_id} - Area lists (replace 
{area_id}):lunatask://area/{area_id}/nowlunatask://area/{area_id}/todaylunatask://area/{area_id}/overduelunatask://area/{area_id}/next-7-dayslunatask://area/{area_id}/high-prioritylunatask://area/{area_id}/recent-completions
 - Global lists:
lunatask://global/nowlunatask://global/todaylunatask://global/overduelunatask://global/next-7-dayslunatask://global/high-prioritylunatask://global/recent-completions
 
Discovery resource returns discovery metadata for list resources, including supported parameters, alias URIs, canonical examples, defaults, and guardrails.
You can filter globally and by area_id. The filters work as follows:
- today: scheduled today
 - overdue: scheduled before today
 - next-7-days: scheduled within the next 7 days (UTC), excluding today
 - recent-completions: tasks completed in the last 72 hours.
 - now: one of the following:
- Tasks without scheduled date but with status as "started" (in progress in the app)
 - Tasks without scheduled date but with highest priority (2)
 - Tasks without scheduled date but with motivation as "must"
 - Tasks without scheduled date but with eisenhower as 1 (urgent and important)
 
 
Note: There is slight difference between the now in LunaTask and now here. This can create some confusion. Currently, now is seen as urgent and not scheduled. This will be solved in this future issue.
The reason behind these filters is that if you try to gather all the tasks from the LunaTask API you will easily fill up your LLM context if you have a lot of tasks. In the future these could be expanded to include:
- filters by 
goal_id - filters for all priority types
 - filters for all motivation types
 - filters for all eisenhower types
 - filters for specific dates
 - filters for completed tasks in a range of dates
 
You give access to Claude Code via:
claude mcp add lunatask-mcp -- uvx --from git+https://github.com/tensorfreitas/lunatask-mcp lunatask-mcp --config-file /your/path/to/lunatask_mcp_config.toml{
    "mcpServers": {
        "lunatask-mcp": {
            "command": "uvx",
            "args": ["--from", "git+https://github.com/tensorfreitas/lunatask-mcp", "lunatask-mcp", "--config-file", "/your/path/to/lunatask_mcp_config.toml"]
        }
    }
}Unlike Claude Code, in Codex you add an MCP server globally and not per project. Add the following to ~/.codex/config.toml (create the file if it does not exist):
[mcp_servers.lunatask-mcp]
command = "uvx"
args = ["--from", "git+https://github.com/tensorfreitas/lunatask-mcp", "lunatask-mcp", "--config-file", "/your/path/to/lunatask_mcp_config.toml"]As discussed in MCP Client Compatibility, some MCP clients do not yet implement the full MCP resource surface. The following clients currently connect but only display tools:
- Codex
 - Gemini CLI
 - LM Studio
 - Qwen CLI
 
Track progress in issue #14. Tools stay available in these clients while resource views are pending.
- Implementation of MCP Server-Sent Events (SSE) for HTTP-based clients
 - Extra Task Resource Filters
 
-  resource filters by 
goal_id - filters for all priority types
 - filters for all motivation types
 - filters for all Eisenhower types
 - filters for specific dates
 - filters for completed tasks in a range of dates
 
- Extra tools
 
-  Implement 
create_notetool -  Implement 
create_journal_entrytool -  Implement 
create_persontool -  Implement 
delete_persontool -  Implement 
create_person_timeline_notetool 
- Extra Resources
 
- Implement Retrieve person resource
 - Implement Retrieve all people resource
 
This project was developed with the assistance of AI. The purpose was to test various workflows using different LLMs and identify the most effective approach for me. Since I’m doing this on my free time, this was the only feasible option. Consequently, some of the documentation or code may not be entirely accurate. I’ve made every effort to review everything, but there might have been some errors that I overlooked. If you discover any issues that require correction, please create an issue on GitHub.