huly-mcp-selfhost 2.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/.env.example +29 -2
  2. package/README.md +450 -15
  3. package/dist/connection.js +1 -1
  4. package/dist/connection.js.map +1 -1
  5. package/dist/env.d.ts +1 -0
  6. package/dist/env.js +17 -0
  7. package/dist/env.js.map +1 -0
  8. package/dist/guard.d.ts +28 -0
  9. package/dist/guard.js +152 -0
  10. package/dist/guard.js.map +1 -0
  11. package/dist/index.js +13 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/junit-cli.d.ts +8 -0
  14. package/dist/junit-cli.js +106 -0
  15. package/dist/junit-cli.js.map +1 -0
  16. package/dist/registry.d.ts +18 -0
  17. package/dist/registry.js +316 -0
  18. package/dist/registry.js.map +1 -0
  19. package/dist/resources.d.ts +12 -0
  20. package/dist/resources.js +212 -0
  21. package/dist/resources.js.map +1 -0
  22. package/dist/schemas.d.ts +1352 -435
  23. package/dist/schemas.js +881 -76
  24. package/dist/schemas.js.map +1 -1
  25. package/dist/server.d.ts +14 -1
  26. package/dist/server.js +141 -123
  27. package/dist/server.js.map +1 -1
  28. package/dist/tools/activity.d.ts +10 -0
  29. package/dist/tools/activity.js +62 -0
  30. package/dist/tools/activity.js.map +1 -0
  31. package/dist/tools/agent.d.ts +121 -0
  32. package/dist/tools/agent.js +400 -0
  33. package/dist/tools/agent.js.map +1 -0
  34. package/dist/tools/attachments.d.ts +4 -4
  35. package/dist/tools/calendar.d.ts +49 -0
  36. package/dist/tools/calendar.js +116 -0
  37. package/dist/tools/calendar.js.map +1 -0
  38. package/dist/tools/cards.d.ts +87 -0
  39. package/dist/tools/cards.js +246 -0
  40. package/dist/tools/cards.js.map +1 -0
  41. package/dist/tools/channels.d.ts +78 -9
  42. package/dist/tools/channels.js +86 -5
  43. package/dist/tools/channels.js.map +1 -1
  44. package/dist/tools/comments.d.ts +17 -5
  45. package/dist/tools/comments.js +26 -9
  46. package/dist/tools/comments.js.map +1 -1
  47. package/dist/tools/components.d.ts +28 -4
  48. package/dist/tools/components.js +69 -19
  49. package/dist/tools/components.js.map +1 -1
  50. package/dist/tools/contacts.d.ts +69 -0
  51. package/dist/tools/contacts.js +130 -0
  52. package/dist/tools/contacts.js.map +1 -0
  53. package/dist/tools/crm.d.ts +61 -0
  54. package/dist/tools/crm.js +117 -0
  55. package/dist/tools/crm.js.map +1 -0
  56. package/dist/tools/documents.d.ts +36 -13
  57. package/dist/tools/documents.js +105 -21
  58. package/dist/tools/documents.js.map +1 -1
  59. package/dist/tools/drive.d.ts +107 -0
  60. package/dist/tools/drive.js +277 -0
  61. package/dist/tools/drive.js.map +1 -0
  62. package/dist/tools/fields.d.ts +33 -0
  63. package/dist/tools/fields.js +124 -0
  64. package/dist/tools/fields.js.map +1 -0
  65. package/dist/tools/generic.d.ts +72 -0
  66. package/dist/tools/generic.js +242 -0
  67. package/dist/tools/generic.js.map +1 -0
  68. package/dist/tools/github.d.ts +21 -0
  69. package/dist/tools/github.js +80 -0
  70. package/dist/tools/github.js.map +1 -0
  71. package/dist/tools/hr.d.ts +97 -0
  72. package/dist/tools/hr.js +150 -0
  73. package/dist/tools/hr.js.map +1 -0
  74. package/dist/tools/inbox.d.ts +23 -0
  75. package/dist/tools/inbox.js +76 -0
  76. package/dist/tools/inbox.js.map +1 -0
  77. package/dist/tools/inventory.d.ts +61 -0
  78. package/dist/tools/inventory.js +103 -0
  79. package/dist/tools/inventory.js.map +1 -0
  80. package/dist/tools/issues.d.ts +61 -13
  81. package/dist/tools/issues.js +231 -35
  82. package/dist/tools/issues.js.map +1 -1
  83. package/dist/tools/labels.d.ts +52 -4
  84. package/dist/tools/labels.js +86 -4
  85. package/dist/tools/labels.js.map +1 -1
  86. package/dist/tools/log-time.d.ts +15 -1
  87. package/dist/tools/log-time.js +70 -6
  88. package/dist/tools/log-time.js.map +1 -1
  89. package/dist/tools/meetings.d.ts +30 -0
  90. package/dist/tools/meetings.js +78 -0
  91. package/dist/tools/meetings.js.map +1 -0
  92. package/dist/tools/members.d.ts +1 -1
  93. package/dist/tools/members.js +17 -1
  94. package/dist/tools/members.js.map +1 -1
  95. package/dist/tools/message-templates.d.ts +54 -0
  96. package/dist/tools/message-templates.js +88 -0
  97. package/dist/tools/message-templates.js.map +1 -0
  98. package/dist/tools/milestones.d.ts +40 -5
  99. package/dist/tools/milestones.js +102 -10
  100. package/dist/tools/milestones.js.map +1 -1
  101. package/dist/tools/organizations.d.ts +6 -6
  102. package/dist/tools/overview.d.ts +55 -0
  103. package/dist/tools/overview.js +395 -0
  104. package/dist/tools/overview.js.map +1 -0
  105. package/dist/tools/planner.d.ts +60 -0
  106. package/dist/tools/planner.js +145 -0
  107. package/dist/tools/planner.js.map +1 -0
  108. package/dist/tools/process.d.ts +50 -0
  109. package/dist/tools/process.js +137 -0
  110. package/dist/tools/process.js.map +1 -0
  111. package/dist/tools/products.d.ts +17 -0
  112. package/dist/tools/products.js +45 -0
  113. package/dist/tools/products.js.map +1 -0
  114. package/dist/tools/projects.d.ts +18 -5
  115. package/dist/tools/projects.js +31 -2
  116. package/dist/tools/projects.js.map +1 -1
  117. package/dist/tools/qms.d.ts +57 -0
  118. package/dist/tools/qms.js +171 -0
  119. package/dist/tools/qms.js.map +1 -0
  120. package/dist/tools/recruiting.d.ts +112 -0
  121. package/dist/tools/recruiting.js +203 -0
  122. package/dist/tools/recruiting.js.map +1 -0
  123. package/dist/tools/relations.d.ts +45 -3
  124. package/dist/tools/relations.js +128 -39
  125. package/dist/tools/relations.js.map +1 -1
  126. package/dist/tools/search.d.ts +15 -2
  127. package/dist/tools/search.js +29 -1
  128. package/dist/tools/search.js.map +1 -1
  129. package/dist/tools/sharing.d.ts +62 -0
  130. package/dist/tools/sharing.js +149 -0
  131. package/dist/tools/sharing.js.map +1 -0
  132. package/dist/tools/statuses.d.ts +3 -3
  133. package/dist/tools/surveys.d.ts +22 -0
  134. package/dist/tools/surveys.js +53 -0
  135. package/dist/tools/surveys.js.map +1 -0
  136. package/dist/tools/templates.d.ts +95 -0
  137. package/dist/tools/templates.js +260 -0
  138. package/dist/tools/templates.js.map +1 -0
  139. package/dist/tools/test-automation.d.ts +81 -0
  140. package/dist/tools/test-automation.js +225 -0
  141. package/dist/tools/test-automation.js.map +1 -0
  142. package/dist/tools/testing.d.ts +234 -0
  143. package/dist/tools/testing.js +401 -0
  144. package/dist/tools/testing.js.map +1 -0
  145. package/dist/tools/workspace-admin.d.ts +55 -0
  146. package/dist/tools/workspace-admin.js +117 -0
  147. package/dist/tools/workspace-admin.js.map +1 -0
  148. package/dist/tools/workspaces.d.ts +2 -2
  149. package/dist/utils/attributes.d.ts +37 -0
  150. package/dist/utils/attributes.js +188 -0
  151. package/dist/utils/attributes.js.map +1 -0
  152. package/dist/utils/classes.d.ts +51 -0
  153. package/dist/utils/classes.js +73 -0
  154. package/dist/utils/classes.js.map +1 -0
  155. package/dist/utils/content.d.ts +6 -0
  156. package/dist/utils/content.js +54 -0
  157. package/dist/utils/content.js.map +1 -0
  158. package/dist/utils/errors.js +1 -1
  159. package/dist/utils/errors.js.map +1 -1
  160. package/dist/utils/files.d.ts +5 -0
  161. package/dist/utils/files.js +50 -0
  162. package/dist/utils/files.js.map +1 -0
  163. package/dist/utils/format.d.ts +4 -0
  164. package/dist/utils/format.js +29 -0
  165. package/dist/utils/format.js.map +1 -1
  166. package/dist/utils/junit.d.ts +13 -0
  167. package/dist/utils/junit.js +81 -0
  168. package/dist/utils/junit.js.map +1 -0
  169. package/dist/utils/markdown.js +9 -4
  170. package/dist/utils/markdown.js.map +1 -1
  171. package/dist/utils/people.d.ts +25 -0
  172. package/dist/utils/people.js +80 -0
  173. package/dist/utils/people.js.map +1 -0
  174. package/dist/utils/resolve.d.ts +17 -0
  175. package/dist/utils/resolve.js +54 -0
  176. package/dist/utils/resolve.js.map +1 -0
  177. package/dist/utils/storage.js.map +1 -1
  178. package/dist/utils/tasks.d.ts +22 -0
  179. package/dist/utils/tasks.js +81 -0
  180. package/dist/utils/tasks.js.map +1 -0
  181. package/dist/watch.d.ts +62 -0
  182. package/dist/watch.js +405 -0
  183. package/dist/watch.js.map +1 -0
  184. package/package.json +9 -5
  185. package/scripts/setup.js +3 -1
