@bgx4k3p/huly-mcp-server 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -425,6 +425,7 @@ Full list of all MCP tools available through this server.
425
425
  | `get_label` | Find a label by name |
426
426
  | `create_label` | Create a new label with optional color |
427
427
  | `update_label` | Update label name, color, or description |
428
+ | `delete_label` | Permanently delete a label |
428
429
  | `add_label` | Add a label to an issue |
429
430
  | `remove_label` | Remove a label from an issue |
430
431
 
@@ -442,8 +443,8 @@ Full list of all MCP tools available through this server.
442
443
  | --- | --- | --- |
443
444
  | `list_components` | List components in a project | -- |
444
445
  | `get_component` | Find a component by name | -- |
445
- | `create_component` | Create a new component | `descriptionFormat`: md/html/plain |
446
- | `update_component` | Update component fields | `descriptionFormat`: md/html/plain |
446
+ | `create_component` | Create a new component (optional lead) | `descriptionFormat`: md/html/plain |
447
+ | `update_component` | Update component name, description, or lead | `descriptionFormat`: md/html/plain |
447
448
  | `delete_component` | Delete a component | -- |
448
449
 
449
450
  ### Milestones
@@ -517,7 +518,7 @@ fetches related data in a single call:
517
518
  | --- | --- | --- | --- | --- | --- |
518
519
  | Project | `create_project` | `get_project` | `list_projects` | `update_project` | `delete_project` |
519
520
  | Issue | `create_issue` | `get_issue` | `list_issues` | `update_issue` | `delete_issue` |
520
- | Label | `create_label` | `get_label` | `list_labels` | `update_label` | `remove_label` |
521
+ | Label | `create_label` | `get_label` | `list_labels` | `update_label` | `delete_label` |
521
522
  | Component | `create_component` | `get_component` | `list_components` | `update_component` | `delete_component` |
522
523
  | Milestone | `create_milestone` | `get_milestone` | `list_milestones` | `update_milestone` | `delete_milestone` |
523
524
  | Comment | `add_comment` | `get_comment` | `list_comments` | `update_comment` | `delete_comment` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgx4k3p/huly-mcp-server",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "description": "MCP server for Huly issue tracking with stdio and Streamable HTTP transports",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,7 +40,8 @@
40
40
  "test:rest": "HULY_TRANSPORT=rest node --test test/integration.test.mjs",
41
41
  "lint": "eslint src/ scripts/",
42
42
  "postinstall": "node scripts/patch-sdk.mjs",
43
- "pack": "node scripts/pack.mjs"
43
+ "pack": "node scripts/pack.mjs",
44
+ "version:sync": "node -e \"const{readFileSync:r,writeFileSync:w}=require('fs');const v=r('VERSION','utf-8').trim();const f='package.json';const j=JSON.parse(r(f,'utf-8'));j.version=v;w(f,JSON.stringify(j,null,2)+'\\n');console.log('Synced version '+v+' to package.json')\""
44
45
  },
