One Yandex 360 toolkit — four ways to use it. Drive Tracker, Wiki, and Forms from a CLI, an MCP server, a Python SDK, or a Claude Code plugin. Built for AI agents first — pleasant for humans too.
- 🧩 One SDK, four surfaces — write logic once, use it as a CLI, an MCP server, a Python library, or a Claude Code plugin.
- 🤖 Agent-native — the MCP server exposes 222 MCP tools (221 domain-scoped read
and write
tracker_*,wiki_*,forms_*tools, one per SDK/CLI operation, plus a cross-cuttingstatustool) with honest annotations (reads are marked read-only; writes declare whether they are destructive/idempotent);ycli mcp start --read-onlyserves a reads-only view for cautious deployments. - 🛡️ Trustworthy — typed pydantic models, the real Yandex API quirks handled for you, and a test suite kept at 100% coverage.
- ⚡ Zero-friction start —
uv add yandex-cli,ycli auth login, go.
uv add yandex-cli # CLI + Python SDK
uv add 'yandex-cli[mcp]' # …plus the MCP server (`ycli mcp start`)Run it without installing, or install it as a standalone tool:
uvx yandex-cli --help # one-off, no install
uv tool install yandex-cli # persistent CLI
uv tool install 'yandex-cli[mcp]' # …with the MCP serverpip install yandex-cli works too. The CLI ships as both yandex-cli and the short ycli.
Pick the surface that fits how you work.
CLI
uv add yandex-cli
ycli --help
ycli tracker issues get TRACKER-1
ycli wiki pages get onboardingOutput formats — a global --format / -o picks how results print:
ycli tracker issues get TRACKER-1 # auto: a pretty table on a TTY…
ycli tracker issues get TRACKER-1 | jq . # …and raw JSON when piped (agent/script-safe)
ycli -o yaml wiki pages get onboarding # or: -o json | -o yaml | -o prettyMCP server (read/write)
Run it over stdio (needs the mcp extra):
ycli mcp start # full read/write tool set (honest annotations)
ycli mcp start --read-only # reads-only view for cautious deploymentsList the exposed tool names without running the server:
ycli mcp methodsPoint an MCP client at it — no prior install needed via uvx (tools are namespaced
tracker_*, wiki_*, forms_*):
{
"mcpServers": {
"yandex": {
"command": "uvx",
"args": ["--from", "yandex-cli[mcp]", "ycli", "mcp", "start"],
"env": {
"YANDEX_ID_OAUTH_TOKEN": "...",
"YANDEX_ID_ORGANIZATION_ID": "..."
}
}
}
}Python SDK
from ycli.yandex.tracker.client import TrackerClient
tracker = TrackerClient(oauth_token="…", organization_id="…")
issue = tracker.issues.get("TRACKER-1")
print(issue.summary)Claude Code plugin
/plugin marketplace add bim-ba/ycli
/plugin install yandex-360@ycli
Teaches an agent to drive Yandex 360 through ycli — including the real API quirks.
See plugins/yandex-360/.
| Skill | Use for |
|---|---|
yandex-360 |
Entry point — install + auth, pick a surface (CLI/MCP/SDK), route to a domain |
yandex-360-tracker |
Issues, epics, comments, transitions, links, worklog, changelog |
yandex-360-wiki |
Wiki pages, page tree, comments, attachments, YFM authoring |
yandex-360-forms |
Forms, questions/schema, responses, publishing |
The skills encode the read/write commands and the gnarly Yandex API quirks
(epic-vs-parent, transition discovery, permanent wiki slugs, fields= rules, Forms
host/header traps, answers pagination).
ycli reads two values from the environment (or a .env file — cp .env.example .env):
YANDEX_ID_OAUTH_TOKEN=... # a Yandex OAuth token with Tracker/Wiki/Forms access
YANDEX_ID_ORGANIZATION_ID=... # your Yandex 360 organization idycli sends the org id as X-Org-Id for every service (HTTP header names are case-insensitive
per RFC 9110, so one casing serves all).
Yandex issues OAuth tokens only through a registered application, so it's a one-time app registration plus one command.
1. Register an OAuth app at oauth.yandex.ru and
grant it the Tracker, Wiki, and Forms permissions (read and write — the
CLI and the MCP server both write; the read scopes alone suffice only if you run the MCP
server with ycli mcp start --read-only). Put the ClientID — and the Client secret
if you want the headless flow — in your .env (ycli reads it from there):
YANDEX_OAUTH_CLIENT_ID=... # from your app
YANDEX_OAUTH_CLIENT_SECRET=... # optional — enables the headless device flow2. Log in. ycli auth login gets a token, detects your organization, and writes both
into .env:
ycli auth login- client id + secret → the device flow: ycli prints a code and a
https://ya.ru/devicelink; approve there and it captures the token — no redirect, works over SSH. - only the client id (or
--implicit) → the browser flow: ycli opens the Yandex authorize page; approve, then copy the token it displays and paste it back.
Prefer to do it by hand?
Headless (device flow):
# 1. start the flow — returns a user_code + verification_url
curl -s -X POST https://oauth.yandex.ru/device/code -d "client_id=$YANDEX_OAUTH_CLIENT_ID"
# 2. open https://ya.ru/device, enter the user_code, approve
# 3. exchange the device_code for the token
curl -s -X POST https://oauth.yandex.ru/token \
-d grant_type=device_code -d "code=<device_code>" \
-d "client_id=$YANDEX_OAUTH_CLIENT_ID" -d "client_secret=$YANDEX_OAUTH_CLIENT_SECRET"Browser (implicit): open
https://oauth.yandex.ru/authorize?response_type=token&client_id=<ClientID> in a logged-in
browser, approve, and copy the token from the page. (Plain curl can't — implicit needs an
interactive browser session.)
Organization id: tracker.yandex.ru/admin/orgs → your organization → copy the identifier.
ycli wraps 231 operations across 50 resources of the Tracker, Wiki, and Forms REST API — every one reachable from the Python SDK and the CLI, plus 222 MCP tools (221 domain-scoped + 1 cross-cutting: status) for agents.
Legend — operations ship on SDK + CLI, and the MCP server mirrors them with honest annotations: reads carry
readOnlyHint, writes carry explicit destructive/idempotent hints, andycli mcp start --read-onlyserves the reads-only view. In each table SDK and CLI mean the operation is wrapped on that surface; MCP is ✅ when the resource exposes at least one MCP tool. Resource and operation names link to the official Yandex API reference (yandex.ru/support/…/api-ref). These tables are generated from the code byscripts/gen_coverage.py— do not edit by hand.
32 resources · 153 operations · 151 MCP tools
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| issues | get · search · count · create · update · move · suggest · scroll_clear | ✅ | ✅ | ✅ |
| comments | list · add · edit · delete · react | ✅ | ✅ | ✅ |
| links | list · add · delete | ✅ | ✅ | ✅ |
| transitions | list · execute | ✅ | ✅ | ✅ |
| worklog | list · search · global_list · create · edit · delete | ✅ | ✅ | ✅ |
| changelog | list | ✅ | ✅ | ✅ |
| checklists | get · create · edit · delete · clear | ✅ | ✅ | ✅ |
| attachments | list · download · download_thumbnail | ✅ | ✅ | ✅ |
| remotelinks | list · create · delete | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| boards | list · get · create · edit · delete | ✅ | ✅ | ✅ |
| sprints | list · get · create · edit · delete · start · archive | ✅ | ✅ | ✅ |
| columns | list · get · create · edit · delete | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| priorities | list · create · edit | ✅ | ✅ | ✅ |
| statuses | list · create · edit | ✅ | ✅ | ✅ |
| resolutions | list · create · edit | ✅ | ✅ | ✅ |
| issuetypes | list · create · edit | ✅ | ✅ | ✅ |
| linktypes | list | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| fields | list · get · create · edit · category_create · category_edit | ✅ | ✅ | ✅ |
| localfields | list · get · create · edit | ✅ | ✅ | ✅ |
| components | list · create · edit | ✅ | ✅ | ✅ |
| queues | list · get · tags · versions · fields · create · delete · restore · set_permissions · tag_remove · version_create | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| macros | list · get · create · edit · delete | ✅ | ✅ | ✅ |
| triggers | get · create · edit · webhook_log | ✅ | ✅ | ✅ |
| autoactions | get · create · logs · log_detail | ✅ | ✅ | ✅ |
| dashboards | create · add_cycle_time_widget | ✅ | ✅ | ✅ |
| bulk | update · move · transition · get · issues | ✅ | ✅ | ✅ |
| import | task · comment · link · worklog · file | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| entities | create · get · edit · delete · search · history · permissions · set_permissions · bulk_update · bulk_status · create_report · comments_list · comments_relative · comments_get · comments_create · comments_edit · comments_delete · checklists_create · checklists_edit · checklists_edit_item · checklists_delete · checklists_delete_item · checklists_move · links_list · links_create · links_delete · attachments_list · attachments_get · attachment_download · attachments_attach · attachments_delete | ✅ | ✅ | ✅ |
| users | get · list | ✅ | ✅ | ✅ |
| applications | list | ✅ | ✅ | ✅ |
| filters | get · create · edit | ✅ | ✅ | ✅ |
| me | get | ✅ | ✅ | ✅ |
9 resources · 43 operations · 42 MCP tools
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| pages | get_by_id · get · descendants · descendants_by_id · grids · create · update · delete · append_content · clone | ✅ | ✅ | ✅ |
| resources | list | ✅ | ✅ | ✅ |
| recovery | restore | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| comments | list · thread · create · delete | ✅ | ✅ | ✅ |
| attachments | list · download · download_by_url · delete · attach · upload | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| grids | get · create · update · delete · add_rows · remove_rows · move_rows · add_columns · remove_columns · move_columns · update_cells · clone | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| operations | clone_get · gridclone_get | ✅ | ✅ | ✅ |
| uploadsessions | create · get · upload_part · finish · abort · abort_all | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| me | get | ✅ | ✅ | ✅ |
9 resources · 35 operations · 28 MCP tools
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| surveys | list · get · create · modify · delete · publish · unpublish | ✅ | ✅ | ✅ |
| questions | get · list · create · modify · delete · move | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| answers | get · list · list_all · export · export_results · download_export | ✅ | ✅ | ✅ |
| operations | get | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| keysets | list · get · create · modify · delete · download | ✅ | ✅ | ✅ |
| filling | get · submit · suggest | ✅ | ✅ | ✅ |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| files | upload · verify · download · delete | ✅ | ✅ | ✅ |
| images | upload | ✅ | ✅ | — |
| Resource | Operations | SDK | CLI | MCP |
|---|---|---|---|---|
| me | get | ✅ | ✅ | ✅ |
Every resource and operation above deep-links to the Yandex API reference: 227 of 231 operations resolve to their own endpoint page and 3 to their resource's page. No public API reference exists yet for tracker.linktypes, tracker.linktypes.list, shown as plain text. See CONTRIBUTING.md for the intentional exclusions (UI-only endpoints with no public REST API) and per-method notes.
src/ycli/
├── cli/ # root Typer CLI → `ycli` / `yandex-cli` (app · context · output)
├── mcp/ # root FastMCP server → `ycli mcp start` (read/write, `[mcp]` extra)
├── settings.py # AppConfig + Credentials (pydantic-settings)
├── log.py # central loguru config
└── yandex/
├── tracker/ # per-domain SDK …
├── wiki/ # each resource group has:
└── forms/ # client.py · cli.py · mcp.py · models.py
plugins/yandex-360/ # distributable Claude Code plugin (skills + instructions)
references/ # vendored Yandex API reference docs (local-only; see references/README.md)
uv sync --all-extras # --all-extras pulls in the `mcp` extra the tests exercise
uv run pytest # 100% coverage gate; HTTP stubbed with `responses` (no live network)See CONTRIBUTING.md for conventions and how to add an endpoint. Contributions welcome.
MIT © 2026 Sava Znatnov