yandex-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yandex_cli-0.1.0/.gitignore +28 -0
- yandex_cli-0.1.0/CHANGELOG.md +17 -0
- yandex_cli-0.1.0/LICENSE +21 -0
- yandex_cli-0.1.0/PKG-INFO +240 -0
- yandex_cli-0.1.0/README.md +209 -0
- yandex_cli-0.1.0/pyproject.toml +91 -0
- yandex_cli-0.1.0/src/ycli/__init__.py +13 -0
- yandex_cli-0.1.0/src/ycli/cli.py +58 -0
- yandex_cli-0.1.0/src/ycli/log.py +27 -0
- yandex_cli-0.1.0/src/ycli/mcp.py +31 -0
- yandex_cli-0.1.0/src/ycli/yandex/__init__.py +0 -0
- yandex_cli-0.1.0/src/ycli/yandex/base.py +67 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/_base.py +17 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/_clideps.py +20 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/_deps.py +10 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/_models.py +18 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/answers/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/answers/cli.py +25 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/answers/client.py +57 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/answers/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/answers/models.py +54 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/cli.py +16 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/client.py +29 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/mcp.py +13 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/me/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/me/cli.py +19 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/me/client.py +25 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/me/mcp.py +20 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/me/models.py +18 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/questions/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/questions/cli.py +25 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/questions/client.py +24 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/questions/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/questions/models.py +46 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/surveys/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/surveys/cli.py +26 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/surveys/client.py +36 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/surveys/mcp.py +26 -0
- yandex_cli-0.1.0/src/ycli/yandex/forms/surveys/models.py +44 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/_base.py +14 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/_clideps.py +46 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/_deps.py +10 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/_models.py +48 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/changelog/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/changelog/cli.py +25 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/changelog/client.py +28 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/changelog/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/changelog/models.py +58 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/cli.py +26 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/client.py +39 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/comments/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/comments/cli.py +28 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/comments/client.py +37 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/comments/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/comments/models.py +34 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issues/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issues/cli.py +132 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issues/client.py +92 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issues/mcp.py +53 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issues/models.py +73 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issuetypes/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issuetypes/cli.py +19 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issuetypes/client.py +24 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issuetypes/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/issuetypes/models.py +27 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/links/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/links/cli.py +43 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/links/client.py +37 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/links/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/links/models.py +56 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/linktypes/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/linktypes/cli.py +19 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/linktypes/client.py +24 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/linktypes/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/linktypes/models.py +28 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/mcp.py +23 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/priorities/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/priorities/cli.py +19 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/priorities/client.py +24 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/priorities/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/priorities/models.py +27 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/transitions/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/transitions/cli.py +34 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/transitions/client.py +52 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/transitions/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/transitions/models.py +27 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/worklog/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/worklog/cli.py +21 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/worklog/client.py +24 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/worklog/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/tracker/worklog/models.py +36 -0
- yandex_cli-0.1.0/src/ycli/yandex/transport.py +116 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/__init__.py +1 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/_base.py +8 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/_clideps.py +20 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/_deps.py +10 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/attachments/__init__.py +0 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/attachments/cli.py +20 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/attachments/client.py +29 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/attachments/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/attachments/models.py +32 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/cli.py +14 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/client.py +27 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/comments/__init__.py +0 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/comments/cli.py +20 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/comments/client.py +29 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/comments/mcp.py +15 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/comments/models.py +40 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/mcp.py +11 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/pages/__init__.py +0 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/pages/cli.py +64 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/pages/client.py +74 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/pages/mcp.py +32 -0
- yandex_cli-0.1.0/src/ycli/yandex/wiki/pages/models.py +82 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
wheels/
|
|
10
|
+
|
|
11
|
+
# Virtual envs / tooling caches
|
|
12
|
+
.venv/
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
|
|
17
|
+
# Coverage
|
|
18
|
+
.coverage
|
|
19
|
+
.coverage.*
|
|
20
|
+
coverage.xml
|
|
21
|
+
htmlcov/
|
|
22
|
+
|
|
23
|
+
# AI-agent local files
|
|
24
|
+
PROMPT.md
|
|
25
|
+
.mcp.json
|
|
26
|
+
|
|
27
|
+
# Secrets
|
|
28
|
+
.env
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2026-06-27
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Initial release: Yandex 360 toolkit for **Tracker**, **Wiki**, and **Forms**.
|
|
13
|
+
- Four surfaces from one codebase: Typer **CLI** (`ycli` / `yandex-cli`), FastMCP **server**
|
|
14
|
+
(`ycli mcp`, read-only, `[mcp]` extra), importable **Python SDK** (`ycli.yandex.*`), and a
|
|
15
|
+
**Claude Code plugin** (`plugins/yandex-360/`).
|
|
16
|
+
- Published on PyPI as **`yandex-cli`** (`uv add yandex-cli`, or `yandex-cli[mcp]` for the server).
|
|
17
|
+
- Test suite at 100% coverage with `responses`-stubbed HTTP.
|
yandex_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sava Znatnov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yandex-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interact with Yandex 360 services (Wiki, Tracker, Forms, …) from a CLI, an MCP server, or a Python SDK.
|
|
5
|
+
Project-URL: Homepage, https://github.com/bim-ba/ycli
|
|
6
|
+
Project-URL: Repository, https://github.com/bim-ba/ycli
|
|
7
|
+
Project-URL: Issues, https://github.com/bim-ba/ycli/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/bim-ba/ycli/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Sava Znatnov <careless.sava@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: cli,fastmcp,forms,mcp,sdk,tracker,typer,wiki,yandex,yandex-360
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: loguru>=0.7.3
|
|
24
|
+
Requires-Dist: pydantic>=2.13.4
|
|
25
|
+
Requires-Dist: requests>=2.34.2
|
|
26
|
+
Requires-Dist: typer>=0.26.8
|
|
27
|
+
Requires-Dist: uplink>=0.10.0
|
|
28
|
+
Provides-Extra: mcp
|
|
29
|
+
Requires-Dist: fastmcp>=3.4.2; extra == 'mcp'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
<div align="center">
|
|
33
|
+
|
|
34
|
+
# ycli
|
|
35
|
+
|
|
36
|
+
**One Yandex 360 toolkit — four ways to use it.**
|
|
37
|
+
Drive **Tracker**, **Wiki**, and **Forms** from a CLI, an MCP server, a Python SDK,
|
|
38
|
+
or a Claude Code plugin. Built for AI agents first — pleasant for humans too.
|
|
39
|
+
|
|
40
|
+
[](https://github.com/bim-ba/ycli/actions/workflows/ci.yml)
|
|
41
|
+
[](https://github.com/bim-ba/ycli)
|
|
42
|
+
[](https://www.python.org/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](https://modelcontextprotocol.io/)
|
|
45
|
+
[](plugins/yandex-360/)
|
|
46
|
+
|
|
47
|
+
<img src="https://raw.githubusercontent.com/bim-ba/ycli/main/docs/assets/demo.gif" alt="ycli in action" width="760">
|
|
48
|
+
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
## Why ycli
|
|
52
|
+
|
|
53
|
+
- 🧩 **One SDK, four surfaces** — write logic once, use it as a CLI, an MCP server, a Python
|
|
54
|
+
library, or a Claude Code plugin.
|
|
55
|
+
- 🤖 **Agent-native** — the MCP server exposes read-only `tracker_*`, `wiki_*`, `forms_*`
|
|
56
|
+
tools so agents explore safely; writes stay in the CLI/SDK.
|
|
57
|
+
- 🛡️ **Trustworthy** — typed pydantic models, the real Yandex API quirks handled for you,
|
|
58
|
+
and a test suite kept at **100% coverage**.
|
|
59
|
+
- ⚡ **Zero-friction start** — `uv add yandex-cli`, two env vars, go.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv add yandex-cli # CLI + Python SDK
|
|
65
|
+
uv add 'yandex-cli[mcp]' # …plus the MCP server (`ycli mcp`)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Run it without installing, or install it as a standalone tool:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uvx yandex-cli --help # one-off, no install
|
|
72
|
+
uv tool install yandex-cli # persistent CLI
|
|
73
|
+
uv tool install 'yandex-cli[mcp]' # …with the MCP server
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`pip install yandex-cli` works too. The CLI ships as both `yandex-cli` and the short `ycli`.
|
|
77
|
+
|
|
78
|
+
## Quick start
|
|
79
|
+
|
|
80
|
+
Pick the surface that fits how you work.
|
|
81
|
+
|
|
82
|
+
<details open>
|
|
83
|
+
<summary><b>CLI</b></summary>
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
uv add yandex-cli
|
|
87
|
+
ycli --help
|
|
88
|
+
ycli tracker issues get TRACKER-1
|
|
89
|
+
ycli wiki pages get onboarding
|
|
90
|
+
```
|
|
91
|
+
</details>
|
|
92
|
+
|
|
93
|
+
<details>
|
|
94
|
+
<summary><b>MCP server</b> (read-only)</summary>
|
|
95
|
+
|
|
96
|
+
Run it over stdio (needs the `mcp` extra):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
ycli mcp
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Point an MCP client at it — no prior install needed via `uvx` (tools are namespaced
|
|
103
|
+
`tracker_*`, `wiki_*`, `forms_*`):
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"yandex": {
|
|
109
|
+
"command": "uvx",
|
|
110
|
+
"args": ["--from", "yandex-cli[mcp]", "ycli", "mcp"],
|
|
111
|
+
"env": {
|
|
112
|
+
"YANDEX_ID_OAUTH_TOKEN": "...",
|
|
113
|
+
"YANDEX_ID_ORGANIZATION_ID": "..."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
</details>
|
|
120
|
+
|
|
121
|
+
<details>
|
|
122
|
+
<summary><b>Python SDK</b></summary>
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from ycli.yandex.tracker.client import TrackerClient
|
|
126
|
+
|
|
127
|
+
tracker = TrackerClient.from_env()
|
|
128
|
+
issue = tracker.issues.get("TRACKER-1")
|
|
129
|
+
print(issue.summary)
|
|
130
|
+
```
|
|
131
|
+
</details>
|
|
132
|
+
|
|
133
|
+
<details>
|
|
134
|
+
<summary><b>Claude Code plugin</b></summary>
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
/plugin marketplace add bim-ba/ycli
|
|
138
|
+
/plugin install yandex-360@ycli
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Teaches an agent to drive Yandex 360 through `ycli` — including the real API quirks.
|
|
142
|
+
See [`plugins/yandex-360/`](plugins/yandex-360/).
|
|
143
|
+
</details>
|
|
144
|
+
|
|
145
|
+
## Skills (Claude Code plugin)
|
|
146
|
+
|
|
147
|
+
| Skill | Use for |
|
|
148
|
+
|-------|---------|
|
|
149
|
+
| `yandex-360` | Entry point — install + auth, pick a surface (CLI/MCP/SDK), route to a domain |
|
|
150
|
+
| `yandex-360-tracker` | Issues, epics, comments, transitions, links, worklog, changelog |
|
|
151
|
+
| `yandex-360-wiki` | Wiki pages, page tree, comments, attachments, YFM authoring |
|
|
152
|
+
| `yandex-360-forms` | Forms, questions/schema, responses, pagination |
|
|
153
|
+
|
|
154
|
+
The skills encode the read/write commands **and** the gnarly Yandex API quirks
|
|
155
|
+
(epic-vs-parent, transition discovery, permanent wiki slugs, `fields=` rules, Forms
|
|
156
|
+
host/header traps, answers pagination).
|
|
157
|
+
|
|
158
|
+
## What's covered
|
|
159
|
+
|
|
160
|
+
Reads ship across **SDK + CLI + MCP**; writes across **SDK + CLI** only (the MCP server is
|
|
161
|
+
read-only by design).
|
|
162
|
+
|
|
163
|
+
### Tracker
|
|
164
|
+
|
|
165
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
166
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
167
|
+
| issues | get · full · search · list · count | ✅ | ✅ | ✅ |
|
|
168
|
+
| issues | create · update | ✅ | ✅ | — |
|
|
169
|
+
| comments | list | ✅ | ✅ | ✅ |
|
|
170
|
+
| comments | add | ✅ | ✅ | — |
|
|
171
|
+
| links | list | ✅ | ✅ | ✅ |
|
|
172
|
+
| links | add | ✅ | ✅ | — |
|
|
173
|
+
| transitions | list | ✅ | ✅ | ✅ |
|
|
174
|
+
| transitions | execute | ✅ | ✅ | — |
|
|
175
|
+
| worklog · changelog · priorities · issuetypes · linktypes | list | ✅ | ✅ | ✅ |
|
|
176
|
+
|
|
177
|
+
### Wiki
|
|
178
|
+
|
|
179
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
180
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
181
|
+
| pages | get · descendants | ✅ | ✅ | ✅ |
|
|
182
|
+
| pages | meta (metadata-only) | — | — | ✅ |
|
|
183
|
+
| pages | create · update | ✅ | ✅ | — |
|
|
184
|
+
| comments | list | ✅ | ✅ | ✅ |
|
|
185
|
+
| attachments | list | ✅ | ✅ | ✅ |
|
|
186
|
+
|
|
187
|
+
### Forms (read-only today)
|
|
188
|
+
|
|
189
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
190
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
191
|
+
| me | get (whoami) | ✅ | ✅ | ✅ |
|
|
192
|
+
| surveys | list · get | ✅ | ✅ | ✅ |
|
|
193
|
+
| questions | list | ✅ | ✅ | ✅ |
|
|
194
|
+
| answers | list (drains all pages) | ✅ | ✅ | ✅ |
|
|
195
|
+
|
|
196
|
+
> **Mail and more — coming.** See [`docs/api-coverage.md`](docs/api-coverage.md) for the full
|
|
197
|
+
> gap analysis and prioritized roadmap.
|
|
198
|
+
|
|
199
|
+
## Configure
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
cp .env.example .env
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
YANDEX_ID_OAUTH_TOKEN=... # get one at https://oauth.yandex.ru/
|
|
207
|
+
YANDEX_ID_ORGANIZATION_ID=... # from the Yandex 360 admin panel
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Header casing differs per service (Tracker `X-Org-ID`, Wiki/Forms `X-Org-Id`) — ycli
|
|
211
|
+
handles it for you.
|
|
212
|
+
|
|
213
|
+
## Project layout
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
src/ycli/
|
|
217
|
+
├── cli.py # root Typer CLI → `ycli` / `yandex-cli`
|
|
218
|
+
├── mcp.py # root FastMCP server → `ycli mcp` (read-only, `[mcp]` extra)
|
|
219
|
+
├── log.py # central loguru config
|
|
220
|
+
└── yandex/
|
|
221
|
+
├── tracker/ # per-domain SDK …
|
|
222
|
+
├── wiki/ # each resource group has:
|
|
223
|
+
└── forms/ # client.py · cli.py · mcp.py · models.py
|
|
224
|
+
plugins/yandex-360/ # distributable Claude Code plugin (skills + instructions)
|
|
225
|
+
docs/references/ # vendored Yandex API reference docs
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Development
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
uv sync --all-extras # --all-extras pulls in the `mcp` extra the tests exercise
|
|
232
|
+
uv run pytest # 100% coverage gate; HTTP stubbed with `responses` (no live network)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for conventions. Contributions welcome — the
|
|
236
|
+
[coverage roadmap](docs/api-coverage.md) is a good place to find a first issue.
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
[MIT](LICENSE) © 2026 Sava Znatnov
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ycli
|
|
4
|
+
|
|
5
|
+
**One Yandex 360 toolkit — four ways to use it.**
|
|
6
|
+
Drive **Tracker**, **Wiki**, and **Forms** from a CLI, an MCP server, a Python SDK,
|
|
7
|
+
or a Claude Code plugin. Built for AI agents first — pleasant for humans too.
|
|
8
|
+
|
|
9
|
+
[](https://github.com/bim-ba/ycli/actions/workflows/ci.yml)
|
|
10
|
+
[](https://github.com/bim-ba/ycli)
|
|
11
|
+
[](https://www.python.org/)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](https://modelcontextprotocol.io/)
|
|
14
|
+
[](plugins/yandex-360/)
|
|
15
|
+
|
|
16
|
+
<img src="https://raw.githubusercontent.com/bim-ba/ycli/main/docs/assets/demo.gif" alt="ycli in action" width="760">
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
## Why ycli
|
|
21
|
+
|
|
22
|
+
- 🧩 **One SDK, four surfaces** — write logic once, use it as a CLI, an MCP server, a Python
|
|
23
|
+
library, or a Claude Code plugin.
|
|
24
|
+
- 🤖 **Agent-native** — the MCP server exposes read-only `tracker_*`, `wiki_*`, `forms_*`
|
|
25
|
+
tools so agents explore safely; writes stay in the CLI/SDK.
|
|
26
|
+
- 🛡️ **Trustworthy** — typed pydantic models, the real Yandex API quirks handled for you,
|
|
27
|
+
and a test suite kept at **100% coverage**.
|
|
28
|
+
- ⚡ **Zero-friction start** — `uv add yandex-cli`, two env vars, go.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv add yandex-cli # CLI + Python SDK
|
|
34
|
+
uv add 'yandex-cli[mcp]' # …plus the MCP server (`ycli mcp`)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Run it without installing, or install it as a standalone tool:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uvx yandex-cli --help # one-off, no install
|
|
41
|
+
uv tool install yandex-cli # persistent CLI
|
|
42
|
+
uv tool install 'yandex-cli[mcp]' # …with the MCP server
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`pip install yandex-cli` works too. The CLI ships as both `yandex-cli` and the short `ycli`.
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
Pick the surface that fits how you work.
|
|
50
|
+
|
|
51
|
+
<details open>
|
|
52
|
+
<summary><b>CLI</b></summary>
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv add yandex-cli
|
|
56
|
+
ycli --help
|
|
57
|
+
ycli tracker issues get TRACKER-1
|
|
58
|
+
ycli wiki pages get onboarding
|
|
59
|
+
```
|
|
60
|
+
</details>
|
|
61
|
+
|
|
62
|
+
<details>
|
|
63
|
+
<summary><b>MCP server</b> (read-only)</summary>
|
|
64
|
+
|
|
65
|
+
Run it over stdio (needs the `mcp` extra):
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
ycli mcp
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Point an MCP client at it — no prior install needed via `uvx` (tools are namespaced
|
|
72
|
+
`tracker_*`, `wiki_*`, `forms_*`):
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"yandex": {
|
|
78
|
+
"command": "uvx",
|
|
79
|
+
"args": ["--from", "yandex-cli[mcp]", "ycli", "mcp"],
|
|
80
|
+
"env": {
|
|
81
|
+
"YANDEX_ID_OAUTH_TOKEN": "...",
|
|
82
|
+
"YANDEX_ID_ORGANIZATION_ID": "..."
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
</details>
|
|
89
|
+
|
|
90
|
+
<details>
|
|
91
|
+
<summary><b>Python SDK</b></summary>
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from ycli.yandex.tracker.client import TrackerClient
|
|
95
|
+
|
|
96
|
+
tracker = TrackerClient.from_env()
|
|
97
|
+
issue = tracker.issues.get("TRACKER-1")
|
|
98
|
+
print(issue.summary)
|
|
99
|
+
```
|
|
100
|
+
</details>
|
|
101
|
+
|
|
102
|
+
<details>
|
|
103
|
+
<summary><b>Claude Code plugin</b></summary>
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
/plugin marketplace add bim-ba/ycli
|
|
107
|
+
/plugin install yandex-360@ycli
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Teaches an agent to drive Yandex 360 through `ycli` — including the real API quirks.
|
|
111
|
+
See [`plugins/yandex-360/`](plugins/yandex-360/).
|
|
112
|
+
</details>
|
|
113
|
+
|
|
114
|
+
## Skills (Claude Code plugin)
|
|
115
|
+
|
|
116
|
+
| Skill | Use for |
|
|
117
|
+
|-------|---------|
|
|
118
|
+
| `yandex-360` | Entry point — install + auth, pick a surface (CLI/MCP/SDK), route to a domain |
|
|
119
|
+
| `yandex-360-tracker` | Issues, epics, comments, transitions, links, worklog, changelog |
|
|
120
|
+
| `yandex-360-wiki` | Wiki pages, page tree, comments, attachments, YFM authoring |
|
|
121
|
+
| `yandex-360-forms` | Forms, questions/schema, responses, pagination |
|
|
122
|
+
|
|
123
|
+
The skills encode the read/write commands **and** the gnarly Yandex API quirks
|
|
124
|
+
(epic-vs-parent, transition discovery, permanent wiki slugs, `fields=` rules, Forms
|
|
125
|
+
host/header traps, answers pagination).
|
|
126
|
+
|
|
127
|
+
## What's covered
|
|
128
|
+
|
|
129
|
+
Reads ship across **SDK + CLI + MCP**; writes across **SDK + CLI** only (the MCP server is
|
|
130
|
+
read-only by design).
|
|
131
|
+
|
|
132
|
+
### Tracker
|
|
133
|
+
|
|
134
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
135
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
136
|
+
| issues | get · full · search · list · count | ✅ | ✅ | ✅ |
|
|
137
|
+
| issues | create · update | ✅ | ✅ | — |
|
|
138
|
+
| comments | list | ✅ | ✅ | ✅ |
|
|
139
|
+
| comments | add | ✅ | ✅ | — |
|
|
140
|
+
| links | list | ✅ | ✅ | ✅ |
|
|
141
|
+
| links | add | ✅ | ✅ | — |
|
|
142
|
+
| transitions | list | ✅ | ✅ | ✅ |
|
|
143
|
+
| transitions | execute | ✅ | ✅ | — |
|
|
144
|
+
| worklog · changelog · priorities · issuetypes · linktypes | list | ✅ | ✅ | ✅ |
|
|
145
|
+
|
|
146
|
+
### Wiki
|
|
147
|
+
|
|
148
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
149
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
150
|
+
| pages | get · descendants | ✅ | ✅ | ✅ |
|
|
151
|
+
| pages | meta (metadata-only) | — | — | ✅ |
|
|
152
|
+
| pages | create · update | ✅ | ✅ | — |
|
|
153
|
+
| comments | list | ✅ | ✅ | ✅ |
|
|
154
|
+
| attachments | list | ✅ | ✅ | ✅ |
|
|
155
|
+
|
|
156
|
+
### Forms (read-only today)
|
|
157
|
+
|
|
158
|
+
| Resource | Operations | SDK | CLI | MCP |
|
|
159
|
+
|----------|-----------|:---:|:---:|:---:|
|
|
160
|
+
| me | get (whoami) | ✅ | ✅ | ✅ |
|
|
161
|
+
| surveys | list · get | ✅ | ✅ | ✅ |
|
|
162
|
+
| questions | list | ✅ | ✅ | ✅ |
|
|
163
|
+
| answers | list (drains all pages) | ✅ | ✅ | ✅ |
|
|
164
|
+
|
|
165
|
+
> **Mail and more — coming.** See [`docs/api-coverage.md`](docs/api-coverage.md) for the full
|
|
166
|
+
> gap analysis and prioritized roadmap.
|
|
167
|
+
|
|
168
|
+
## Configure
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
cp .env.example .env
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
YANDEX_ID_OAUTH_TOKEN=... # get one at https://oauth.yandex.ru/
|
|
176
|
+
YANDEX_ID_ORGANIZATION_ID=... # from the Yandex 360 admin panel
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Header casing differs per service (Tracker `X-Org-ID`, Wiki/Forms `X-Org-Id`) — ycli
|
|
180
|
+
handles it for you.
|
|
181
|
+
|
|
182
|
+
## Project layout
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
src/ycli/
|
|
186
|
+
├── cli.py # root Typer CLI → `ycli` / `yandex-cli`
|
|
187
|
+
├── mcp.py # root FastMCP server → `ycli mcp` (read-only, `[mcp]` extra)
|
|
188
|
+
├── log.py # central loguru config
|
|
189
|
+
└── yandex/
|
|
190
|
+
├── tracker/ # per-domain SDK …
|
|
191
|
+
├── wiki/ # each resource group has:
|
|
192
|
+
└── forms/ # client.py · cli.py · mcp.py · models.py
|
|
193
|
+
plugins/yandex-360/ # distributable Claude Code plugin (skills + instructions)
|
|
194
|
+
docs/references/ # vendored Yandex API reference docs
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
uv sync --all-extras # --all-extras pulls in the `mcp` extra the tests exercise
|
|
201
|
+
uv run pytest # 100% coverage gate; HTTP stubbed with `responses` (no live network)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for conventions. Contributions welcome — the
|
|
205
|
+
[coverage roadmap](docs/api-coverage.md) is a good place to find a first issue.
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
[MIT](LICENSE) © 2026 Sava Znatnov
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "yandex-cli"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Interact with Yandex 360 services (Wiki, Tracker, Forms, …) from a CLI, an MCP server, or a Python SDK."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
authors = [{ name = "Sava Znatnov", email = "careless.sava@gmail.com" }]
|
|
10
|
+
keywords = ["yandex", "yandex-360", "tracker", "wiki", "forms", "cli", "mcp", "sdk", "fastmcp", "typer"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
20
|
+
"Topic :: Utilities",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"loguru>=0.7.3",
|
|
24
|
+
"pydantic>=2.13.4",
|
|
25
|
+
"requests>=2.34.2",
|
|
26
|
+
"typer>=0.26.8",
|
|
27
|
+
"uplink>=0.10.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# The MCP server (`ycli mcp`) is optional — install with `yandex-cli[mcp]`.
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
mcp = ["fastmcp>=3.4.2"]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
yandex-cli = "ycli.cli:main"
|
|
36
|
+
ycli = "ycli.cli:main"
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://github.com/bim-ba/ycli"
|
|
40
|
+
Repository = "https://github.com/bim-ba/ycli"
|
|
41
|
+
Issues = "https://github.com/bim-ba/ycli/issues"
|
|
42
|
+
Changelog = "https://github.com/bim-ba/ycli/blob/main/CHANGELOG.md"
|
|
43
|
+
|
|
44
|
+
[build-system]
|
|
45
|
+
requires = ["hatchling"]
|
|
46
|
+
build-backend = "hatchling.build"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/ycli"]
|
|
50
|
+
|
|
51
|
+
# Keep the sdist lean: ship only the package + changelog (pyproject, README, and
|
|
52
|
+
# LICENSE are always included from metadata) — not the repo's docs, tests, Claude
|
|
53
|
+
# plugin, agent config, or vendored API references.
|
|
54
|
+
[tool.hatch.build.targets.sdist]
|
|
55
|
+
only-include = ["src/ycli", "CHANGELOG.md"]
|
|
56
|
+
|
|
57
|
+
# TestPyPI as an explicit publish target (used by `uv publish --index testpypi`).
|
|
58
|
+
# `explicit = true` keeps it out of normal dependency resolution.
|
|
59
|
+
[[tool.uv.index]]
|
|
60
|
+
name = "testpypi"
|
|
61
|
+
url = "https://test.pypi.org/simple/"
|
|
62
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
63
|
+
explicit = true
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
asyncio_mode = "auto"
|
|
68
|
+
addopts = "--cov=ycli --cov-report=term-missing --cov-fail-under=100"
|
|
69
|
+
markers = [
|
|
70
|
+
"integration: tests that exercise CLI/MCP wiring end-to-end (no live network)",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[tool.coverage.run]
|
|
74
|
+
source = ["ycli"]
|
|
75
|
+
|
|
76
|
+
[tool.coverage.report]
|
|
77
|
+
show_missing = true
|
|
78
|
+
exclude_also = [
|
|
79
|
+
"if __name__ == .__main__.:",
|
|
80
|
+
"if TYPE_CHECKING:",
|
|
81
|
+
"raise NotImplementedError",
|
|
82
|
+
"\\.\\.\\.",
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[dependency-groups]
|
|
86
|
+
dev = [
|
|
87
|
+
"pytest>=9.1.1",
|
|
88
|
+
"pytest-asyncio>=1.4.0",
|
|
89
|
+
"pytest-cov>=7.1.0",
|
|
90
|
+
"responses>=0.26.1",
|
|
91
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""ycli — interact with Yandex 360 services (Wiki, Tracker, Forms, …).
|
|
2
|
+
|
|
3
|
+
One codebase, many surfaces: a Typer CLI (``ycli``), a FastMCP server (``ycli mcp``),
|
|
4
|
+
and an importable Python SDK under ``ycli.yandex``. Distributed on PyPI as ``yandex-cli``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from importlib.metadata import version
|
|
10
|
+
|
|
11
|
+
# Single source of truth: the version declared in pyproject.toml (read from installed
|
|
12
|
+
# metadata under the distribution name `yandex-cli`).
|
|
13
|
+
__version__ = version("yandex-cli")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""``ycli`` root CLI — mounts each domain's sub-app. Domain logic lives in <domain>/cli.py.
|
|
2
|
+
|
|
3
|
+
Run a subcommand directly: ``uv run ycli wiki pages get <slug>`` (or ``python -m ycli.cli``).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
from ycli.log import configure
|
|
11
|
+
from ycli.yandex.forms.cli import app as forms_app
|
|
12
|
+
from ycli.yandex.tracker.cli import app as tracker_app
|
|
13
|
+
from ycli.yandex.wiki.cli import app as wiki_app
|
|
14
|
+
|
|
15
|
+
app = typer.Typer(
|
|
16
|
+
name="ycli",
|
|
17
|
+
help="ycli — Yandex 360 API SDK CLI.",
|
|
18
|
+
no_args_is_help=True,
|
|
19
|
+
pretty_exceptions_show_locals=False,
|
|
20
|
+
add_completion=False,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@app.callback()
|
|
25
|
+
def _main() -> None:
|
|
26
|
+
"""Configure logging once before any subcommand runs."""
|
|
27
|
+
configure()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
app.add_typer(wiki_app)
|
|
31
|
+
app.add_typer(tracker_app)
|
|
32
|
+
app.add_typer(forms_app)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.command(name="mcp")
|
|
36
|
+
def mcp() -> None:
|
|
37
|
+
"""Run the read-only MCP server over stdio (requires the ``mcp`` extra).
|
|
38
|
+
|
|
39
|
+
Tools are namespaced ``wiki_*``, ``tracker_*``, ``forms_*``. Point an MCP client
|
|
40
|
+
at ``ycli mcp``.
|
|
41
|
+
"""
|
|
42
|
+
try:
|
|
43
|
+
from ycli.mcp import main as run_server
|
|
44
|
+
except ModuleNotFoundError as exc: # pragma: no cover - only without the 'mcp' extra
|
|
45
|
+
raise typer.BadParameter(
|
|
46
|
+
"The MCP server requires the 'mcp' extra. Install it with: "
|
|
47
|
+
"uv add 'yandex-cli[mcp]' (or: uv tool install 'yandex-cli[mcp]')."
|
|
48
|
+
) from exc
|
|
49
|
+
run_server()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main() -> None: # pragma: no cover
|
|
53
|
+
"""Console-script entry point (``ycli`` / ``yandex-cli``)."""
|
|
54
|
+
app()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__": # pragma: no cover
|
|
58
|
+
main()
|