Skip to main content
Glama
grigoreo-dev

otask-mcp-server

by grigoreo-dev

otask-mcp-server

MCP-сервер для O!task API. Отдаёт операции O!task (пространства/задачи) как MCP-инструменты для агентов (Claude, Cursor, OpenCode, n8n MCP Client Tool).

Неофициально. otask-mcp — независимый open-source MCP-коннектор к API O!task. Не аффилирован с O!task, не является его частью и не поддерживается им.

Unofficial. otask-mcp is an independent open-source MCP connector for the O!task API. Not affiliated with, endorsed by, or part of the O!task product/team.

🚀 Возможности

  • stdio — локальный MCP для Claude Desktop / Cursor / OpenCode

  • HTTP gateway / passthrough — Streamable HTTP для n8n и self-host

  • Remote MCP (Cloudflare Worker) — OAuth-логин O!task (2-step wizard), без пароля в конфиге клиента

  • Allow-list пространство/project, defaults, inbox-сценарии (otask_list_tasks)

  • Discovery: otask_list_workspaces (пространства без ручного slug)

  • Open source: grigoreo-dev/otask-mcp

npm i -g @grigoreo-dev/otask-mcp
# или: npx @grigoreo-dev/otask-mcp
# HTTP: npx otask-mcp-http   # bin name stays unscoped

Публикация на npm: push tag vX.Y.Z (версия в tag = package.json). CI: .github/workflows/publish.yml (OIDC Trusted Publisher, без NPM_TOKEN).

Related MCP server: ticktick-mcp-server

🔒 Приватность и доверие

Неофициально: otask-mcp — независимый open-source коннектор, не продукт O!task и не поддерживается им.

Касается Cloudflare Worker (remote MCP) и библиотеки @cloudflare/workers-oauth-provider:

Что

Где

Кто видит

Пароль O!task

только memory на POST /authorize

нигде не пишется (ни KV, ни env, ни git)

Токен O!task + scope (props)

grant в Cloudflare KV (OAUTH_KV)

end-to-end encrypted: ключ шифрования — секрет access-токена MCP; из сырого KV нельзя прочитать props без валидного Bearer

userId

KV, не зашифрован

HMAC-SHA256(email, secret pepper) — не email; без секрета USER_ID_PEPPER перебором по словарю email не сматчить

metadata

KV, не зашифрован

пусто ({}) — email в хранилище не пишется

Access token MCP

у клиента (Claude и т.д.)

клиент + тот, кто перехватит Bearer

  • Пароль не хранится после логина: email+password → POST api.otask.ru/.../login → API-токен → в props, пароль drop.

  • O!task Bearer нужен для запросов к API → лежит в encrypted props, не в открытом виде.

  • userId = HMAC-SHA256(email, USER_ID_PEPPER): стабильный id (повторный логин заменяет старый grant), но email в KV нет и хэш не перебрать без секрета.

  • Публичный Worker без OTASK_* / MCP_AUTH_TOKEN в env: multi-user, каждый — своя OAuth-сессия.

  • После expiry/401 — повторный Connect (re-login).

  • Код open source: self-deploy и аудит. Паттерн: Remote MCP on Cloudflare.

  • Официальный URL: https://otask-mcp.grigoreo.dev/mcp.

Доверие к оператору Worker: в хранилище нет ни пароля, ни email plaintext, а O!task-токен — только encrypted props. Но владелец Cloudflare-аккаунта может сменить код Worker (залогировать ctx.props / токен на своём деплое). Гарантия — открытый код: не доверяете чужому demo → self-deploy.

Не кладите OTASK_PASSWORD, OTASK_AUTH_KEY и токены в git, скриншоты и issue.

☁️ Remote MCP (Cloudflare)

Официальный публичный endpoint:

https://otask-mcp.grigoreo.dev/mcp

Multi-user OAuth, OTASK_* в env Worker нет. Self-host: см. 🔧 Self-deploy Worker.

Подключение (OAuth)

Лендинг (что это за коннектор, как подключаться):