45
46
  "dependencies": {
46
47
  "@hcengineering/api-client": "^0.7.3",
package/src/client.mjs CHANGED
@@ -751,7 +751,11 @@ export class HulyClient {
751
751
  if (projectType?.tasks?.length) {
752
752
  const taskTypes = await client.findAll(task.class.TaskType, {});
753
753
  const scoped = taskTypes.filter(tt => projectType.tasks.includes(tt._id));
754
- if (scoped.length) return scoped[0]._id;
754
+ if (scoped.length) {
755
+ // Prefer the type named "Task" (the common default), not the first in list (often Epic)
756
+ const taskType = scoped.find(tt => nameMatch(tt.name || tt._id.split(':').pop(), 'Task'));
757
+ return (taskType || scoped[0])._id;
758
+ }
755
759
  }
756
760
 
757
761
  throw new Error(
@@ -1778,6 +1782,17 @@ export class HulyClient {
1778
1782
  };
1779
1783
  }
1780
1784
 
1785
+ async deleteLabel(name) {
1786
+ const client = await this._getClient();
1787
+ const tagElement = await client.findOne(tags.class.TagElement, {
1788
+ title: name,
1789
+ targetClass: tracker.class.Issue
1790
+ });
1791
+ if (!tagElement) throw new Error(`Label "${name}" not found`);
1792
+ await client.removeDoc(tags.class.TagElement, tagElement.space, tagElement._id);
1793
+ return { message: `Label "${name}" deleted`, id: tagElement._id };
1794
+ }
1795
+
1781
1796
  /**
1782
1797
  * Add a "related to" relationship between two issues.
1783
1798
  * @param {string} issueId - Issue identifier
package/src/dispatch.mjs CHANGED
@@ -117,11 +117,12 @@ export const workspaceTools = {
117
117
  create_label: (a, c) => c.createLabel(a.name, a.color, a.description),
118
118
  update_label: (a, c) =>
119
119
  c.updateLabel(a.name, { newName: a.newName, color: a.color, description: a.description }),
120
+ delete_label: (a, c) => c.deleteLabel(a.name),
120
121
 
121
122
  // Relations
122
123
  add_relation: (a, c) => c.addRelation(a.issueId, a.relatedToIssueId),
123
124
  add_blocked_by: (a, c) => c.addBlockedBy(a.issueId, a.blockedByIssueId),
124
- set_parent: (a, c) => c.setParent(a.issueId, a.parentIssueId),
125
+ set_parent: (a, c) => c.setParent(a.issueId, a.parentId),
125
126
 
126
127
  // Task types & statuses
127
128
  list_task_types: (a, c) => c.listTaskTypes(a.project, { cursor: a.cursor, limit: a.limit }),
package/src/mcpShared.mjs CHANGED
@@ -388,6 +388,11 @@ function getToolDefinitions() {
388
388
  description: 'Update an existing label\'s name, color, or description. Use list_labels to see available labels.',
389
389
  inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Current label name to find' }, newName: { type: 'string', description: 'New label name' }, color: { type: ['string', 'number'], description: 'New color: name (red, salmon, pink, hotpink, magenta, purple, indigo, violet, navy, blue, sky, cyan, teal, ocean, mint, green, olive, lime, gold, orange, brown, silver, gray, slate), palette index (0-23), or RGB hex (e.g., 0xBB83FC)' }, description: { type: 'string', description: 'New description' }, ...workspaceProp }, required: ['name'] }
390
390
  },
391
+ {
392
+ name: 'delete_label',
393
+ description: 'Permanently delete a label. Irreversible — confirm with the user before proceeding.',
394
+ inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Label name to delete' }, ...workspaceProp }, required: ['name'] }
395
+ },
391
396
  {
392
397
  name: 'get_label',
393
398
  description: 'Get details for a specific label by name.',
@@ -482,12 +487,12 @@ function getToolDefinitions() {
482
487
  {
483
488
  name: 'create_component',
484
489
  description: 'Create a new component in a project.',
485
- inputSchema: { type: 'object', properties: { project: { type: 'string', description: 'Project identifier' }, name: { type: 'string', description: 'Component name' }, description: { type: 'string', description: 'Component description' }, ...workspaceProp }, required: ['project', 'name'] }
490
+ inputSchema: { type: 'object', properties: { project: { type: 'string', description: 'Project identifier' }, name: { type: 'string', description: 'Component name' }, description: { type: 'string', description: 'Component description' }, lead: { type: 'string', description: 'Lead member name' }, ...workspaceProp }, required: ['project', 'name'] }
486
491
  },
487
492
  {
488
493
  name: 'update_component',
489
- description: 'Update a component\'s name or description.',
490
- inputSchema: { type: 'object', properties: { project: { type: 'string', description: 'Project identifier' }, name: { type: 'string', description: 'Current component name' }, newName: { type: 'string', description: 'New component name' }, description: { type: 'string', description: 'New description' }, ...workspaceProp }, required: ['project', 'name'] }
494
+ description: 'Update a component\'s name, description, or lead.',
495
+ inputSchema: { type: 'object', properties: { project: { type: 'string', description: 'Project identifier' }, name: { type: 'string', description: 'Current component name' }, newName: { type: 'string', description: 'New component name' }, description: { type: 'string', description: 'New description' }, lead: { type: 'string', description: 'Lead member name (empty string to clear)' }, ...workspaceProp }, required: ['project', 'name'] }
491
496
  },
492
497
  {
493
498
  name: 'delete_component',