Metadata-Version: 2.4
Name: yandex-cli
Version: 0.10.0
Summary: Interact with Yandex 360 services (Wiki, Tracker, Forms, …) from a CLI, an MCP server, or a Python SDK.
Project-URL: Homepage, https://github.com/bim-ba/ycli
Project-URL: Repository, https://github.com/bim-ba/ycli
Project-URL: Documentation, https://github.com/bim-ba/ycli/tree/main/docs
Project-URL: Issues, https://github.com/bim-ba/ycli/issues
Project-URL: Changelog, https://github.com/bim-ba/ycli/blob/main/CHANGELOG.md
Author-email: Sava Znatnov <careless.sava@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,fastmcp,forms,mcp,sdk,tracker,typer,wiki,yandex,yandex-360
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic-settings>=2.14.2
Requires-Dist: pydantic>=2.13.4
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: requests>=2.34.2
Requires-Dist: rich>=15.0.0
Requires-Dist: typer>=0.26.8
Requires-Dist: uplink>=0.10.0
Provides-Extra: mcp
Requires-Dist: fastmcp>=3.4.2; extra == 'mcp'
Description-Content-Type: text/markdown

<div align="center">

# ycli

**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.

[![CI](https://img.shields.io/github/actions/workflow/status/bim-ba/ycli/ci.yml?branch=main&logo=githubactions&logoColor=white&label=ci)](https://github.com/bim-ba/ycli/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=pytest&logoColor=white)](https://github.com/bim-ba/ycli)
[![PyPI](https://img.shields.io/pypi/v/yandex-cli?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/yandex-cli/)
[![Python](https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white)](https://www.python.org/)
[![License](https://img.shields.io/badge/license-MIT-lightgrey?logo=opensourceinitiative&logoColor=white)](LICENSE)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/bim-ba/ycli)

<img src="https://raw.githubusercontent.com/bim-ba/ycli/main/docs/assets/demo.gif" alt="ycli in action" width="760">

</div>

## Why ycli

- 🧩 **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 read-only `tracker_*`, `wiki_*`, `forms_*`
  tools so agents explore safely; writes stay in the CLI/SDK.
- 🛡️ **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`, two env vars, go.

## Install

```bash
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:

```bash
uvx yandex-cli --help                 # one-off, no install
uv tool install yandex-cli            # persistent CLI
uv tool install 'yandex-cli[mcp]'     # …with the MCP server
```

`pip install yandex-cli` works too. The CLI ships as both `yandex-cli` and the short `ycli`.

## Quick start

Pick the surface that fits how you work.

<details open>
<summary><b>CLI</b></summary>

```bash
uv add yandex-cli
ycli --help
ycli tracker issues get TRACKER-1
ycli wiki pages get onboarding
```

**Output formats** — a global `--format` / `-o` picks how results print:

```bash
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 pretty
```
</details>

<details>
<summary><b>MCP server</b> (read-only)</summary>

Run it over stdio (needs the `mcp` extra):

```bash
ycli mcp start
```

List the exposed tool names without running the server:

```bash
ycli mcp methods
```

Point an MCP client at it — no prior install needed via `uvx` (tools are namespaced
`tracker_*`, `wiki_*`, `forms_*`):

```json
{
  "mcpServers": {
    "yandex": {
      "command": "uvx",
      "args": ["--from", "yandex-cli[mcp]", "ycli", "mcp", "start"],
      "env": {
        "YANDEX_ID_OAUTH_TOKEN": "...",
        "YANDEX_ID_ORGANIZATION_ID": "..."
      }
    }
  }
}
```
</details>

<details>
<summary><b>Python SDK</b></summary>

```python
from ycli.yandex.tracker.client import TrackerClient

tracker = TrackerClient(oauth_token="…", organization_id="…")
issue = tracker.issues.get("TRACKER-1")
print(issue.summary)
```
</details>

<details>
<summary><b>Claude Code plugin</b></summary>

```
/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/`](plugins/yandex-360/).
</details>

## Skills (Claude Code plugin)

| 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, pagination |

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).

<!-- COVERAGE:START (generated by scripts/gen_coverage.py — do not edit by hand) -->
## Coverage

`ycli` wraps the **near-complete public REST API** of Tracker, Wiki, and Forms — 230 operations across 50 resources, every one reachable from the **Python SDK** and the **CLI**. Reads are additionally exposed as 80 read-only **MCP** tools for agents.

> **Legend** — reads ship on **SDK + CLI + MCP**; writes and binary downloads on **SDK + CLI** (the MCP server is read-only by design). In each table **SDK** and **CLI** mean the operation is wrapped on that surface; **MCP** is ✅ when the resource exposes at least one read-only tool. These tables are generated from the code by [`scripts/gen_coverage.py`](scripts/gen_coverage.py) — do not edit by hand.

### Tracker

**32 resources · 153 operations · 57 MCP tools**

#### Issues & work items

| 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 | ✅ | ✅ | ✅ |

#### Agile boards

| 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 | ✅ | ✅ | ✅ |

#### Dictionaries

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| priorities | list · create · edit | ✅ | ✅ | ✅ |
| statuses | list · create · edit | ✅ | ✅ | ✅ |
| resolutions | list · create · edit | ✅ | ✅ | ✅ |
| issuetypes | list · create · edit | ✅ | ✅ | ✅ |
| linktypes | list | ✅ | ✅ | ✅ |

#### Fields, queues & structure

| 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 | ✅ | ✅ | ✅ |

#### Automation & bulk

| 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 | ✅ | ✅ | — |

#### Entities, users & search

| 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 | ✅ | ✅ | ✅ |

### Wiki

**9 resources · 43 operations · 13 MCP tools**

#### Pages

| 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 | ✅ | ✅ | — |

#### Collaboration

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| comments | list · thread · create · delete | ✅ | ✅ | ✅ |
| attachments | list · download · download_by_url · delete · attach · upload | ✅ | ✅ | ✅ |

#### Grids (dynamic tables)

| 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 | ✅ | ✅ | ✅ |

#### Async & uploads

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| operations | clone_get · gridclone_get | ✅ | ✅ | ✅ |
| uploadsessions | create · get · upload_part · finish · abort · abort_all | ✅ | ✅ | ✅ |

#### Identity

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| me | get | ✅ | ✅ | ✅ |

### Forms

**9 resources · 34 operations · 10 MCP tools**

#### Surveys & questions

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| surveys | list · get · create · modify · delete · publish · unpublish | ✅ | ✅ | ✅ |
| questions | get · list · create · modify · delete · move | ✅ | ✅ | ✅ |

#### Responses & export

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| answers | list · list_all · export · export_results · download_export | ✅ | ✅ | ✅ |
| operations | get | ✅ | ✅ | ✅ |

#### Distribution

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| keysets | list · get · create · modify · delete · download | ✅ | ✅ | ✅ |
| filling | get · submit · suggest | ✅ | ✅ | ✅ |

#### Media

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| files | upload · verify · download · delete | ✅ | ✅ | — |
| images | upload | ✅ | ✅ | — |

#### Identity

| Resource | Operations | SDK | CLI | MCP |
|----------|------------|:---:|:---:|:---:|
| me | get | ✅ | ✅ | ✅ |

See [`docs/api-coverage.md`](docs/api-coverage.md) for the intentional exclusions (UI-only endpoints with no public REST API) and per-method notes.
<!-- COVERAGE:END -->

## Configure

`ycli` reads two values from the environment (or a `.env` file — `cp .env.example .env`):

```bash
YANDEX_ID_OAUTH_TOKEN=...        # a Yandex OAuth token with Tracker/Wiki/Forms access
YANDEX_ID_ORGANIZATION_ID=...    # your Yandex 360 organization id
```

Header casing differs per service (Tracker `X-Org-ID`, Wiki/Forms `X-Org-Id`) — ycli
handles it for you.

### Get your credentials

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](https://oauth.yandex.ru/client/new) and
grant it the **Tracker**, **Wiki**, and **Forms** permissions (read **and** write for the
full CLI; the read scopes alone are enough for the read-only MCP server). Copy the
**ClientID** — and the **Client secret** if you want the headless flow:

```bash
export YANDEX_OAUTH_CLIENT_ID=...        # from your app
export YANDEX_OAUTH_CLIENT_SECRET=...    # optional — enables the headless device flow
```

**2. Log in.** `ycli auth login` gets a token, detects your organization, and writes both
into `.env`:

```bash
ycli auth login
```

- **client id + secret** → the **device flow**: ycli prints a code and a
  `https://ya.ru/device` link; 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.

<details>
<summary><b>Prefer to do it by hand?</b></summary>

**Headless (device flow):**

```bash
# 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](https://tracker.yandex.ru/admin/orgs) →
your organization → copy the identifier.
</details>

## Project layout

```text
src/ycli/
├── cli.py              # root Typer CLI  → `ycli` / `yandex-cli`
├── mcp.py              # root FastMCP server → `ycli mcp start` (read-only, `[mcp]` extra)
├── 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)
docs/references/        # vendored Yandex API reference docs
```

## Development

```bash
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](CONTRIBUTING.md) for conventions. Contributions welcome — the
[coverage roadmap](docs/api-coverage.md) is a good place to find a first issue.

## License

[MIT](LICENSE) © 2026 Sava Znatnov