https://otask-mcp.grigoreo.dev/
  1. Откройте лендинг https://otask-mcp.grigoreo.dev/ — краткое описание Remote MCP и URL /mcp (это не 404).

  2. В MCP-клиенте добавьте remote server с URL https://otask-mcp.grigoreo.dev/mcp (или свой self-deploy …/mcp).

  3. Запустите Connect / OAuth flow клиента.

  4. Шаг 1: ввод email + пароль O!task.

  5. Шаг 2: выбор пространства по умолчанию, проекта и (опционально) разрешённых пространств/проектов из выпадающих списков — вручную вводить UUID-slug больше не нужно.

  6. Пустой список разрешённых = доступ ко всем пространствам/проектам аккаунта (без allow-list ограничения).

  7. После успешного authorize клиент получает access token сессии MCP; вызовы /mcp идут с этим токеном.

Явные ws_slug / project args в tools по-прежнему работают. Self-host stdio/HTTP: env OTASK_DEFAULT_*. Про UUID-slug vs #N на доске: docs/SLUGS.md.

На публичном Worker нет OTASK_* в env: multi-user, credentials только в сессии пользователя.

💻 stdio (локально)

Локальный процесс; credentials только из env сервера.

OTASK_AUTH_KEY=...
# или OTASK_EMAIL + OTASK_PASSWORD
OTASK_DEFAULT_WS=...
OTASK_DEFAULT_PROJECT=my-project
OTASK_ALLOWED_WS=...
OTASK_ALLOWED_PROJECTS=my-project
bun start
# или: npx @grigoreo-dev/otask-mcp

stdio требует OTASK_* (без них падает при старте).

🐳 Docker / HTTP

bun run start:http
# Docker: образ из Dockerfile, PORT=3847

MCP

POST/GET /mcp (Streamable HTTP)

Health

GET /health{ ok, mode, authMode, projectGuard, wsGuard, defaults } ("env" | "header" | "off")

Пример self-host: https://otask-mcp.example/mcp (порт 3847 в Docker).

Gateway (credentials O!task на сервере)

OTASK_AUTH_KEY=...
MCP_AUTH_TOKEN=...
OTASK_DEFAULT_WS=...
OTASK_DEFAULT_PROJECT=...
OTASK_ALLOWED_WS=...
OTASK_ALLOWED_PROJECTS=...

Клиент: Authorization: Bearer <MCP_AUTH_TOKEN> (не токен O!task). Не шлите X-Otask-* allow/default (берутся из env).

Passthrough (токен O!task у клиента)

Env сервера: без OTASK_AUTH_KEY / OTASK_EMAIL / OTASK_PASSWORD.

Клиент: Authorization: Bearer <токен api.otask.ru>. Опционально: X-Otask-Allowed-Projects, X-Otask-Allowed-Ws, X-Otask-Default-Ws, X-Otask-Default-Project.

Проверка: GET /healthauthMode: "gateway" | "passthrough".

🔀 Режимы auth

Режим

Где

Команда / URL

Авторизация клиента

stdio

локально

bun start / otask-mcp

Нет HTTP; OTASK_* в env процесса

HTTP gateway

Node/Docker

bun run start:http

Authorization: Bearer <MCP_AUTH_TOKEN>; на сервере есть OTASK_*

HTTP passthrough

Node/Docker

bun run start:http

Authorization: Bearer <токен O!task>; нет OTASK_* в env

remote Worker

Cloudflare

https://…/mcp + OAuth

OAuth Connect → логин email+password на Worker; API-токен в сессии, не в env Worker

Определение HTTP (Node): hasServerOtaskCredentials() — gateway, если задан статический ключ или email+password; иначе passthrough. HTTP gateway требует MCP_AUTH_TOKEN, если заданы OTASK_* (иначе падает при старте).

🤖 Промпты для агентов

Скопируйте блок в чат агента.

Claude web → официальный URL (https://otask-mcp.grigoreo.dev/mcp)

Подключи remote MCP сервер O!task:
- URL: https://otask-mcp.grigoreo.dev/mcp
- Лендинг: https://otask-mcp.grigoreo.dev/
- Используй OAuth / Connect flow клиента (2 шага: логин → выбор пространства/проекта)
- Default пространство/project задаются на шаге 2 wizard (или явными args tools)
- Для discovery: otask_list_workspaces, otask_list_projects
Не сохраняй мой пароль в файлы репозитория.

Cursor → официальный URL

Добавь в MCP config Cursor remote server O!task:
url: https://otask-mcp.grigoreo.dev/mcp
auth: oauth
После connect проверь otask_me.

Self-deploy Worker

Задеплой otask-mcp Worker из репозитория grigoreo-dev/otask-mcp:
1) bun install; bun run build (из корня)
2) wrangler login (один раз)
3) bun run deploy:worker   # KV OAUTH_KV создаётся автоматически
4) Дай мне URL /mcp и пропиши в MCP клиент с OAuth

Docker passthrough

Подними otask-mcp HTTP passthrough в Docker без OTASK_* в env.
Клиент шлёт Authorization: Bearer <O!task token>.
PORT 3847. Проверь GET /health.

stdio local

Установи @grigoreo-dev/otask-mcp, настрой stdio MCP с OTASK_EMAIL+OTASK_PASSWORD
или OTASK_AUTH_KEY. Добавь в Claude Desktop / Cursor mcp servers.

Gateway self-host

HTTP gateway: задай OTASK_* + MCP_AUTH_TOKEN.
Клиент шлёт Bearer MCP_AUTH_TOKEN, не токен O!task.

🔧 Self-deploy Worker

Пакет: packages/worker (не публикуется на npm). Подробнее: packages/worker/README.md.

# из корня репозитория
bun install
bunx wrangler login              # один раз (браузер, без API-токена)
# секрет для HMAC userId (email не хранится в KV в переборно-открытом виде)
bunx wrangler secret put USER_ID_PEPPER --config packages/worker/wrangler.toml

bun run deploy:worker            # build + deploy; KV OAUTH_KV создаётся автоматически

Подробнее (GH Actions, Workers Builds из git, secrets): packages/worker/README.md.

  • Endpoint MCP: https://otask-mcp.<ваш-subdomain>.workers.dev/mcp (или свой custom domain, как официальный https://otask-mcp.grigoreo.dev/mcp)

  • OAuth: /authorize, /oauth/token, /oauth/register

  • Не задавайте OTASK_* в [vars] для multi-user публичного деплоя

  • GitHub Actions (кнопка Deploy): нужны secrets CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID

  • Cloudflare Workers Builds (git в dashboard): токен в GitHub не нужен — CF GitHub App; build из monorepo

Rate limiting — в dashboard Cloudflare (см. worker README), не в коде v1.

Переменные окружения

Переменная

Где используется

Когда обязательна

Назначение

OTASK_AUTH_KEY

stdio, HTTP gateway

stdio или gateway (альтернатива: email/password)

Статический O!task Bearer, которым пользуется сервер

OTASK_EMAIL

stdio, HTTP gateway

вместе с OTASK_PASSWORD как альтернатива ключу

Логин для получения токена

OTASK_PASSWORD

stdio, HTTP gateway

вместе с OTASK_EMAIL

Пароль для логина

MCP_AUTH_TOKEN

HTTP gateway

режим gateway

Общий секрет, который должен отправлять клиент; не токен O!task

OTASK_DEFAULT_WS

stdio, HTTP

опционально

Slug пространства по умолчанию (UUID; если tool не передал ws_slug)

OTASK_DEFAULT_PROJECT

stdio, HTTP

опционально

Project slug (UUID) или numeric id по умолчанию

OTASK_ALLOWED_WS

stdio, HTTP gateway

опционально

Allow-list slug пространств через запятую

OTASK_ALLOWED_PROJECTS

stdio, HTTP gateway

опционально

Allow-list project slug и/или numeric id через запятую

PORT

HTTP

опционально (по умолчанию 3847)

Порт прослушивания

HOST

HTTP

опционально (по умолчанию 0.0.0.0)

Адрес привязки

Default должен входить в allow-list, если list непустой (иначе сервер падает при старте).

Remote Worker: user credentials не через эти env (OAuth-сессия).

HTTP-заголовки

Заголовок

Режим

Назначение

Authorization: Bearer …

gateway

Должен совпадать с MCP_AUTH_TOKEN

Authorization: Bearer …

passthrough

Токен O!task API; проксируется на каждый запрос к API

Authorization: Bearer …

remote Worker

Access token OAuth-сессии MCP (после Connect)

X-Otask-Allowed-Projects

только passthrough

Allow-list projects; в gateway — env

X-Otask-Allowed-Ws

только passthrough

Allow-list пространств

X-Otask-Default-Ws

passthrough (override env)

Default slug пространства

X-Otask-Default-Project

passthrough (override env)

Default project slug/id

Примеры для n8n

Gateway

  • URL: https://otask-mcp.example/mcp

  • Transport: HTTP Streamable

  • Credential / header: Authorization: Bearer <MCP_AUTH_TOKEN>

  • Не отправляйте X-Otask-* allow/default headers

Passthrough

  • URL: https://otask-mcp.example/mcp

  • Transport: HTTP Streamable

  • Credential / header: Authorization: Bearer <токен api.otask.ru>

  • Опционально: X-Otask-Allowed-*, X-Otask-Default-*

Инструменты

Регистрируются в packages/core/src/tools/registry.ts:

Инструмент

Назначение

otask_me

Текущий пользователь (id, имя, email, timezone)

otask_list_workspaces

Список пространств (teams); без slug; при одном пространстве агент/резолвер может подставить его автоматически

otask_list_tasks

Задачи пространства; по умолчанию mine=true; фильтры performer_ids, project_ids, priority_ids, due, page

otask_get_task

Получить одну задачу по пространству + slug задачи

otask_update_task

Обновить существующую задачу

otask_list_projects

Список проектов пространства (с фильтром по allow-list)

otask_list_project_tasks

Задачи проекта: по умолчанию активные задачи из UI board snapshot; active_only=false для полного legacy-списка

otask_list_board

Доски/колонки (статусы) с type, is_system, tasks_count; type=completed помечает завершённую колонку

otask_list_members

Участники пространства

otask_list_tags

Теги пространства

otask_list_comments

Комментарии к задаче

otask_add_comment

Добавить комментарий (parent_id для ответов)

otask_create_task

Создать задачу (name, board_id, board_column_id, end_at, …)

otask_move_task

Переместить задачу в другую колонку

otask_archive_task

Архивировать задачу

Про UUID-slug vs номера досок #N: docs/SLUGS.md.

Inbox (после OTASK_DEFAULT_WS):

otask_me
otask_list_tasks  # mine=true
otask_list_tasks due=today
otask_list_tasks due=overdue

Defaults и allow-list (пространства + projects)

Что

Env (gateway/stdio)

Header (passthrough)

Default пространство

OTASK_DEFAULT_WS

X-Otask-Default-Ws (override)

Default project

OTASK_DEFAULT_PROJECT (slug или id)

X-Otask-Default-Project

Limit пространств

OTASK_ALLOWED_WS

X-Otask-Allowed-Ws

Limit projects

OTASK_ALLOWED_PROJECTS

X-Otask-Allowed-Projects

Формат allow-list: значения через запятую. Projects: slug (UUID) и/или numeric id. Пространства: только slug (UUID). Пусто = без ограничения (off). Подробнее: docs/SLUGS.md.

otask_list_board по умолчанию шлёт type=status (так требует O!task API).

Снимок API-документации

bun run docs:parse

Пишет в docs/catalog/ (или bun run docs:parse --file path для офлайн HTML).

Разработка

Монорепо: packages/core, packages/stdio, packages/http-node, packages/worker.

bun install
bun run build          # core → stdio → http-node
bun test
bun start              # stdio MCP
bun run start:http     # Streamable HTTP MCP
bun run dev            # stdio hot reload
bun run dev:http       # HTTP hot reload

Добавление инструмента

  1. packages/core/src/services/api.ts / client.ts — метод API при необходимости

  2. packages/core/src/schemas/ — Zod input schema

  3. packages/core/src/tools/my-tool.ts — factory → ToolDefinition

  4. packages/core/src/tools/registry.ts — добавить в toolFactories

Contributing

See CONTRIBUTING.md for setup, PR checks, and the release tag flow.

Available Tools

2 tools
otask_get_taskGet O!task TaskA
Read-onlyIdempotent

Fetch a task from O!task by workspace and task slug.

Use before otask_update_task to inspect current field values (board_id, performers, tags, etc.).

