@bgx4k3p/huly-mcp-server 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +457 -0
- package/package.json +49 -0
- package/src/client.mjs +2326 -0
- package/src/index.mjs +47 -0
- package/src/mcp.mjs +1140 -0
- package/src/pool.mjs +111 -0
- package/src/server.mjs +1094 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bgx4k3p
|
|
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,457 @@
|
|
|
1
|
+
# Huly MCP Server
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://nodejs.org)
|
|
5
|
+
[](https://modelcontextprotocol.io)
|
|
6
|
+
[](test/integration.test.mjs)
|
|
7
|
+
[](test/integration.test.mjs)
|
|
8
|
+
[](https://www.npmjs.com/package/@bgx4k3p/huly-mcp-server)
|
|
9
|
+
[](https://huly.io)
|
|
10
|
+
[](Dockerfile)
|
|
11
|
+
|
|
12
|
+
MCP and HTTP REST server providing full coverage of the
|
|
13
|
+
[Huly](https://huly.io) SDK — issues, projects, workspaces, members,
|
|
14
|
+
and account management. Tested against self-hosted Huly.
|
|
15
|
+
May also work with [Huly Cloud](https://app.huly.io) (not yet tested).
|
|
16
|
+
|
|
17
|
+
## Why This Exists
|
|
18
|
+
|
|
19
|
+
Huly has no REST API. The only programmatic access is through their JavaScript SDK,
|
|
20
|
+
which connects via WebSocket. This server wraps that SDK and exposes **MCP tools**
|
|
21
|
+
and a **full HTTP REST API** with OpenAPI spec, authentication, rate limiting, and SSE events.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone https://github.com/bgx4k3p/huly-mcp-server.git
|
|
27
|
+
cd huly-mcp-server
|
|
28
|
+
npm install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Authentication
|
|
32
|
+
|
|
33
|
+
You can authenticate with either **email/password** or a **token**.
|
|
34
|
+
|
|
35
|
+
#### Email and Password
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export HULY_URL=https://your-huly-instance.com
|
|
39
|
+
export HULY_EMAIL=your@email.com
|
|
40
|
+
export HULY_PASSWORD=your-password
|
|
41
|
+
export HULY_WORKSPACE=your-workspace
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Token (recommended)
|
|
45
|
+
|
|
46
|
+
Get a token from your Huly credentials — no env vars needed beforehand:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
node src/index.mjs --get-token -e your@email.com -p your-password -u https://your-huly-instance.com
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then use it:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
export HULY_URL=https://your-huly-instance.com
|
|
56
|
+
export HULY_TOKEN=<paste-token-from-above>
|
|
57
|
+
export HULY_WORKSPACE=your-workspace
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The token does not expire. You can store it in a secrets manager or
|
|
61
|
+
`~/.secrets` file and stop exposing your password in environment variables.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Integrations
|
|
66
|
+
|
|
67
|
+
### Claude Code (MCP)
|
|
68
|
+
|
|
69
|
+
Add to your `.mcp.json`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"huly": {
|
|
75
|
+
"command": "node",
|
|
76
|
+
"args": ["path/to/huly-mcp-server/src/index.mjs"],
|
|
77
|
+
"env": {
|
|
78
|
+
"HULY_URL": "https://your-huly-instance.com",
|
|
79
|
+
"HULY_EMAIL": "${HULY_EMAIL}",
|
|
80
|
+
"HULY_PASSWORD": "${HULY_PASSWORD}",
|
|
81
|
+
"HULY_WORKSPACE": "${HULY_WORKSPACE}"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then ask Claude things like:
|
|
89
|
+
|
|
90
|
+
- "List my issues in the OPS project"
|
|
91
|
+
- "Create a bug report for the login page crash"
|
|
92
|
+
- "Summarize the PROJ project — what's overdue?"
|
|
93
|
+
- "Break down this feature into subtasks using the feature template"
|
|
94
|
+
|
|
95
|
+
All tools have detailed descriptions optimized for AI agents.
|
|
96
|
+
MCP Resources are also available at `huly://projects/{id}` and `huly://issues/{id}`.
|
|
97
|
+
|
|
98
|
+
### n8n / Automation Workflows
|
|
99
|
+
|
|
100
|
+
Start the HTTP server:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run start:server
|
|
104
|
+
# Listening on port 3001
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use HTTP Request nodes pointing to `http://localhost:3001/api/...`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# List projects
|
|
111
|
+
curl http://localhost:3001/api/projects
|
|
112
|
+
|
|
113
|
+
# Create an issue
|
|
114
|
+
curl -X POST http://localhost:3001/api/projects/OPS/issues \
|
|
115
|
+
-H "Content-Type: application/json" \
|
|
116
|
+
-d '{"title": "New issue", "priority": "high"}'
|
|
117
|
+
|
|
118
|
+
# Get project summary
|
|
119
|
+
curl http://localhost:3001/api/projects/OPS/summary
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
OpenAPI spec available at `GET /api/openapi.json` for auto-discovery in n8n and other tools.
|
|
123
|
+
|
|
124
|
+
### Docker
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
docker build -t huly-mcp-server .
|
|
128
|
+
|
|
129
|
+
docker run -d \
|
|
130
|
+
-p 3001:3001 \
|
|
131
|
+
-e HULY_URL=https://your-huly-instance.com \
|
|
132
|
+
-e HULY_EMAIL=admin@example.com \
|
|
133
|
+
-e HULY_PASSWORD=secret \
|
|
134
|
+
-e HULY_WORKSPACE=my-workspace \
|
|
135
|
+
huly-mcp-server
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For MCP stdio mode in Docker:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
docker run -i \
|
|
142
|
+
-e HULY_URL=https://your-huly-instance.com \
|
|
143
|
+
-e HULY_EMAIL=admin@example.com \
|
|
144
|
+
-e HULY_PASSWORD=secret \
|
|
145
|
+
-e HULY_WORKSPACE=my-workspace \
|
|
146
|
+
huly-mcp-server node src/mcp.mjs
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Server Configuration
|
|
152
|
+
|
|
153
|
+
These settings control the MCP server itself — authentication, rate limiting,
|
|
154
|
+
connection pooling. They are separate from the Huly credentials above.
|
|
155
|
+
|
|
156
|
+
### Environment Variables
|
|
157
|
+
|
|
158
|
+
| Variable | Required | Default | Description |
|
|
159
|
+
| --- | --- | --- | --- |
|
|
160
|
+
| **Huly Connection** | | | |
|
|
161
|
+
| `HULY_URL` | No | `http://localhost:8087` | Huly instance URL |
|
|
162
|
+
| `HULY_TOKEN` | No | - | Auth token (alternative to email/password) |
|
|
163
|
+
| `HULY_EMAIL` | No | - | Huly login email (required if no token) |
|
|
164
|
+
| `HULY_PASSWORD` | No | - | Huly login password (required if no token) |
|
|
165
|
+
| `HULY_WORKSPACE` | Yes* | - | Default workspace slug |
|
|
166
|
+
| **Server Settings** | | | |
|
|
167
|
+
| `PORT` | No | `3001` | HTTP server port |
|
|
168
|
+
| `MCP_AUTH_TOKEN` | No | - | Bearer token for HTTP server auth (disabled if unset) |
|
|
169
|
+
| `HULY_RATE_LIMIT` | No | `100` | Max requests per minute per IP |
|
|
170
|
+
| `HULY_POOL_TTL_MS` | No | `1800000` | Connection pool TTL in ms (30 min) |
|
|
171
|
+
|
|
172
|
+
*`HULY_WORKSPACE` is required for MCP mode. For HTTP mode it can be
|
|
173
|
+
omitted if every request specifies a workspace via header or query param.
|
|
174
|
+
|
|
175
|
+
### HTTP Server Authentication
|
|
176
|
+
|
|
177
|
+
The HTTP server optionally requires a bearer token. This protects **your server**
|
|
178
|
+
from unauthorized access — it's separate from Huly's own authentication.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Generate a token
|
|
182
|
+
openssl rand -hex 32
|
|
183
|
+
|
|
184
|
+
# Start with auth enabled
|
|
185
|
+
MCP_AUTH_TOKEN=your-token-here npm run start:server
|
|
186
|
+
|
|
187
|
+
# Clients must include it in requests
|
|
188
|
+
curl -H "Authorization: Bearer your-token-here" http://localhost:3001/api/projects
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If `MCP_AUTH_TOKEN` is not set, auth is disabled (fine for local-only usage).
|
|
192
|
+
|
|
193
|
+
MCP stdio mode (Claude Code) does not use this token — stdio is inherently local.
|
|
194
|
+
|
|
195
|
+
### Rate Limiting
|
|
196
|
+
|
|
197
|
+
Per-IP rate limiting is always active. Response headers show current state:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
X-RateLimit-Limit: 100
|
|
201
|
+
X-RateLimit-Remaining: 97
|
|
202
|
+
X-RateLimit-Reset: 1710000000
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Returns `429 Too Many Requests` when exceeded.
|
|
206
|
+
|
|
207
|
+
### SSE Event Stream
|
|
208
|
+
|
|
209
|
+
Subscribe to real-time mutation events:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
curl -N http://localhost:3001/api/events
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Events: `issue.created`, `issue.updated`, `issue.moved`, `issue.assigned`,
|
|
216
|
+
`issue.comment_added`, `issue.label_added`, `issues.batch_created`,
|
|
217
|
+
`issues.template_created`, and more.
|
|
218
|
+
|
|
219
|
+
### Multi-Workspace
|
|
220
|
+
|
|
221
|
+
All tools/endpoints accept an optional workspace parameter. The connection pool caches clients by workspace slug:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# MCP: pass workspace in tool arguments
|
|
225
|
+
{"tool": "list_projects", "arguments": {"workspace": "workspace-a"}}
|
|
226
|
+
|
|
227
|
+
# HTTP: via header or query param
|
|
228
|
+
curl -H "X-Huly-Workspace: workspace-a" http://localhost:3001/api/projects
|
|
229
|
+
curl "http://localhost:3001/api/projects?workspace=workspace-b"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Testing
|
|
235
|
+
|
|
236
|
+
Uses Node.js built-in `node:test` and `node:assert` — no test framework dependencies.
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npm test
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
| Section | Tests | Description |
|
|
243
|
+
| --- | --- | --- |
|
|
244
|
+
| **Unit** | 28 | Constants, ID parsing, route matching, rate limiting, auth |
|
|
245
|
+
| **Integration** | 43 | Full CRUD lifecycle against live Huly |
|
|
246
|
+
| **Account-Level** | 11 | Workspaces, profile, social IDs |
|
|
247
|
+
| **Mock** | 28 | Destructive ops, token auth via mocks |
|
|
248
|
+
| **HTTP Server** | 52 | Every REST endpoint via real HTTP requests |
|
|
249
|
+
|
|
250
|
+
**100% method coverage.** All test issues are prefixed with `[TEST]` and cleaned up after each run.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Network Configurations
|
|
255
|
+
|
|
256
|
+
- **Local:** `HULY_URL=http://localhost:8087`
|
|
257
|
+
- **Remote:** `HULY_URL=https://huly.example.com`
|
|
258
|
+
- **Behind nginx proxy:** Point to the proxy port
|
|
259
|
+
|
|
260
|
+
### Cloudflare Access / Tunnel
|
|
261
|
+
|
|
262
|
+
If Huly is behind Cloudflare Access with MFA, create a
|
|
263
|
+
bypass Application for `/_*` or these individual paths:
|
|
264
|
+
|
|
265
|
+
- `/_accounts`
|
|
266
|
+
- `/_transactor`
|
|
267
|
+
- `/_collaborator`
|
|
268
|
+
- `/_rekoni`
|
|
269
|
+
- `/config.json`
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Architecture
|
|
274
|
+
|
|
275
|
+
```text
|
|
276
|
+
src/
|
|
277
|
+
client.mjs # HulyClient class - all business logic
|
|
278
|
+
pool.mjs # Connection pool - caches clients by workspace with TTL
|
|
279
|
+
mcp.mjs # MCP stdio entry point - MCP tools + resources
|
|
280
|
+
server.mjs # HTTP REST entry point - auth, rate limiting, SSE, OpenAPI
|
|
281
|
+
index.mjs # Backwards compat - re-exports mcp.mjs
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
Claude Code -> stdio -> mcp.mjs -> pool.mjs -> client.mjs -> REST -> Huly
|
|
286
|
+
n8n / curl -> HTTP -> server.mjs -> pool.mjs -> client.mjs -> REST -> Huly
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## API Reference
|
|
292
|
+
|
|
293
|
+
Full list of all MCP tools and HTTP endpoints available through this server.
|
|
294
|
+
|
|
295
|
+
### MCP Tools
|
|
296
|
+
|
|
297
|
+
#### Account & Workspace Management
|
|
298
|
+
|
|
299
|
+
| Tool | Description |
|
|
300
|
+
| --- | --- |
|
|
301
|
+
| `list_workspaces` | List all accessible workspaces |
|
|
302
|
+
| `get_workspace_info` | Get workspace details by slug |
|
|
303
|
+
| `create_workspace` | Create a new workspace |
|
|
304
|
+
| `update_workspace_name` | Rename a workspace |
|
|
305
|
+
| `delete_workspace` | Permanently delete a workspace |
|
|
306
|
+
| `get_workspace_members` | List workspace members and roles |
|
|
307
|
+
| `update_workspace_role` | Change a member's role |
|
|
308
|
+
| `get_account_info` | Get current user's account info |
|
|
309
|
+
| `get_user_profile` | Get current user's profile |
|
|
310
|
+
| `set_my_profile` | Update profile fields |
|
|
311
|
+
| `change_password` | Change password |
|
|
312
|
+
| `change_username` | Change username |
|
|
313
|
+
|
|
314
|
+
#### Invites
|
|
315
|
+
|
|
316
|
+
| Tool | Description |
|
|
317
|
+
| --- | --- |
|
|
318
|
+
| `send_invite` | Send workspace invite email |
|
|
319
|
+
| `resend_invite` | Resend pending invite |
|
|
320
|
+
| `create_invite_link` | Generate shareable invite link |
|
|
321
|
+
|
|
322
|
+
#### Integrations, Mailboxes, Social IDs, Subscriptions
|
|
323
|
+
|
|
324
|
+
| Tool | Description |
|
|
325
|
+
| --- | --- |
|
|
326
|
+
| `list_integrations` / `get_integration` / `create_integration` / `update_integration` / `delete_integration` | Full CRUD for integrations |
|
|
327
|
+
| `list_mailboxes` / `create_mailbox` / `delete_mailbox` | Mailbox management |
|
|
328
|
+
| `find_person_by_social_key` / `get_social_ids` / `add_email_social_id` | Person/social ID management |
|
|
329
|
+
| `list_subscriptions` | List account subscriptions |
|
|
330
|
+
|
|
331
|
+
#### Projects & Issues
|
|
332
|
+
|
|
333
|
+
| Tool | Description |
|
|
334
|
+
| --- | --- |
|
|
335
|
+
| `list_projects` / `get_project` | Browse projects |
|
|
336
|
+
| `list_issues` / `get_issue` / `create_issue` / `update_issue` | Full issue CRUD with filtering |
|
|
337
|
+
| `search_issues` | Full-text search across projects |
|
|
338
|
+
| `get_my_issues` | Issues assigned to current user |
|
|
339
|
+
| `batch_create_issues` | Create multiple issues at once |
|
|
340
|
+
| `move_issue` | Move issue between projects |
|
|
341
|
+
| `summarize_project` | Aggregated project metrics |
|
|
342
|
+
| `get_issue_history` | Activity timeline for an issue |
|
|
343
|
+
| `create_issues_from_template` | Create from feature/bug/sprint/release templates |
|
|
344
|
+
|
|
345
|
+
#### Labels, Relations, Milestones, Members, Comments, Time Tracking
|
|
346
|
+
|
|
347
|
+
| Tool | Description |
|
|
348
|
+
| --- | --- |
|
|
349
|
+
| `list_labels` / `create_label` / `add_label` / `remove_label` | Label management |
|
|
350
|
+
| `add_relation` / `add_blocked_by` / `set_parent` | Issue relationships |
|
|
351
|
+
| `list_milestones` / `get_milestone` / `create_milestone` / `set_milestone` | Milestone management |
|
|
352
|
+
| `list_members` / `assign_issue` | Member management |
|
|
353
|
+
| `add_comment` / `list_comments` | Comments |
|
|
354
|
+
| `set_due_date` / `set_estimation` / `log_time` | Time tracking |
|
|
355
|
+
| `list_task_types` / `list_statuses` | Metadata |
|
|
356
|
+
|
|
357
|
+
### HTTP REST Endpoints
|
|
358
|
+
|
|
359
|
+
#### System Routes
|
|
360
|
+
|
|
361
|
+
| Method | Path | Description |
|
|
362
|
+
| --- | --- | --- |
|
|
363
|
+
| GET | `/health` | Health check |
|
|
364
|
+
| GET | `/api/openapi.json` | OpenAPI 3.0.3 spec |
|
|
365
|
+
| GET | `/api/events` | SSE event stream |
|
|
366
|
+
|
|
367
|
+
#### Account & Workspace Routes
|
|
368
|
+
|
|
369
|
+
| Method | Path | Description |
|
|
370
|
+
| --- | --- | --- |
|
|
371
|
+
| GET | `/api/workspaces` | List workspaces |
|
|
372
|
+
| GET | `/api/workspaces/:slug/info` | Get workspace info |
|
|
373
|
+
| POST | `/api/workspaces` | Create workspace |
|
|
374
|
+
| PATCH | `/api/workspaces/:slug/name` | Rename workspace |
|
|
375
|
+
| DELETE | `/api/workspaces/:slug` | Delete workspace |
|
|
376
|
+
| GET | `/api/workspaces/:slug/members` | List members |
|
|
377
|
+
| PATCH | `/api/workspaces/:slug/role` | Update member role |
|
|
378
|
+
| POST | `/api/workspaces/:slug/invites` | Send invite |
|
|
379
|
+
| POST | `/api/workspaces/:slug/invite-link` | Create invite link |
|
|
380
|
+
| GET | `/api/account` | Get account info |
|
|
381
|
+
| GET | `/api/profile` | Get user profile |
|
|
382
|
+
| PATCH | `/api/profile` | Update profile |
|
|
383
|
+
| GET | `/api/integrations` | List integrations |
|
|
384
|
+
| POST | `/api/integrations` | Create integration |
|
|
385
|
+
| DELETE | `/api/integrations/:id` | Delete integration |
|
|
386
|
+
| GET | `/api/mailboxes` | List mailboxes |
|
|
387
|
+
| GET | `/api/social-ids` | List social IDs |
|
|
388
|
+
| GET | `/api/subscriptions` | List subscriptions |
|
|
389
|
+
|
|
390
|
+
#### Project & Issue Routes
|
|
391
|
+
|
|
392
|
+
| Method | Path | Description |
|
|
393
|
+
| --- | --- | --- |
|
|
394
|
+
| GET | `/api/projects` | List all projects |
|
|
395
|
+
| GET | `/api/projects/:identifier` | Get project by identifier |
|
|
396
|
+
| GET | `/api/projects/:project/summary` | Project summary with metrics |
|
|
397
|
+
| GET | `/api/projects/:project/issues` | List issues (query: status, priority, label, milestone, limit) |
|
|
398
|
+
| GET | `/api/projects/:project/issues/:number` | Get issue |
|
|
399
|
+
| POST | `/api/projects/:project/issues` | Create issue |
|
|
400
|
+
| PATCH | `/api/issues/:issueId` | Update issue |
|
|
401
|
+
| POST | `/api/issues/:issueId/move` | Move to different project |
|
|
402
|
+
| GET | `/api/issues/:issueId/history` | Get activity history |
|
|
403
|
+
| GET | `/api/my-issues` | Issues assigned to current user |
|
|
404
|
+
| POST | `/api/projects/:project/batch-issues` | Batch create issues |
|
|
405
|
+
| POST | `/api/projects/:project/template` | Create from template |
|
|
406
|
+
| GET | `/api/search?query=...&project=...&limit=...` | Search issues |
|
|
407
|
+
|
|
408
|
+
#### Other Resource Routes
|
|
409
|
+
|
|
410
|
+
| Method | Path | Description |
|
|
411
|
+
| --- | --- | --- |
|
|
412
|
+
| GET | `/api/labels` | List all labels |
|
|
413
|
+
| POST | `/api/labels` | Create label |
|
|
414
|
+
| POST | `/api/issues/:issueId/labels` | Add label to issue |
|
|
415
|
+
| DELETE | `/api/issues/:issueId/labels/:label` | Remove label |
|
|
416
|
+
| POST | `/api/issues/:issueId/relations` | Add relation |
|
|
417
|
+
| POST | `/api/issues/:issueId/blocked-by` | Add blocked-by |
|
|
418
|
+
| POST | `/api/issues/:issueId/parent` | Set parent |
|
|
419
|
+
| GET | `/api/projects/:project/task-types` | List task types |
|
|
420
|
+
| GET | `/api/statuses` | List all statuses |
|
|
421
|
+
| GET | `/api/projects/:project/milestones` | List milestones |
|
|
422
|
+
| GET | `/api/projects/:project/milestones/:name` | Get milestone |
|
|
423
|
+
| POST | `/api/projects/:project/milestones` | Create milestone |
|
|
424
|
+
| PATCH | `/api/issues/:issueId/milestone` | Set/clear milestone |
|
|
425
|
+
| GET | `/api/members` | List workspace members |
|
|
426
|
+
| PATCH | `/api/issues/:issueId/assignee` | Assign/unassign issue |
|
|
427
|
+
| GET | `/api/issues/:issueId/comments` | List comments |
|
|
428
|
+
| POST | `/api/issues/:issueId/comments` | Add comment |
|
|
429
|
+
| PATCH | `/api/issues/:issueId/due-date` | Set/clear due date |
|
|
430
|
+
| PATCH | `/api/issues/:issueId/estimation` | Set estimation |
|
|
431
|
+
| POST | `/api/issues/:issueId/time-logs` | Log time |
|
|
432
|
+
|
|
433
|
+
### Issue Templates
|
|
434
|
+
|
|
435
|
+
Use `create_issues_from_template` (MCP) or `POST /api/projects/:project/template` (HTTP):
|
|
436
|
+
|
|
437
|
+
| Template | Creates |
|
|
438
|
+
| --- | --- |
|
|
439
|
+
| `feature` | Epic + design/implement/test/docs/review sub-issues |
|
|
440
|
+
| `bug` | Bug + reproduce/root-cause/fix/regression-test sub-issues |
|
|
441
|
+
| `sprint` | Planning/standup/review/retro ceremony issues |
|
|
442
|
+
| `release` | Epic + freeze/QA/changelog/staging/prod/verify sub-issues |
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Security
|
|
447
|
+
|
|
448
|
+
`npm audit` reports moderate vulnerabilities in Svelte (SSR XSS).
|
|
449
|
+
These come from Huly SDK transitive dependencies — the SDK shares packages
|
|
450
|
+
with Huly's web frontend. This server never renders HTML or uses Svelte.
|
|
451
|
+
The vulnerabilities are **not exploitable** in this context.
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## License
|
|
456
|
+
|
|
457
|
+
[MIT](LICENSE)
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bgx4k3p/huly-mcp-server",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MCP and HTTP REST server for Huly issue tracking with multi-workspace support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "bgx4k3p",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/bgx4k3p/huly-mcp-server.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/bgx4k3p/huly-mcp-server",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"huly",
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"issue-tracker",
|
|
18
|
+
"rest-api",
|
|
19
|
+
"claude",
|
|
20
|
+
"ai-agent"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"src/",
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"bin": {
|
|
31
|
+
"huly-mcp-server": "src/index.mjs"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"start": "node src/index.mjs",
|
|
35
|
+
"start:mcp": "node src/mcp.mjs",
|
|
36
|
+
"start:server": "node src/server.mjs",
|
|
37
|
+
"test": "node --test test/integration.test.mjs"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@hcengineering/api-client": "^0.7.3",
|
|
41
|
+
"@hcengineering/chunter": "^0.7.0",
|
|
42
|
+
"@hcengineering/core": "^0.7.4",
|
|
43
|
+
"@hcengineering/tags": "^0.7.0",
|
|
44
|
+
"@hcengineering/task": "^0.7.0",
|
|
45
|
+
"@hcengineering/tracker": "^0.7.0",
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
47
|
+
"jsdom": "^29.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|