@mmtr-tech/yandex-tracker-mcp 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
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.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @mmtr-tech/yandex-tracker-mcp
2
+
3
+ MCP server for the [Yandex Tracker](https://yandex.ru/support/tracker/en/api-ref/access) API (OAuth + Yandex 360 organization).
4
+
5
+ [Русская версия](README.ru.md)
6
+
7
+ ## Install / run in Cursor
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "yandex-tracker": {
13
+ "command": "npx",
14
+ "args": ["-y", "@mmtr-tech/yandex-tracker-mcp"],
15
+ "env": {
16
+ "API_TOKEN": "your-oauth-token",
17
+ "X_ORG_ID": "your-org-id"
18
+ }
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ Optional: `"API_BASE_URL": "https://api.tracker.yandex.net/v3"` (this is the default).
25
+
26
+ After changing the config, **Restart Cursor** (toggling MCP is often not enough).
27
+
28
+ ### Environment
29
+
30
+ | Variable | Required | Description |
31
+ |----------|----------|-------------|
32
+ | `API_TOKEN` | yes | OAuth token (`Authorization: OAuth …`) |
33
+ | `X_ORG_ID` | yes | Yandex 360 organization id (`X-Org-ID`) |
34
+ | `API_BASE_URL` | no | Defaults to `https://api.tracker.yandex.net/v3` |
35
+
36
+ ## Getting an OAuth token and X_ORG_ID
37
+
38
+ You need a Tracker user **OAuth token** and a Yandex 360 **organization id**.
39
+
40
+ ### 1. Register an app in Yandex OAuth
41
+
42
+ App types: [Register an application](https://yandex.ru/dev/id/doc/en/register-client).
43
+
44
+ For this MCP, choose **“For API access or debugging”** (not “for user authorization”). The type cannot be changed later.
45
+
46
+ 1. Open [oauth.yandex.ru](https://oauth.yandex.ru) → **Create**.
47
+ 2. Select **For API access or debugging**.
48
+ 3. Set a name and contact email.
49
+ 4. Add scopes:
50
+ - `tracker:read` — read only;
51
+ - `tracker:write` — create/update/comments/transitions (required for write tools).
52
+ 5. Create the app and copy the **ClientID**.
53
+
54
+ Tracker guide: [API access → OAuth](https://yandex.ru/support/tracker/en/api-ref/access).
55
+
56
+ ### 2. Issue a token
57
+
58
+ ```text
59
+ https://oauth.yandex.ru/authorize?response_type=token&client_id=<ClientID>
60
+ ```
61
+
62
+ Open the link while signed in as the Tracker user that should call the API. The string shown is your `API_TOKEN`.
63
+
64
+ The token acts with that user’s permissions. Access can be revoked in Yandex ID settings.
65
+
66
+ ### 3. Find X_ORG_ID
67
+
68
+ In Tracker: **Administration → Organizations** → copy the organization id (`X-Org-ID`).
69
+
70
+ ### 4. Verify access
71
+
72
+ ```bash
73
+ curl -X GET 'https://api.tracker.yandex.net/v3/myself' \
74
+ -H "Authorization: OAuth $API_TOKEN" \
75
+ -H "X-Org-ID: $X_ORG_ID"
76
+ ```
77
+
78
+ Expect `200` and JSON with `login` / `display`. `401` means a bad token, scopes, or org id.
79
+
80
+ ## Tools
81
+
82
+ ### Read
83
+
84
+ | Tool | API |
85
+ |------|-----|
86
+ | `get_myself` | `GET /myself` |
87
+ | `get_user` | `GET /users/{id}` |
88
+ | `list_users` | `GET /users` |
89
+ | `list_queues` | `GET /queues/` |
90
+ | `get_queue` | `GET /queues/{id}` |
91
+ | `list_queue_versions` | `GET /queues/{id}/versions` |
92
+ | `list_queue_components` | `GET /queues/{id}?expand=components` |
93
+ | `get_issue` | `GET /issues/{id}` |
94
+ | `search_issues` | `POST /issues/_search` |
95
+ | `count_issues` | `POST /issues/_count` |
96
+ | `get_issue_comments` | `GET /issues/{id}/comments` |
97
+ | `get_issue_links` | `GET /issues/{id}/links` |
98
+ | `get_issue_transitions` | `GET /issues/{id}/transitions` |
99
+ | `get_issue_changelog` | `GET /issues/{id}/changelog` |
100
+ | `get_issue_attachments` | attachment metadata only |
101
+ | `get_issue_worklog` | `GET /issues/{id}/worklog` |
102
+ | `get_issue_checklist` | `GET /issues/{id}/checklistItems` |
103
+ | `list_boards` | `GET /boards/` |
104
+ | `list_board_sprints` | `GET /boards/{id}/sprints` |
105
+
106
+ For `search_issues` / `count_issues`, provide **exactly one** mode (`query` or `filter`; search also supports `keys` / `queue`).
107
+
108
+ Example queries: `Queue: TEST`, `Queue: TEST Assignee: me() Sort by: Updated DESC`, `Key: TEST-1`.
109
+
110
+ ### Write (side effects)
111
+
112
+ | Tool | API |
113
+ |------|-----|
114
+ | `create_issue` | `POST /issues/` (optional `fields`) |
115
+ | `update_issue` | `PATCH /issues/{id}` (`fields` / operators) |
116
+ | `add_issue_comment` | `POST /issues/{id}/comments` |
117
+ | `execute_transition` | status transition |
118
+ | `create_issue_link` / `delete_issue_link` | issue links |
119
+ | `add_issue_followers` / `remove_issue_followers` | watchers |
120
+ | `add_issue_worklog` | time tracking |
121
+ | `update_checklist_item` | checklist |
122
+ | `upload_issue_attachment` | upload from local `filePath` |
123
+
124
+ Status changes only via `execute_transition` (call `get_issue_transitions` first). Requires OAuth scope `tracker:write`.
125
+
126
+ ## Local development
127
+
128
+ ```bash
129
+ git clone <repo>
130
+ cd yandex-tracker
131
+ cp .env.example .env
132
+ npm install
133
+ npm run test:unit
134
+ npm run typecheck
135
+ npm run dev
136
+ ```
137
+
138
+ Or point `mcp.json` at `src/index.ts` with `npx tsx` (see the repository).
139
+
140
+ ## License
141
+
142
+ MIT
package/README.ru.md ADDED
@@ -0,0 +1,142 @@
1
+ # @mmtr-tech/yandex-tracker-mcp
2
+
3
+ MCP-сервер для API [Яндекс Трекера](https://yandex.ru/support/tracker/ru/api-ref/access) (OAuth + организация Яндекс 360).
4
+
5
+ [English version](README.md)
6
+
7
+ ## Установка / запуск в Cursor
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "yandex-tracker": {
13
+ "command": "npx",
14
+ "args": ["-y", "@mmtr-tech/yandex-tracker-mcp"],
15
+ "env": {
16
+ "API_TOKEN": "your-oauth-token",
17
+ "X_ORG_ID": "your-org-id"
18
+ }
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ Опционально: `"API_BASE_URL": "https://api.tracker.yandex.net/v3"` (это значение по умолчанию).
25
+
26
+ После изменения конфига — **Restart Cursor** (toggle MCP часто недостаточен).
27
+
28
+ ### Env
29
+
30
+ | Переменная | Обязательно | Описание |
31
+ |------------|-------------|----------|
32
+ | `API_TOKEN` | да | OAuth-токен (`Authorization: OAuth …`) |
33
+ | `X_ORG_ID` | да | Id организации Яндекс 360 (`X-Org-ID`) |
34
+ | `API_BASE_URL` | нет | По умолчанию `https://api.tracker.yandex.net/v3` |
35
+
36
+ ## Как получить OAuth-токен и X_ORG_ID
37
+
38
+ Нужны **OAuth-токен** пользователя Трекера и **id организации** Яндекс 360.
39
+
40
+ ### 1. Зарегистрировать приложение в Яндекс OAuth
41
+
42
+ Инструкция по типам приложений: [Регистрация приложения](https://yandex.ru/dev/id/doc/ru/register-client#access).
43
+
44
+ Для этого MCP выбирайте тип **«Для доступа к API или отладки»** (не «для авторизации пользователей»). Тип после создания не меняется.
45
+
46
+ 1. Откройте [oauth.yandex.ru](https://oauth.yandex.ru) → **Создать**.
47
+ 2. Выберите **Для доступа к API или отладки**.
48
+ 3. Укажите название и почту.
49
+ 4. В поле доступов добавьте:
50
+ - `tracker:read` — только чтение;
51
+ - `tracker:write` — создание/правка/комменты/переходы (нужен для write-tools).
52
+ 5. Создайте приложение и скопируйте **ClientID**.
53
+
54
+ Подробнее по Трекеру: [Доступ к API → OAuth](https://yandex.ru/support/tracker/ru/api-ref/access).
55
+
56
+ ### 2. Выпустить токен
57
+
58
+ ```text
59
+ https://oauth.yandex.ru/authorize?response_type=token&client_id=<ClientID>
60
+ ```
61
+
62
+ Откройте ссылку под аккаунтом, от имени которого будете ходить в Трекер. Появившаяся строка — это `API_TOKEN`.
63
+
64
+ Токен действует с правами этого пользователя. Отозвать доступ можно в настройках Яндекс ID.
65
+
66
+ ### 3. Узнать X_ORG_ID
67
+
68
+ В Трекере: **Администрирование → Организации** → скопируйте идентификатор (`X-Org-ID`).
69
+
70
+ ### 4. Проверить доступ
71
+
72
+ ```bash
73
+ curl -X GET 'https://api.tracker.yandex.net/v3/myself' \
74
+ -H "Authorization: OAuth $API_TOKEN" \
75
+ -H "X-Org-ID: $X_ORG_ID"
76
+ ```
77
+
78
+ Ожидается `200` и JSON с `login` / `display`. `401` — неверный токен, scopes или org id.
79
+
80
+ ## Tools
81
+
82
+ ### Чтение
83
+
84
+ | Tool | API |
85
+ |------|-----|
86
+ | `get_myself` | `GET /myself` |
87
+ | `get_user` | `GET /users/{id}` |
88
+ | `list_users` | `GET /users` |
89
+ | `list_queues` | `GET /queues/` |
90
+ | `get_queue` | `GET /queues/{id}` |
91
+ | `list_queue_versions` | `GET /queues/{id}/versions` |
92
+ | `list_queue_components` | `GET /queues/{id}?expand=components` |
93
+ | `get_issue` | `GET /issues/{id}` |
94
+ | `search_issues` | `POST /issues/_search` |
95
+ | `count_issues` | `POST /issues/_count` |
96
+ | `get_issue_comments` | `GET /issues/{id}/comments` |
97
+ | `get_issue_links` | `GET /issues/{id}/links` |
98
+ | `get_issue_transitions` | `GET /issues/{id}/transitions` |
99
+ | `get_issue_changelog` | `GET /issues/{id}/changelog` |
100
+ | `get_issue_attachments` | метаданные вложений |
101
+ | `get_issue_worklog` | `GET /issues/{id}/worklog` |
102
+ | `get_issue_checklist` | `GET /issues/{id}/checklistItems` |
103
+ | `list_boards` | `GET /boards/` |
104
+ | `list_board_sprints` | `GET /boards/{id}/sprints` |
105
+
106
+ `search_issues` / `count_issues`: укажите **ровно один** режим (`query` или `filter`; у search ещё `keys` / `queue`).
107
+
108
+ Примеры `query`: `Queue: TEST`, `Queue: TEST Assignee: me() Sort by: Updated DESC`, `Key: TEST-1`.
109
+
110
+ ### Запись (побочные эффекты)
111
+
112
+ | Tool | API |
113
+ |------|-----|
114
+ | `create_issue` | `POST /issues/` (+ опц. `fields`) |
115
+ | `update_issue` | `PATCH /issues/{id}` (+ `fields` / операторы) |
116
+ | `add_issue_comment` | `POST /issues/{id}/comments` |
117
+ | `execute_transition` | переход статуса |
118
+ | `create_issue_link` / `delete_issue_link` | связи |
119
+ | `add_issue_followers` / `remove_issue_followers` | наблюдатели |
120
+ | `add_issue_worklog` | списание времени |
121
+ | `update_checklist_item` | чеклист |
122
+ | `upload_issue_attachment` | загрузка файла с локального `filePath` |
123
+
124
+ Статус меняется только через `execute_transition` (сначала `get_issue_transitions`). Нужен OAuth scope `tracker:write`.
125
+
126
+ ## Локальная разработка
127
+
128
+ ```bash
129
+ git clone <repo>
130
+ cd yandex-tracker
131
+ cp .env.example .env
132
+ npm install
133
+ npm run test:unit
134
+ npm run typecheck
135
+ npm run dev
136
+ ```
137
+
138
+ Либо в `mcp.json` укажите путь к `src/index.ts` через `npx tsx` (см. репозиторий).
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,185 @@
1
+ export interface TrackerClientConfig {
2
+ baseUrl: string;
3
+ token: string;
4
+ orgId: string;
5
+ sslVerify?: boolean;
6
+ timeoutMs?: number;
7
+ }
8
+ export interface ListQueuesParams {
9
+ perPage?: number;
10
+ page?: number;
11
+ expand?: string;
12
+ }
13
+ export interface GetQueueParams {
14
+ queueId: string;
15
+ expand?: string;
16
+ }
17
+ export interface GetIssueParams {
18
+ issueId: string;
19
+ expand?: string;
20
+ fields?: string;
21
+ }
22
+ export interface SearchIssuesParams {
23
+ query?: string;
24
+ filter?: Record<string, unknown>;
25
+ keys?: string | string[];
26
+ queue?: string;
27
+ order?: string;
28
+ perPage?: number;
29
+ page?: number;
30
+ expand?: string;
31
+ fields?: string;
32
+ }
33
+ export interface ListCommentsParams {
34
+ issueId: string;
35
+ perPage?: number;
36
+ expand?: string;
37
+ /** Comment id after which the next page starts. */
38
+ afterId?: number;
39
+ }
40
+ export interface CreateIssueParams {
41
+ queue: string;
42
+ summary: string;
43
+ description?: string;
44
+ type?: string;
45
+ priority?: string;
46
+ assignee?: string;
47
+ parent?: string;
48
+ tags?: string[];
49
+ markupType?: string;
50
+ /** Extra / custom fields merged into the request body. */
51
+ fields?: Record<string, unknown>;
52
+ }
53
+ export interface UpdateIssueParams {
54
+ issueId: string;
55
+ summary?: string;
56
+ description?: string;
57
+ type?: string;
58
+ priority?: string;
59
+ assignee?: string | null;
60
+ parent?: string | null;
61
+ tags?: string[];
62
+ markupType?: string;
63
+ version?: number;
64
+ /** Extra / custom fields merged into the PATCH body (supports Tracker operators). */
65
+ fields?: Record<string, unknown>;
66
+ }
67
+ export interface AddCommentParams {
68
+ issueId: string;
69
+ text: string;
70
+ markupType?: string;
71
+ summonees?: string[];
72
+ }
73
+ export interface ExecuteTransitionParams {
74
+ issueId: string;
75
+ transitionId: string;
76
+ comment?: string;
77
+ resolution?: string;
78
+ fields?: Record<string, unknown>;
79
+ }
80
+ export interface GetIssueChangelogParams {
81
+ issueId: string;
82
+ perPage?: number;
83
+ /** Changelog entry id after which the next page starts. */
84
+ afterId?: string;
85
+ field?: string;
86
+ type?: string;
87
+ }
88
+ export interface GetUserParams {
89
+ userId: string;
90
+ expand?: string;
91
+ }
92
+ export interface ListUsersParams {
93
+ perPage?: number;
94
+ /** User uid cursor — start listing after this id. */
95
+ id?: number;
96
+ email?: string;
97
+ expand?: string;
98
+ }
99
+ export interface CreateIssueLinkParams {
100
+ issueId: string;
101
+ relationship: string;
102
+ linkedIssueId: string;
103
+ }
104
+ export interface DeleteIssueLinkParams {
105
+ issueId: string;
106
+ linkId: string | number;
107
+ }
108
+ export interface FollowersParams {
109
+ issueId: string;
110
+ users: string[];
111
+ version?: number;
112
+ }
113
+ export interface IssueWorklogListParams {
114
+ issueId: string;
115
+ perPage?: number;
116
+ afterId?: number;
117
+ }
118
+ export interface AddIssueWorklogParams {
119
+ issueId: string;
120
+ duration: string;
121
+ start?: string;
122
+ comment?: string;
123
+ }
124
+ export interface CountIssuesParams {
125
+ query?: string;
126
+ filter?: Record<string, unknown>;
127
+ }
128
+ export interface UpdateChecklistItemParams {
129
+ issueId: string;
130
+ itemId: string;
131
+ checked?: boolean;
132
+ text?: string;
133
+ }
134
+ export interface UploadAttachmentParams {
135
+ issueId: string;
136
+ filePath: string;
137
+ filename?: string;
138
+ }
139
+ export interface ListBoardSprintsParams {
140
+ boardId: string | number;
141
+ }
142
+ /**
143
+ * HTTP client for Yandex Tracker API v3 (OAuth + X-Org-ID / Yandex 360).
144
+ */
145
+ export declare class TrackerClient {
146
+ private http;
147
+ private config;
148
+ constructor(config: TrackerClientConfig);
149
+ getMyself(): Promise<unknown>;
150
+ listQueues(params?: ListQueuesParams): Promise<unknown>;
151
+ getQueue(params: GetQueueParams): Promise<unknown>;
152
+ getIssue(params: GetIssueParams): Promise<unknown>;
153
+ searchIssues(params: SearchIssuesParams): Promise<unknown>;
154
+ getIssueComments(params: ListCommentsParams): Promise<unknown>;
155
+ getIssueLinks(issueId: string): Promise<unknown>;
156
+ getIssueTransitions(issueId: string): Promise<unknown>;
157
+ getIssueChangelog(params: GetIssueChangelogParams): Promise<unknown>;
158
+ getIssueAttachments(issueId: string): Promise<unknown>;
159
+ getUser(params: GetUserParams): Promise<unknown>;
160
+ listUsers(params?: ListUsersParams): Promise<unknown>;
161
+ createIssue(params: CreateIssueParams): Promise<unknown>;
162
+ updateIssue(params: UpdateIssueParams): Promise<unknown>;
163
+ createIssueLink(params: CreateIssueLinkParams): Promise<unknown>;
164
+ deleteIssueLink(params: DeleteIssueLinkParams): Promise<unknown>;
165
+ addIssueFollowers(params: FollowersParams): Promise<unknown>;
166
+ removeIssueFollowers(params: FollowersParams): Promise<unknown>;
167
+ getIssueWorklog(params: IssueWorklogListParams): Promise<unknown>;
168
+ addIssueWorklog(params: AddIssueWorklogParams): Promise<unknown>;
169
+ getQueueVersions(queueId: string): Promise<unknown>;
170
+ getQueueComponents(queueId: string): Promise<unknown>;
171
+ countIssues(params: CountIssuesParams): Promise<unknown>;
172
+ getIssueChecklist(issueId: string): Promise<unknown>;
173
+ updateChecklistItem(params: UpdateChecklistItemParams): Promise<unknown>;
174
+ listBoards(params?: {
175
+ perPage?: number;
176
+ page?: number;
177
+ }): Promise<unknown>;
178
+ listBoardSprints(params: ListBoardSprintsParams): Promise<unknown>;
179
+ uploadIssueAttachment(params: UploadAttachmentParams): Promise<unknown>;
180
+ addIssueComment(params: AddCommentParams): Promise<unknown>;
181
+ executeTransition(params: ExecuteTransitionParams): Promise<unknown>;
182
+ private wrapError;
183
+ }
184
+ export declare function createTrackerClient(): TrackerClient;
185
+ //# sourceMappingURL=tracker-client.d.ts.map