package/.env.example CHANGED
@@ -18,7 +18,34 @@ HULY_PASSWORD=your-password
18
18
  # Front service (document/description content + file uploads). Not used for discovery.
19
19
  # HULY_FRONT_URL=https://your-huly-instance.com
20
20
 
21
- # ─── Legacy (optional) ───────────────────────────────────────────────────────
22
- # Restrict this server to a single workspace (slug, name or id). Leave unset to
21
+ # ─── Single workspace (optional) ─────────────────────────────────────────────
22
+ # Pin this server to one workspace (slug, name or id). Tools then take no
23
+ # workspace argument, which saves ~20% of the tool-list tokens. Leave unset to
23
24
  # use all workspaces of the account.
24
25
  # HULY_WORKSPACE=your-workspace-slug
26
+
27
+ # ─── Toolsets (optional) ─────────────────────────────────────────────────────
28
+ # Which tool groups to expose (each tool costs context tokens in every session).
29
+ # Default: agent,tracker,documents,chat,contacts,inbox,activity,planner,generic
30
+ # Also available: tracker-admin, calendar, github, generic-write, collaboration, cards,
31
+ # fields, drive, templates, testing, products — or "all".
32
+ # HULY_TOOLSETS=all
33
+ # Start with HULY_TOOLSETS and let Claude load more toolsets on demand (enable_toolsets).
34
+ # Needs a client that handles tools/list_changed.
35
+ # HULY_DYNAMIC_TOOLSETS=1
36
+
37
+ # ─── Guard rails for agents (optional) ───────────────────────────────────────
38
+ # Only allow changes in these projects (reads are never blocked):
39
+ # HULY_WRITE_PROJECTS=TSK,WEB
40
+ # Append every change as one JSON line to this file:
41
+ # HULY_AUDIT_LOG=/var/log/huly-mcp-audit.jsonl
42
+ # Default agent name for claim_issue:
43
+ # HULY_AGENT_NAME=claude
44
+ # Ask before deletes and other risky tools: auto (ask when the client can), strict, off
45
+ # HULY_CONFIRM=auto
46
+
47
+ # ─── Local files (optional) ──────────────────────────────────────────────────
48
+ # upload_file(localPath) / download_file(savePath) only work inside this directory:
49
+ # HULY_FILE_ROOT=/home/me/huly-files
50
+ # How often subscribed huly:// resources are checked for changes (ms):
51
+ # HULY_SUBSCRIBE_POLL_MS=30000
package/README.md CHANGED
@@ -27,41 +27,188 @@ This is a fork of [varaprasadreddy9676/huly-mcp](https://github.com/varaprasadre
27
27
  - **Issue Statuses** — `list_issue_statuses`, `create_issue_status` (custom workflow states)
28
28
  - **Organizations** — `list_organizations`, `get_organization`, `create_organization`, `update_organization`
29
29
 
30
- **Investigated and deliberately not built:** Calendar (not a native event system in Huly — it's a Google Calendar sync bridge requiring infra this fork doesn't assume you're running) and Drive/HR/Recruiting/CRM-Leads/Board (blocked by an [upstream npm packaging bug](https://github.com/hcengineering/platform/issues/10881) — `@hcengineering/*` packages published `0.7.411`+ ship without their `types/` directory, and these modules have no earlier version to pin around it).
30
+ **Beyond the tracker (3.0):** inbox, activity history, planner to-dos and time blocking, calendar events, chat threads/reactions/pins, GitHub pull requests, contact persons — plus generic read access to *every* Huly class (`list_classes`, `describe_class`, `query_documents`) and optional guarded writes (`generic_*`). Modules without a published npm type package (Recruiting, CRM, HR, Board, Drive, …) are reachable through the generic tools; dedicated tools for them follow in 3.1/3.2.
31
+
32
+ **Deliberately not built:** Love (live video office), Gmail/Telegram/Bitrix bridges (need their own service setup), analytics and UI preferences.
31
33
 
32
34
  ---
33
35
 
34
- ## Tools (48 total)
36
+ ## Tools (222 total, grouped in toolsets)
35
37
 
36
38
  All tools except `list_workspaces` take a `workspace` argument — required for every change, optional for reads when only one workspace is available.
37
39
 
40
+ ### Toolsets
41
+
42
+ Every tool schema is sent to the model in each session (Claude Desktop loads all of them up front), so tools are grouped and only the default toolsets are enabled unless you choose otherwise:
43
+
44
+ ```bash
45
+ HULY_TOOLSETS=all # everything
46
+ HULY_TOOLSETS=tracker,documents,planner # just these ('core' = list_workspaces is always on)
47
+ ```
48
+
49
+ **Load on demand** (`HULY_DYNAMIC_TOOLSETS=1`): `HULY_TOOLSETS` becomes the starting set, and Claude loads more toolsets itself via `enable_toolsets`. Called without arguments, it lists every toolset with its tools; called with names, it loads them and tells the client that the tool list changed. With `HULY_TOOLSETS=agent,inbox` a session starts at ≈1.8k tokens instead of ≈9–11k. This needs a client that reloads the tool list on `notifications/tools/list_changed`: it is tested with the MCP SDK client, but **not yet verified in Claude Desktop**. Without the variable, nothing changes.
50
+
51
+ | Toolset | Default | Tools | Contents |
52
+ |---------|:-:|--:|----------|
53
+ | `agent` | ✓ | 12 | agent workflow: my day at a glance, standup, project report, release notes, issue context in one call, start/finish work, plan → issue tree, changes since, claims, repo → project — plus [resources and prompts](#agent-workflow) |
54
+ | `tracker` | ✓ | 37 | projects, issues, comments, time, labels, relations, milestones, components, statuses, attachments, search |
55
+ | `documents` | ✓ | 8 | teamspaces and documents (tree, move, rename) |
56
+ | `chat` | ✓ | 12 | channels, DMs, threads, edit/delete, reactions, pins |
57
+ | `contacts` | ✓ | 11 | members, organizations, persons, contact channels |
58
+ | `inbox` | ✓ | 3 | notifications, triage (what changed since last read), mark read/archive |
59
+ | `activity` | ✓ | 1 | change history of an issue/object |
60
+ | `planner` | ✓ | 5 | to-dos, time blocking |
61
+ | `generic` | ✓ | 4 | fulltext search across everything, read any Huly class |
62
+ | `tracker-admin` | | 12 | rarely needed admin: create/update project, create status, update/delete label, label categories, delete milestone/component, repair parent links, project types and workflows |
63
+ | `calendar` | | 4 | calendar events |
64
+ | `github` | | 2 | pull requests synced by Huly's GitHub integration (read-only) |
65
+ | `generic-write` | | 3 | create/update/delete any class — dry run by default, deletes need `confirm` |
66
+ | `collaboration` | | 8 | followers (collaborators) of issues/documents, public guest links, document comments |
67
+ | `cards` | | 8 | cards: types and tags, create/edit/move/delete, nesting, field values |
68
+ | `fields` | | 3 | custom fields on issues, project types, card types or any class; set values |
69
+ | `drive` | | 10 | drives, folders, versioned files: upload, download, move, restore versions |
70
+ | `templates` | | 11 | issue templates with sub-issues, new issue from template; message templates |
71
+ | `testing` | | 23 | test management: projects, suites, cases, plans, runs, results; JUnit import, report, bugs from failed tests |
72
+ | `products` | | 2 | products and versions (read-only) |
73
+ | `members` | | 4 | workspace settings, invite links and e-mails, member roles |
74
+ | `recruiting` | | 9 | vacancies, candidates, applications |
75
+ | `crm` | | 5 | leads, customers |
76
+ | `hr` | | 7 | departments, staff, vacation/sick/remote days |
77
+ | `inventory` | | 5 | categories, products, variants (SKU) |
78
+ | `meetings` | | 2 | office rooms, meeting minutes and transcripts (read-only) |
79
+ | `qms` | | 4 | controlled documents and trainings (read-only) |
80
+ | `process` | | 4 | process definitions and executions; start and cancel |
81
+ | `surveys` | | 2 | surveys and aggregated poll answers (read-only) |
82
+
83
+ Context cost of `tools/list` (≈3.5 chars/token):
84
+
85
+ | | default (94 tools) | `all` (222 tools) |
86
+ |---|--:|--:|
87
+ | several workspaces | ~38.7k chars ≈ **11k tokens** | ~88.8k chars ≈ **25.4k tokens** |
88
+ | pinned with `HULY_WORKSPACE` | ~31.6k chars ≈ **9k tokens** | ~72k chars ≈ **20.6k tokens** |
89
+
90
+ For comparison, 2.2.0 needed ≈12.8k tokens for 64 tools. **Using one workspace? Set `HULY_WORKSPACE`** — the `workspace` argument then disappears from every tool (−20%). **Claude Code** loads MCP tools on demand, so there even `HULY_TOOLSETS=all` costs little up front.
91
+
92
+ ### Agent workflow
93
+
94
+ Tools, resources and prompts for AI agents working on Huly issues (toolset `agent`):
95
+
96
+ | Tool | What it does |
97
+ |------|--------------|
98
+ | `my_day` | Today (or `date`) in one call: own calendar events and work slots, open to-dos (overdue and due first), open issues assigned to me (in progress first), PRs waiting for my review and my own open PRs, unread inbox grouped by object. Times in UTC |
99
+ | `standup` | What I did since the last working day (Monday → Friday, or `since`): status changes, new issues, comments, time, finished to-dos; then today (calendar, to-dos, my issues) and my issues blocked by open ones |
100
+ | `release_notes` | Release notes from a milestone: done issues as "New and changed" and "Fixes" (by title or label, English and German), merged PR numbers, epics left out; open issues listed separately |
101
+ | `project_report` | Weekly (or `since`: `14d`, ISO date) report of a project: done in the period (status changed to done — not just touched by sync), new, in progress (flagged when untouched), blocked by open issues, overdue, PRs merged and open, open milestones with progress and target, time logged per person. To keep it in Huly, pass the text to `create_document` + `update_document` |
102
+ | `get_issue_context` | Everything about an issue in one call: fields, description, parent chain, sub-issues, blocked by / blocks, related, PRs, comments, suggested branch name |
103
+ | `start_work` | Status → In Progress, assign to me, optionally claim — returns the full context |
104
+ | `finish_work` | Work summary as comment, PR (`#12`, URL or Huly id) linked as sub-issue, status → Review in progress, claim released. Validates the PR before changing anything |
105
+ | `create_issue_tree` | Plan → epic + sub-issues with priorities, components, milestones, assignees, labels and blockers (`"#2"` = second child). Same-title issues are reused, dry run by default |
106
+ | `changes_since` | Issues/PRs changed since `24h`, `7d` or an ISO time — which fields changed, new comments, by whom |
107
+ | `find_project_for_repo` | Workspace + project linked to a GitHub repo (`owner/name`, URL or git remote) via Huly's GitHub integration |
108
+ | `claim_issue` / `release_issue` | Lease an issue to an agent (label `agent:working` + comment marker) so parallel agents skip it; expires after `minutes` |
109
+
110
+ **Resources** — `huly://<workspace>/issue/<PROJ-12>` and `huly://<workspace>/document/<id>`. Your open assigned issues are listed, so in Claude Code you can `@`-mention them.
111
+
112
+ **Prompts** — `start`, `finish`, `plan`, `triage`, `standup` (in Claude Code: `/mcp__huly__start` …).
113
+
114
+ **Guard rails** (environment):
115
+
116
+ | Variable | Effect |
117
+ |----------|--------|
118
+ | `HULY_WRITE_PROJECTS=TSK,WEB` | Changes are only allowed when every project they touch (project keys and `PROJ-12` ids in the arguments) is listed. Reads are never blocked. Tools without a project (chat, documents, planner) are not affected |
119
+ | `HULY_AUDIT_LOG=/path/audit.jsonl` | Every change is appended as one JSON line (time, tool, shortened arguments, success, first line of the result) |
120
+ | `HULY_AGENT_NAME=claude-2` | Default agent name for claims |
121
+ | `HULY_CONFIRM=auto` | Deletes and other hard-to-undo tools (`delete_*`, `bulk_update_issues`, `move_issue`, `generic_update`/`generic_delete`, `revoke_public_link`, `restore_file_version`) ask you first via MCP elicitation when the client can show a form (Claude Code in an interactive session). `auto` (default): ask when possible, otherwise run as before. `strict`: refuse when the client cannot ask (unattended agents). `off`: never ask. Dry runs never ask |
122
+
123
+ ### Huly hands work to Claude: `huly-mcp watch`
124
+
125
+ `huly-mcp watch` turns Huly into the place where you give Claude work. It polls for open issues that carry a label (`--label claude`) or are assigned to the account it runs as (`--assigned`, the default), and for each one:
126
+
127
+ 1. claims the issue (`claim_issue`), so a second watcher or agent skips it,
128
+ 2. runs a command for it — by default `claude -p` in the current directory, with this MCP server attached and a prompt that says: read the issue, do the work, hand back with `finish_work`,
129
+ 3. releases the claim if the run did not (`finish_work` releases it), and comments on the issue if the run failed or timed out.
130
+
131
+ ```bash
132
+ cd ~/code/my-repo
133
+ npx huly-mcp-selfhost watch --workspace acme --project WEB --label claude --dry-run # what would run
134
+ npx huly-mcp-selfhost watch --workspace acme --project WEB --label claude # poll every 60 s
135
+ ```
136
+
137
+ - **Each issue runs once.** A state file (`~/.huly-mcp/watch-<workspace>.json`) remembers it. To run it again, remove the label and add it again.
138
+ - **The command is yours.** `--command` takes any program; the placeholders `{prompt}` `{issue}` `{title}` `{workspace}` `{agent}` `{trigger}` `{mcpConfig}` are filled in per argument — no shell is involved, so issue titles cannot inject shell commands. The run also gets `HULY_ISSUE`, `HULY_ISSUE_TITLE` and `HULY_WORKSPACE` in its environment. Examples: a GitHub Action (`--command "gh workflow run agent.yml -f issue={issue}"`), or Claude with more tools (`--command "claude -p {prompt} --mcp-config {mcpConfig} --allowedTools mcp__huly,Bash(npm test),Edit"`).
139
+ - **Default command:** `claude -p {prompt} --mcp-config {mcpConfig} --strict-mcp-config --allowedTools mcp__huly --permission-mode acceptEdits`. `{mcpConfig}` is a temporary MCP config that starts this server limited to the watched workspace; the credentials are passed through the environment, not written to the file.
140
+ - **Unattended means careful.** Runs get `HULY_CONFIRM=strict` unless you set it: deletes and other risky tools are refused, because nobody is there to confirm them. `HULY_WRITE_PROJECTS` limits which projects are watched and changed. Issue text reaches the agent as instructions — only watch projects whose writers you trust.
141
+ - **Its own identity.** Give the agent its own Huly account (invite e.g. `claude@your-domain` to the workspace) and start the watcher with that account's credentials (`--env-file agent.env` with `HULY_EMAIL`/`HULY_PASSWORD` or `HULY_TOKEN`). Then you hand work to Claude by assigning an issue to that user, and every comment, status change and claim shows up under its name instead of yours. `--agent <name>` (or `HULY_AGENT_NAME`) names it in claims.
142
+ - Other options: `--interval <sec>`, `--timeout <min>` (default 60), `--once`, `--cwd <dir>`, `--prompt <template>`, `--state <file>`. `huly-mcp watch --help` lists them all.
143
+
144
+ ### CI test results into Huly: `huly-mcp junit`
145
+
146
+ `huly-mcp junit report.xml --project "App"` imports a JUnit XML report as a test run in Huly's test management. Almost every test runner writes JUnit XML (Jest/Vitest with a JUnit reporter, `pytest --junitxml`, `go-junit-report`, Gradle, Maven Surefire, xcpretty). Suites and cases that do not exist yet are created; failed tests keep their message and stack trace. Then ask Claude *"What is flaky in App?"* (`get_test_report`) or *"File bugs for today's failures in PROJ"* (`create_issue_from_test_result`).
147
+
148
+ ```yaml
149
+ # .github/workflows/test.yml (after the test step)
150
+ - name: Report to Huly
151
+ if: always()
152
+ run: npx -y huly-mcp-selfhost junit reports/junit.xml --project "App" --run "CI ${{ github.ref_name }} #${{ github.run_number }}"
153
+ env:
154
+ HULY_URL: ${{ secrets.HULY_URL }}
155
+ HULY_TOKEN: ${{ secrets.HULY_TOKEN }}
156
+ HULY_WORKSPACE: my-workspace
157
+ ```
158
+
159
+ Options: `--run <name>`, `--parent-suite <suite>`, `--no-create` (only existing cases), `--fail-on-failures` (exit code 1 when tests failed), `--dry-run`, `--workspace`. `huly-mcp junit --help` lists them.
160
+
161
+ ### Tool reference
162
+
38
163
  | Category | Tool | Description |
39
164
  |----------|------|-------------|
40
165
  | **Workspaces** | `list_workspaces` | List the workspaces this account can access (name, slug, id) |
41
166
  | **Projects** | `list_projects` | List all projects in a workspace |
42
167
  | | `get_project` | Get project details + available statuses |
43
- | | `create_project` | Create a new tracker project with a unique identifier |
44
- | **Issues** | `list_issues` | List issues with optional status / priority filters |
45
- | | `get_issue` | Get full details of an issue (e.g. `PROJ-42`) |
168
+ | | `create_project` | Create a new tracker project with a unique identifier *(tracker-admin)* |
169
+ | | `update_project` | Change name, description, default assignee or default status *(tracker-admin)* |
170
+ | **Issues** | `list_issues` | List issues — open ones by default (`status: "all"` or a status name for others), filterable by priority, milestone, component, label, assignee, parent; `offset` pages through long lists ("51–100 of 118") |
171
+ | | `get_issue` | Full details of an issue (e.g. `PROJ-42`): assignee, milestone, component, labels, parent, links |
46
172
  | | `create_issue` | Create a new issue (with optional Markdown description) |
47
173
  | | `update_issue` | Update title, description, status, priority, assignee, due date, component, milestone |
48
174
  | | `delete_issue` | Permanently delete an issue by identifier |
175
+ | | `bulk_update_issues` | Same change on many issues at once — validates all before writing |
176
+ | | `move_issue` | Move an issue (with sub-issues, comments, attachments, labels, time) to another project |
177
+ | | `list_sub_issues` | Sub-issue tree of an epic with status and progress |
49
178
  | **Comments** | `add_comment` | Add a comment to an issue |
50
- | | `list_comments` | List all comments on an issue (includes IDs for `delete_comment`) |
179
+ | | `list_comments` | Newest comments on an issue, oldest first (includes IDs for `delete_comment`); comments over 1,500 chars are shortened with a marker unless `full: true` |
180
+ | | `update_comment` | Edit a comment |
51
181
  | | `delete_comment` | Delete a specific comment by ID |
52
182
  | **Time Tracking** | `log_time` | Log hours spent on an issue |
183
+ | | `list_time_reports` | Logged time per issue or project, totals per member, member/date filters |
53
184
  | **Labels** | `list_labels` | List all labels with color + usage count |
54
185
  | | `create_label` | Create a new label with an optional hex color |
55
186
  | | `add_label` | Add a label to an issue (auto-creates if it doesn't exist) |
56
187
  | | `remove_label` | Remove a label from an issue |
188
+ | | `update_label` | Rename or recolor a label (updated on every issue) *(tracker-admin)* |
189
+ | | `delete_label` | Delete a label and remove it from every issue *(tracker-admin)* |
57
190
  | **Relations** | `add_relation` | Mark two issues as related (bidirectional) |
58
191
  | | `add_blocked_by` | Mark an issue as blocked by another issue |
59
192
  | | `set_parent` | Set or clear the parent epic of an issue |
60
- | **Members** | `list_members` | List workspace members |
193
+ | | `remove_relation` | Remove a "related" link |
194
+ | | `remove_blocked_by` | Remove a "blocked by" link |
195
+ | | `repair_parent_links` | Fix sub-issues linked by huly-mcp ≤ 2.1 that don't show under their parent (dry run by default) *(tracker-admin)* |
196
+ | **Members** | `list_members` | List workspace members with names and roles |
197
+ | **Persons** (`contacts`) | `list_persons` | Contact persons with their channels |
198
+ | | `get_person` | Person details, contact channels, organizations |
199
+ | | `create_person` | Create a contact person (with optional channels) |
200
+ | | `update_person` | Change name or city |
201
+ | | `add_contact_channel` | Add email, phone, LinkedIn, … |
202
+ | | `remove_contact_channel` | Remove a contact channel |
61
203
  | **Milestones** | `list_milestones` | List milestones for a project |
62
204
  | | `create_milestone` | Create a milestone with a target date and status |
205
+ | | `get_milestone` | Milestone details with progress (done/open/canceled issues) and the open issues |
206
+ | | `update_milestone` | Change name, target date, status or description |
207
+ | | `delete_milestone` | Delete a milestone; its issues are unassigned or moved (`moveIssuesTo`) *(tracker-admin)* |
63
208
  | **Components** | `list_components` | List components (sub-areas) in a project |
64
209
  | | `create_component` | Create a new component with optional lead |
210
+ | | `update_component` | Change name, description or lead |
211
+ | | `delete_component` | Delete a component; its issues are unassigned or moved (`moveIssuesTo`) *(tracker-admin)* |
65
212
  | **Documents** | `list_teamspaces` | List document teamspaces |
66
213
  | | `create_teamspace` | Create a new teamspace (top-level document folder) |
67
214
  | | `list_documents` | List documents in a teamspace |
@@ -70,21 +217,89 @@ All tools except `list_workspaces` take a `workspace` argument — required for
70
217
  | | `create_document` | Create a new document in a teamspace |
71
218
  | | `update_document` | Write Markdown content to a document — Mermaid diagrams render natively |
72
219
  | | `link_document` | Link a document to an issue — appears in the Relations panel |
220
+ | | `list_documents` | Shows the full document tree; `update_document` also renames and moves (incl. to another teamspace, with sub-documents) |
73
221
  | **Search** | `search_issues` | Full-text search across all issues of a workspace |
222
+ | | `search` | Full-text search across everything — issues, documents, messages, cards, files, persons … (`kinds` filter) *(generic)* |
74
223
  | **Chat** | `list_channels` | List all channels in the workspace |
75
224
  | | `create_channel` | Create a new channel |
76
225
  | | `start_direct_message` | Start (or find) a 1:1 direct message with a workspace member |
77
226
  | | `send_message` | Send a message to a channel or direct message |
78
- | | `list_messages` | List messages in a channel or direct message |
227
+ | | `list_messages` | List messages with authors, ids, replies, reactions, pins |
228
+ | | `list_thread` | A message with its thread replies |
229
+ | | `reply_to_message` | Reply in a thread (channel messages and issue comments) |
230
+ | | `update_message` | Edit a message or reply |
231
+ | | `delete_message` | Delete a message or reply |
232
+ | | `add_reaction` / `remove_reaction` | Emoji reactions |
233
+ | | `pin_message` | Pin or unpin a message |
79
234
  | **Attachments** | `attach_file` | Attach a file to an issue (base64-encoded content) |
80
235
  | | `list_attachments` | List files attached to an issue |
81
236
  | | `delete_attachment` | Delete a file attachment from an issue |
82
237
  | **Issue Statuses** | `list_issue_statuses` | List all issue statuses (workflow states), grouped by phase |
83
- | | `create_issue_status` | Create a new issue status — available in every project immediately |
238
+ | | `create_issue_status` | Create a new issue status — available in every project immediately *(tracker-admin)* |
84
239
  | **Organizations** | `list_organizations` | List all organizations (companies) in the workspace |
85
240
  | | `get_organization` | Get details of an organization, including description |
86
241
  | | `create_organization` | Create a new organization (company contact) |
87
242
  | | `update_organization` | Set the description of an organization from Markdown |
243
+ | **Inbox** (`inbox`) | `list_notifications` | Your notifications, grouped by issue/PR/document |
244
+ | | `triage_inbox` | Work through the inbox in one call: per unread item its status and assignee, which fields changed and the new comments (plain text, shortened) since you last read it |
245
+ | | `mark_notifications_read` | Mark read by object, ids or all; optionally archive |
246
+ | **Activity** (`activity`) | `get_activity` | Who changed what, plus comments, for an issue or object |
247
+ | **Planner** (`planner`) | `list_todos` | Your to-dos (open/done, due date filter) |
248
+ | | `create_todo` | Create a to-do, optionally attached to an issue |
249
+ | | `update_todo` | Change title, due date, priority; mark done/reopen |
250
+ | | `delete_todo` | Delete a to-do |
251
+ | | `schedule_todo` | Block time for a to-do in your calendar |
252
+ | **Calendar** (`calendar`) | `list_events` | Events and work slots in a date range |
253
+ | | `create_event` / `update_event` / `delete_event` | Manage events in your calendar |
254
+ | **GitHub** (`github`) | `list_pull_requests` | PRs by project, issue, state |
255
+ | | `get_pull_request` | State, branches, reviews, review comments, linked issue |
256
+ | **Generic** (`generic`) | `list_classes` | All data classes of the workspace (filter by module, optional counts) |
257
+ | | `describe_class` | Attributes and types of a class |
258
+ | | `query_documents` | Read documents of any class; secrets are redacted |
259
+ | **Generic write** (`generic-write`) | `generic_create` / `generic_update` / `generic_delete` | Any class; dry run by default, deletes also need `confirm: true`; system classes, spaces and credentials are blocked |
260
+ | **Collaboration** (`collaboration`) | `list_collaborators` / `add_collaborator` / `remove_collaborator` | Who follows an issue/document (and gets its notifications) |
261
+ | | `create_public_link` / `list_public_links` / `revoke_public_link` | Read-only guest links for issues and documents |
262
+ | | `list_document_comments` / `add_document_comment` | Comments on documents |
263
+ | **Cards** (`cards`) | `list_card_types` / `create_card_type` / `delete_card_type` | Card types (MasterTags) and tags |
264
+ | | `list_cards` / `get_card` | Cards by type, parent or title; one card with fields, tags, children, content |
265
+ | | `create_card` / `update_card` / `delete_card` | With content (Markdown), parent, tags and field values |
266
+ | **Custom fields** (`fields`) | `list_custom_fields` | Fields of issues, a project type, card type or class — or the values on one object |
267
+ | | `create_custom_field` | string, number, boolean, date, markup, enum (with values) or ref |
268
+ | | `set_custom_fields` | Set values on an issue, card or document (validated against the type) |
269
+ | **Drive** (`drive`) | `list_drives` / `create_drive` / `list_drive_files` | Drives and their folder tree |
270
+ | | `create_folder` / `update_drive_item` / `delete_drive_item` | Folders; rename/move files and folders (across drives too) |
271
+ | | `upload_file` / `download_file` | Base64 or local files under `HULY_FILE_ROOT`; same name → new version |
272
+ | | `list_file_versions` / `restore_file_version` | File history |
273
+ | **Issue templates** (`templates`) | `list_issue_templates` / `get_issue_template` | Templates with their sub-issues |
274
+ | | `create_issue_template` / `update_issue_template` / `delete_issue_template` | Priority, assignee, component, milestone, estimation, labels, sub-issues |
275
+ | | `create_issue_from_template` | New issue plus sub-issues from a template |
276
+ | **Test management** (`testing`) | `list_test_projects` / `create_test_project` | Test projects |
277
+ | | `list_test_cases` / `create_test_suite` / `get_test_case` / `create_test_case` / `update_test_case` / `delete_test_case` | Suites (nested) and cases |
278
+ | | `list_test_plans` / `create_test_plan` | Plans from suites and/or cases |
279
+ | | `create_test_run` / `list_test_runs` / `get_test_run` / `set_test_result` | Runs with Passed/Failed/Blocked results; results can be assigned |
280
+ | | `create_test_cases` | Many cases in one call (e.g. drafted from a spec or an issue); existing names are skipped |
281
+ | | `update_test_suite` / `delete_test_suite` / `update_test_run` / `delete_test_run` / `delete_test_plan` | Rename/move suites (no cycles), delete with `recursive`, run due dates |
282
+ | | `import_test_results` | JUnit XML from CI (Jest, Vitest, pytest, Go, Gradle, Maven, xcpretty …) as a run; missing suites/cases are created, failures keep message and stack trace |
283
+ | | `get_test_report` | Over the latest runs: failing now, flaky (flipped ≥ 2×), blocked, never run, per-suite table |
284
+ | | `create_issue_from_test_result` | Bug from a failed result: steps + failure in the description, related to the test case, comment on the result |
285
+ | **Products** (`products`) | `list_products` / `get_product` | Products and their versions (read-only) |
286
+ | **Labels** (`tracker-admin`) | `list_label_categories` / `create_label_category` / `set_label_category` | Group issue labels |
287
+ | **Project types** (`tracker-admin`) | `list_project_types` | Project types, their task types and status workflows, and which projects use them |
288
+ | **Workspace** (`members`) | `get_workspace_settings` | Your role, members per role, invite defaults, integrations |
289
+ | | `create_invite_link` / `send_invite` / `set_member_role` | Invite links (personal or with use limit and e-mail mask; nothing is sent), invitation e-mails, roles. `send_invite` and `set_member_role` ask for confirmation |
290
+ | **Recruiting** (`recruiting`) | `list_vacancies` / `create_vacancy` / `update_vacancy` | Vacancies with applications per status; archive via `update_vacancy` |
291
+ | | `list_candidates` / `create_candidate` | Candidates (person + title, e-mail, onsite/remote) |
292
+ | | `list_applications` / `create_application` / `update_application` / `delete_application` | Applications `APP-n` through the vacancy's workflow, one per candidate and vacancy |
293
+ | **CRM** (`crm`) | `list_leads` / `create_lead` / `update_lead` / `delete_lead` / `list_customers` | Leads `LEAD-n` in funnels; a new customer (person or organization) can be created with the lead |
294
+ | **HR** (`hr`) | `list_departments` / `create_department` / `delete_department` / `set_department` | Department tree, team leads, members |
295
+ | | `list_time_off` / `create_time_off` / `delete_time_off` | Vacation, sick days, PTO, overtime, remote days |
296
+ | **Inventory** (`inventory`) | `list_inventory` / `create_inventory_category` / `create_inventory_product` / `update_inventory_item` / `delete_inventory_item` | Categories, products, variants with SKU (Huly beta module) |
297
+ | **Message templates** (`templates`) | `list_message_templates` / `get_message_template` / `create_message_template` / `update_message_template` / `delete_message_template` | Reusable texts with `${field}` placeholders |
298
+ | **Meetings** (`meetings`) | `list_meetings` / `get_meeting` | Rooms, meeting minutes, action items and transcripts (read-only) |
299
+ | **QMS** (`qms`) | `list_controlled_documents` / `get_controlled_document` | Controlled documents: version, state, reviewers/approvers, requests, content (read-only) |
300
+ | | `list_trainings` / `get_training` | Trainings, questions (answers optional) and trainee results (read-only) |
301
+ | **Processes** (`process`) | `list_processes` / `list_executions` / `start_process` / `cancel_execution` | Process states and transitions; running executions; run a process on a card like Huly's "Run process" menu (processes that ask for input in the app are refused); cancel asks first |
302
+ | **Surveys** (`surveys`) | `list_surveys` / `get_survey` | Surveys and aggregated poll answers (read-only) |
88
303
 
89
304
  ---
90
305
 
@@ -124,11 +339,12 @@ npm run build
124
339
 
125
340
  ### Docker (network-reachable server, not local stdio)
126
341
 
127
- For deployments where the MCP server needs to be reachable over the network (behind a reverse proxy, remote MCP clients, etc.) rather than launched locally per-client, a prebuilt image is published to GHCR on every push to `main`:
342
+ For deployments where the MCP server needs to be reachable over the network (behind a reverse proxy, remote MCP clients, etc.) rather than launched locally per-client, a prebuilt image is published to Docker Hub and GHCR for every release, for `linux/amd64` and `linux/arm64`:
128
343
 
129
344
  ```bash
130
- docker pull jokeks2023/huly-mcp:latest
345
+ docker pull jokeks2023/huly-mcp:latest # latest release; also :3, :3.1, :3.1.0
131
346
  # also mirrored at ghcr.io/jokeks2023/huly-mcp:latest
347
+ # :edge = latest build from main
132
348
  ```
133
349
 
134
350
  Or with Compose — copy `.env.example` to `.env`, fill in your credentials (no workspace needed), then:
@@ -147,7 +363,7 @@ A single Huly account can belong to several workspaces — e.g. a personal one a
147
363
 
148
364
  - **`list_workspaces`** returns name, slug and id of every available workspace.
149
365
  - **Every other tool takes a `workspace` argument** — the slug, the name or the id (case-insensitive):
150
- `list_projects(workspace="jokeks2023")`, `get_issue(workspace="avms", identifier="PROJ-1")`, `log_time(workspace="jokeks2023", identifier="WEB-12", hours=2)`.
366
+ `list_projects(workspace="jokeks2023")`, `get_issue(workspace="acme", identifier="PROJ-1")`, `log_time(workspace="jokeks2023", identifier="WEB-12", hours=2)`.
151
367
  - **Changes always require `workspace`.** Every tool that creates, updates, deletes, links, sends, attaches or logs something has `workspace` as a required argument — the server never falls back to an implicit, default or "last used" workspace for a write.
152
368
  - **Reads may omit `workspace` only if exactly one workspace is available.** With several, the call fails and lists the options.
153
369
  - **IDs are per workspace.** `PROJ-1`, a document id or a comment id identifies something only together with its workspace — the same id can exist in two workspaces. Pass the same `workspace` you got the id from.
@@ -155,7 +371,7 @@ A single Huly account can belong to several workspaces — e.g. a personal one a
155
371
 
156
372
  **Workspace slug:** the part of the Huly URL after the domain: `huly.app/workbench/`**`myteam`** → `myteam`. You don't need to look it up — `list_workspaces` (or `npm run setup`) prints it.
157
373
 
158
- **Legacy `HULY_WORKSPACE`:** still honoured, but only as an optional *restriction*: if set, this server exposes just that one workspace (as before). Leave it unset to use all workspaces.
374
+ **`HULY_WORKSPACE`:** pins the server to that one workspace. Tools then have no `workspace` argument at all, which saves ~20% of the tool-list tokens. Leave it unset to use all workspaces of the account.
159
375
 
160
376
  ---
161
377
 
@@ -167,10 +383,44 @@ A single Huly account can belong to several workspaces — e.g. a personal one a
167
383
  | `HULY_TOKEN` | one auth option | Account token for SSO accounts (Google/GitHub) — get it with `npm run setup` |
168
384
  | `HULY_ACCOUNTS_URL` | self-hosted only | Account service — login and workspace discovery. Default `https://account.huly.app`. Self-hosted: your instance's accounts URL, e.g. `https://huly.example.com/_accounts` |
169
385
  | `HULY_FRONT_URL` | self-hosted (optional on Cloud) | Front service — document/description content and file uploads. Not involved in login or workspace discovery. Self-hosted: e.g. `https://huly.example.com` |
170
- | `HULY_WORKSPACE` | no (legacy) | Restrict the server to a single workspace |
386
+ | `HULY_WORKSPACE` | no | Pin the server to one workspace; tools then take no `workspace` argument (fewer tokens) |
387
+ | `HULY_DYNAMIC_TOOLSETS` | no | `1`: start with `HULY_TOOLSETS` and load more on demand via `enable_toolsets` (see [Toolsets](#toolsets)) |
388
+ | `HULY_TOOLSETS` | no | Comma-separated toolsets to enable, or `all` (see [Toolsets](#toolsets)). Default: `agent,tracker,documents,chat,contacts,inbox,activity,planner,generic` |
389
+ | `HULY_WRITE_PROJECTS` | no | Only allow changes in these projects, e.g. `TSK,WEB` (see [Agent workflow](#agent-workflow)) |
390
+ | `HULY_AUDIT_LOG` | no | Append every change as JSON line to this file |
391
+ | `HULY_AGENT_NAME` | no | Default agent name for `claim_issue` (default `claude`) |
392
+ | `HULY_CONFIRM` | no | `auto` (default), `strict` or `off` — ask before deletes and other risky tools (see [Agent workflow](#agent-workflow)) |
393
+ | `HULY_FILE_ROOT` | no | Directory for local files: `upload_file` (`localPath`) and `download_file` (`savePath`) only work inside it. Off when unset — the server may run remotely |
394
+ | `HULY_SUBSCRIBE_POLL_MS` | no | How often subscribed `huly://` resources are checked for changes (default 30000, minimum 5000) |
171
395
 
172
396
  ---
173
397
 
398
+ ## Claude Code plugin
399
+
400
+ The repo is also a Claude Code plugin marketplace. The plugin bundles the MCP server with a workflow skill, hooks and commands:
401
+
402
+ ```
403
+ /plugin marketplace add JoKeks2023/huly-mcp
404
+ /plugin install huly@huly-mcp
405
+ ```
406
+
407
+ > **Note:** the plugin starts `huly-mcp-selfhost@^3.0.0` from npm. To try a local checkout instead: `npm run build`, then point `plugin/.mcp.json` at `dist/index.js` and start `claude --plugin-dir ./plugin`.
408
+
409
+ Claude Code then asks for your Huly settings (e-mail + password or token, and for self-hosted Huly the accounts and front URL; passwords and tokens go to the OS keychain).
410
+
411
+ | Part | What it does |
412
+ |------|--------------|
413
+ | MCP server | `huly-mcp-selfhost` via `npx`, configured from the plugin settings (toolsets and writable projects included) |
414
+ | Skill `huly-workflow` | When and how to use Huly while coding: find the project for the repo, duplicate check before new issues, component + milestone, status flow, PR → issue links, epics for plans |
415
+ | Hook on session start | Reports the GitHub repo and branch; a branch like `proj-12-login` points Claude to issue `PROJ-12` (no network, no credentials) |
416
+ | Hook after `gh pr create` / `gh pr merge` | Reminds Claude to link the new PR to its issue (`finish_work`) or to check the status after a merge |
417
+ | `/huly:start [PROJ-12]` | Pick up an issue (from the argument or the branch), load the context, plan |
418
+ | `/huly:finish [PROJ-12] [PR]` | Honest summary, PR link, status to review |
419
+ | `/huly:plan <goal>` | Plan → epic + sub-issues (dry run first) |
420
+ | `/huly:triage`, `/huly:standup [24h]` | Inbox triage, stand-up from recent changes |
421
+
422
+ Without the plugin, the same server works in Claude Code as a plain MCP server (see below); the MCP prompts `start`, `finish`, `plan`, `triage`, `standup` are available there too.
423
+
174
424
  ## Compatible Clients
175
425
 
176
426
  The same MCP server works across all major AI coding tools. All examples use **email + password** and the npm package via `npx`; for SSO accounts replace the two credentials with `"HULY_TOKEN": "your-token"` (see [Authentication](#authentication)). To run a local build instead, replace `npx` + args with `node` + `["/absolute/path/to/huly-mcp/dist/index.js"]`.
@@ -354,7 +604,7 @@ For network access (HTTP/SSE) use the [Docker image](#docker-network-reachable-s
354
604
 
355
605
  **Workspaces:**
356
606
  - *"Which Huly workspaces do I have?"*
357
- - *"List the projects in my AVMS workspace"*
607
+ - *"List the projects in my Acme workspace"*
358
608
  - *"In the jokeks2023 workspace, log 2 hours on WEB-12"*
359
609
 
360
610
  **Projects & issues:**
@@ -371,6 +621,23 @@ For network access (HTTP/SSE) use the [Docker image](#docker-network-reachable-s
371
621
  - *"List milestones for the PROJ project"*
372
622
  - *"Create a component called 'Auth' in PROJ"*
373
623
  - *"List all components in PROJ"*
624
+ - *"How far along is milestone v2.0 Launch in PROJ?"*
625
+ - *"Move the v2.0 Launch milestone to 2026-07-15 and set it to In Progress"*
626
+ - *"Delete milestone 'Beta' in PROJ and move its issues to 'v2.0 Launch'"*
627
+
628
+ **Planning & bulk work:**
629
+ - *"Which issues in milestone v2.0 Launch carry the label 'bug' and are still unassigned?"*
630
+ - *"Set PROJ-12, PROJ-13 and PROJ-20 to In Progress and put them into milestone v2.0 Launch"*
631
+ - *"Show me the sub-issue tree of PROJ-1 and how far along it is"*
632
+ - *"How many hours did we log on PROJ in October, per person?"*
633
+ - *"Move PROJ-42 to the OPS project"*
634
+
635
+ **Inbox, planner, calendar:**
636
+ - *"What's new in my inbox? Mark everything about PROJ-12 as read"*
637
+ - *"Create a to-do 'Review PR' on PROJ-7 due Friday and block 45 minutes tomorrow at 9"*
638
+ - *"What's on my calendar this week?"*
639
+ - *"Show the history of PROJ-12 — who moved it to Done?"*
640
+ - *"Which pull requests are waiting for review in PROJ?"*
374
641
 
375
642
  **Labels & relations:**
376
643
  - *"Add the label 'bug' to PROJ-42"*
@@ -545,8 +812,176 @@ See [`src/connection.ts`](src/connection.ts).
545
812
 
546
813
  ---
547
814
 
815
+ ## Development and CI
816
+
817
+ ```bash
818
+ npm ci && npm run build && npm test
819
+ ```
820
+
821
+ GitHub Actions check every pull request:
822
+
823
+ | Workflow | What it checks |
824
+ |---|---|
825
+ | `ci.yml` | build and tests on Node 20/22/24 (Linux), macOS and Windows; the built server answers `tools/list` over stdio; `npm pack` contents; gitleaks and a personal-data check; the Docker image (build, stdio smoke, Trivy); actionlint; a **token report** comment with the `tools/list` size before and after the PR |
826
+ | `codeql.yml` | CodeQL security analysis (also weekly) |
827
+ | `links.yml` | broken links in Markdown and the site (on PRs that touch them, and weekly → issue) |
828
+ | `dependabot-automerge.yml` | Dependabot patch/minor updates merge by themselves once checks are green; majors and Huly packages wait for review |
829
+ | `scheduled.yml` | nightly live smoke test against a sandbox workspace; weekly: the latest `@hcengineering/*` packages, and Huly modules that have no tools yet (see `.github/huly-modules-ignore.txt`). Failures open or update an issue |
830
+ | `release.yml` | on a `vX.Y.Z` tag: version and changelog check, tests, personal-data check, `npm publish --provenance` (Trusted Publishing), GitHub release from the changelog section, MCP registry entry |
831
+
832
+ Security reports: see [SECURITY.md](SECURITY.md).
833
+
834
+ `test/repo.test.ts` keeps the docs honest: tool counts in this README, the site and `DOCKERHUB.md` must match the registry, the version must match everywhere, and the plugin must be well-formed.
835
+
836
+ **Releasing:**
837
+ 1. Move the `Unreleased` changelog entries under `### X.Y.Z — date`.
838
+ 2. Bump the version in `package.json`, `server.json`, `plugin/.claude-plugin/plugin.json` and `src/server.ts`. The tests check that they agree.
839
+ 3. Merge, then tag `vX.Y.Z` on `main`. The rest runs by itself.
840
+
841
+ **Environments and secrets:**
842
+ - Environment `release` (tags `v*` only): used by `release.yml`. npm Trusted Publishing names this environment.
843
+ - Environment `sandbox`: used by the nightly live jobs.
844
+
845
+ Secrets:
846
+ - `PERSONAL_DATA_PATTERNS`: private terms that must never appear in the repo, one regex per line.
847
+ - `NPM_TOKEN`: fallback only, until Trusted Publishing is set up on npmjs.com.
848
+ - In the environment `sandbox`: `HULY_SMOKE_WORKSPACE`, `HULY_SMOKE_PROJECT`, `HULY_SMOKE_EMAIL` + `HULY_SMOKE_PASSWORD` (or `HULY_SMOKE_TOKEN`), `HULY_SMOKE_ACCOUNTS_URL`, `HULY_SMOKE_FRONT_URL`: a **throwaway** workspace for the nightly live test. Without them the live jobs skip.
849
+
850
+ ---
851
+
548
852
  ## Changelog
549
853
 
854
+ ### Unreleased
855
+
856
+ _Nothing yet._
857
+
858
+ ### 3.1.0 — 2026-11-04
859
+
860
+ First 3.x release on npm. 3.0.0 was only released on GitHub; everything from it is included here.
861
+
862
+ **One call instead of several**
863
+ - **New: `my_day`** (toolset `agent`, on by default) — "what's on today?" in one call: calendar, to-dos, my issues, reviews, unread inbox.
864
+ - **New: `standup`, `triage_inbox`, `release_notes`** — one call each instead of several: yesterday/today/blockers, the inbox with what changed since last read, and release notes from a milestone.
865
+ - **New: `project_report`** (toolset `agent`) — weekly report of a project: done, new, in progress, blocked, overdue, PRs, milestones, time logged.
866
+
867
+ **More of Huly**
868
+ - **New: test management, much more of it** — `import_test_results` and the CLI `huly-mcp junit` bring CI results (JUnit XML) into Huly as test runs; `get_test_report` shows failing, flaky, blocked and never-run cases over the latest runs; `create_issue_from_test_result` turns a failed test into a bug (steps and failure included, related to the test case); `create_test_cases` creates many cases at once; suites can be renamed, moved and deleted, runs renamed, dated and deleted, plans deleted, results assigned.
869
+ - **New: `start_process` / `cancel_execution`** — run a process on a card and cancel a running one. Starting works like Huly's "Run process" menu; Huly's process service then moves the execution on. Processes whose start asks for input in the app are refused, and so is a second run where the process forbids parallel runs. Cancelling asks first.
870
+ - `get_issue` names related non-issue documents (e.g. a test case) instead of showing a bare id.
871
+
872
+ **Changed behaviour**
873
+ - **Changed: `list_issues` lists open issues by default.** Pass `status: "all"` for every issue, or a status name. Long lists show `51–100 of 118` and page with `offset`. In a mature project this cuts the answer by ~80%.
874
+ - **Changed: `list_comments` returns the newest comments** (before: the oldest), still in chronological order. Comments over 1,500 characters are shortened with a visible marker; `full: true` shows them whole. Issue descriptions are never shortened, because `update_issue` replaces them.
875
+ - **Changed: Docker tags.** `latest` now means the latest *release* (before: the latest commit on `main`), and `main` builds are tagged `edge`. There are new tags `3` and `3.1` for release lines, and images are built for `linux/arm64` as well, with an SBOM and provenance.
876
+ - `list_labels`: dead code for the ignored `projectIdentifier` removed. No behaviour change.
877
+
878
+ **Fewer tokens**
879
+ - **Fewer tokens:**
880
+ - With `HULY_WORKSPACE` set, tools take no `workspace` argument (−20% tool-list size). Changes still go to exactly that workspace.
881
+ - Validation limits (`minLength`, `maximum` …) are no longer sent in tool schemas. They are still enforced, with a clear error.
882
+ - `list_issues` uses one line per issue and leaves out "No priority".
883
+ - `list_notifications` shows notification ids only with `ids: true`. Marking read by object (`PROJ-12`) does not need them.
884
+ - **New: load toolsets on demand** (`HULY_DYNAMIC_TOOLSETS=1`, opt-in): start small and let Claude load toolsets with `enable_toolsets`. With `agent,inbox` a session starts at ≈1.8k tokens. Not yet verified in Claude Desktop.
885
+ - Server instructions are 41 % shorter (1,463 → 858 chars). They now point to the one-call overviews (`my_day`, `standup`, `triage_inbox` …); hints that the tool descriptions already carry were dropped.
886
+ - Read tools describe `workspace` more briefly (the rule for omitting it is in the server instructions), which keeps the default set within its context budget.
887
+
888
+ **Security**
889
+ - **Security fixes from code scanning:**
890
+ - Docker image: `mcp-proxy` 0.14.0 with `mcp` 1.30.0 (fixes 5 CVEs); npm is removed from the runtime image (23 alerts in npm's bundled packages); Debian security updates are applied at build time.
891
+ - `uuid` is pinned to 11.1.1 via an npm override (a CVE in 8.3.2, pulled in by Huly's server client).
892
+ - Code: entity decoding in `triage_inbox` no longer double-unescapes (`&amp;lt;` stays `&lt;`); JUnit comment removal is repeated until nothing is left; a check-then-read race in `huly-mcp-setup` is gone.
893
+
894
+ **CI and releases**
895
+ - **CI and automation:**
896
+ - every PR is checked on three platforms, with a token report, a personal-data check, a Docker scan and CodeQL
897
+ - releases publish themselves from a tag
898
+ - a nightly live test runs against a sandbox workspace
899
+ - weekly checks cover new Huly packages and Huly modules without tools
900
+ - see [Development and CI](#development-and-ci)
901
+
902
+ ### 3.0.0 — 2026-11-04
903
+
904
+ One large release instead of several small ones, built in stages (see [#11](https://github.com/JoKeks2023/huly-mcp/issues/11)).
905
+
906
+ Breaking:
907
+ - Tools are grouped into toolsets.
908
+ - `calendar`, `github`, `generic-write` and `tracker-admin` are not enabled by default.
909
+ - `HULY_TOOLSETS=all` enables everything.
910
+
911
+ **Toolsets and the core modules**
912
+ - **New: toolsets** (`HULY_TOOLSETS`) and slimmer tool schemas. The 64 tools of 2.2.0 now cost about 36 % fewer tokens.
913
+ - **New: inbox** — `list_notifications`, `mark_notifications_read`
914
+ - **New: activity** — `get_activity`
915
+ - **New: planner** — `list_todos`, `create_todo`, `update_todo`, `delete_todo`, `schedule_todo`
916
+ - **New: calendar** — `list_events`, `create_event`, `update_event`, `delete_event`
917
+ - **New: chat** — `list_thread`, `reply_to_message`, `update_message`, `delete_message`, `add_reaction`, `remove_reaction`, `pin_message`. `list_messages` now shows authors and message ids.
918
+ - **New: GitHub** — `list_pull_requests`, `get_pull_request`
919
+ - **New: persons** — `list_persons`, `get_person`, `create_person`, `update_person`, `add_contact_channel`, `remove_contact_channel`
920
+ - **New: generic access** — `list_classes`, `describe_class` and `query_documents` (secrets redacted). `generic_create`, `generic_update` and `generic_delete` are opt-in and run as a dry run by default.
921
+
922
+ **Agent workflow**
923
+ - **New: agent workflow** (toolset `agent`, on by default) — `get_issue_context`, `start_work`, `finish_work`, `create_issue_tree`, `changes_since`, `claim_issue`, `release_issue`, `find_project_for_repo`
924
+ - **New: MCP resources** (`huly://…/issue/…`, `huly://…/document/…`)
925
+ - **New: MCP prompts** (`start`, `finish`, `plan`, `triage`, `standup`)
926
+ - **New: guard rails** — `HULY_WRITE_PROJECTS` limits changes to the listed projects, and `HULY_AUDIT_LOG` records every change.
927
+ - **Changed: toolset `tracker-admin`.** These tools are no longer in the default set: `create_project`, `update_project`, `create_issue_status`, `update_label`, `delete_label`, `delete_milestone`, `delete_component`, `repair_parent_links`. Enable them with `HULY_TOOLSETS=…,tracker-admin` or `all`.
928
+
929
+ **Claude Code plugin**
930
+ - **New: Claude Code plugin** (`/plugin marketplace add JoKeks2023/huly-mcp`, `/plugin install huly@huly-mcp`). It bundles:
931
+ - the MCP server with its settings
932
+ - the `huly-workflow` skill
933
+ - session-start and PR hooks
934
+ - the commands `/huly:start`, `/huly:finish`, `/huly:plan`, `/huly:triage`, `/huly:standup`
935
+
936
+ **More of Huly**
937
+ - **New: fulltext search across everything** — `search` (issues, documents, messages, cards, files, persons …)
938
+ - **New: toolset `collaboration`** — followers of issues/documents, public guest links, document comments
939
+ - **New: toolset `cards`** — card types and tags, cards with content, nesting and field values
940
+ - **New: toolset `fields`** — custom fields on issues, project types, card types or any class, and their values
941
+ - **New: toolset `drive`** — drives, folders, versioned files (upload, download, move, restore)
942
+ - **New: toolset `templates`** — issue templates; new issue with sub-issues from a template
943
+ - **New: toolset `testing`** — test projects, suites, cases, plans, runs and results
944
+ - **New: toolset `products`** — products and versions (read-only)
945
+ - **New: label categories** (`tracker-admin`)
946
+ - **New: documents** — `list_documents` shows the whole tree; `update_document` renames and moves (also to another teamspace); new documents are placed after their siblings
947
+ - **New: MCP argument completions** for prompts and `huly://` resources (workspaces, projects, issue ids) and **resource subscriptions** (`notifications/resources/updated` when a subscribed issue or document changes)
948
+
949
+ **Business modules**
950
+ - **New: toolsets `members`, `recruiting`, `crm`, `hr`, `inventory`** — invitations and roles, vacancies/candidates/applications, leads/customers, departments and time off, inventory
951
+ - **New: message templates** (`templates`) and **project types with workflows** (`tracker-admin`)
952
+ - **New, read-only: `meetings`** (minutes, transcripts), **`qms`** (controlled documents, trainings), **`process`**, **`surveys`**
953
+ - Not included: Huly's Board module (hidden and off by default in Huly itself).
954
+
955
+ **Agents**
956
+ - **New: confirmation for risky tools** — deletes, bulk updates, moves, generic writes, revoking links and restoring file versions ask the user via MCP elicitation when the client supports it (`HULY_CONFIRM`). Declining changes nothing.
957
+ - **New: `huly-mcp watch`** — Huly hands work to an agent: issues with a label or assigned to the agent's own account are claimed, passed to `claude -p` (or any command) and released afterwards. Runs are unattended, so they default to `HULY_CONFIRM=strict`.
958
+
959
+ **Fixes**
960
+ - `create_teamspace`, `create_channel`, `start_direct_message` and `create_project` stored the user's social id as member/owner; Huly 0.7 expects the account id. Spaces created with earlier versions may list you twice as member and have no proper owner.
961
+ - Public links created on servers whose `FRONT_URL` is `localhost` are shown with `HULY_FRONT_URL` instead.
962
+ - Empty or unresolved `HULY_*` variables (for example plugin settings left blank) now count as not set.
963
+ - Nested tool errors no longer repeat the "Huly MCP:" prefix.
964
+
965
+ ### 2.2.0 — planning, bulk edits, fixes for Huly 0.7
966
+
967
+ - **New: filters in `list_issues`** — milestone, component, label, assignee, parent (null = without / top-level)
968
+ - **New: `bulk_update_issues`, `move_issue`, `list_sub_issues`, `list_time_reports`**
969
+ - **New: `update_project`, `update_comment`, `update_label`, `delete_label`, `remove_relation`, `remove_blocked_by`**
970
+ - **New: `repair_parent_links`** — re-links sub-issues created by earlier versions (dry run by default)
971
+ - **More detail in `get_issue`** — assignee, milestone, component, labels, parent, blocked by, related
972
+ - **`list_members`** shows names
973
+ - **Fix: `set_parent`** now links like Huly itself (`attachedTo`). Before, sub-issues did not appear under their parent in Huly. Existing links: `repair_parent_links` or `set_parent` again
974
+ - **Fix: people lookup on Huly 0.7** — `log_time` failed ("Could not identify current user"), assigning by name (`assignee`, `lead`) never matched and comment authors showed as "Unknown". People are now resolved via the Employee mixin; names are shown as "First Last" and ambiguous names are rejected
975
+ - **Fix: bold/italic text** in issue, document and organization descriptions no longer breaks into separate lines
976
+ - **Fix: `update_issue`** accepts `componentLabel: null` (as documented) and rejects invalid due dates
977
+
978
+ ### 2.1.0 — milestones & components, security updates
979
+
980
+ - **New: `get_milestone`, `update_milestone`, `delete_milestone`** — progress overview, edit name/date/status/description, delete with issues unassigned or moved via `moveIssuesTo`
981
+ - **New: `update_component`, `delete_component`** — edit name/description/lead, delete with issues unassigned or moved via `moveIssuesTo`
982
+ - **Changed: `list_components`** renders Markdown/ProseMirror descriptions as text
983
+ - **Security:** all open dependency advisories fixed — `@modelcontextprotocol/sdk` 1.32, `ws` 8.22, `zod` 4, `dompurify` 3.4.17 (override)
984
+
550
985
  ### 2.0.0 — multi-workspace
551
986
 
552
987
  Breaking: tools that change data require `workspace`; `HULY_WORKSPACE` only restricts the server to one workspace.