@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 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.1",
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",
@@ -6,5 +6,6 @@ export declare function enrichConfigWithRedaction(config: YoutrackConfig): {
6
6
  timezone: string;
7
7
  holidays: string[] | undefined;
8
8
  preHolidays: string[] | undefined;
9
+ compactMode: boolean;
9
10
  };
10
11
  //# sourceMappingURL=config.d.ts.map
@@ -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) {
@@ -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
- export declare function registerIssueSearchTools(server: McpServer, client: YoutrackClient): void;
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: Each issue includes predefined fields only - id, idReadable, summary, project (id, shortName, name), parent (id, idReadable), assignee (id, login, name). Description is not included to reduce response size - use issue_details or issues_details to get full details. Custom fields are not included.", issueSearchByUserActivityArgs, async (rawInput) => {
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
@@ -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: JSON.stringify(structuredContent, null, 2),
17
+ text: contentText,
12
18
  },
13
19
  ],
14
20
  structuredContent,