TaskPad
by Evert-vh
README.md
# TaskPad
A Windows system-tray task manager and reminder engine with deep AI and automation integration.
- **System tray icon** — colour-coded badge (blue / green / amber / red) with a task count
- **Floating overlay** — always-on-top compact task list; drag it anywhere on screen
- **Reminder engine** — fires desktop alerts and system sounds at the scheduled time
- **MCP server** — Claude Code, Claude Desktop, and claude.ai can all read and write your tasks
- **REST API** — JSON API on `localhost:8765` for n8n, Home Assistant, or any HTTP client
- **Outbound webhooks** — push `task.created`, `task.completed`, `reminder.fired`, etc. to any URL
---
## Table of contents
1. [Requirements](#requirements)
2. [Installation](#installation)
3. [Running from source](#running-from-source)
4. [Tray icon guide](#tray-icon-guide)
5. [Cloudflare tunnel setup](#cloudflare-tunnel-setup)
6. [Claude Desktop setup](#claude-desktop-setup)
7. [Claude Code setup](#claude-code-setup)
8. [claude.ai browser setup](#claudeai-browser-setup)
9. [n8n integration](#n8n-integration)
10. [REST API reference](#rest-api-reference)
11. [Outbound webhook events](#outbound-webhook-events)
12. [Configuration file](#configuration-file)
13. [Building the installer](#building-the-installer)
---
## Requirements
| Requirement | Version |
|---|---|
| Windows | 10 / 11 (64-bit) |
| Python | 3.10 or later |
| Pip packages | see `requirements.txt` |
TaskPad stores its data in `%APPDATA%\TaskPad\` (i.e. `C:\Users\<you>\AppData\Roaming\TaskPad\`).
---
## Installation
Run the installer — `TaskPad-Setup-1.0.0.exe` — and follow the wizard.
The wizard will:
1. Copy all source files to `C:\Program Files\TaskPad\` (or your chosen path).
2. Optionally add a desktop shortcut and a Windows autostart entry.
3. Run `pip install -r requirements.txt` with the detected Python interpreter.
4. Ask for an optional **Cloudflare tunnel URL** (for Claude AI) and **n8n webhook URL** — you can skip these and configure them later from the tray menu.
After the installer completes, tick **"Launch TaskPad now"** on the final page or start it from the Start menu / desktop shortcut.
> **Note:** If Python was not detected, install it from [python.org/downloads](https://www.python.org/downloads/), then open a terminal in the install folder and run:
> ```
> pip install -r requirements.txt
> ```
---
## Running from source
```powershell
# Clone / copy the source, then:
pip install -r requirements.txt
python main.py
```
**MCP stdio mode** (for Claude Code / Claude Desktop):
```powershell
python main.py --mcp
```
---
## Tray icon guide
The tray icon colour tells you your task state at a glance:
| Colour | Meaning |
|---|---|
| Blue | No pending tasks |
| Green | Tasks exist, none due / reminded today |
| Amber | At least one reminder is scheduled for today |
| Red | Urgent task or a reminder is due within the hour |
A number badge in the top-right corner shows the count of incomplete tasks (up to 99).
**Right-click menu:**
| Menu item | Action |
|---|---|
| Open TaskPad | Show/hide the floating overlay |
| Add Task… | Quick-add dialog |
| Start on Boot / Stop at Boot | Toggle Windows autostart |
| Sound Settings… | Choose system sound or custom WAV |
| MCP Settings… | Set your static Cloudflare tunnel URL |
| Integration Settings… | View API key, API URL, set n8n webhook |
| MCP URL | Shows the active public MCP URL |
| Copy MCP URL | Copies it to clipboard |
| Quit | Exit the tray app |
---
## Cloudflare tunnel setup
TaskPad exposes the MCP server on port **8766** (HTTP/SSE). To make it reachable from claude.ai or n8n on another machine you need to expose that port via a Cloudflare tunnel.
### Option A — Permanent named tunnel (recommended)
This gives you a stable URL that survives restarts.
1. **Create the tunnel in the Cloudflare dashboard:**
- Cloudflare Zero Trust → Access → Tunnels → **Create a tunnel**
- Name it (e.g. `taskpad`).
- Under **Public hostname**, add a subdomain pointing to `http://localhost:8766`
e.g. `taskpad.yourdomain.com`
- Install / authenticate `cloudflared` on this machine (the dashboard shows the command).
2. **Tell TaskPad the stable URL:**
- Right-click tray icon → **MCP Settings…**
- Enter `https://taskpad.yourdomain.com` and save.
- TaskPad will use this URL immediately (no cloudflared management needed — you run `cloudflared` separately as a service).
3. **Expose the REST API too** (for n8n on another server):
- Add a second public hostname in the same tunnel:
`taskpad-api.yourdomain.com` → `http://localhost:8765`
- Use this URL as the base URL in n8n.
### Option B — Quick ephemeral tunnel (development / testing)
If `cloudflared` is on your PATH or in `%APPDATA%\TaskPad\cloudflared.exe`, TaskPad will start a quick tunnel automatically on launch and show a tray notification with the URL. The URL changes every restart.
TaskPad will download `cloudflared.exe` automatically from GitHub if it is not found.
---
## Claude Desktop setup
1. Open Claude Desktop → Settings → Developer → Edit Config (`claude_desktop_config.json`).
2. Add under `"mcpServers"`:
```json
{
"mcpServers": {
"taskpad": {
"command": "python",
"args": ["C:\\Program Files\\TaskPad\\main.py", "--mcp"]
}
}
}
```
3. Restart Claude Desktop. TaskPad should appear in the tool list.
> Use `pythonw` instead of `python` if you want to suppress the console window.
---
## Claude Code setup
Run once in a terminal:
```bash
claude mcp add taskpad -s user -- python "C:\Program Files\TaskPad\main.py" --mcp
```
Verify it is registered:
```bash
claude mcp list
```
Claude Code will now have access to all TaskPad tools in every project.
---
## claude.ai browser setup
claude.ai connects over HTTP/SSE (not stdio), so it needs the tunnel URL.
1. Complete the [Cloudflare tunnel setup](#cloudflare-tunnel-setup) to get a stable public URL.
2. In claude.ai → Settings → Integrations → Add MCP server:
- **URL:** `https://taskpad.yourdomain.com/sse`
3. Save. The TaskPad tools will appear in your claude.ai conversations.
---
## n8n integration
TaskPad acts as both an **inbound** HTTP server (n8n calls it) and an **outbound** webhook sender (TaskPad calls n8n).
### Inbound — n8n creates tasks in TaskPad
Use an **HTTP Request** node in n8n:
| Field | Value |
|---|---|
| Method | `POST` |
| URL | `https://taskpad-api.yourdomain.com/webhook` |
| Header | `X-API-Key: <your-api-key>` |
| Body | JSON (see below) |
Example body (email flagged → task with link back):
```json
{
"title": "Follow up on invoice from Acme",
"category": "work",
"priority": "high",
"remind_at": "2026-08-01T09:00:00",
"notes": "Flagged in Outlook — needs reply by EOD",
"source_url": "https://outlook.office.com/mail/deeplink/..."
}
```
Find your API key: right-click tray → **Integration Settings…** → copy the key shown.
### Outbound — TaskPad notifies n8n
1. In n8n, create a **Webhook** node. Copy its URL.
2. In TaskPad: right-click tray → **Integration Settings…** → paste the URL in *n8n webhook URL* and save.
TaskPad will POST a JSON payload to that URL for each enabled event.
---
## REST API reference
Base URL (local): `http://127.0.0.1:8765`
Base URL (remote): `https://taskpad-api.yourdomain.com`
All endpoints except `/health` require the header:
```
X-API-Key: <your-api-key>
```
Interactive docs are available at `http://127.0.0.1:8765/docs` while TaskPad is running.
### Endpoints
| Method | Path | Description |
|---|---|---|
| GET | `/health` | Health check (no auth) |
| GET | `/tasks` | List tasks. Query params: `category`, `completed` |
| POST | `/tasks` | Create a task |
| GET | `/tasks/{id}` | Get a single task |
| PATCH | `/tasks/{id}` | Update task fields |
| DELETE | `/tasks/{id}` | Delete a task |
| POST | `/tasks/{id}/complete` | Mark complete/incomplete. Query param: `done=true/false` |
| POST | `/webhook` | Simplified create endpoint (same as POST /tasks, shorter schema) |
### Task schema
```json
{
"title": "string (required)",
"category": "work | personal | shared",
"task_type": "todo | reminder | both",
"priority": "urgent | high | normal | none",
"notes": "string",
"tags": ["string"],
"due_date": "YYYY-MM-DD or null",
"remind_at": "ISO datetime or null",
"repeat": "none | daily | weekdays | weekly | monthly | every_n_days",
"repeat_n": 1,
"repeat_days": [0,1,2,3,4],
"repeat_day_of_month": 1,
"enabled": true,
"source_url": "https://... or null"
}
```
### Example — create a task with curl
```bash
curl -X POST https://taskpad-api.yourdomain.com/tasks \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Review PR #42",
"category": "work",
"priority": "high",
"remind_at": "2026-08-01T10:00:00",
"source_url": "https://github.com/your-org/your-repo/pull/42"
}'
```
---
## Outbound webhook events
When a webhook URL is configured, TaskPad POSTs a JSON body to it for each event.
| Event | When it fires |
|---|---|
| `task.created` | Task added (via tray, MCP, or API) |
| `task.updated` | Task fields changed |
| `task.completed` | Task marked complete |
| `task.uncompleted` | Task marked incomplete |
| `task.deleted` | Task removed |
| `reminder.fired` | Reminder alert shown |
| `task.overdue` | Overdue check triggered |
Payload shape:
```json
{
"event": "task.created",
"task_id": "abc123",
"title": "Review PR #42",
"category": "work",
"priority": "high",
"task_type": "todo",
"remind_at": "2026-08-01T10:00:00",
"due_date": null,
"completed": false,
"source_url": "https://github.com/...",
"created_at": "2026-07-28T08:00:00",
"updated_at": "2026-07-28T08:00:00"
}
```
---
## Configuration file
`%APPDATA%\TaskPad\config.json` — created automatically on first run.
```json
{
"api_key": "auto-generated 48-char hex key",
"mcp_public_url": "https://taskpad.yourdomain.com",
"webhook_url": "https://n8n.yourdomain.com/webhook/taskpad",
"webhook_events": [
"task.created", "task.completed", "reminder.fired", "task.overdue"
],
"sound_type": "system",
"system_sound": "SystemExclamation"
}
```
All settings are editable from the tray menu — direct JSON editing is not normally required.
---
## Releasing a new version
`release.ps1` handles the full release cycle in one command:
```powershell
.\release.ps1 # bump patch (1.0.0 → 1.0.1), build, commit, tag, push
.\release.ps1 -Bump minor # bump minor (1.0.0 → 1.1.0)
.\release.ps1 -Bump major # bump major (1.0.0 → 2.0.0)
.\release.ps1 -Version 1.5.0 # explicit version
.\release.ps1 -NoBuild # commit + tag only, skip installer build
.\release.ps1 -NoPush # build + tag locally, do not push to remote
```
What it does, in order:
1. Reads the current version from `version.py`
2. Calculates the new version (or uses `-Version`)
3. Asks for confirmation before doing anything
4. Writes the new version back to `version.py`
5. Builds the installer via `build.ps1` (unless `-NoBuild`)
6. `git commit` — `chore: release v1.0.1`
7. `git tag -a v1.0.1`
8. `git push` + `git push --tags` (unless `-NoPush` or no remote)
If the project has not been initialised as a git repo yet, the script will run `git init` and do an initial commit automatically.
---
## Building the installer
**Prerequisites:**
- Python 3.10+ with Pillow (`pip install Pillow`)
- [Inno Setup 6](https://jrsoftware.org/isdl.php) installed
**To release a new version**, edit `version.py`:
```python
__version__ = "1.1.0"
```
Then run from the project root:
```powershell
.\build.ps1
```
Or override the version without editing the file:
```powershell
.\build.ps1 -Version 1.1.0
```
The build script will:
1. Read `version.py` (or use `-Version` override).
2. Generate `assets/icon.ico` (all sizes from 16 to 256 px).
3. Compile `installer/taskpad.iss` with ISCC, injecting the version.
4. Output `installer/output/TaskPad-Setup-<version>.exe`.
The version string also appears in the tray icon tooltip (`TaskPad v1.1.0`).
---
## File layout
```
TaskPad/
├── main.py # Entry point — tray app or --mcp mode
├── models.py # Task dataclass
├── store.py # SQLite storage + config helpers
├── scheduler.py # Reminder / overdue scheduler
├── requirements.txt
├── LICENSE.txt
├── build.ps1 # Build script (icon + Inno Setup)
├── api/
│ ├── server.py # FastAPI REST server on :8765
│ └── webhooks.py # Outbound webhook sender
├── mcp_server/
│ ├── server.py # MCP stdio server (--mcp flag)
│ ├── http_server.py # MCP HTTP/SSE server on :8766
│ └── tunnel.py # Cloudflare tunnel manager
├── ui/
│ ├── overlay.py # Floating task overlay
│ ├── alert.py # Reminder alert dialog
│ └── widgets.py # Custom PIL-based widgets
├── assets/
│ └── icon.ico # Generated by build.ps1
└── installer/
├── taskpad.iss # Inno Setup script
├── launcher.vbs # No-console launcher (wscript.exe)
├── generate_icon.py # PIL icon generator
└── write_config.py # Post-install config writer
```
---
## License
MIT — see `LICENSE.txt`.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues