mcp server
task-planner
Task planner where a task is a recurrence rule, nine kinds including spaced repetition, materialized into daily occurrences. Go backend with REST, MCP and a Kafka outbox, Wails desktop client, and the
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 28, 2026tasks — приложение задач
Приложение задач под Windows: headless-бэкенд на Go + десктоп-клиент на Wails. Любые задачи — от «убраться дома» до цепочек закрепления знаний (spaced repetition). Часть экосистемы activization: владеет данными о задачах, публикует события в Kafka для бота, отдаёт ICS-фид для внешних календарей.
Прототип и источник идей модели — планер в Google Таблицах: planer.md (темы, форматы повторений, перенос невыполненных со сдвигом цепочки).
Структура
tasks/
├── backend/ Go-сервис: REST + MCP + генератор вхождений + outbox-релей
│ ├── cmd/tasks/ точка входа
│ ├── internal/ config, handler, service, repository, models, kafka
│ ├── migrations/ SQL-миграции (golang-migrate, встроены в бинарник)
│ └── Dockerfile multi-stage сборка
├── desktop/ Wails v2 приложение (React + TS + Tailwind)
│ ├── frontend/ UI: календарь, дерево тем и задач, темы
│ └── main.go окно + биндинг адреса бэкенда
├── docker-compose.yml postgres:16 (порт 5433) + backend (порт 8081)
└── planer.md UX-прототип (Google Apps Script)
Запуск
Docker (через WSL)
Команды выполняются из каталога tasks/ (WSL наследует текущий каталог). Compose подключается к внешней сети ecosystem — на чистой машине её нужно создать один раз:
wsl -d Ubuntu-22.04 -- docker network create ecosystem # однократно
wsl -d Ubuntu-22.04 -- docker compose up -d --build
Поднимает Postgres на localhost:5433 и бэкенд на http://localhost:8081. Kafka не обязательна: события копятся в outbox и уходят, когда брокер появится (общая Kafka — infra/docker-compose.yml экосистемы).
Локально без Docker
wsl -d Ubuntu-22.04 -- docker compose up -d postgres
cd backend
go run ./cmd/tasks
Десктоп
cd desktop
& "$env:USERPROFILE\go\bin\wails.exe" dev # разработка
& "$env:USERPROFILE\go\bin\wails.exe" build # сборка → build\bin\tasks-desktop.exe
Клиент ходит на http://localhost:8081 (переопределяется переменной TASKS_API_URL).
Конфигурация
.env в каталоге backend/ (или корне tasks/), переменные окружения поверх. Префикс TASKS_:
| Переменная | Default | Смысл |
|---|---|---|
| TASKS_HTTP_PORT | 8081 | порт REST + MCP |
| TASKS_DB_HOST / PORT / USER / PASSWORD / NAME | localhost / 5433 / tasks / tasks / tasks | Postgres |
| TASKS_KAFKA_BROKERS | localhost:9094 | брокеры через запятую |
| TASKS_KAFKA_TOPIC | tasks.events | топик CloudEvents |
| TASKS_TIMEZONE | Europe/Moscow | локальная TZ пользователя |
| TASKS_WINDOW_DAYS | 60 | окно материализации вхождений |
| TASKS_OUTBOX_INTERVAL_SECONDS | 5 | период outbox-релея |
| TASKS_DB_DRIVER | postgres | postgres или sqlite (мобильное) |
| TASKS_DB_PATH | tasks.db | путь к файлу SQLite (при driver=sqlite) |
| TASKS_SYNC_URL | — | URL сервера-источника для синхронизации (пусто = не синхронизировать) |
| TASKS_SYNC_TOKEN | — | bearer-токен эндпоинтов /api/v1/sync |
| TASKS_SYNC_INTERVAL_SECONDS | 60 | период push/pull синхронизации |
Мобильное приложение (Android)
Тот же самый бэкенд и тот же самый фронтенд (desktop/frontend), только упакованные под телефон — без переписывания и дублирования UI.
backend/mobile/— gomobile-пакет: весь бэкенд задач на SQLite (ncruces/go-sqlite3— чистый Go/WASM без сисколлов, иначе seccomp Android убивает процесс) слушает127.0.0.1:18081и сам раздаёт собранныйdesktop/frontendкак статику.android/— тонкая Kotlin-обёртка: WebView открывает локальный бэкенд; в меню — настройки синхронизации (URL сервера ПК + токен).api.tsфронта сам выбирает транспорт: в Wails — через биндинг, в мобильном/браузере — same-origin по/healthz, иначеlocalhost:8081.
Синхронизация с ПК (internal/syncer): двусторонняя, REST /api/v1/sync/changes (GET отдаёт изменения с курсора, POST принимает). Конфликты — last-write-wins по updated_at; удаления через sync_tombstones (сервер ретранслирует их другим устройствам); ID вхождений детерминированные (uuid5 от task_id+date), поэтому одно и то же вхождение не двоится на двух устройствах.
Сборка APK (окружение — C:\Users\pavel\android-tools, ничего в систему не ставится):
deploy\build-android.ps1
Скрипт собирает фронт → кладёт в backend/mobile/webdist → gomobile bind в android/app/libs/tasks.aar → gradle APK в android/app/build/outputs/apk/.
API (кратко)
REST /api/v1 (JSON snake_case, ошибки {"error":{"code","message"}}):
CRUD /topics, /tasks; GET /occurrences?from&to&status&task_id; POST /occurrences/{id}/complete|skip; POST /tasks/{id}/reschedule-missed; GET /plans/{date}; PUT /plans/{date}/items; POST /plans/{date}/commit; GET /calendar.ics; GET /healthz.
MCP (streamable HTTP /mcp): list_tasks, create_task (плоские поля повторений + effort_minutes, requires_pomodoro, topic/parent_topic), complete_occurrence, skip_occurrence, list_due, get_day_plan, commit_day_plan, reschedule_missed, create_topic (с родителем — дерево тем), list_topics.
Подробности — в backend/README.md и docs/contracts.md экосистемы. Модель данных — docs/data-model.md.
Тесты
cd backend
go test ./...
Покрыто: генератор повторений (все 9 видов, monthly-прижатие, SR c series_step), перенос невыполненных, план дня, outbox-релей с mock-продюсером, REST-хендлеры (httptest).