@vitalyostanin/youtrack-mcp 0.3.1 → 0.5.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/README-ru.md +52 -9
- package/README.md +46 -3
- package/dist/package.json +2 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.js +7 -0
- package/dist/src/server.js +3 -1
- package/dist/src/tools/issue-search-tools.d.ts +2 -1
- package/dist/src/tools/issue-search-tools.js +8 -3
- package/dist/src/tools/issue-star-tools.d.ts +7 -0
- package/dist/src/tools/issue-star-tools.js +67 -0
- package/dist/src/types.d.ts +44 -0
- package/dist/src/utils/mappers.d.ts +5 -0
- package/dist/src/utils/mappers.js +9 -0
- package/dist/src/utils/tool-response.d.ts +1 -1
- package/dist/src/utils/tool-response.js +8 -2
- package/dist/src/youtrack-client.d.ts +52 -1
- package/dist/src/youtrack-client.js +551 -149
- package/package.json +2 -1
package/README-ru.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
MCP сервер для полноценной интеграции с YouTrack со следующими возможностями:
|
|
7
7
|
|
|
8
8
|
- **Управление задачами** - создание, обновление, комментирование, назначение, изменение статуса, пакетные операции
|
|
9
|
+
- **Звездочки для задач** - отметка важных задач звездочками, массовое добавление (до 50), список отмеченных задач
|
|
9
10
|
- **Управление вложениями** - загрузка файлов (до 10), скачивание по подписанным URL, удаление
|
|
10
11
|
- **Учёт трудозатрат** - создание записей с идемпотентными операциями, массовое создание за период
|
|
11
12
|
- **Детальные отчёты по времени** - сводные отчёты, анализ отклонений, статистика по пользователям
|
|
@@ -26,9 +27,11 @@ MCP сервер для полноценной интеграции с YouTrack
|
|
|
26
27
|
- [Запуск сервера (stdio)](#запуск-сервера-stdio)
|
|
27
28
|
- [Конфигурация для Code (Рекомендуется)](#конфигурация-для-code-рекомендуется)
|
|
28
29
|
- [Конфигурация для Claude Code CLI](#конфигурация-для-claude-code-cli)
|
|
30
|
+
- [Конфигурация для VS Code Cline](#конфигурация-для-vs-code-cline)
|
|
29
31
|
- [Инструменты MCP](#инструменты-mcp)
|
|
30
32
|
- [Сервис](#сервис)
|
|
31
33
|
- [Задачи](#задачи)
|
|
34
|
+
- [Звездочки задач](#звездочки-задач)
|
|
32
35
|
- [Трудозатраты](#трудозатраты)
|
|
33
36
|
- [Пользователи и проекты](#пользователи-и-проекты)
|
|
34
37
|
- [Статьи](#статьи)
|
|
@@ -38,12 +41,13 @@ MCP сервер для полноценной интеграции с YouTrack
|
|
|
38
41
|
|
|
39
42
|
- Node.js ≥ 20
|
|
40
43
|
- Переменные окружения:
|
|
41
|
-
- `YOUTRACK_URL` — базовый URL YouTrack
|
|
42
|
-
- `YOUTRACK_TOKEN` — постоянный токен с правами на чтение задач и work items
|
|
43
|
-
- `YOUTRACK_TIMEZONE` — опциональная таймзона для операций с датами (по умолчанию: `Europe/Moscow`), должна быть валидным идентификатором IANA (например, `Europe/London`, `America/New_York`, `Asia/Tokyo`)
|
|
44
|
-
- `YOUTRACK_HOLIDAYS` — опциональный список праздничных дат через запятую (формат `YYYY-MM-DD`), исключаемых из отчётов и массовых операций
|
|
45
|
-
- `YOUTRACK_PRE_HOLIDAYS` — опциональный список предпраздничных дат через запятую, для которых норма времени уменьшается автоматически
|
|
46
|
-
- `YOUTRACK_USER_ALIASES` — опциональный список соответствий `alias:login` через запятую (например, `me:vyt,petya:p.petrov`), используется при автоматическом выборе исполнителей
|
|
44
|
+
- `YOUTRACK_URL` — базовый URL YouTrack
|
|
45
|
+
- `YOUTRACK_TOKEN` — постоянный токен с правами на чтение задач и work items
|
|
46
|
+
- `YOUTRACK_TIMEZONE` — опциональная таймзона для операций с датами (по умолчанию: `Europe/Moscow`), должна быть валидным идентификатором IANA (например, `Europe/London`, `America/New_York`, `Asia/Tokyo`)
|
|
47
|
+
- `YOUTRACK_HOLIDAYS` — опциональный список праздничных дат через запятую (формат `YYYY-MM-DD`), исключаемых из отчётов и массовых операций
|
|
48
|
+
- `YOUTRACK_PRE_HOLIDAYS` — опциональный список предпраздничных дат через запятую, для которых норма времени уменьшается автоматически
|
|
49
|
+
- `YOUTRACK_USER_ALIASES` — опциональный список соответствий `alias:login` через запятую (например, `me:vyt,petya:p.petrov`), используется при автоматическом выборе исполнителей
|
|
50
|
+
- `YOUTRACK_COMPACT_MODE` — опциональный, управляет минимизацией ответов для оптимизации контекстного окна AI (по умолчанию: `true`). Установите `false` для Claude Code, чтобы получать полный текст ответа в поле MCP content вместо минимальной заглушки. При `true` полные данные доступны в поле `structuredContent`
|
|
47
51
|
|
|
48
52
|
## Установка
|
|
49
53
|
|
|
@@ -54,7 +58,7 @@ MCP сервер для полноценной интеграции с YouTrack
|
|
|
54
58
|
```bash
|
|
55
59
|
YOUTRACK_URL="https://youtrack.example.com" \
|
|
56
60
|
YOUTRACK_TOKEN="perm:your-token-here" \
|
|
57
|
-
npx -y @vitalyostanin/youtrack-mcp
|
|
61
|
+
npx -y @vitalyostanin/youtrack-mcp@latest
|
|
58
62
|
```
|
|
59
63
|
|
|
60
64
|
### Используя Claude MCP CLI
|
|
@@ -189,7 +193,7 @@ node dist/index.js
|
|
|
189
193
|
```toml
|
|
190
194
|
[mcp_servers.youtrack-mcp]
|
|
191
195
|
command = "npx"
|
|
192
|
-
args = ["-y", "@vitalyostanin/youtrack-mcp"]
|
|
196
|
+
args = ["-y", "@vitalyostanin/youtrack-mcp@latest"]
|
|
193
197
|
env = { "YOUTRACK_URL" = "https://youtrack.example.com", "YOUTRACK_TOKEN" = "perm:your-token-here" }
|
|
194
198
|
```
|
|
195
199
|
|
|
@@ -208,7 +212,36 @@ env = { "YOUTRACK_URL" = "https://youtrack.example.com", "YOUTRACK_TOKEN" = "per
|
|
|
208
212
|
"youtrack-mcp": {
|
|
209
213
|
"type": "stdio",
|
|
210
214
|
"command": "npx",
|
|
211
|
-
"args": ["-y", "@vitalyostanin/youtrack-mcp"],
|
|
215
|
+
"args": ["-y", "@vitalyostanin/youtrack-mcp@latest"],
|
|
216
|
+
"env": {
|
|
217
|
+
"YOUTRACK_URL": "https://youtrack.example.com",
|
|
218
|
+
"YOUTRACK_TOKEN": "perm:your-token-here",
|
|
219
|
+
"YOUTRACK_COMPACT_MODE": "false"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Примечание:** Эта конфигурация использует npx для запуска опубликованного пакета. Для локальной разработки используйте `"command": "node"` с `"args": ["/абсолютный/путь/к/youtrack-mcp/dist/index.js"]`. Переменные окружения `YOUTRACK_TIMEZONE`, `YOUTRACK_HOLIDAYS`, `YOUTRACK_PRE_HOLIDAYS` и `YOUTRACK_USER_ALIASES` являются опциональными.
|
|
227
|
+
|
|
228
|
+
**Для пользователей Claude Code:** Установите `YOUTRACK_COMPACT_MODE` в `"false"`, чтобы включить полные данные ответа в поле MCP content. Это помогает Claude Code легче получать доступ к структурированным данным. При `true` (по умолчанию) в поле content возвращается только минимальная заглушка для оптимизации использования контекстного окна для других AI агентов.
|
|
229
|
+
|
|
230
|
+
## Конфигурация для VS Code Cline
|
|
231
|
+
|
|
232
|
+
Чтобы использовать этот MCP сервер с расширением [Cline](https://github.com/cline/cline) в VS Code:
|
|
233
|
+
|
|
234
|
+
1. Откройте VS Code с установленным расширением Cline
|
|
235
|
+
2. Нажмите на иконку MCP Servers в верхней навигации Cline
|
|
236
|
+
3. Выберите вкладку "Configure" и нажмите "Configure MCP Servers"
|
|
237
|
+
4. Добавьте следующую конфигурацию в `cline_mcp_settings.json`:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"mcpServers": {
|
|
242
|
+
"youtrack-mcp": {
|
|
243
|
+
"command": "npx",
|
|
244
|
+
"args": ["-y", "@vitalyostanin/youtrack-mcp@latest"],
|
|
212
245
|
"env": {
|
|
213
246
|
"YOUTRACK_URL": "https://youtrack.example.com",
|
|
214
247
|
"YOUTRACK_TOKEN": "perm:your-token-here"
|
|
@@ -249,6 +282,16 @@ env = { "YOUTRACK_URL" = "https://youtrack.example.com", "YOUTRACK_TOKEN" = "per
|
|
|
249
282
|
| `issue_change_state` | Изменение состояния/статуса задачи через переходы workflow. **Использование:** Перемещение задач через состояния рабочего процесса (например, 'Открыта' → 'В работе'). Автоматически определяет доступные переходы и валидирует запрошенное изменение состояния. Регистронезависимое сопоставление имён состояний. **Возвращает:** информацию о предыдущем состоянии, новом состоянии и использованном переходе | `issueId` — код задачи, `stateName` — имя целевого состояния (например, 'В работе', 'Открыта', 'Исправлена', 'Проверена'). Регистронезависимое |
|
|
250
283
|
| `issue_search_by_user_activity` | Поиск задач по активности пользователей в заданный период. **Использование:** Поиск задач, где пользователи обновляли, были упомянуты, создавали, были назначены или комментировали. Поддерживает два режима фильтрации: `issue_updated` (по умолчанию, быстрый) использует поле issue.updated, `user_activity` (медленный, точный) проверяет фактические даты активности пользователя, включая комментарии, упоминания и историю изменений полей. **Когда использовать точный режим:** когда нужна точная дата участия пользователя (например, когда пользователь был исполнителем, но позже был изменён). **Возвращает:** краткую информацию о задачах (id, idReadable, summary, project, parent, assignee) без description для уменьшения размера ответа. В режиме `user_activity` включает поле `lastActivityDate` с точной датой последней активности пользователя. Результаты отсортированы по времени активности (новые первыми). Поддерживает пагинацию. **Ограничение:** по умолчанию 100 задач, макс 200 | `userLogins[]` — массив логинов пользователей для поиска активности (updater, mentions, reporter, assignee, commenter), опционально `startDate` (формат YYYY-MM-DD или timestamp), `endDate`, `dateFilterMode` (`issue_updated` или `user_activity`), `limit` (по умолчанию 100, макс 200), `skip` для пагинации |
|
|
251
284
|
|
|
285
|
+
### Звездочки задач
|
|
286
|
+
|
|
287
|
+
| Tool | Описание | Основные параметры |
|
|
288
|
+
| --- | --- | --- |
|
|
289
|
+
| `issue_star` | Добавление звездочки к задаче для текущего пользователя. **Использование:** Отметка важных задач, добавление задач в список наблюдения, быстрый доступ к часто используемым задачам. **Возвращает:** подтверждение статуса звездочки с issueId и флагом starred. **Примечание:** Идемпотентная операция - возвращает успех, даже если задача уже отмечена звездочкой | `issueId` — код задачи (например, `PROJ-123`) |
|
|
290
|
+
| `issue_unstar` | Удаление звездочки у задачи для текущего пользователя. **Использование:** Удаление задач из списка наблюдения, очистка ненужных звездочек, управление списком отмеченных задач. **Возвращает:** подтверждение операции снятия звездочки с issueId и флагом starred. **Примечание:** Идемпотентная операция - возвращает успех, даже если задача не была отмечена звездочкой | `issueId` — код задачи |
|
|
291
|
+
| `issues_star_batch` | Добавление звездочек к нескольким задачам (пакетный режим, макс 50 задач). **Использование:** Массовая отметка важных задач, пакетное добавление в список наблюдения, обработка нескольких задач одновременно, быстрая настройка списка отмеченных задач. **Возвращает:** объект с массивами `successful` (отмеченные задачи) и `failed` (ошибки с ID задач). **Примечание:** Операции обрабатываются с ограничением конкурентности (10 одновременных запросов) для предотвращения перегрузки API. Возможен частичный успех - некоторые задачи могут быть обработаны успешно, а другие - нет | `issueIds[]` — массив кодов задач (например, `['PROJ-123', 'PROJ-124']`), макс 50 |
|
|
292
|
+
| `issues_unstar_batch` | Удаление звездочек у нескольких задач (пакетный режим, макс 50 задач). **Использование:** Массовая очистка списка наблюдения, пакетное удаление ненужных звездочек, обработка нескольких задач одновременно, управление списком отмеченных задач. **Возвращает:** объект с массивами `successful` (задачи с удаленными звездочками) и `failed` (ошибки с ID задач). **Примечание:** Операции обрабатываются с ограничением конкурентности (10 одновременных запросов) для предотвращения перегрузки API. Возможен частичный успех - некоторые задачи могут быть обработаны успешно, а другие - нет | `issueIds[]` — массив кодов задач, макс 50 |
|
|
293
|
+
| `issues_starred_list` | Получение всех отмеченных звездочками задач для текущего пользователя. **Использование:** Просмотр списка наблюдения, получение часто используемых задач, поиск всех отмеченных важных задач, проверка наличия звездочек у задач. **Возвращает:** массив отмеченных задач (краткий формат без description) и общее количество. **Примечание:** Ограничено 200 задачами за запрос. Результаты включают только базовую информацию (id, idReadable, summary, project, parent, assignee) без description для уменьшения размера ответа. Опциональное поле message в ответах star/unstar предоставляет информацию о статусе операции (например, 'Issue already starred', 'Issue starred successfully') | Опционально `limit` — максимальное количество задач (по умолчанию 50, макс 200), `skip` — количество задач для пропуска при пагинации (по умолчанию 0) |
|
|
294
|
+
|
|
252
295
|
### Трудозатраты
|
|
253
296
|
|
|
254
297
|
| Tool | Описание | Основные параметры |
|
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
MCP server for comprehensive YouTrack integration with the following capabilities:
|
|
7
7
|
|
|
8
8
|
- **Issue management** - create, update, comment, assign, change state, batch operations
|
|
9
|
+
- **Issue starring** - mark important issues with stars, batch starring (up to 50), list starred issues
|
|
9
10
|
- **Attachment management** - upload files (up to 10), download with signed URLs, delete
|
|
10
11
|
- **Work items tracking** - create entries with idempotent operations, batch creation for periods
|
|
11
12
|
- **Detailed time reports** - summary reports, deviation analysis, multi-user statistics
|
|
@@ -26,9 +27,11 @@ MCP server for comprehensive YouTrack integration with the following capabilitie
|
|
|
26
27
|
- [Running the server (stdio)](#running-the-server-stdio)
|
|
27
28
|
- [Configuration for Code (Recommended)](#configuration-for-code-recommended)
|
|
28
29
|
- [Configuration for Claude Code CLI](#configuration-for-claude-code-cli)
|
|
30
|
+
- [Configuration for VS Code Cline](#configuration-for-vs-code-cline)
|
|
29
31
|
- [MCP Tools](#mcp-tools)
|
|
30
32
|
- [Service](#service)
|
|
31
33
|
- [Issues](#issues)
|
|
34
|
+
- [Issue Stars](#issue-stars)
|
|
32
35
|
- [Work Items](#work-items)
|
|
33
36
|
- [Users and Projects](#users-and-projects)
|
|
34
37
|
- [Articles](#articles)
|
|
@@ -45,6 +48,7 @@ MCP server for comprehensive YouTrack integration with the following capabilitie
|
|
|
45
48
|
- `YOUTRACK_HOLIDAYS` — optional comma-separated list of holiday dates (format `YYYY-MM-DD`), excluded from reports and batch operations
|
|
46
49
|
- `YOUTRACK_PRE_HOLIDAYS` — optional comma-separated list of pre-holiday dates with reduced working hours
|
|
47
50
|
- `YOUTRACK_USER_ALIASES` — optional comma-separated list of `alias:login` mappings (e.g., `me:vyt,petya:p.petrov`), used for automatic assignee selection
|
|
51
|
+
- `YOUTRACK_COMPACT_MODE` — optional, controls response minimization for AI context window optimization (default: `true`). Set to `false` for Claude Code to get full response text in MCP content field instead of minimal stub. When `true`, full data is available in `structuredContent` field
|
|
48
52
|
|
|
49
53
|
## Installation
|
|
50
54
|
|
|
@@ -55,7 +59,7 @@ You can run the server directly with npx without installation:
|
|
|
55
59
|
```bash
|
|
56
60
|
YOUTRACK_URL="https://youtrack.example.com" \
|
|
57
61
|
YOUTRACK_TOKEN="perm:your-token-here" \
|
|
58
|
-
npx -y @vitalyostanin/youtrack-mcp
|
|
62
|
+
npx -y @vitalyostanin/youtrack-mcp@latest
|
|
59
63
|
```
|
|
60
64
|
|
|
61
65
|
### Using Claude MCP CLI
|
|
@@ -190,7 +194,7 @@ To use this MCP server with [Code](https://github.com/just-every/code), add the
|
|
|
190
194
|
```toml
|
|
191
195
|
[mcp_servers.youtrack-mcp]
|
|
192
196
|
command = "npx"
|
|
193
|
-
args = ["-y", "@vitalyostanin/youtrack-mcp"]
|
|
197
|
+
args = ["-y", "@vitalyostanin/youtrack-mcp@latest"]
|
|
194
198
|
env = { "YOUTRACK_URL" = "https://youtrack.example.com", "YOUTRACK_TOKEN" = "perm:your-token-here" }
|
|
195
199
|
```
|
|
196
200
|
|
|
@@ -209,7 +213,36 @@ To use this MCP server with [Claude Code CLI](https://github.com/anthropics/clau
|
|
|
209
213
|
"youtrack-mcp": {
|
|
210
214
|
"type": "stdio",
|
|
211
215
|
"command": "npx",
|
|
212
|
-
"args": ["-y", "@vitalyostanin/youtrack-mcp"],
|
|
216
|
+
"args": ["-y", "@vitalyostanin/youtrack-mcp@latest"],
|
|
217
|
+
"env": {
|
|
218
|
+
"YOUTRACK_URL": "https://youtrack.example.com",
|
|
219
|
+
"YOUTRACK_TOKEN": "perm:your-token-here",
|
|
220
|
+
"YOUTRACK_COMPACT_MODE": "false"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Note:** This configuration uses npx to run the published package. For local development, use `"command": "node"` with `"args": ["/absolute/path/to/youtrack-mcp/dist/index.js"]`. The `YOUTRACK_TIMEZONE`, `YOUTRACK_HOLIDAYS`, `YOUTRACK_PRE_HOLIDAYS`, and `YOUTRACK_USER_ALIASES` environment variables are optional.
|
|
228
|
+
|
|
229
|
+
**For Claude Code users:** Set `YOUTRACK_COMPACT_MODE` to `"false"` to include full response data in the MCP content field. This helps Claude Code access structured data more easily. When `true` (default), only a minimal stub is returned in the content field to optimize context window usage for other AI agents.
|
|
230
|
+
|
|
231
|
+
## Configuration for VS Code Cline
|
|
232
|
+
|
|
233
|
+
To use this MCP server with [Cline](https://github.com/cline/cline) extension in VS Code:
|
|
234
|
+
|
|
235
|
+
1. Open VS Code with Cline extension installed
|
|
236
|
+
2. Click the MCP Servers icon in Cline's top navigation
|
|
237
|
+
3. Select the "Configure" tab and click "Configure MCP Servers"
|
|
238
|
+
4. Add the following configuration to `cline_mcp_settings.json`:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"mcpServers": {
|
|
243
|
+
"youtrack-mcp": {
|
|
244
|
+
"command": "npx",
|
|
245
|
+
"args": ["-y", "@vitalyostanin/youtrack-mcp@latest"],
|
|
213
246
|
"env": {
|
|
214
247
|
"YOUTRACK_URL": "https://youtrack.example.com",
|
|
215
248
|
"YOUTRACK_TOKEN": "perm:your-token-here"
|
|
@@ -252,6 +285,16 @@ All tools return `structuredContent` with a `success` flag and payload formatted
|
|
|
252
285
|
| `issue_attachment_upload` | Upload files to issue | `issueId`, `filePaths[]` — array of file paths (max 10), optionally `muteUpdateNotifications` |
|
|
253
286
|
| `issue_attachment_delete` | Delete attachment (requires confirmation) | `issueId`, `attachmentId`, `confirmation` (must be `true`) |
|
|
254
287
|
|
|
288
|
+
### Issue Stars
|
|
289
|
+
|
|
290
|
+
| Tool | Description | Main Parameters |
|
|
291
|
+
| --- | --- | --- |
|
|
292
|
+
| `issue_star` | Add star to issue for current user | `issueId` — issue code (e.g., PROJ-123). Idempotent operation - returns success even if already starred |
|
|
293
|
+
| `issue_unstar` | Remove star from issue for current user | `issueId` — issue code. Idempotent operation - returns success even if not currently starred |
|
|
294
|
+
| `issues_star_batch` | Add stars to multiple issues (batch mode, max 50) | `issueIds[]` — array of issue codes (max 50). Returns object with `successful` and `failed` arrays. Processes with concurrency limit (10 concurrent requests) |
|
|
295
|
+
| `issues_unstar_batch` | Remove stars from multiple issues (batch mode, max 50) | `issueIds[]` — array of issue codes (max 50). Returns object with `successful` and `failed` arrays. Processes with concurrency limit (10 concurrent requests) |
|
|
296
|
+
| `issues_starred_list` | Get all starred issues for current user | Optionally `limit` (default 50, max 200), `skip` for pagination. Returns array of starred issues with basic information (id, idReadable, summary, project, parent, assignee) without description fields |
|
|
297
|
+
|
|
255
298
|
### Work Items
|
|
256
299
|
|
|
257
300
|
| Tool | Description | Main Parameters |
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitalyostanin/youtrack-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "tsc -p tsconfig.json",
|
|
6
6
|
"postbuild": "chmod +x dist/index.js",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.20.0",
|
|
54
|
+
"@vitalyostanin/mutex-pool": "^0.0.3",
|
|
54
55
|
"axios": "^1.12.2",
|
|
55
56
|
"form-data": "^4.0.1",
|
|
56
57
|
"luxon": "^3.5.0",
|
package/dist/src/config.d.ts
CHANGED
package/dist/src/config.js
CHANGED
|
@@ -6,6 +6,11 @@ const configSchema = z.object({
|
|
|
6
6
|
YOUTRACK_HOLIDAYS: z.string().optional(),
|
|
7
7
|
YOUTRACK_PRE_HOLIDAYS: z.string().optional(),
|
|
8
8
|
YOUTRACK_USER_ALIASES: z.string().optional(),
|
|
9
|
+
YOUTRACK_COMPACT_MODE: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.default("true")
|
|
13
|
+
.transform((val) => val !== "false"),
|
|
9
14
|
});
|
|
10
15
|
export function loadConfig(env = process.env) {
|
|
11
16
|
const parsed = configSchema.safeParse(env);
|
|
@@ -32,6 +37,7 @@ export function loadConfig(env = process.env) {
|
|
|
32
37
|
userAliases: parsed.data.YOUTRACK_USER_ALIASES
|
|
33
38
|
? parseAliasMap(parsed.data.YOUTRACK_USER_ALIASES)
|
|
34
39
|
: undefined,
|
|
40
|
+
compactMode: parsed.data.YOUTRACK_COMPACT_MODE,
|
|
35
41
|
};
|
|
36
42
|
}
|
|
37
43
|
export function enrichConfigWithRedaction(config) {
|
|
@@ -41,6 +47,7 @@ export function enrichConfigWithRedaction(config) {
|
|
|
41
47
|
timezone: config.timezone,
|
|
42
48
|
holidays: config.holidays,
|
|
43
49
|
preHolidays: config.preHolidays,
|
|
50
|
+
compactMode: config.compactMode,
|
|
44
51
|
};
|
|
45
52
|
}
|
|
46
53
|
function parseCsvList(value) {
|
package/dist/src/server.js
CHANGED
|
@@ -10,6 +10,7 @@ import { registerArticleSearchTools } from "./tools/article-search-tools.js";
|
|
|
10
10
|
import { registerUserTools } from "./tools/user-tools.js";
|
|
11
11
|
import { registerProjectTools } from "./tools/project-tools.js";
|
|
12
12
|
import { registerAttachmentTools } from "./tools/attachment-tools.js";
|
|
13
|
+
import { registerIssueStarTools } from "./tools/issue-star-tools.js";
|
|
13
14
|
import { YoutrackClient } from "./youtrack-client.js";
|
|
14
15
|
import { loadConfig } from "./config.js";
|
|
15
16
|
import { initializeTimezone } from "./utils/date.js";
|
|
@@ -35,7 +36,7 @@ export class YoutrackServer {
|
|
|
35
36
|
registerServiceInfoTool(this.server, this.client);
|
|
36
37
|
registerIssueTools(this.server, this.client);
|
|
37
38
|
registerIssueActivityTools(this.server, this.client);
|
|
38
|
-
registerIssueSearchTools(this.server, this.client);
|
|
39
|
+
registerIssueSearchTools(this.server, this.client, config);
|
|
39
40
|
registerWorkitemTools(this.server, this.client);
|
|
40
41
|
registerWorkitemReportTools(this.server, this.client);
|
|
41
42
|
registerArticleTools(this.server, this.client);
|
|
@@ -43,6 +44,7 @@ export class YoutrackServer {
|
|
|
43
44
|
registerUserTools(this.server, this.client);
|
|
44
45
|
registerProjectTools(this.server, this.client);
|
|
45
46
|
registerAttachmentTools(this.server, this.client);
|
|
47
|
+
registerIssueStarTools(this.server, this.client);
|
|
46
48
|
}
|
|
47
49
|
async connect(transport) {
|
|
48
50
|
await this.server.connect(transport);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { YoutrackClient } from "../youtrack-client.js";
|
|
3
|
-
|
|
3
|
+
import type { YoutrackConfig } from "../types.js";
|
|
4
|
+
export declare function registerIssueSearchTools(server: McpServer, client: YoutrackClient, config: YoutrackConfig): void;
|
|
4
5
|
//# sourceMappingURL=issue-search-tools.d.ts.map
|
|
@@ -17,6 +17,10 @@ const issueSearchByUserActivityArgs = {
|
|
|
17
17
|
.enum(["issue_updated", "user_activity"])
|
|
18
18
|
.optional()
|
|
19
19
|
.describe("Date filter mode: 'issue_updated' (default, fast) filters by issue.updated field; 'user_activity' (slow, precise) filters by actual user activity dates including comments, mentions, and field changes history. Use 'user_activity' when you need exact date of user's involvement, e.g., when user was assignee but later changed."),
|
|
20
|
+
briefOutput: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Return brief issue data without description fields (default: true). Set to false to include full description and wikifiedDescription fields."),
|
|
20
24
|
limit: z
|
|
21
25
|
.number()
|
|
22
26
|
.int()
|
|
@@ -32,8 +36,8 @@ const issueSearchByUserActivityArgs = {
|
|
|
32
36
|
.describe("Number of results to skip for pagination (default: 0)"),
|
|
33
37
|
};
|
|
34
38
|
const issueSearchByUserActivitySchema = z.object(issueSearchByUserActivityArgs);
|
|
35
|
-
export function registerIssueSearchTools(server, client) {
|
|
36
|
-
server.tool("issue_search_by_user_activity", "Search for issues where specified users had activity (updated, mentioned, reported, assigned, commented) within a given time period. Supports two filter modes: 'issue_updated' (default, fast) uses issue.updated field, 'user_activity' (slow, precise) checks actual user activity dates including comments, mentions, and field changes history. Results are sorted by activity time (most recent first). When 'user_activity' mode is used, each issue includes 'lastActivityDate' field with exact timestamp of user's last activity. Supports pagination via limit and skip parameters. Note:
|
|
39
|
+
export function registerIssueSearchTools(server, client, config) {
|
|
40
|
+
server.tool("issue_search_by_user_activity", "Search for issues where specified users had activity (updated, mentioned, reported, assigned, commented) within a given time period. Supports two filter modes: 'issue_updated' (default, fast) uses issue.updated field, 'user_activity' (slow, precise) checks actual user activity dates including comments, mentions, and field changes history. Results are sorted by activity time (most recent first). When 'user_activity' mode is used, each issue includes 'lastActivityDate' field with exact timestamp of user's last activity. Supports pagination via limit and skip parameters. Note: By default (briefOutput=true), each issue includes minimal fields only - id, idReadable, summary, project (id, shortName, name), parent (id, idReadable), assignee (id, login, name). Description fields are excluded to reduce response size. Set briefOutput=false to include full description and wikifiedDescription fields. Custom fields are not included.", issueSearchByUserActivityArgs, async (rawInput) => {
|
|
37
41
|
try {
|
|
38
42
|
const payload = issueSearchByUserActivitySchema.parse(rawInput);
|
|
39
43
|
const results = await client.searchIssuesByUserActivity({
|
|
@@ -41,10 +45,11 @@ export function registerIssueSearchTools(server, client) {
|
|
|
41
45
|
startDate: payload.startDate,
|
|
42
46
|
endDate: payload.endDate,
|
|
43
47
|
dateFilterMode: payload.dateFilterMode,
|
|
48
|
+
briefOutput: payload.briefOutput,
|
|
44
49
|
limit: payload.limit,
|
|
45
50
|
skip: payload.skip,
|
|
46
51
|
});
|
|
47
|
-
const response = toolSuccess(results);
|
|
52
|
+
const response = toolSuccess(results, config.compactMode);
|
|
48
53
|
return response;
|
|
49
54
|
}
|
|
50
55
|
catch (error) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { YoutrackClient } from "../youtrack-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register issue star management tools
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerIssueStarTools(server: McpServer, client: YoutrackClient): void;
|
|
7
|
+
//# sourceMappingURL=issue-star-tools.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { toolSuccess, toolError } from "../utils/tool-response.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a tool handler with standard error handling
|
|
5
|
+
*/
|
|
6
|
+
function createToolHandler(handler) {
|
|
7
|
+
return async (args) => {
|
|
8
|
+
try {
|
|
9
|
+
const result = await handler(args);
|
|
10
|
+
const response = toolSuccess(result);
|
|
11
|
+
return response;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const errorResponse = toolError(error);
|
|
15
|
+
return errorResponse;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register issue star management tools
|
|
21
|
+
*/
|
|
22
|
+
export function registerIssueStarTools(server, client) {
|
|
23
|
+
// Tool: issue_star
|
|
24
|
+
server.tool("issue_star", "Add star to YouTrack issue for current user. Use for: Marking important issues, Adding issues to watchlist, Quick access to frequently used issues. Returns: Confirmation of star status with issueId and starred flag. Note: If issue is already starred, returns success without making changes (idempotent operation).", {
|
|
25
|
+
issueId: z.string().min(1).describe("Issue code (e.g., PROJ-123)"),
|
|
26
|
+
}, createToolHandler(async (args) => client.starIssue(args.issueId)));
|
|
27
|
+
// Tool: issue_unstar
|
|
28
|
+
server.tool("issue_unstar", "Remove star from YouTrack issue for current user. Use for: Removing issues from watchlist, Cleaning up unneeded stars, Managing starred issues list. Returns: Confirmation of unstar operation with issueId and starred flag. Note: If issue is not currently starred, returns success without making changes (idempotent operation).", {
|
|
29
|
+
issueId: z.string().min(1).describe("Issue code (e.g., PROJ-123)"),
|
|
30
|
+
}, createToolHandler(async (args) => client.unstarIssue(args.issueId)));
|
|
31
|
+
// Tool: issues_star_batch
|
|
32
|
+
server.tool("issues_star_batch", "Add stars to multiple YouTrack issues (batch mode, max 50 issues). Use for: Bulk marking important issues, Batch adding to watchlist, Processing multiple issues at once, Quick setup of starred issues list. Returns: Object with 'successful' array (starred issues) and 'failed' array (errors with issue IDs). Note: Operations are processed with concurrency limit (10 concurrent requests) to prevent API overload. Partial success is possible - some issues may succeed while others fail.", {
|
|
33
|
+
issueIds: z
|
|
34
|
+
.array(z.string().min(1))
|
|
35
|
+
.min(1)
|
|
36
|
+
.max(50)
|
|
37
|
+
.describe("Array of issue codes (e.g., ['PROJ-123', 'PROJ-124']), max 50"),
|
|
38
|
+
}, createToolHandler(async (args) => client.starIssues(args.issueIds)));
|
|
39
|
+
// Tool: issues_unstar_batch
|
|
40
|
+
server.tool("issues_unstar_batch", "Remove stars from multiple YouTrack issues (batch mode, max 50 issues). Use for: Bulk cleanup of watchlist, Batch removal of unneeded stars, Processing multiple issues at once, Managing starred issues list. Returns: Object with 'successful' array (unstarred issues) and 'failed' array (errors with issue IDs). Note: Operations are processed with concurrency limit (10 concurrent requests) to prevent API overload. Partial success is possible - some issues may succeed while others fail.", {
|
|
41
|
+
issueIds: z
|
|
42
|
+
.array(z.string().min(1))
|
|
43
|
+
.min(1)
|
|
44
|
+
.max(50)
|
|
45
|
+
.describe("Array of issue codes (e.g., ['PROJ-123', 'PROJ-124']), max 50"),
|
|
46
|
+
}, createToolHandler(async (args) => client.unstarIssues(args.issueIds)));
|
|
47
|
+
// Tool: issues_starred_list
|
|
48
|
+
server.tool("issues_starred_list", "Get all starred issues for current user with pagination. Use for: Viewing watchlist, Getting frequently used issues, Finding all marked important issues, Checking which issues are starred. Returns: Array of starred issues (brief format without description fields), returnedCount (count of issues in current page), and pagination info. Note: Default limit is 50 issues, max 200. Results include basic issue information only (id, idReadable, summary, project, parent, assignee) without description fields to reduce payload size. The optional message field in star/unstar responses provides status information about the operation (e.g., 'Issue already starred', 'Issue starred successfully').", {
|
|
49
|
+
limit: z
|
|
50
|
+
.number()
|
|
51
|
+
.int()
|
|
52
|
+
.positive()
|
|
53
|
+
.max(200)
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Maximum number of issues to return (default: 50, max: 200)"),
|
|
56
|
+
skip: z
|
|
57
|
+
.number()
|
|
58
|
+
.int()
|
|
59
|
+
.min(0)
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Number of issues to skip for pagination (default: 0)"),
|
|
62
|
+
}, createToolHandler(async (args) => client.getStarredIssues({
|
|
63
|
+
limit: args.limit,
|
|
64
|
+
skip: args.skip,
|
|
65
|
+
})));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=issue-star-tools.js.map
|
package/dist/src/types.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface YoutrackConfig {
|
|
|
12
12
|
holidays?: string[];
|
|
13
13
|
preHolidays?: string[];
|
|
14
14
|
userAliases?: UserAliasMap;
|
|
15
|
+
compactMode: boolean;
|
|
15
16
|
}
|
|
16
17
|
export interface DurationValue {
|
|
17
18
|
minutes?: number;
|
|
@@ -23,6 +24,10 @@ export interface YoutrackProject {
|
|
|
23
24
|
shortName: string;
|
|
24
25
|
name?: string;
|
|
25
26
|
}
|
|
27
|
+
export interface YoutrackIssueWatchers {
|
|
28
|
+
hasStar: boolean;
|
|
29
|
+
$type: string;
|
|
30
|
+
}
|
|
26
31
|
export interface YoutrackIssue {
|
|
27
32
|
id: string;
|
|
28
33
|
idReadable: string;
|
|
@@ -36,6 +41,7 @@ export interface YoutrackIssue {
|
|
|
36
41
|
id?: string;
|
|
37
42
|
} | null;
|
|
38
43
|
assignee?: YoutrackUser | null;
|
|
44
|
+
watchers?: YoutrackIssueWatchers | null;
|
|
39
45
|
}
|
|
40
46
|
export interface YoutrackIssueCreateInput {
|
|
41
47
|
project: string;
|
|
@@ -344,6 +350,7 @@ export interface IssueSearchInput {
|
|
|
344
350
|
startDate?: string | number | Date;
|
|
345
351
|
endDate?: string | number | Date;
|
|
346
352
|
dateFilterMode?: "issue_updated" | "user_activity";
|
|
353
|
+
briefOutput?: boolean;
|
|
347
354
|
limit?: number;
|
|
348
355
|
skip?: number;
|
|
349
356
|
}
|
|
@@ -525,4 +532,41 @@ export interface IssueActivitiesPayload {
|
|
|
525
532
|
skip?: number;
|
|
526
533
|
};
|
|
527
534
|
}
|
|
535
|
+
export interface YoutrackIssueWatcher {
|
|
536
|
+
id: string;
|
|
537
|
+
user: YoutrackUser;
|
|
538
|
+
isStarred: boolean;
|
|
539
|
+
$type: string;
|
|
540
|
+
}
|
|
541
|
+
export interface IssueStarInput {
|
|
542
|
+
issueId: string;
|
|
543
|
+
}
|
|
544
|
+
export interface IssueStarBatchInput {
|
|
545
|
+
issueIds: string[];
|
|
546
|
+
}
|
|
547
|
+
export interface IssueStarPayload {
|
|
548
|
+
issueId: string;
|
|
549
|
+
starred: boolean;
|
|
550
|
+
message?: string;
|
|
551
|
+
}
|
|
552
|
+
export interface IssueStarBatchPayload {
|
|
553
|
+
successful: Array<{
|
|
554
|
+
issueId: string;
|
|
555
|
+
starred: boolean;
|
|
556
|
+
}>;
|
|
557
|
+
failed: Array<{
|
|
558
|
+
issueId: string;
|
|
559
|
+
error: string;
|
|
560
|
+
}>;
|
|
561
|
+
}
|
|
562
|
+
export interface PaginationInfo {
|
|
563
|
+
returned: number;
|
|
564
|
+
limit: number;
|
|
565
|
+
skip: number;
|
|
566
|
+
}
|
|
567
|
+
export interface IssuesStarredPayload {
|
|
568
|
+
issues: MappedYoutrackIssue[];
|
|
569
|
+
returnedCount: number;
|
|
570
|
+
pagination: PaginationInfo;
|
|
571
|
+
}
|
|
528
572
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -46,6 +46,11 @@ export declare function mapIssue(issue: YoutrackIssue): MappedYoutrackIssue;
|
|
|
46
46
|
* Map YoutrackIssueDetails to MappedYoutrackIssueDetails
|
|
47
47
|
*/
|
|
48
48
|
export declare function mapIssueDetails(issue: YoutrackIssueDetails): MappedYoutrackIssueDetails;
|
|
49
|
+
/**
|
|
50
|
+
* Map YoutrackIssue to brief version (without description fields)
|
|
51
|
+
* Used for reducing payload size in issue_search_by_user_activity tool
|
|
52
|
+
*/
|
|
53
|
+
export declare function mapIssueBrief(issue: YoutrackIssue): MappedYoutrackIssue;
|
|
49
54
|
/**
|
|
50
55
|
* Map YoutrackWorkItem to MappedYoutrackWorkItem
|
|
51
56
|
*/
|
|
@@ -48,6 +48,15 @@ export function mapIssueDetails(issue) {
|
|
|
48
48
|
resolved: timestampToIsoDateTime(issue.resolved),
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Map YoutrackIssue to brief version (without description fields)
|
|
53
|
+
* Used for reducing payload size in issue_search_by_user_activity tool
|
|
54
|
+
*/
|
|
55
|
+
export function mapIssueBrief(issue) {
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
|
+
const { description, wikifiedDescription, ...rest } = issue;
|
|
58
|
+
return rest;
|
|
59
|
+
}
|
|
51
60
|
/**
|
|
52
61
|
* Map YoutrackWorkItem to MappedYoutrackWorkItem
|
|
53
62
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
export declare function toolSuccess<T>(payload: T): CallToolResult;
|
|
2
|
+
export declare function toolSuccess<T>(payload: T, compactMode?: boolean): CallToolResult;
|
|
3
3
|
export declare function toolError(error: unknown): CallToolResult;
|
|
4
4
|
//# sourceMappingURL=tool-response.d.ts.map
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { ZodError } from "zod";
|
|
2
|
-
export function toolSuccess(payload) {
|
|
2
|
+
export function toolSuccess(payload, compactMode = true) {
|
|
3
3
|
const structuredContent = {
|
|
4
4
|
success: true,
|
|
5
5
|
payload,
|
|
6
6
|
};
|
|
7
|
+
// In compact mode, minimize content field to reduce context window usage for AI agents.
|
|
8
|
+
// Claude Code (when compactMode=false) gets full data in content field for better accessibility.
|
|
9
|
+
// Other AI agents benefit from minimal content to save context window tokens.
|
|
10
|
+
const contentText = compactMode
|
|
11
|
+
? "Success. Use structuredContent for full data."
|
|
12
|
+
: JSON.stringify(structuredContent, null, 2);
|
|
7
13
|
return {
|
|
8
14
|
content: [
|
|
9
15
|
{
|
|
10
16
|
type: "text",
|
|
11
|
-
text:
|
|
17
|
+
text: contentText,
|
|
12
18
|
},
|
|
13
19
|
],
|
|
14
20
|
structuredContent,
|