huly-mcp-selfhost 3.5.0 → 3.6.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/CHANGELOG.md +17 -0
- package/README.md +72 -11
- package/dist/index.js +63 -28
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to [huly-mcp-selfhost](https://www.npmjs.com/package/huly-mcp-selfhost). Versions follow [semver](https://semver.org).
|
|
4
4
|
|
|
5
|
+
### 3.6.0 — 2026-11-12
|
|
6
|
+
|
|
7
|
+
- **New: Claude Desktop extension** — `huly-mcp-selfhost.mcpb` on every GitHub release: double-click, enter your Huly login in Claude Desktop's form (password and token go to the system keychain), done — no Node.js, no JSON. Built from the same bundled server; the release smoke-tests it before attaching it.
|
|
8
|
+
- **Clearer tool descriptions** for the tools rated weakest by Glama's Tool Definition Quality Score (`list_todos`, `search`, `create_document`, `delete_comment`, …): verb first, the key default or side effect, the tool to use instead. +732 characters in the default tool list (+1.9 %). `create_document` now points to `update_document` for the body.
|
|
9
|
+
- **`changes_since` is shorter** — fields set when an issue was created count as "new", and when one person made every change the name appears once in the heading (−14 % measured on 14 days of changes).
|
|
10
|
+
- **`triage_inbox`**: a comment that appears on several items (bots commenting on every PR) is shown once in full; GitHub-synced accounts are named by their login (`dependabot[bot] (GitHub)`) instead of "Unknown".
|
|
11
|
+
- **Aliases per tool**: `update_milestone`/`get_milestone` accept `milestoneLabel` for `label`, `update_component` accepts `componentLabel` — the names other tools use.
|
|
12
|
+
- **Release workflow** waits up to 15 minutes for npm before the MCP registry publish and retries it (3.5.1 needed a manual re-run).
|
|
13
|
+
- Website and README: navigation with jump links, back-to-top links, plugin icon for the Claude directory.
|
|
14
|
+
- Issue forms (bug report asks for `check_setup` output), questions in GitHub Discussions, private security reports.
|
|
15
|
+
|
|
16
|
+
### 3.5.1 — 2026-11-11
|
|
17
|
+
|
|
18
|
+
- **Fixed: `resources/list` failed without a usable login** — it tried to list your open issues and errored when the login was missing or wrong (e.g. in an inspector or a client not set up yet). Now the guides are listed and issues are simply left out. Found through Glama's inspection.
|
|
19
|
+
- **Release workflow** waits until npm shows the new version before registering it with the MCP registry (3.5.0 was refused once because npm was a few seconds behind).
|
|
20
|
+
- npm and registry descriptions: 227 tools.
|
|
21
|
+
|
|
5
22
|
### 3.5.0 — 2026-11-11
|
|
6
23
|
|
|
7
24
|
- **Fixed: MCP registry name** — the registry namespace is case-sensitive and must match the GitHub owner: `io.github.JoKeks2023/huly-mcp-selfhost` (was lowercase, refused with 403). A test checks it.
|
package/README.md
CHANGED
|
@@ -8,7 +8,22 @@
|
|
|
8
8
|
|
|
9
9
|
**Huly for AI agents.** An MCP server for [Huly](https://huly.io) — self-hosted or Huly Cloud — that lets Claude and other agents work in your workspaces: issues, epics, milestones, documents, chat, inbox, planner, test management and more. 227 tools, built for agent workflows and to spend as few tokens as possible.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<b><a href="#quick-start">Quick start</a></b> ·
|
|
13
|
+
<a href="#compatible-clients">Clients</a> ·
|
|
14
|
+
<a href="#claude-code-plugin">Claude Code plugin</a> ·
|
|
15
|
+
<a href="#command-line">Command line</a> ·
|
|
16
|
+
<a href="#team-server-over-http">Team server</a> ·
|
|
17
|
+
<a href="#tools-227-total-grouped-in-toolsets">Tools</a> ·
|
|
18
|
+
<a href="#configuration">Configuration</a> ·
|
|
19
|
+
<a href="#authentication">Authentication</a>
|
|
20
|
+
<br>
|
|
21
|
+
<a href="https://jokeks2023.github.io/huly-mcp/">Website</a> ·
|
|
22
|
+
<a href="https://github.com/JoKeks2023/huly-mcp/wiki/">Docs</a> ·
|
|
23
|
+
<a href="https://github.com/JoKeks2023/huly-mcp/blob/main/CHANGELOG.md">Changelog</a> ·
|
|
24
|
+
<a href="https://www.npmjs.com/package/huly-mcp-selfhost">npm</a> ·
|
|
25
|
+
<a href="https://hub.docker.com/r/jokeks2023/huly-mcp">Docker Hub</a>
|
|
26
|
+
</p>
|
|
12
27
|
|
|
13
28
|
## Highlights
|
|
14
29
|
|
|
@@ -21,14 +36,16 @@
|
|
|
21
36
|
- **Claude Code plugin:** `/huly:setup` asks once per repo how Huly is used there and writes the rules; skill, hooks and `/huly:*` commands. Guides and a `setup` prompt for every other MCP client too.
|
|
22
37
|
- **Self-hosted first:** document and description content, file uploads and internal URLs work on `huly-selfhost`; one account, all its workspaces.
|
|
23
38
|
|
|
39
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
40
|
+
|
|
24
41
|
## Tokens, measured
|
|
25
42
|
|
|
26
43
|
What the model reads — measured on a real self-hosted project (≈60 issues):
|
|
27
44
|
|
|
28
45
|
| | Characters | ≈ Tokens |
|
|
29
46
|
|---|--:|--:|
|
|
30
|
-
| Tool list, default toolsets (99 tools, each callable directly) | 38,
|
|
31
|
-
| Tool list, pinned workspace |
|
|
47
|
+
| Tool list, default toolsets (99 tools, each callable directly) | 38,991 | 11.1k |
|
|
48
|
+
| Tool list, pinned workspace | 35,299 | 10.1k |
|
|
32
49
|
| Open issues of a project (one call, ≈30 issues) | 2,768 | 0.8k |
|
|
33
50
|
| One issue with description | 318 | 0.1k |
|
|
34
51
|
| Project report (done, in progress, blocked, milestones, PRs, time) | ~2,700 | 0.8k |
|
|
@@ -40,7 +57,7 @@ Lists default to open items, empty fields are left out, and one call answers wha
|
|
|
40
57
|
|
|
41
58
|
<picture>
|
|
42
59
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/JoKeks2023/huly-mcp/main/docs/assets/benchmark-dark.svg">
|
|
43
|
-
<img alt="Characters per answer: huly-mcp-selfhost needs 2.9× less text per answer (median),
|
|
60
|
+
<img alt="Characters per answer: huly-mcp-selfhost needs 2.9× less text per answer (median), 13× smaller tool definitions, one call instead of up to four" src="https://raw.githubusercontent.com/JoKeks2023/huly-mcp/main/docs/assets/benchmark-light.svg" width="900">
|
|
44
61
|
</picture>
|
|
45
62
|
|
|
46
63
|
Same self-hosted Huly, same questions, the best parameters on both sides, measured 2026-11-11. For the other server only the text content is counted, not the duplicate JSON copy it also returns. Where we return more (components), it is because we include each component's description and code paths.
|
|
@@ -59,13 +76,15 @@ Same self-hosted Huly, same questions, the best parameters on both sides, measur
|
|
|
59
76
|
| Milestones | 208 (1 call) | 503 (1 call) | 2.4× less |
|
|
60
77
|
| Components | 1,302 (1 call) | 692 (1 call) | 2.0× more |
|
|
61
78
|
| Documents of a teamspace | 106 (1 call) | 305 (1 call) | 2.9× less |
|
|
62
|
-
| Tool definitions (49 tools with the same name) |
|
|
79
|
+
| Tool definitions (49 tools with the same name) | 16,579 | 216,890 | 13.1× less |
|
|
63
80
|
|
|
64
81
|
</details>
|
|
65
82
|
|
|
83
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
84
|
+
|
|
66
85
|
## Quick start
|
|
67
86
|
|
|
68
|
-
You need
|
|
87
|
+
You need a Huly account — [Huly Cloud](https://huly.app) or self-hosted — and, except for the Claude Desktop extension, Node.js 20+.
|
|
69
88
|
|
|
70
89
|
**Claude Code** — install the plugin, then fill in its settings when asked:
|
|
71
90
|
|
|
@@ -76,7 +95,9 @@ You need Node.js 20+ and a Huly account — [Huly Cloud](https://huly.app) or se
|
|
|
76
95
|
|
|
77
96
|
Then run `/huly:setup` in a repository. Details: [Claude Code plugin](#claude-code-plugin).
|
|
78
97
|
|
|
79
|
-
**Claude Desktop
|
|
98
|
+
**Claude Desktop** — download [`huly-mcp-selfhost.mcpb`](https://github.com/JoKeks2023/huly-mcp/releases/latest/download/huly-mcp-selfhost.mcpb), double-click it and enter your Huly login. Nothing else to install.
|
|
99
|
+
|
|
100
|
+
**Cursor, VS Code, Windsurf, Zed, …** (or Claude Desktop by hand) — add the server to your client's MCP config:
|
|
80
101
|
|
|
81
102
|
```json
|
|
82
103
|
{
|
|
@@ -105,6 +126,8 @@ Then ask: *"What's on my plate today?"*, *"Plan the login redesign as an epic in
|
|
|
105
126
|
|
|
106
127
|
---
|
|
107
128
|
|
|
129
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
130
|
+
|
|
108
131
|
## Claude Code plugin
|
|
109
132
|
|
|
110
133
|
The repo is also a Claude Code plugin marketplace. The plugin bundles the MCP server with a workflow skill, hooks and commands:
|
|
@@ -114,7 +137,7 @@ The repo is also a Claude Code plugin marketplace. The plugin bundles the MCP se
|
|
|
114
137
|
/plugin install huly@huly-mcp
|
|
115
138
|
```
|
|
116
139
|
|
|
117
|
-
> **Note:** the plugin starts the npm package at exactly its own version (e.g. `huly-mcp-selfhost@3.
|
|
140
|
+
> **Note:** the plugin starts the npm package at exactly its own version (e.g. `huly-mcp-selfhost@3.6.0`; the plugin directory does not accept version ranges), so a plugin update brings the matching server. To try a local checkout instead: `npm run build`, then point `plugin/.mcp.json` at `dist/index.js` and start `claude --plugin-dir ./plugin`.
|
|
118
141
|
|
|
119
142
|
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).
|
|
120
143
|
|
|
@@ -135,6 +158,8 @@ Without the plugin, the same server works in Claude Code as a plain MCP server (
|
|
|
135
158
|
|
|
136
159
|
---
|
|
137
160
|
|
|
161
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
162
|
+
|
|
138
163
|
## Command line
|
|
139
164
|
|
|
140
165
|
Every tool also works from the terminal — for scripts, CI and quick looks without a chat. Same login (`HULY_*` environment or `--env-file`), same safety rules (write scope, audit log, confirmation for hard-to-undo changes).
|
|
@@ -159,6 +184,8 @@ huly-mcp my_day --format json | jq -r .text
|
|
|
159
184
|
|
|
160
185
|
---
|
|
161
186
|
|
|
187
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
188
|
+
|
|
162
189
|
## Tools (227 total, grouped in toolsets)
|
|
163
190
|
|
|
164
191
|
All tools except `list_workspaces` take a `workspace` argument — required for every change, optional for reads when only one workspace is available.
|
|
@@ -210,8 +237,8 @@ Context cost of `tools/list` (≈3.5 chars/token):
|
|
|
210
237
|
|
|
211
238
|
| | default (99 tools) | `all` (227 tools) |
|
|
212
239
|
|---|--:|--:|
|
|
213
|
-
| several workspaces | ~
|
|
214
|
-
| pinned with `HULY_WORKSPACE` | ~
|
|
240
|
+
| several workspaces | ~39.0k chars ≈ **11.1k tokens** | ~84.2k chars ≈ **24.1k tokens** |
|
|
241
|
+
| pinned with `HULY_WORKSPACE` | ~35.3k chars ≈ **10.1k tokens** | ~75.8k chars ≈ **21.7k tokens** |
|
|
215
242
|
|
|
216
243
|
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 (−10%). **Claude Code** loads MCP tools on demand, so there even `HULY_TOOLSETS=all` costs little up front.
|
|
217
244
|
|
|
@@ -434,6 +461,8 @@ Options: `--run <name>`, `--parent-suite <suite>`, `--no-create` (only existing
|
|
|
434
461
|
|
|
435
462
|
---
|
|
436
463
|
|
|
464
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
465
|
+
|
|
437
466
|
## Workspaces (one account, several workspaces)
|
|
438
467
|
|
|
439
468
|
A single Huly account can belong to several workspaces — e.g. a personal one and a team one. This server logs in **once** with your account credentials and discovers every workspace that account can access via the account service (`getUserWorkspaces()`). You **don't configure a workspace** in the environment.
|
|
@@ -452,6 +481,8 @@ A single Huly account can belong to several workspaces — e.g. a personal one a
|
|
|
452
481
|
|
|
453
482
|
---
|
|
454
483
|
|
|
484
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
485
|
+
|
|
455
486
|
## Configuration
|
|
456
487
|
|
|
457
488
|
| Variable | Required | Purpose |
|
|
@@ -479,6 +510,8 @@ A single Huly account can belong to several workspaces — e.g. a personal one a
|
|
|
479
510
|
|
|
480
511
|
---
|
|
481
512
|
|
|
513
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
514
|
+
|
|
482
515
|
## Authentication
|
|
483
516
|
|
|
484
517
|
Create a `.env` file in the project root (or pass via `env` in your client config). No workspace is needed in either option.
|
|
@@ -522,6 +555,8 @@ HULY_FRONT_URL=https://your-huly-instance.com # document content
|
|
|
522
555
|
|
|
523
556
|
---
|
|
524
557
|
|
|
558
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
559
|
+
|
|
525
560
|
## Compatible clients
|
|
526
561
|
|
|
527
562
|
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"]`.
|
|
@@ -532,6 +567,10 @@ The same MCP server works across all major AI coding tools. All examples use **e
|
|
|
532
567
|
|
|
533
568
|
### Claude Desktop
|
|
534
569
|
|
|
570
|
+
**One click:** download [`huly-mcp-selfhost.mcpb`](https://github.com/JoKeks2023/huly-mcp/releases/latest/download/huly-mcp-selfhost.mcpb) and double-click it (or *Settings → Extensions → Advanced settings → Install Extension…*). Claude Desktop shows a form for your Huly login; password and token go to the system keychain. No Node.js or JSON needed — Claude Desktop brings its own Node.js.
|
|
571
|
+
|
|
572
|
+
**Or by hand** in the config file:
|
|
573
|
+
|
|
535
574
|
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
536
575
|
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
537
576
|
|
|
@@ -703,11 +742,13 @@ For network access (HTTP/SSE) use the [Docker image](#docker).
|
|
|
703
742
|
|
|
704
743
|
---
|
|
705
744
|
|
|
745
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
746
|
+
|
|
706
747
|
## Running the server
|
|
707
748
|
|
|
708
749
|
### npx (recommended)
|
|
709
750
|
|
|
710
|
-
Every client example uses `"command": "npx", "args": ["-y", "huly-mcp-selfhost"]`. Pin a version (`huly-mcp-selfhost@3.
|
|
751
|
+
Every client example uses `"command": "npx", "args": ["-y", "huly-mcp-selfhost"]`. Pin a version (`huly-mcp-selfhost@3.6.0`) if you want updates only when you choose.
|
|
711
752
|
|
|
712
753
|
### From source
|
|
713
754
|
|
|
@@ -766,6 +807,8 @@ Set `MCP_ALLOWED_HOSTS` to the host names clients use (DNS-rebinding protection)
|
|
|
766
807
|
|
|
767
808
|
---
|
|
768
809
|
|
|
810
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
811
|
+
|
|
769
812
|
## Example prompts
|
|
770
813
|
|
|
771
814
|
**Workspaces:**
|
|
@@ -824,6 +867,8 @@ Set `MCP_ALLOWED_HOSTS` to the host names clients use (DNS-rebinding protection)
|
|
|
824
867
|
|
|
825
868
|
---
|
|
826
869
|
|
|
870
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
871
|
+
|
|
827
872
|
## Document content
|
|
828
873
|
|
|
829
874
|
### Reading: `get_document`
|
|
@@ -890,6 +935,8 @@ The Mermaid block renders as a live interactive diagram in Huly's document edito
|
|
|
890
935
|
|
|
891
936
|
---
|
|
892
937
|
|
|
938
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
939
|
+
|
|
893
940
|
## Bulk CSV Import
|
|
894
941
|
|
|
895
942
|
Import many issues at once from a CSV file — useful for migrating from other tools:
|
|
@@ -914,6 +961,8 @@ Required column: `title`. Optional: `priority` (Urgent/High/Medium/Low), `status
|
|
|
914
961
|
|
|
915
962
|
---
|
|
916
963
|
|
|
964
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
965
|
+
|
|
917
966
|
## Architecture
|
|
918
967
|
|
|
919
968
|
```text
|
|
@@ -940,6 +989,8 @@ See [`src/connection.ts`](https://github.com/JoKeks2023/huly-mcp/blob/main/src/c
|
|
|
940
989
|
|
|
941
990
|
---
|
|
942
991
|
|
|
992
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
993
|
+
|
|
943
994
|
## Development and CI
|
|
944
995
|
|
|
945
996
|
```bash
|
|
@@ -979,16 +1030,22 @@ Secrets:
|
|
|
979
1030
|
|
|
980
1031
|
---
|
|
981
1032
|
|
|
1033
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
1034
|
+
|
|
982
1035
|
## Changelog
|
|
983
1036
|
|
|
984
1037
|
See [CHANGELOG.md](https://github.com/JoKeks2023/huly-mcp/blob/main/CHANGELOG.md).
|
|
985
1038
|
|
|
986
1039
|
---
|
|
987
1040
|
|
|
1041
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
1042
|
+
|
|
988
1043
|
## Credits
|
|
989
1044
|
|
|
990
1045
|
Started as a fork of [varaprasadreddy9676/huly-mcp](https://github.com/varaprasadreddy9676/huly-mcp) (npm `huly-mcp-sdk`) by SaiVaraprasad Medapati and grown from its 33 tools to 227, with self-hosted support, toolsets, agent workflow and the Claude Code plugin. Published separately as `huly-mcp-selfhost`. Not affiliated with Huly Labs.
|
|
991
1046
|
|
|
1047
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
1048
|
+
|
|
992
1049
|
## Links
|
|
993
1050
|
|
|
994
1051
|
- Website: https://jokeks2023.github.io/huly-mcp/
|
|
@@ -996,6 +1053,10 @@ Started as a fork of [varaprasadreddy9676/huly-mcp](https://github.com/varaprasa
|
|
|
996
1053
|
- npm: https://www.npmjs.com/package/huly-mcp-selfhost · Docker: https://hub.docker.com/r/jokeks2023/huly-mcp · MCP Registry: `io.github.JoKeks2023/huly-mcp-selfhost`
|
|
997
1054
|
- Security: [SECURITY.md](https://github.com/JoKeks2023/huly-mcp/blob/main/SECURITY.md)
|
|
998
1055
|
|
|
1056
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
|
1057
|
+
|
|
999
1058
|
## License
|
|
1000
1059
|
|
|
1001
1060
|
[Eclipse Public License 2.0](https://github.com/JoKeks2023/huly-mcp/blob/main/LICENSE)
|
|
1061
|
+
|
|
1062
|
+
<div align="right"><a href="#huly-mcp-selfhost">↑ Back to top</a></div>
|
package/dist/index.js
CHANGED
|
@@ -90627,7 +90627,7 @@ async function socialIdNames(client, ids) {
|
|
|
90627
90627
|
if (ids.length === 0) return /* @__PURE__ */ new Map();
|
|
90628
90628
|
const identities = await client.findAll(import_contact.default.class.SocialIdentity, { _id: { $in: ids } });
|
|
90629
90629
|
const names2 = await peopleNames(client);
|
|
90630
|
-
return new Map(identities.map((i) => [i._id, names2.get(i.attachedTo) ?? "Unknown"]));
|
|
90630
|
+
return new Map(identities.map((i) => [i._id, names2.get(i.attachedTo) ?? (i.type === "github" && typeof i.value === "string" ? `${i.value} (GitHub)` : "Unknown")]));
|
|
90631
90631
|
}
|
|
90632
90632
|
async function currentAccountUuid(client) {
|
|
90633
90633
|
const me = await currentPerson(client);
|
|
@@ -92316,7 +92316,7 @@ var createDocument = wrapToolHandler(async (args) => {
|
|
|
92316
92316
|
docId
|
|
92317
92317
|
);
|
|
92318
92318
|
return `\u2705 Document **"${args.title}"** created (id: \`${docId}\`) in teamspace "${teamspace.name}".
|
|
92319
|
-
|
|
92319
|
+
Write its content with update_document.`;
|
|
92320
92320
|
});
|
|
92321
92321
|
var deleteDocument = wrapToolHandler(async (args) => {
|
|
92322
92322
|
const client = await getConnection(args.workspace);
|
|
@@ -94223,20 +94223,26 @@ var changesSince = wrapToolHandler(async (args) => {
|
|
|
94223
94223
|
]);
|
|
94224
94224
|
const authors = await socialIdNames(client, [...new Set([...updates, ...comments].map((m) => m.createdBy).filter((x) => x != null))]);
|
|
94225
94225
|
const statusName2 = new Map(statuses.map((s) => [s._id, s.name]));
|
|
94226
|
-
const
|
|
94226
|
+
const rows = issues.map((issue2) => {
|
|
94227
94227
|
const ups = updates.filter((u) => u.attachedTo === issue2._id);
|
|
94228
|
-
const fields = [...new Set(ups.map((u) => u.attributeUpdates?.attrKey).filter((k) => k != null && k !== "rank").map((k) => k === "attachedTo" ? "parent" : k))];
|
|
94229
94228
|
const cs = comments.filter((c) => c.attachedTo === issue2._id);
|
|
94229
|
+
const isNew = issue2.createdOn >= since;
|
|
94230
|
+
const fields = isNew ? [] : [...new Set(ups.map((u) => u.attributeUpdates?.attrKey).filter((k) => k != null && k !== "rank").map((k) => k === "attachedTo" ? "parent" : k))];
|
|
94230
94231
|
const who = [...new Set([...ups, ...cs].map((m) => authors.get(m.createdBy)).filter((n) => n != null))];
|
|
94231
94232
|
const parts = [
|
|
94232
|
-
|
|
94233
|
+
isNew ? "new" : void 0,
|
|
94233
94234
|
fields.length > 0 ? `changed ${fields.join(", ")}` : void 0,
|
|
94234
94235
|
cs.length > 0 ? `+${cs.length} comment(s)` : void 0
|
|
94235
94236
|
].filter((p) => p != null);
|
|
94237
|
+
return { issue: issue2, who, what: parts.length > 0 ? parts.join(" \xB7 ") : "updated" };
|
|
94238
|
+
});
|
|
94239
|
+
const everyone = [...new Set(rows.flatMap((r) => r.who))];
|
|
94240
|
+
const single = everyone.length === 1 && rows.every((r) => r.who.length === 1);
|
|
94241
|
+
const lines = rows.map(({ issue: issue2, who, what }) => {
|
|
94236
94242
|
const kind = issue2._class === C.PullRequest ? "PR " : "";
|
|
94237
|
-
return `- ${kind}**${issue2.identifier}** [${statusName2.get(issue2.status) ?? "?"}] ${issue2.title} \u2014 ${
|
|
94243
|
+
return `- ${kind}**${issue2.identifier}** [${statusName2.get(issue2.status) ?? "?"}] ${issue2.title} \u2014 ${what}${!single && who.length > 0 ? ` (by ${who.join(", ")})` : ""} \xB7 ${formatDate(issue2.modifiedOn)}`;
|
|
94238
94244
|
});
|
|
94239
|
-
return `## Changes since ${new Date(since).toISOString()} (${issues.length}${issues.length === args.limit ? "+" : ""})
|
|
94245
|
+
return `## Changes since ${new Date(since).toISOString()} (${issues.length}${issues.length === args.limit ? "+" : ""})${single ? `, all by ${everyone[0]}` : ""}
|
|
94240
94246
|
|
|
94241
94247
|
${lines.join("\n")}`;
|
|
94242
94248
|
});
|
|
@@ -97322,6 +97328,7 @@ var triageInbox = wrapToolHandler(async (args) => {
|
|
|
97322
97328
|
const ctxs = await client.findAll(C.DocNotifyContext, { _id: { $in: ctxIds } });
|
|
97323
97329
|
const statuses = new Map((await client.findAll("core:class:Status", {})).map((s) => [s._id, s.name]));
|
|
97324
97330
|
const names2 = await peopleNames(client);
|
|
97331
|
+
const seen = /* @__PURE__ */ new Map();
|
|
97325
97332
|
const out = [`# Inbox triage \u2014 ${unread.length}${unread.length === 500 ? "+" : ""} unread on ${groups.size} item(s)${groups.size > limit ? `, newest ${limit} shown` : ""}`];
|
|
97326
97333
|
for (const ctxId of ctxIds) {
|
|
97327
97334
|
const notes = groups.get(ctxId);
|
|
@@ -97342,10 +97349,23 @@ var triageInbox = wrapToolHandler(async (args) => {
|
|
|
97342
97349
|
const comments = msgs.filter((m) => typeof m.message === "string" && (m._class === "chunter:class:ChatMessage" || h.isDerived(m._class, "chunter:class:ChatMessage")));
|
|
97343
97350
|
const fields = [...new Set(msgs.filter((m) => m._class === C.DocUpdateMessage).map((m) => m.action === "create" ? "created" : m.attributeUpdates?.attrKey === "attachedTo" ? "parent" : m.attributeUpdates?.attrKey).filter((k) => k != null && !["rank", "subIssues", "comments", "modifiedOn"].includes(k)))];
|
|
97344
97351
|
if (fields.length > 0) out.push(`- changed: ${fields.join(", ")}`);
|
|
97345
|
-
for (const m of comments.slice(0, 3).reverse())
|
|
97352
|
+
for (const m of comments.slice(0, 3).reverse()) {
|
|
97353
|
+
const text3 = plain(m.message);
|
|
97354
|
+
const author = who.get(m.createdBy) ?? "?";
|
|
97355
|
+
const key = `${author}\0${text3.slice(0, 160)}`;
|
|
97356
|
+
const first = seen.get(key);
|
|
97357
|
+
if (first != null) {
|
|
97358
|
+
first.count++;
|
|
97359
|
+
out.push(`- \u{1F4AC} **${author}**: _same comment as on ${first.where}_`);
|
|
97360
|
+
continue;
|
|
97361
|
+
}
|
|
97362
|
+
seen.set(key, { line: out.length, where: label2.split(/[:\s]/)[0], count: 1 });
|
|
97363
|
+
out.push(`- \u{1F4AC} **${author}**: ${clip(text3, 200, "list_comments")}`);
|
|
97364
|
+
}
|
|
97346
97365
|
if (comments.length > 3) out.push(`- _${comments.length - 3} older new comment(s)_`);
|
|
97347
97366
|
if (fields.length === 0 && comments.length === 0) out.push("- (no details recorded)");
|
|
97348
97367
|
}
|
|
97368
|
+
for (const f of seen.values()) if (f.count > 1) out[f.line] += ` _(same on ${f.count} items)_`;
|
|
97349
97369
|
out.push("", "_Done with an item? mark_notifications_read with its id (e.g. PROJ-12)._");
|
|
97350
97370
|
return out.join("\n");
|
|
97351
97371
|
});
|
|
@@ -97541,7 +97561,7 @@ var ListComponentsSchema = external_exports.object({
|
|
|
97541
97561
|
var CreateComponentSchema = external_exports.object({
|
|
97542
97562
|
workspace: WorkspaceArg,
|
|
97543
97563
|
projectIdentifier: external_exports.string().describe("Project key"),
|
|
97544
|
-
label: external_exports.string().min(1),
|
|
97564
|
+
label: external_exports.string().min(1).describe("Component name"),
|
|
97545
97565
|
description: external_exports.string().optional(),
|
|
97546
97566
|
lead: external_exports.string().optional().describe("Person name")
|
|
97547
97567
|
});
|
|
@@ -97586,7 +97606,7 @@ var GetDocumentSchema = external_exports.object({
|
|
|
97586
97606
|
var CreateDocumentSchema = external_exports.object({
|
|
97587
97607
|
workspace: WorkspaceArg,
|
|
97588
97608
|
teamspaceId: external_exports.string().describe("Teamspace id"),
|
|
97589
|
-
title: external_exports.string().min(1),
|
|
97609
|
+
title: external_exports.string().min(1).describe("Document title"),
|
|
97590
97610
|
parentId: external_exports.string().optional().describe("Parent document id; omit for top-level")
|
|
97591
97611
|
});
|
|
97592
97612
|
var SearchIssuesSchema = external_exports.object({
|
|
@@ -97606,7 +97626,7 @@ var ListLabelsSchema = external_exports.object({
|
|
|
97606
97626
|
});
|
|
97607
97627
|
var CreateLabelSchema = external_exports.object({
|
|
97608
97628
|
workspace: WorkspaceArg,
|
|
97609
|
-
title: external_exports.string().min(1),
|
|
97629
|
+
title: external_exports.string().min(1).describe("Label name"),
|
|
97610
97630
|
color: external_exports.string().optional().describe("Hex color, e.g. #FF6B6B")
|
|
97611
97631
|
});
|
|
97612
97632
|
var AddLabelSchema = external_exports.object({
|
|
@@ -98500,7 +98520,7 @@ var TOOLS = [
|
|
|
98500
98520
|
{ name: "undo_changes", toolset: "core", description: "Undo your last changes made through this server: created \u2192 removed, changed \u2192 old values, deleted \u2192 restored. Dry run first", schema: UndoChangesSchema, handler: undoChanges },
|
|
98501
98521
|
{ name: "check_setup", toolset: "core", description: "Diagnose the setup: version and updates, login, workspaces, front URL, settings (no secrets)", schema: CheckSetupSchema, handler: checkSetup },
|
|
98502
98522
|
{ name: "list_projects", toolset: "tracker", description: "List all projects in a Huly workspace", schema: ListProjectsSchema, handler: listProjects },
|
|
98503
|
-
{ name: "get_project", toolset: "tracker", description: '
|
|
98523
|
+
{ name: "get_project", toolset: "tracker", description: 'Project by key (e.g. "PROJ"): name, description, issue count, statuses', schema: GetProjectSchema, handler: getProject },
|
|
98504
98524
|
{ name: "create_project", toolset: "tracker-admin", description: "Create a tracker project", schema: CreateProjectSchema, handler: createProject },
|
|
98505
98525
|
{ name: "update_project", toolset: "tracker-admin", description: "Update project name, description, default assignee/status", schema: UpdateProjectSchema, handler: updateProject },
|
|
98506
98526
|
{ name: "list_issues", toolset: "tracker", description: "List issues of a project; filters: status, priority, milestone, component, label, assignee, parent", schema: ListIssuesSchema, handler: listIssues },
|
|
@@ -98513,12 +98533,12 @@ var TOOLS = [
|
|
|
98513
98533
|
{ name: "list_sub_issues", toolset: "tracker", description: "Sub-issue tree of an issue with progress", schema: ListSubIssuesSchema, handler: listSubIssues },
|
|
98514
98534
|
{ name: "add_comment", toolset: "tracker", description: "Add a comment to an issue", schema: AddCommentSchema, handler: addComment },
|
|
98515
98535
|
{ name: "list_comments", toolset: "tracker", description: "List comments of an issue (with ids)", schema: ListCommentsSchema, handler: listComments },
|
|
98516
|
-
{ name: "delete_comment", toolset: "tracker", description: "
|
|
98536
|
+
{ name: "delete_comment", toolset: "tracker", description: "Permanently delete a comment on an issue (commentId from list_comments); to edit: update_comment", schema: DeleteCommentSchema, handler: deleteComment },
|
|
98517
98537
|
{ name: "update_comment", toolset: "tracker", description: "Edit a comment by id", schema: UpdateCommentSchema, handler: updateComment },
|
|
98518
98538
|
{ name: "log_time", toolset: "tracker", description: "Log hours spent on an issue", schema: LogTimeSchema, handler: logTime },
|
|
98519
98539
|
{ name: "list_time_reports", toolset: "tracker", description: "Logged time for an issue or project, totals per person; person/date filters", schema: ListTimeReportsSchema, handler: listTimeReports },
|
|
98520
98540
|
{ name: "list_labels", toolset: "tracker", description: "List all labels in the workspace", schema: ListLabelsSchema, handler: listLabels },
|
|
98521
|
-
{ name: "create_label", toolset: "tracker", description: "Create a
|
|
98541
|
+
{ name: "create_label", toolset: "tracker", description: "Create a workspace-wide label (optional hex color); an existing title is reused. Tag an issue: add_label", schema: CreateLabelSchema, handler: createLabel },
|
|
98522
98542
|
{ name: "add_label", toolset: "tracker", description: "Add label to issue (auto-creates label)", schema: AddLabelSchema, handler: addLabel },
|
|
98523
98543
|
{ name: "remove_label", toolset: "tracker", description: "Remove a label from an issue", schema: RemoveLabelSchema, handler: removeLabel },
|
|
98524
98544
|
{ name: "update_label", toolset: "tracker-admin", description: "Rename/recolor a label (on every issue)", schema: UpdateLabelSchema, handler: updateLabel },
|
|
@@ -98536,14 +98556,14 @@ var TOOLS = [
|
|
|
98536
98556
|
{ name: "update_milestone", toolset: "tracker", description: "Update a milestone (name, target date, status, description)", schema: UpdateMilestoneSchema, handler: updateMilestone },
|
|
98537
98557
|
{ name: "delete_milestone", toolset: "tracker-admin", description: "Delete milestone; its issues are unassigned or moved (moveIssuesTo)", schema: DeleteMilestoneSchema, handler: deleteMilestone },
|
|
98538
98558
|
{ name: "list_components", toolset: "tracker", description: "List components (sub-areas) in a project", schema: ListComponentsSchema, handler: listComponents },
|
|
98539
|
-
{ name: "create_component", toolset: "tracker", description: "Create a
|
|
98559
|
+
{ name: "create_component", toolset: "tracker", description: "Create a component (sub-area) in a project; issues get it via componentLabel. Change it: update_component", schema: CreateComponentSchema, handler: createComponent },
|
|
98540
98560
|
{ name: "update_component", toolset: "tracker", description: "Update a component (name, description, lead)", schema: UpdateComponentSchema, handler: updateComponent },
|
|
98541
98561
|
{ name: "delete_component", toolset: "tracker-admin", description: "Delete component; its issues are unassigned or moved (moveIssuesTo)", schema: DeleteComponentSchema, handler: deleteComponent },
|
|
98542
|
-
{ name: "list_teamspaces", toolset: "documents", description: "List
|
|
98562
|
+
{ name: "list_teamspaces", toolset: "documents", description: "List document teamspaces with their ids (teamspaceId for list_documents, create_document)", schema: ListTeamspacesSchema, handler: listTeamspaces },
|
|
98543
98563
|
{ name: "create_teamspace", toolset: "documents", description: "Create a document teamspace", schema: CreateTeamspaceSchema, handler: createTeamspace },
|
|
98544
98564
|
{ name: "list_documents", toolset: "documents", description: "List documents in a teamspace", schema: ListDocumentsSchema, handler: listDocuments },
|
|
98545
98565
|
{ name: "get_document", toolset: "documents", description: "Document metadata and content", schema: GetDocumentSchema, handler: getDocument },
|
|
98546
|
-
{ name: "create_document", toolset: "documents", description: "Create
|
|
98566
|
+
{ name: "create_document", toolset: "documents", description: "Create an empty document in a teamspace, optionally under a parent; returns its id. Write the body with update_document", schema: CreateDocumentSchema, handler: createDocument },
|
|
98547
98567
|
{ name: "delete_document", toolset: "documents", description: "Permanently delete a document by its ID", schema: DeleteDocumentSchema, handler: deleteDocument },
|
|
98548
98568
|
{ name: "update_document", toolset: "documents", description: "Replace content (Markdown), rename or move a document", schema: UpdateDocumentSchema, handler: updateDocument },
|
|
98549
98569
|
{ name: "list_document_comments", toolset: "collaboration", description: "Comments on a document", schema: ListDocumentCommentsSchema, handler: listDocumentComments },
|
|
@@ -98557,11 +98577,11 @@ var TOOLS = [
|
|
|
98557
98577
|
{ name: "list_messages", toolset: "chat", description: "List messages in a channel or direct message", schema: ListMessagesSchema, handler: listMessages },
|
|
98558
98578
|
{ name: "attach_file", toolset: "tracker", description: "Attach a file to an issue (base64-encoded content)", schema: AttachFileSchema, handler: attachFile },
|
|
98559
98579
|
{ name: "list_attachments", toolset: "tracker", description: "List files attached to an issue", schema: ListAttachmentsSchema, handler: listAttachments },
|
|
98560
|
-
{ name: "delete_attachment", toolset: "tracker", description: "
|
|
98580
|
+
{ name: "delete_attachment", toolset: "tracker", description: "Permanently delete a file attached to an issue (attachmentId from list_attachments)", schema: DeleteAttachmentSchema, handler: deleteAttachment },
|
|
98561
98581
|
{ name: "list_issue_statuses", toolset: "tracker", description: "List all issue statuses (workflow states), grouped by phase", schema: ListIssueStatusesSchema, handler: listIssueStatuses },
|
|
98562
98582
|
{ name: "create_issue_status", toolset: "tracker-admin", description: "Create a workspace-wide issue status", schema: CreateIssueStatusSchema, handler: createIssueStatus },
|
|
98563
98583
|
{ name: "list_organizations", toolset: "contacts", description: "List all organizations (companies) in the workspace", schema: ListOrganizationsSchema, handler: listOrganizations },
|
|
98564
|
-
{ name: "get_organization", toolset: "contacts", description: "
|
|
98584
|
+
{ name: "get_organization", toolset: "contacts", description: "Organization (company) by id from list_organizations: city, linked members, description", schema: GetOrganizationSchema, handler: getOrganization },
|
|
98565
98585
|
{ name: "create_organization", toolset: "contacts", description: "Create a new organization (company contact)", schema: CreateOrganizationSchema, handler: createOrganization },
|
|
98566
98586
|
{ name: "update_organization", toolset: "contacts", description: "Set the description of an organization from Markdown", schema: UpdateOrganizationSchema, handler: updateOrganization },
|
|
98567
98587
|
// Chat: threads, editing, reactions, pins (channel messages and issue comments)
|
|
@@ -98569,9 +98589,9 @@ var TOOLS = [
|
|
|
98569
98589
|
{ name: "reply_to_message", toolset: "chat", description: "Reply in the thread of a message or comment", schema: ReplyToMessageSchema, handler: replyToMessage },
|
|
98570
98590
|
{ name: "update_message", toolset: "chat", description: "Edit a message or thread reply", schema: UpdateMessageSchema, handler: updateMessage },
|
|
98571
98591
|
{ name: "delete_message", toolset: "chat", description: "Delete a message or thread reply", schema: DeleteMessageSchema, handler: deleteMessage },
|
|
98572
|
-
{ name: "add_reaction", toolset: "chat", description: "
|
|
98592
|
+
{ name: "add_reaction", toolset: "chat", description: "Add your emoji reaction to a message or comment (no-op if already there); undo: remove_reaction", schema: ReactionSchema, handler: addReaction },
|
|
98573
98593
|
{ name: "remove_reaction", toolset: "chat", description: "Remove your emoji reaction", schema: ReactionSchema, handler: removeReaction },
|
|
98574
|
-
{ name: "pin_message", toolset: "chat", description: "Pin or
|
|
98594
|
+
{ name: "pin_message", toolset: "chat", description: "Pin a message or comment in its channel; pinned=false unpins", schema: PinMessageSchema, handler: pinMessage },
|
|
98575
98595
|
// Inbox
|
|
98576
98596
|
{ name: "list_notifications", toolset: "inbox", description: "Your inbox notifications, grouped by issue/PR/document", schema: ListNotificationsSchema, handler: listNotifications },
|
|
98577
98597
|
{ name: "triage_inbox", toolset: "inbox", description: "Unread items with what changed since last read: new comments, fields, status", schema: TriageInboxSchema, handler: triageInbox },
|
|
@@ -98580,7 +98600,7 @@ var TOOLS = [
|
|
|
98580
98600
|
// Activity
|
|
98581
98601
|
{ name: "get_activity", toolset: "activity", description: "Change history and comments of an issue or object", schema: GetActivitySchema, handler: getActivity },
|
|
98582
98602
|
// Planner
|
|
98583
|
-
{ name: "list_todos", toolset: "planner", description: "
|
|
98603
|
+
{ name: "list_todos", toolset: "planner", description: "List your own planner to-dos: open by default, in planner order; filter by status or due date", schema: ListTodosSchema, handler: listTodos },
|
|
98584
98604
|
{ name: "create_todo", toolset: "planner", description: "Create a to-do, optionally on an issue", schema: CreateTodoSchema, handler: createTodo },
|
|
98585
98605
|
{ name: "update_todo", toolset: "planner", description: "Update a to-do or mark it done", schema: UpdateTodoSchema, handler: updateTodo },
|
|
98586
98606
|
{ name: "delete_todo", toolset: "planner", description: "Delete a to-do", schema: DeleteTodoSchema, handler: deleteTodo },
|
|
@@ -98616,7 +98636,7 @@ var TOOLS = [
|
|
|
98616
98636
|
{ name: "find_project_for_repo", toolset: "agent", description: "Huly workspace + project linked to a GitHub repo", schema: FindProjectForRepoSchema, handler: findProjectForRepo },
|
|
98617
98637
|
{ name: "release_issue", toolset: "agent", description: "Release an agent claim", schema: ReleaseIssueSchema, handler: releaseIssue },
|
|
98618
98638
|
// Generic access to any class
|
|
98619
|
-
{ name: "search", toolset: "generic", description: "Fulltext search across
|
|
98639
|
+
{ name: "search", toolset: "generic", description: "Fulltext search across all content (issues, docs, messages, cards, files \u2026); issues only, with status: search_issues", schema: SearchAllSchema, handler: searchAll },
|
|
98620
98640
|
{ name: "list_classes", toolset: "generic", description: "Huly data classes (for modules without dedicated tools)", schema: ListClassesSchema, handler: listClasses },
|
|
98621
98641
|
{ name: "describe_class", toolset: "generic", description: "Attributes and types of a class", schema: DescribeClassSchema, handler: describeClass },
|
|
98622
98642
|
{ name: "query_documents", toolset: "generic", description: "Read documents of any class (secrets redacted)", schema: QueryDocumentsSchema, handler: queryDocuments },
|
|
@@ -98888,7 +98908,13 @@ var import_core49 = __toESM(require_lib4());
|
|
|
98888
98908
|
var DONE = /* @__PURE__ */ new Set([import_task7.default.statusCategory.Won, import_task7.default.statusCategory.Lost]);
|
|
98889
98909
|
async function myOpenIssues(limit = 30) {
|
|
98890
98910
|
const out = [];
|
|
98891
|
-
|
|
98911
|
+
let workspaces;
|
|
98912
|
+
try {
|
|
98913
|
+
workspaces = await listWorkspaces();
|
|
98914
|
+
} catch {
|
|
98915
|
+
return [];
|
|
98916
|
+
}
|
|
98917
|
+
for (const ws2 of workspaces) {
|
|
98892
98918
|
try {
|
|
98893
98919
|
const client = await getConnection(ws2.url);
|
|
98894
98920
|
const me = await currentPerson(client);
|
|
@@ -99144,7 +99170,7 @@ function createServer(options = {}) {
|
|
|
99144
99170
|
if (enabled.has("agent")) instructions += `
|
|
99145
99171
|
- Guides: resources huly://guide/workflow, huly://guide/costs, huly://guide/onboarding, huly://guide/features; prompt "setup" writes a project's Huly rules.`;
|
|
99146
99172
|
if (dynamic) instructions = instructions.replace("- Missing tools may be in a disabled toolset (HULY_TOOLSETS).", "- More tools (calendar, cards, drive, testing, recruiting, \u2026) load on demand: enable_toolsets.");
|
|
99147
|
-
const server = new McpServer({ name: "huly-mcp-selfhost", version: "3.
|
|
99173
|
+
const server = new McpServer({ name: "huly-mcp-selfhost", version: "3.6.0" }, { instructions });
|
|
99148
99174
|
const asker = elicitationAsker(server);
|
|
99149
99175
|
const registered = /* @__PURE__ */ new Map();
|
|
99150
99176
|
for (const tool of TOOLS) {
|
|
@@ -99217,6 +99243,15 @@ var ARG_ALIASES = {
|
|
|
99217
99243
|
component: "componentLabel",
|
|
99218
99244
|
milestone: "milestoneLabel"
|
|
99219
99245
|
};
|
|
99246
|
+
var TOOL_ARG_ALIASES = {
|
|
99247
|
+
get_milestone: { milestoneLabel: "label", milestone: "label" },
|
|
99248
|
+
update_milestone: { milestoneLabel: "label", milestone: "label" },
|
|
99249
|
+
update_component: { componentLabel: "label", component: "label" }
|
|
99250
|
+
};
|
|
99251
|
+
function aliasTarget(tool, name2, known) {
|
|
99252
|
+
const target = TOOL_ARG_ALIASES[tool]?.[name2] ?? ARG_ALIASES[name2];
|
|
99253
|
+
return target != null && known.has(target) ? target : void 0;
|
|
99254
|
+
}
|
|
99220
99255
|
function normalizeArguments(tool, args, known) {
|
|
99221
99256
|
const out = {};
|
|
99222
99257
|
const unknown2 = [];
|
|
@@ -99225,8 +99260,8 @@ function normalizeArguments(tool, args, known) {
|
|
|
99225
99260
|
out[k] = v;
|
|
99226
99261
|
continue;
|
|
99227
99262
|
}
|
|
99228
|
-
const target =
|
|
99229
|
-
if (target != null &&
|
|
99263
|
+
const target = aliasTarget(tool, k, known);
|
|
99264
|
+
if (target != null && !(target in args)) {
|
|
99230
99265
|
out[target] = v;
|
|
99231
99266
|
continue;
|
|
99232
99267
|
}
|
|
@@ -104381,7 +104416,7 @@ function buildArgs(tool, parsed, io) {
|
|
|
104381
104416
|
continue;
|
|
104382
104417
|
}
|
|
104383
104418
|
const name2 = camel(rawName);
|
|
104384
|
-
const target = byName.has(name2) ? name2 :
|
|
104419
|
+
const target = byName.has(name2) ? name2 : aliasTarget(tool.name, name2, new Set(byName.keys()));
|
|
104385
104420
|
if (target == null) {
|
|
104386
104421
|
const flags = params.filter((p) => p.name !== "workspace").map((p) => `--${kebab(p.name)}`);
|
|
104387
104422
|
const hint = closest(`--${rawName}`, flags);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huly-mcp-selfhost",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "MCP server for Huly (self-hosted and Huly Cloud):
|
|
3
|
+
"version": "3.6.0",
|
|
4
|
+
"description": "MCP server for Huly (self-hosted and Huly Cloud): 227 tools for Claude and other AI agents — issues, epics, documents, chat, planner, test management — with toolsets for low token use, an agent workflow and a Claude Code plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"huly",
|
|
7
7
|
"huly-selfhost",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"start": "node dist/index.js",
|
|
48
48
|
"setup": "node scripts/setup.js",
|
|
49
49
|
"prepublishOnly": "npm run build",
|
|
50
|
-
"test": "node --import tsx --test test/*.test.ts"
|
|
50
|
+
"test": "node --import tsx --test test/*.test.ts",
|
|
51
|
+
"mcpb": "node scripts/mcpb.js"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {},
|
|
53
54
|
"devDependencies": {
|