Args:

  • ws_slug: Workspace UUID from panel.otask.ru URL (/ws/{ws_slug}/...)

  • task_slug: Task UUID from URL (.../tasks/{task_slug})

Returns JSON with key task fields: id, slug, name, description, end_at, board_id, board_column_id, priority_id, project_id, performers, tags.

Docs: https://api.otask.ru/docs#zadaci-GETapi-v1-ws--ws_slug--tasks--task_slug

ParametersJSON Schema
NameRequiredDescriptionDefault
ws_slugYesWorkspace slug (UUID from panel.otask.ru URL)
task_slugYesTask slug (UUID from panel.otask.ru URL)

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint, destructiveHint, and idempotentHint, so the description doesn't need to restate safety. It adds value by listing the returned fields, providing transparency on the output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise: one sentence for purpose, one for usage guidance, parameter list, return fields, and a docs link. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description lists all returned fields, provides a docs link, and gives clear parameter extraction instructions. Everything an agent needs to use this tool correctly is included.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds practical context for both parameters (UUID extraction from URL), which helps agents correctly extract values. This goes beyond schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Fetch a task from O!task by workspace and task slug.' This is a specific verb and resource. It also distinguishes from the sibling 'otask_update_task' by advising use before updates.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly recommends using before otask_update_task to inspect current field values. While it doesn't mention when not to use, the read-only nature is clear from annotations and context. Alternative is implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

otask_update_taskUpdate O!task TaskA

Update an existing O!task task. Sends POST /api/v1/ws/{ws_slug}/tasks/{task_slug}/update.

The O!task API requires a full task payload. This tool fetches the current task, merges your changes, then submits the update. Only pass fields you want to change.

Common updates:

  • board_column_id: move task to another column/status

  • name, description, end_at, priority_id

  • performers, tags, subtasks, files

  • comment: optional note recorded with the update

Args:

  • ws_slug, task_slug: UUIDs from panel.otask.ru

  • Any task fields to change (all optional except slugs)

Returns updated task summary on success.

Docs: https://api.otask.ru/docs#zadaci-POSTapi-v1-ws--ws_slug--tasks--task_slug--update

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoTask title
tagsNoTag IDs as strings
filesNoAttached files
end_atNoDue date (ISO 8601)
commentNoComment added with the update (use empty string to skip)
ws_slugYesWorkspace slug (UUID from panel.otask.ru URL)
board_idNoBoard ID
subtasksNo
task_slugYesTask slug (UUID from panel.otask.ru URL)
performersNoPerformer IDs as strings
project_idNoProject ID
descriptionNoTask description (HTML allowed)
priority_idNoPriority ID
board_column_idNoColumn/status ID

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate non-readOnly, non-idempotent, non-destructive. Description adds that it fetches current task, merges changes, and submits full payload, providing crucial behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with bullet points for common updates and Args. No unnecessary sentences; every part adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complex tool with 14 parameters, high schema coverage, no output schema. Description covers the merging process and return value ('returns updated task summary'), making it fairly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 93%, so baseline is 3. Description adds value by explaining common parameter usage (e.g., 'board_column_id: move task') but does not significantly extend beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Update an existing O!task task' with the HTTP method and endpoint. Distinguishes from sibling 'otask_get_task' by being an update operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises 'Only pass fields you want to change' and lists common updates. While it doesn't mention when to use an alternative (e.g., create), the context is clear for update vs. read.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv1.1.0
    • First observedotask_get_task
    • First observedotask_update_task

TDQS

A4/5.0
Disambiguation5/5

The two tools have completely distinct purposes: one retrieves a task's current state, the other updates it. There is no overlap or ambiguity between them.

Naming Consistency5/5

Both tools follow the same 'otask_verb_task' pattern with snake_case, using 'get' and 'update' as clear verbs. Perfectly consistent.

Tool Count2/5

With only two tools (get and update), the server feels extremely limited for a task management API. Typical CRUD operations (create, delete, list) are missing, making the tool count too low for the apparent domain.

Completeness1/5

The tool surface is severely incomplete. Basic operations like creating, deleting, and listing tasks are absent. An agent cannot perform end-to-end task management with only get and update.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

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/grigoreo-dev/otask-mcp'

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