@abdullahtas/youtrack-mcp-server 0.1.1
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/.github/workflows/publish.yml +27 -0
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/dist/client.d.ts +13 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +68 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/activities.d.ts +4 -0
- package/dist/tools/activities.d.ts.map +1 -0
- package/dist/tools/activities.js +41 -0
- package/dist/tools/activities.js.map +1 -0
- package/dist/tools/attachments.d.ts +4 -0
- package/dist/tools/attachments.d.ts.map +1 -0
- package/dist/tools/attachments.js +31 -0
- package/dist/tools/attachments.js.map +1 -0
- package/dist/tools/commands.d.ts +4 -0
- package/dist/tools/commands.d.ts.map +1 -0
- package/dist/tools/commands.js +43 -0
- package/dist/tools/commands.js.map +1 -0
- package/dist/tools/comments.d.ts +4 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +55 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/custom-fields.d.ts +4 -0
- package/dist/tools/custom-fields.d.ts.map +1 -0
- package/dist/tools/custom-fields.js +41 -0
- package/dist/tools/custom-fields.js.map +1 -0
- package/dist/tools/issues.d.ts +4 -0
- package/dist/tools/issues.d.ts.map +1 -0
- package/dist/tools/issues.js +128 -0
- package/dist/tools/issues.js.map +1 -0
- package/dist/tools/projects.d.ts +4 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +46 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/saved-queries.d.ts +4 -0
- package/dist/tools/saved-queries.d.ts.map +1 -0
- package/dist/tools/saved-queries.js +28 -0
- package/dist/tools/saved-queries.js.map +1 -0
- package/dist/tools/sprints.d.ts +4 -0
- package/dist/tools/sprints.d.ts.map +1 -0
- package/dist/tools/sprints.js +143 -0
- package/dist/tools/sprints.js.map +1 -0
- package/dist/tools/tags.d.ts +4 -0
- package/dist/tools/tags.d.ts.map +1 -0
- package/dist/tools/tags.js +67 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/time-tracking.d.ts +4 -0
- package/dist/tools/time-tracking.d.ts.map +1 -0
- package/dist/tools/time-tracking.js +78 -0
- package/dist/tools/time-tracking.js.map +1 -0
- package/dist/tools/users.d.ts +4 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +36 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/types.d.ts +160 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
- package/src/.gitkeep +0 -0
- package/src/client.ts +86 -0
- package/src/index.ts +52 -0
- package/src/tools/.gitkeep +0 -0
- package/src/tools/activities.ts +67 -0
- package/src/tools/attachments.ts +47 -0
- package/src/tools/commands.ts +64 -0
- package/src/tools/comments.ts +90 -0
- package/src/tools/custom-fields.ts +79 -0
- package/src/tools/issues.ts +174 -0
- package/src/tools/projects.ts +70 -0
- package/src/tools/saved-queries.ts +45 -0
- package/src/tools/sprints.ts +205 -0
- package/src/tools/tags.ts +94 -0
- package/src/tools/time-tracking.ts +111 -0
- package/src/tools/users.ts +54 -0
- package/src/types.ts +129 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: '20'
|
|
19
|
+
registry-url: 'https://registry.npmjs.org'
|
|
20
|
+
|
|
21
|
+
- run: npm ci
|
|
22
|
+
|
|
23
|
+
- run: npm run build
|
|
24
|
+
|
|
25
|
+
- run: npm publish --provenance --access public
|
|
26
|
+
env:
|
|
27
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 abdullahtas
|
|
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,161 @@
|
|
|
1
|
+
# YouTrack MCP Server
|
|
2
|
+
|
|
3
|
+
A comprehensive Model Context Protocol (MCP) server for JetBrains YouTrack. Provides full REST API access through 44 tools for AI agents.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 44 tools covering issues, comments, projects, sprints, custom fields, time tracking, tags, users, activities, attachments, saved queries, and batch commands
|
|
8
|
+
- Works with any YouTrack instance (Cloud or Server)
|
|
9
|
+
- Zero config -- just set two environment variables
|
|
10
|
+
- Full YouTrack query language support
|
|
11
|
+
- Optimized API calls with selective field loading
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @abdullahtas/youtrack-mcp-server
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Requires two environment variables:
|
|
20
|
+
|
|
21
|
+
| Variable | Required | Description |
|
|
22
|
+
|----------|----------|-------------|
|
|
23
|
+
| `YOUTRACK_URL` | Yes | Your YouTrack instance URL (e.g. `https://your-org.youtrack.cloud`) |
|
|
24
|
+
| `YOUTRACK_TOKEN` | Yes | Permanent token for authentication |
|
|
25
|
+
|
|
26
|
+
**How to get a token:** YouTrack Profile -> Authentication -> New token. Grant the scope needed for your use case (typically `YouTrack`).
|
|
27
|
+
|
|
28
|
+
## Usage with Claude Desktop
|
|
29
|
+
|
|
30
|
+
Add the following to your Claude Desktop configuration file:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"youtrack": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["-y", "@abdullahtas/youtrack-mcp-server"],
|
|
38
|
+
"env": {
|
|
39
|
+
"YOUTRACK_URL": "https://your-instance.youtrack.cloud",
|
|
40
|
+
"YOUTRACK_TOKEN": "perm:your-token-here"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage with Claude Code
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
claude mcp add youtrack -- env YOUTRACK_URL=https://your-instance.youtrack.cloud YOUTRACK_TOKEN=perm:xxx npx -y @abdullahtas/youtrack-mcp-server
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Available Tools
|
|
54
|
+
|
|
55
|
+
### Issues
|
|
56
|
+
|
|
57
|
+
| Tool | Description |
|
|
58
|
+
|------|-------------|
|
|
59
|
+
| `create_issue` | Create a new issue in a YouTrack project |
|
|
60
|
+
| `get_issue` | Get details of a specific issue by its readable ID (e.g. "BC-123") |
|
|
61
|
+
| `update_issue` | Update an existing issue (summary and/or description) |
|
|
62
|
+
| `delete_issue` | Delete an issue by its readable ID |
|
|
63
|
+
| `search_issues` | Search for issues using YouTrack query language |
|
|
64
|
+
| `link_issues` | Link two issues together with a specified link type |
|
|
65
|
+
| `get_issue_links` | Get all links for a specific issue |
|
|
66
|
+
|
|
67
|
+
### Comments
|
|
68
|
+
|
|
69
|
+
| Tool | Description |
|
|
70
|
+
|------|-------------|
|
|
71
|
+
| `get_comments` | Get comments for a specific issue |
|
|
72
|
+
| `add_comment` | Add a comment to an issue |
|
|
73
|
+
| `update_comment` | Update an existing comment on an issue |
|
|
74
|
+
| `delete_comment` | Delete a comment from an issue |
|
|
75
|
+
|
|
76
|
+
### Projects
|
|
77
|
+
|
|
78
|
+
| Tool | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| `list_projects` | List all projects in YouTrack |
|
|
81
|
+
| `get_project` | Get details of a specific project |
|
|
82
|
+
| `get_project_issues` | Get issues belonging to a specific project, optionally filtered by query |
|
|
83
|
+
|
|
84
|
+
### Agile & Sprints
|
|
85
|
+
|
|
86
|
+
| Tool | Description |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| `list_agile_boards` | List all agile boards in YouTrack |
|
|
89
|
+
| `get_agile_board` | Get details of a specific agile board including its sprints |
|
|
90
|
+
| `list_sprints` | List all sprints for a specific agile board |
|
|
91
|
+
| `get_sprint` | Get details of a specific sprint including its issues |
|
|
92
|
+
| `get_current_sprint` | Get the current active sprint for a specific agile board |
|
|
93
|
+
| `create_sprint` | Create a new sprint on an agile board |
|
|
94
|
+
| `update_sprint` | Update an existing sprint on an agile board |
|
|
95
|
+
| `add_issue_to_sprint` | Add an issue to a sprint using its readable ID |
|
|
96
|
+
|
|
97
|
+
### Custom Fields
|
|
98
|
+
|
|
99
|
+
| Tool | Description |
|
|
100
|
+
|------|-------------|
|
|
101
|
+
| `get_issue_custom_fields` | Get all custom fields for a specific issue |
|
|
102
|
+
| `update_custom_field` | Update a custom field value on an issue |
|
|
103
|
+
| `get_project_custom_fields` | Get all custom field definitions for a project |
|
|
104
|
+
|
|
105
|
+
### Time Tracking
|
|
106
|
+
|
|
107
|
+
| Tool | Description |
|
|
108
|
+
|------|-------------|
|
|
109
|
+
| `get_work_items` | Get time tracking work items for an issue |
|
|
110
|
+
| `add_work_item` | Add a time tracking work item to an issue |
|
|
111
|
+
| `update_work_item` | Update an existing time tracking work item |
|
|
112
|
+
| `delete_work_item` | Delete a time tracking work item from an issue |
|
|
113
|
+
|
|
114
|
+
### Tags
|
|
115
|
+
|
|
116
|
+
| Tool | Description |
|
|
117
|
+
|------|-------------|
|
|
118
|
+
| `list_tags` | List all issue tags in YouTrack |
|
|
119
|
+
| `create_tag` | Create a new issue tag |
|
|
120
|
+
| `add_tag` | Add a tag to an issue |
|
|
121
|
+
| `remove_tag` | Remove a tag from an issue |
|
|
122
|
+
|
|
123
|
+
### Users
|
|
124
|
+
|
|
125
|
+
| Tool | Description |
|
|
126
|
+
|------|-------------|
|
|
127
|
+
| `get_current_user` | Get the currently authenticated YouTrack user |
|
|
128
|
+
| `list_users` | List YouTrack users |
|
|
129
|
+
| `get_user` | Get a specific YouTrack user by ID |
|
|
130
|
+
|
|
131
|
+
### Activities
|
|
132
|
+
|
|
133
|
+
| Tool | Description |
|
|
134
|
+
|------|-------------|
|
|
135
|
+
| `get_issue_activities` | Get activity history for a specific issue |
|
|
136
|
+
| `get_activities` | Get global activity stream across all issues |
|
|
137
|
+
|
|
138
|
+
### Attachments
|
|
139
|
+
|
|
140
|
+
| Tool | Description |
|
|
141
|
+
|------|-------------|
|
|
142
|
+
| `get_attachments` | Get all attachments for an issue |
|
|
143
|
+
| `delete_attachment` | Delete an attachment from an issue |
|
|
144
|
+
|
|
145
|
+
### Saved Queries
|
|
146
|
+
|
|
147
|
+
| Tool | Description |
|
|
148
|
+
|------|-------------|
|
|
149
|
+
| `list_saved_queries` | List all saved search queries in YouTrack |
|
|
150
|
+
| `create_saved_query` | Create a new saved search query |
|
|
151
|
+
|
|
152
|
+
### Power Tools
|
|
153
|
+
|
|
154
|
+
| Tool | Description |
|
|
155
|
+
|------|-------------|
|
|
156
|
+
| `execute_command` | Execute a YouTrack command on one or more issues (e.g. "State In Progress", "Assignee me") |
|
|
157
|
+
| `raw_query` | Execute a raw YouTrack query and return issues with custom fields specification |
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { YouTrackConfig, PaginationParams } from './types.js';
|
|
2
|
+
export declare class YouTrackClient {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private token;
|
|
5
|
+
constructor(config: YouTrackConfig);
|
|
6
|
+
private get headers();
|
|
7
|
+
private buildUrl;
|
|
8
|
+
get<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
|
|
9
|
+
post<T>(path: string, body?: unknown, params?: Record<string, string | number | undefined>): Promise<T>;
|
|
10
|
+
delete(path: string, params?: Record<string, string | number | undefined>): Promise<void>;
|
|
11
|
+
list<T>(path: string, fields: string, pagination?: PaginationParams, extraParams?: Record<string, string>): Promise<T[]>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElF,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,cAAc;IAKlC,OAAO,KAAK,OAAO,GAMlB;IAED,OAAO,CAAC,QAAQ;IAYV,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYtF,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiBvG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzF,IAAI,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,gBAAgB,EAC7B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,CAAC,EAAE,CAAC;CAShB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export class YouTrackClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
token;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, '');
|
|
6
|
+
this.token = config.token;
|
|
7
|
+
}
|
|
8
|
+
get headers() {
|
|
9
|
+
return {
|
|
10
|
+
Authorization: `Bearer ${this.token}`,
|
|
11
|
+
Accept: 'application/json',
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
buildUrl(path, params) {
|
|
16
|
+
const url = new URL(`${this.baseUrl}/api${path}`);
|
|
17
|
+
if (params) {
|
|
18
|
+
for (const [key, value] of Object.entries(params)) {
|
|
19
|
+
if (value !== undefined) {
|
|
20
|
+
url.searchParams.set(key, String(value));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return url.toString();
|
|
25
|
+
}
|
|
26
|
+
async get(path, params) {
|
|
27
|
+
const url = this.buildUrl(path, params);
|
|
28
|
+
const response = await fetch(url, { method: 'GET', headers: this.headers });
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const error = (await response.json().catch(() => ({ error: response.statusText })));
|
|
31
|
+
throw new Error(`YouTrack API error (${response.status}): ${error.error_description || error.error || response.statusText}`);
|
|
32
|
+
}
|
|
33
|
+
return response.json();
|
|
34
|
+
}
|
|
35
|
+
async post(path, body, params) {
|
|
36
|
+
const url = this.buildUrl(path, params);
|
|
37
|
+
const response = await fetch(url, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: this.headers,
|
|
40
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const error = (await response.json().catch(() => ({ error: response.statusText })));
|
|
44
|
+
throw new Error(`YouTrack API error (${response.status}): ${error.error_description || error.error || response.statusText}`);
|
|
45
|
+
}
|
|
46
|
+
if (response.status === 204)
|
|
47
|
+
return {};
|
|
48
|
+
return response.json();
|
|
49
|
+
}
|
|
50
|
+
async delete(path, params) {
|
|
51
|
+
const url = this.buildUrl(path, params);
|
|
52
|
+
const response = await fetch(url, { method: 'DELETE', headers: this.headers });
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const error = (await response.json().catch(() => ({ error: response.statusText })));
|
|
55
|
+
throw new Error(`YouTrack API error (${response.status}): ${error.error_description || error.error || response.statusText}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async list(path, fields, pagination, extraParams) {
|
|
59
|
+
const params = {
|
|
60
|
+
fields,
|
|
61
|
+
$top: pagination?.top ?? 50,
|
|
62
|
+
$skip: pagination?.skip ?? 0,
|
|
63
|
+
...extraParams,
|
|
64
|
+
};
|
|
65
|
+
return this.get(path, params);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { YouTrackClient } from './client.js';
|
|
5
|
+
import { registerIssueTools } from './tools/issues.js';
|
|
6
|
+
import { registerCommentTools } from './tools/comments.js';
|
|
7
|
+
import { registerProjectTools } from './tools/projects.js';
|
|
8
|
+
import { registerSprintTools } from './tools/sprints.js';
|
|
9
|
+
import { registerCustomFieldTools } from './tools/custom-fields.js';
|
|
10
|
+
import { registerTimeTrackingTools } from './tools/time-tracking.js';
|
|
11
|
+
import { registerTagTools } from './tools/tags.js';
|
|
12
|
+
import { registerUserTools } from './tools/users.js';
|
|
13
|
+
import { registerActivityTools } from './tools/activities.js';
|
|
14
|
+
import { registerAttachmentTools } from './tools/attachments.js';
|
|
15
|
+
import { registerSavedQueryTools } from './tools/saved-queries.js';
|
|
16
|
+
import { registerCommandTools } from './tools/commands.js';
|
|
17
|
+
const YOUTRACK_URL = process.env.YOUTRACK_URL;
|
|
18
|
+
const YOUTRACK_TOKEN = process.env.YOUTRACK_TOKEN;
|
|
19
|
+
if (!YOUTRACK_URL || !YOUTRACK_TOKEN) {
|
|
20
|
+
console.error('Error: YOUTRACK_URL and YOUTRACK_TOKEN environment variables are required.');
|
|
21
|
+
console.error('');
|
|
22
|
+
console.error('Usage:');
|
|
23
|
+
console.error(' YOUTRACK_URL=https://your-instance.youtrack.cloud YOUTRACK_TOKEN=perm:xxx youtrack-mcp-server');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const client = new YouTrackClient({ baseUrl: YOUTRACK_URL, token: YOUTRACK_TOKEN });
|
|
27
|
+
const server = new McpServer({
|
|
28
|
+
name: 'youtrack-mcp-server',
|
|
29
|
+
version: '0.1.0',
|
|
30
|
+
});
|
|
31
|
+
registerIssueTools(server, client);
|
|
32
|
+
registerCommentTools(server, client);
|
|
33
|
+
registerProjectTools(server, client);
|
|
34
|
+
registerSprintTools(server, client);
|
|
35
|
+
registerCustomFieldTools(server, client);
|
|
36
|
+
registerTimeTrackingTools(server, client);
|
|
37
|
+
registerTagTools(server, client);
|
|
38
|
+
registerUserTools(server, client);
|
|
39
|
+
registerActivityTools(server, client);
|
|
40
|
+
registerAttachmentTools(server, client);
|
|
41
|
+
registerSavedQueryTools(server, client);
|
|
42
|
+
registerCommandTools(server, client);
|
|
43
|
+
const transport = new StdioServerTransport();
|
|
44
|
+
await server.connect(transport);
|
|
45
|
+
console.error('YouTrack MCP Server running on stdio');
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;AAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAElD,IAAI,CAAC,YAAY,IAAI,CAAC,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAC5F,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,CAAC,KAAK,CAAC,iGAAiG,CAAC,CAAC;IACjH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;AAEpF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACnC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACzC,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC1C,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACjC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activities.d.ts","sourceRoot":"","sources":["../../src/tools/activities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AASnD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuDrF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const ISSUE_ACTIVITY_FIELDS = 'id,timestamp,author(login,name),category(id),field(name,$type),added(id,name,login,text),removed(id,name,login,text)';
|
|
3
|
+
const ACTIVITY_FIELDS = 'id,timestamp,author(login,name),category(id),target(id,idReadable),field(name,$type),added(id,name,login,text),removed(id,name,login,text)';
|
|
4
|
+
export function registerActivityTools(server, client) {
|
|
5
|
+
server.registerTool('get_issue_activities', {
|
|
6
|
+
description: 'Get activity history for a specific issue',
|
|
7
|
+
inputSchema: z.object({
|
|
8
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
9
|
+
categories: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe('Comma-separated activity categories, e.g. "CommentsCategory,CustomFieldCategory"'),
|
|
13
|
+
top: z.number().optional().default(50).describe('Maximum number of results (default 50)'),
|
|
14
|
+
skip: z.number().optional().default(0).describe('Number of results to skip (default 0)'),
|
|
15
|
+
}),
|
|
16
|
+
}, async (params) => {
|
|
17
|
+
const extraParams = {};
|
|
18
|
+
if (params.categories)
|
|
19
|
+
extraParams.categories = params.categories;
|
|
20
|
+
const result = await client.list(`/issues/${params.issueId}/activities`, ISSUE_ACTIVITY_FIELDS, { top: params.top, skip: params.skip }, extraParams);
|
|
21
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
22
|
+
});
|
|
23
|
+
server.registerTool('get_activities', {
|
|
24
|
+
description: 'Get global activity stream across all issues',
|
|
25
|
+
inputSchema: z.object({
|
|
26
|
+
categories: z
|
|
27
|
+
.string()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe('Comma-separated activity categories, e.g. "CommentsCategory,CustomFieldCategory"'),
|
|
30
|
+
top: z.number().optional().default(50).describe('Maximum number of results (default 50)'),
|
|
31
|
+
skip: z.number().optional().default(0).describe('Number of results to skip (default 0)'),
|
|
32
|
+
}),
|
|
33
|
+
}, async (params) => {
|
|
34
|
+
const extraParams = {};
|
|
35
|
+
if (params.categories)
|
|
36
|
+
extraParams.categories = params.categories;
|
|
37
|
+
const result = await client.list('/activities', ACTIVITY_FIELDS, { top: params.top, skip: params.skip }, extraParams);
|
|
38
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=activities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activities.js","sourceRoot":"","sources":["../../src/tools/activities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,qBAAqB,GACzB,sHAAsH,CAAC;AAEzH,MAAM,eAAe,GACnB,4IAA4I,CAAC;AAE/I,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAsB;IAC7E,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;QACE,WAAW,EAAE,2CAA2C;QACxD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YAChE,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,kFAAkF,CAAC;YAC/F,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;YACzF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACzF,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,WAAW,GAA2B,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,UAAU;YAAE,WAAW,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAElE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B,WAAW,MAAM,CAAC,OAAO,aAAa,EACtC,qBAAqB,EACrB,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EACtC,WAAW,CACZ,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,WAAW,EAAE,8CAA8C;QAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,kFAAkF,CAAC;YAC/F,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;YACzF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACzF,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,WAAW,GAA2B,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,UAAU;YAAE,WAAW,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAElE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B,aAAa,EACb,eAAe,EACf,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EACtC,WAAW,CACZ,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../src/tools/attachments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuCvF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const ATTACHMENT_FIELDS = 'id,name,url,size,mimeType,created,author(login,name)';
|
|
3
|
+
export function registerAttachmentTools(server, client) {
|
|
4
|
+
server.registerTool('get_attachments', {
|
|
5
|
+
description: 'Get all attachments for an issue',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
8
|
+
}),
|
|
9
|
+
}, async (params) => {
|
|
10
|
+
const result = await client.get(`/issues/${params.issueId}/attachments`, { fields: ATTACHMENT_FIELDS });
|
|
11
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
12
|
+
});
|
|
13
|
+
server.registerTool('delete_attachment', {
|
|
14
|
+
description: 'Delete an attachment from an issue',
|
|
15
|
+
inputSchema: z.object({
|
|
16
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
17
|
+
attachmentId: z.string().describe('Attachment ID'),
|
|
18
|
+
}),
|
|
19
|
+
}, async (params) => {
|
|
20
|
+
await client.delete(`/issues/${params.issueId}/attachments/${params.attachmentId}`);
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
type: 'text',
|
|
25
|
+
text: `Attachment ${params.attachmentId} has been deleted from issue ${params.issueId}.`,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/tools/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,iBAAiB,GAAG,sDAAsD,CAAC;AAEjF,MAAM,UAAU,uBAAuB,CAAC,MAAiB,EAAE,MAAsB;IAC/E,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EAAE,kCAAkC;QAC/C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;SACjE,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAC7B,WAAW,MAAM,CAAC,OAAO,cAAc,EACvC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAC9B,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,WAAW,EAAE,oCAAoC;QACjD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;YAChE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;SACnD,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,MAAM,CAAC,OAAO,gBAAgB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACpF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,cAAc,MAAM,CAAC,YAAY,gCAAgC,MAAM,CAAC,OAAO,GAAG;iBACzF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/tools/commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuDpF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const ISSUE_LIST_FIELDS = 'id,idReadable,summary,resolved,project(id,name,shortName),customFields(id,name,$type,value(id,name)),tags(id,name)';
|
|
3
|
+
export function registerCommandTools(server, client) {
|
|
4
|
+
server.registerTool('execute_command', {
|
|
5
|
+
description: 'Execute a YouTrack command on one or more issues (e.g. "State In Progress", "Assignee me", "Priority Critical")',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
query: z.string().describe('YouTrack command string, e.g. "State In Progress"'),
|
|
8
|
+
issues: z
|
|
9
|
+
.array(z.string())
|
|
10
|
+
.describe('Array of issue readable IDs, e.g. ["BC-1", "BC-2"]'),
|
|
11
|
+
}),
|
|
12
|
+
}, async (params) => {
|
|
13
|
+
await client.post('/commands', {
|
|
14
|
+
query: params.query,
|
|
15
|
+
issues: params.issues.map((id) => ({ idReadable: id })),
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: 'text',
|
|
21
|
+
text: `Command "${params.query}" executed successfully on issues: ${params.issues.join(', ')}`,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
server.registerTool('raw_query', {
|
|
27
|
+
description: 'Execute a raw YouTrack query and return issues with custom fields specification. Power-user tool for advanced queries.',
|
|
28
|
+
inputSchema: z.object({
|
|
29
|
+
query: z.string().describe('YouTrack search query string'),
|
|
30
|
+
fields: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.default(ISSUE_LIST_FIELDS)
|
|
34
|
+
.describe('Fields specification for the response'),
|
|
35
|
+
top: z.number().optional().default(50).describe('Maximum number of results (default 50)'),
|
|
36
|
+
skip: z.number().optional().default(0).describe('Number of results to skip (default 0)'),
|
|
37
|
+
}),
|
|
38
|
+
}, async (params) => {
|
|
39
|
+
const result = await client.list('/issues', params.fields, { top: params.top, skip: params.skip }, { query: params.query });
|
|
40
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/tools/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,iBAAiB,GACrB,oHAAoH,CAAC;AAEvH,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAsB;IAC5E,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EACT,iHAAiH;QACnH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;YAC/E,MAAM,EAAE,CAAC;iBACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBACjB,QAAQ,CAAC,oDAAoD,CAAC;SAClE,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;YAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;SACxD,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,YAAY,MAAM,CAAC,KAAK,sCAAsC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBAC/F;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;QACE,WAAW,EACT,wHAAwH;QAC1H,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;YAC1D,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,OAAO,CAAC,iBAAiB,CAAC;iBAC1B,QAAQ,CAAC,uCAAuC,CAAC;YACpD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;YACzF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;SACzF,CAAC;KACH,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B,SAAS,EACT,MAAM,CAAC,MAAM,EACb,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EACtC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CACxB,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/tools/comments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAiFpF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const COMMENT_FIELDS = 'id,text,author(login,name),created,updated';
|
|
3
|
+
const COMMENT_CREATE_FIELDS = 'id,text,author(login,name),created';
|
|
4
|
+
export function registerCommentTools(server, client) {
|
|
5
|
+
server.registerTool('get_comments', {
|
|
6
|
+
description: 'Get comments for a specific issue',
|
|
7
|
+
inputSchema: z.object({
|
|
8
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
9
|
+
top: z.number().optional().describe('Maximum number of comments to return'),
|
|
10
|
+
skip: z.number().optional().describe('Number of comments to skip'),
|
|
11
|
+
}),
|
|
12
|
+
}, async (params) => {
|
|
13
|
+
const result = await client.list(`/issues/${params.issueId}/comments`, COMMENT_FIELDS, { top: params.top, skip: params.skip });
|
|
14
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
15
|
+
});
|
|
16
|
+
server.registerTool('add_comment', {
|
|
17
|
+
description: 'Add a comment to an issue',
|
|
18
|
+
inputSchema: z.object({
|
|
19
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
20
|
+
text: z.string().describe('Comment text'),
|
|
21
|
+
}),
|
|
22
|
+
}, async (params) => {
|
|
23
|
+
const result = await client.post(`/issues/${params.issueId}/comments`, { text: params.text }, { fields: COMMENT_CREATE_FIELDS });
|
|
24
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
25
|
+
});
|
|
26
|
+
server.registerTool('update_comment', {
|
|
27
|
+
description: 'Update an existing comment on an issue',
|
|
28
|
+
inputSchema: z.object({
|
|
29
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
30
|
+
commentId: z.string().describe('Comment ID'),
|
|
31
|
+
text: z.string().describe('Updated comment text'),
|
|
32
|
+
}),
|
|
33
|
+
}, async (params) => {
|
|
34
|
+
const result = await client.post(`/issues/${params.issueId}/comments/${params.commentId}`, { text: params.text }, { fields: COMMENT_FIELDS });
|
|
35
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
36
|
+
});
|
|
37
|
+
server.registerTool('delete_comment', {
|
|
38
|
+
description: 'Delete a comment from an issue',
|
|
39
|
+
inputSchema: z.object({
|
|
40
|
+
issueId: z.string().describe('Issue readable ID, e.g. "BC-123"'),
|
|
41
|
+
commentId: z.string().describe('Comment ID'),
|
|
42
|
+
}),
|
|
43
|
+
}, async (params) => {
|
|
44
|
+
await client.delete(`/issues/${params.issueId}/comments/${params.commentId}`);
|
|
45
|
+
return {
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: 'text',
|
|
49
|
+
text: `Comment ${params.commentId} has been deleted from issue ${params.issueId}.`,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/tools/comments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { YouTrackClient } from '../client.js';
|
|
3
|
+
export declare function registerCustomFieldTools(server: McpServer, client: YouTrackClient): void;
|
|
4
|
+
//# sourceMappingURL=custom-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-fields.d.ts","sourceRoot":"","sources":["../../src/tools/custom-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AASnD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAmExF"}
|