@firfi/huly-mcp 0.17.1 → 0.18.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 (3) hide show
  1. package/README.md +6 -6
  2. package/dist/index.cjs +465 -236
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -273,7 +273,7 @@ Resource roadmap:
273
273
  |------|-------------|
274
274
  | `list_projects` | List all Huly projects. Returns projects sorted by name. Supports filtering by archived status. |
275
275
  | `get_project` | Get full details of a Huly project including its statuses. Returns project name, description, archived flag, default status, and all available statuses. |
276
- | `list_statuses` | List all issue statuses for a Huly project with category info. Returns status name, isDone, isCanceled, and isDefault flags. Use this to discover valid statuses before creating or updating issues. |
276
+ | `list_statuses` | List all issue statuses for a Huly project with workflow category and default info. Returns status name, category, and isDefault. Use this to discover valid statuses before creating or updating issues. |
277
277
  | `create_project` | Create a new Huly tracker project. Idempotent: returns existing project if one with the same identifier already exists (created=false). Identifier must be 1-5 uppercase alphanumeric chars starting with a letter. |
278
278
  | `update_project` | Update a Huly project. Only provided fields are modified. Set description to null to clear it. |
279
279
  | `delete_project` | Permanently delete a Huly project. All issues, milestones, and components in this project will be orphaned. This action cannot be undone. |
@@ -283,7 +283,7 @@ Resource roadmap:
283
283
  | Tool | Description |
284
284
  |------|-------------|
285
285
  | `preview_deletion` | Preview the impact of deleting a Huly entity before actually deleting it. Shows affected sub-entities, relations, and warnings. Supports issues, projects, components, and milestones. Use this to understand cascade effects before calling a delete operation. |
286
- | `list_issues` | Query Huly issues with optional filters. Returns issues sorted by modification date (newest first). Supports filtering by project, status, assignee, component, and parentIssue (to list children of a specific issue). Supports searching by title substring (titleSearch) and description content (descriptionSearch). |
286
+ | `list_issues` | Query Huly issues with optional filters. Returns issues sorted by modification date (newest first). Supports filtering by project, exact workflow status name (status), Huly SDK task.statusCategory key (statusCategory: UnStarted, ToDo, Active, Won, Lost), assignee, component, and parentIssue (to list children of a specific issue). Supports searching by title substring (titleSearch) and description content (descriptionSearch). |
287
287
  | `get_issue` | Retrieve full details for a Huly issue including markdown description. Use this to view issue content, comments, or full metadata. |
288
288
  | `create_issue` | Create a new issue in a Huly project. Optionally set taskType by ID or display name; it is resolved within the target project's project type, and status is validated against that task type's workflow. Use list_task_types or get_project_type to discover valid task types and statuses. Optionally create as a sub-issue by specifying parentIssue. Description supports markdown formatting. Returns the created issue identifier. |
289
289
  | `update_issue` | Update fields on an existing Huly issue. Optionally set taskType by ID or display name; it is resolved within the target project's project type, and the status is preserved only when valid for the new task type. Use list_task_types or get_project_type to discover valid task types and statuses. Only provided fields are modified. Description updates support markdown. |
@@ -453,9 +453,9 @@ Resource roadmap:
453
453
  | `list_associations` | List Huly association definitions: class-level typed links that define which document classes may be related. Use this before create_relation to discover association IDs, source/target classes, and whether relation writes are supported. |
454
454
  | `create_association` | Idempotently create one Huly association definition between two non-system classes. Use sourceClass/targetClass with sourceRole/targetRole and cardinality; returns an existing identical association by default. |
455
455
  | `delete_association` | Idempotently delete one Huly association definition only when no concrete relations reference it. If relations exist, delete_relation must clean them up first; deleting an already-missing association is a successful no-op. |
456
- | `list_relations` | List concrete Huly relation instances under an association, optionally filtered by source and target documents. Requires at least one filter to avoid broad workspace scans. |
457
- | `create_relation` | Idempotently create one concrete relation between two resolved documents for a writable association. Enforces association endpoint classes, direction, duplicate handling, automation-only restrictions, and cardinality. |
458
- | `delete_relation` | Idempotently delete one concrete relation by relation ID or by exact association/source/target triple. Triple deletes use the same direction semantics as create_relation and fail if the selector is ambiguous. |
456
+ | `list_relations` | List concrete Huly relation instances under an association, optionally filtered by source and target documents. Endpoint locators support raw, issue, document, and card. Requires at least one filter to avoid broad workspace scans. |
457
+ | `create_relation` | Idempotently create one concrete relation between two resolved documents for a writable association. Endpoint locators support raw, issue, document, and card. Enforces association endpoint classes, direction, duplicate handling, automation-only restrictions, and cardinality. |
458
+ | `delete_relation` | Idempotently delete one concrete relation by relation ID or by exact association/source/target triple. Triple endpoint locators support raw, issue, document, and card. Triple deletes use the same direction semantics as create_relation and fail if the selector is ambiguous. |
459
459
 
460
460
  ### Activity
461
461
 
@@ -568,7 +568,7 @@ Resource roadmap:
568
568
  | `get_project_type` | Inspect one Huly tracker project type in a single call. Accepts projectType as ID or display name; when omitted, uses the unambiguous Classic tracker type. Returns task types, statuses, categories, and task-type-to-status mappings. |
569
569
  | `list_task_types` | List Huly issue/task types. Optionally filter by projectType ID or display name. Returns task type identity, parent project type, kind, issue class, and available status count. |
570
570
  | `create_task_type` | Add a Huly issue/task type to a project type idempotently by normalized name. Copies required workflow configuration from an existing template task type unless templateTaskType is supplied. Returns created, IDs, affected task type IDs, and a workspace-level workflow warning. |
571
- | `create_issue_status` | Add a Huly issue workflow status idempotently by normalized name within a project type and task type scope. Accepts category as backlog, todo, active, done, or canceled; taskType may be ID or display name, and omission applies the status to every task type in the project type. |
571
+ | `create_issue_status` | Add a Huly issue workflow status idempotently by normalized name within a project type and task type scope. Accepts category as a Huly SDK task.statusCategory key: UnStarted, ToDo, Active, Won, Lost; taskType may be ID or display name, and omission applies the status to every task type in the project type. |
572
572
 
573
573
  ### Test-Management
574
574
 
package/dist/index.cjs CHANGED
@@ -151180,7 +151180,9 @@ var Email = Schema_exports.NonEmptyString.pipe(
151180
151180
  }),
151181
151181
  Schema_exports.brand("Email")
151182
151182
  );
151183
- var StatusName = NonEmptyString2.pipe(Schema_exports.brand("StatusName"));
151183
+ var StatusName = NonEmptyString2.annotations({
151184
+ description: "Exact workflow status display name from the target project. Status names are workspace data, not a fixed enum; call list_statuses or get_project_type to discover valid values."
151185
+ }).pipe(Schema_exports.brand("StatusName"));
151184
151186
  var PersonName = NonEmptyString2.pipe(Schema_exports.brand("PersonName"));
151185
151187
  var PersonRefInput = Schema_exports.Union(Email, PersonName);
151186
151188
  var ComponentLabel = NonEmptyString2.pipe(Schema_exports.brand("ComponentLabel"));
@@ -151585,6 +151587,7 @@ var RelationDirectionSchema = Schema_exports.Literal(...RelationDirectionValues)
151585
151587
  var DefaultRelationDirection = "source-to-target";
151586
151588
  var relationDirectionDescription = `Relation traversal direction: ${enumValuesDescription(RelationDirectionValues)}. Defaults to ${DefaultRelationDirection}.`;
151587
151589
  var RelationIfExistsSchema = Schema_exports.Literal("return_existing", "fail");
151590
+ var RelationEndpointFieldSchema = Schema_exports.Literal("source", "target");
151588
151591
  var AssociationIfExistsSchema = Schema_exports.Literal("return_existing", "fail");
151589
151592
  var RawObjectLocatorSchema = Schema_exports.Struct({
151590
151593
  kind: Schema_exports.Literal("raw"),
@@ -151613,19 +151616,29 @@ var DocumentObjectLocatorSchema = Schema_exports.Struct({
151613
151616
  description: "Teamspace name or ID. If omitted, document title matches must be unique across the workspace."
151614
151617
  }))
151615
151618
  });
151619
+ var CardObjectLocatorSchema = Schema_exports.Struct({
151620
+ kind: Schema_exports.Literal("card"),
151621
+ card: CardIdentifier.annotations({
151622
+ description: "Card ID or exact card title. Card IDs can be resolved without cardSpace; title lookup requires cardSpace."
151623
+ }),
151624
+ cardSpace: Schema_exports.optional(CardSpaceIdentifier.annotations({
151625
+ description: "Card space name or ID. Required when card is a title so title lookup is scoped and not ambiguous across the workspace."
151626
+ }))
151627
+ });
151616
151628
  var GenericObjectLocatorSchema = Schema_exports.Union(
151617
151629
  RawObjectLocatorSchema,
151618
151630
  IssueObjectLocatorSchema,
151619
- DocumentObjectLocatorSchema
151631
+ DocumentObjectLocatorSchema,
151632
+ CardObjectLocatorSchema
151620
151633
  ).annotations({
151621
151634
  title: "GenericObjectLocator",
151622
- description: "Explicit locator for a Huly document endpoint. Use raw for known _id values, issue for tracker issues, or document for Huly documents. Card locators are intentionally not included until a robust card resolver is available."
151635
+ description: "Explicit locator for a Huly document endpoint. Use raw for known _id/class pairs, issue for tracker issues, document for Huly documents, or card for Huly cards."
151623
151636
  });
151624
151637
  var ResolvedObjectSummarySchema = Schema_exports.Struct({
151625
151638
  id: DocId,
151626
151639
  class: ObjectClassName,
151627
151640
  display: NonEmptyString2,
151628
- locatorKind: Schema_exports.Literal("raw", "issue", "document"),
151641
+ locatorKind: Schema_exports.Literal("raw", "issue", "document", "card"),
151629
151642
  warning: Schema_exports.optional(Schema_exports.String)
151630
151643
  });
151631
151644
  var AssociationSummarySchema = Schema_exports.Struct({
@@ -151986,7 +151999,7 @@ var RelationDirectionAmbiguousError = class extends Schema_exports.TaggedError()
151986
151999
  var RelationEndpointClassMismatchError = class extends Schema_exports.TaggedError()(
151987
152000
  "RelationEndpointClassMismatchError",
151988
152001
  {
151989
- field: Schema_exports.String,
152002
+ field: RelationEndpointFieldSchema,
151990
152003
  expectedClass: Schema_exports.String,
151991
152004
  actualClass: Schema_exports.String
151992
152005
  }
@@ -151998,7 +152011,7 @@ var RelationEndpointClassMismatchError = class extends Schema_exports.TaggedErro
151998
152011
  var GenericObjectIdentifierAmbiguousError = class extends Schema_exports.TaggedError()(
151999
152012
  "GenericObjectIdentifierAmbiguousError",
152000
152013
  {
152001
- field: Schema_exports.String,
152014
+ field: RelationEndpointFieldSchema,
152002
152015
  identifier: Schema_exports.String,
152003
152016
  candidates: Schema_exports.Array(Schema_exports.Struct({
152004
152017
  id: DocId,
@@ -152015,7 +152028,7 @@ var GenericObjectIdentifierAmbiguousError = class extends Schema_exports.TaggedE
152015
152028
  var GenericObjectLocatorInvalidError = class extends Schema_exports.TaggedError()(
152016
152029
  "GenericObjectLocatorInvalidError",
152017
152030
  {
152018
- field: Schema_exports.String,
152031
+ field: RelationEndpointFieldSchema,
152019
152032
  reason: Schema_exports.String
152020
152033
  }
152021
152034
  ) {
@@ -152026,7 +152039,7 @@ var GenericObjectLocatorInvalidError = class extends Schema_exports.TaggedError(
152026
152039
  var GenericObjectNotFoundError = class extends Schema_exports.TaggedError()(
152027
152040
  "GenericObjectNotFoundError",
152028
152041
  {
152029
- field: Schema_exports.String,
152042
+ field: RelationEndpointFieldSchema,
152030
152043
  identifier: Schema_exports.String,
152031
152044
  class: Schema_exports.optional(Schema_exports.String)
152032
152045
  }
@@ -163495,101 +163508,73 @@ var GetHulyContextResultSchema = Schema_exports.Struct({
163495
163508
  });
163496
163509
  var getHulyContextResultJsonSchema = JSONSchema_exports.make(GetHulyContextResultSchema);
163497
163510
 
163498
- // src/domain/schemas/projects.ts
163499
- var ProjectSummarySchema = Schema_exports.Struct({
163500
- identifier: ProjectIdentifier,
163501
- name: NonEmptyString2,
163502
- description: Schema_exports.optional(Schema_exports.String),
163503
- archived: Schema_exports.Boolean
163504
- }).annotations({
163505
- title: "ProjectSummary",
163506
- description: "Project summary for list operations"
163507
- });
163508
- var ListProjectsParamsSchema = Schema_exports.Struct({
163509
- includeArchived: Schema_exports.optional(Schema_exports.Boolean.annotations({
163510
- description: "Include archived projects in results (default: false, showing only active)"
163511
- })),
163512
- limit: Schema_exports.optional(
163513
- LimitParam.annotations({
163514
- description: "Maximum number of projects to return (default: 50)"
163515
- })
163516
- )
163517
- }).annotations({
163518
- title: "ListProjectsParams",
163519
- description: "Parameters for listing projects"
163520
- });
163521
- var ProjectSchema = Schema_exports.Struct({
163522
- identifier: ProjectIdentifier,
163523
- name: NonEmptyString2,
163524
- description: Schema_exports.optional(Schema_exports.String),
163525
- archived: Schema_exports.Boolean,
163526
- defaultStatus: Schema_exports.optional(StatusName),
163527
- statuses: Schema_exports.optional(Schema_exports.Array(StatusName))
163528
- }).annotations({
163529
- title: "Project",
163530
- description: "Full project with status information"
163531
- });
163532
- var GetProjectParamsSchema = Schema_exports.Struct({
163533
- project: ProjectIdentifier.annotations({ description: "Project identifier (e.g., 'HULY')" })
163534
- }).annotations({ title: "GetProjectParams", description: "Parameters for getting a project" });
163535
- var CreateProjectParamsSchema = Schema_exports.Struct({
163536
- name: NonEmptyString2.annotations({ description: "Project name" }),
163537
- identifier: Schema_exports.String.pipe(
163538
- Schema_exports.pattern(/^[A-Z][A-Z0-9_]{0,4}$/)
163539
- ).annotations({
163540
- description: "Unique project identifier, 1-5 uppercase alphanumeric chars starting with letter (e.g., 'HULY', 'QA')"
163541
- }),
163542
- description: Schema_exports.optional(Schema_exports.String.annotations({ description: "Project description" })),
163543
- private: Schema_exports.optional(Schema_exports.Boolean.annotations({ description: "Whether project is private (default: false)" }))
163544
- }).annotations({ title: "CreateProjectParams", description: "Parameters for creating a project" });
163545
- var UPDATE_PROJECT_FIELDS = ["name", "description"];
163546
- var UpdateProjectParamsSchema = Schema_exports.Struct({
163547
- project: ProjectIdentifier.annotations({ description: "Project identifier to update" }),
163548
- name: Schema_exports.optional(NonEmptyString2.annotations({ description: "New project name" })),
163549
- description: Schema_exports.optional(
163550
- Schema_exports.NullOr(Schema_exports.String).annotations({ description: "New description (null to clear)" })
163551
- )
163552
- }).annotations({
163553
- title: "UpdateProjectParams",
163554
- description: `Parameters for updating a project. ${atLeastOneUpdateFieldMessage(UPDATE_PROJECT_FIELDS)}`
163555
- });
163556
- var DeleteProjectParamsSchema = Schema_exports.Struct({
163557
- project: ProjectIdentifier.annotations({ description: "Project identifier to delete" })
163558
- }).annotations({ title: "DeleteProjectParams", description: "Parameters for deleting a project" });
163559
- var ListStatusesParamsSchema = Schema_exports.Struct({
163560
- project: ProjectIdentifier.annotations({ description: "Project identifier (e.g., 'HULY')" })
163561
- }).annotations({ title: "ListStatusesParams", description: "Parameters for listing project statuses" });
163562
- var StatusDetailSchema = Schema_exports.Struct({
163563
- name: StatusName,
163564
- isDone: Schema_exports.Boolean,
163565
- isCanceled: Schema_exports.Boolean,
163566
- isDefault: Schema_exports.Boolean
163567
- }).annotations({
163568
- title: "StatusDetail",
163569
- description: "Issue status with category and default info"
163570
- });
163571
- var listProjectsParamsJsonSchema = JSONSchema_exports.make(ListProjectsParamsSchema);
163572
- var listStatusesParamsJsonSchema = JSONSchema_exports.make(ListStatusesParamsSchema);
163573
- var getProjectParamsJsonSchema = JSONSchema_exports.make(GetProjectParamsSchema);
163574
- var createProjectParamsJsonSchema = JSONSchema_exports.make(CreateProjectParamsSchema);
163575
- var updateProjectParamsJsonSchema = withAtLeastOneRequired(
163576
- JSONSchema_exports.make(UpdateProjectParamsSchema),
163577
- UPDATE_PROJECT_FIELDS
163578
- );
163579
- var deleteProjectParamsJsonSchema = JSONSchema_exports.make(DeleteProjectParamsSchema);
163580
- var parseListProjectsParams = Schema_exports.decodeUnknown(ListProjectsParamsSchema);
163581
- var parseListStatusesParams = Schema_exports.decodeUnknown(ListStatusesParamsSchema);
163582
- var parseGetProjectParams = Schema_exports.decodeUnknown(GetProjectParamsSchema);
163583
- var parseCreateProjectParams = Schema_exports.decodeUnknown(CreateProjectParamsSchema);
163584
- var parseUpdateProjectParams = Schema_exports.decodeUnknown(UpdateProjectParamsSchema);
163585
- var parseDeleteProjectParams = Schema_exports.decodeUnknown(DeleteProjectParamsSchema);
163586
- var parseProject = Schema_exports.decodeUnknown(ProjectSchema);
163511
+ // src/huly/huly-plugins.ts
163512
+ var activity = require_lib23().default;
163513
+ var attachment = require_lib24().default;
163514
+ var calendar = require_lib25().default;
163515
+ var cardPlugin = require_lib26().default;
163516
+ var chunter = require_lib27().default;
163517
+ var contact = require_lib28().default;
163518
+ var core = require_lib4().default;
163519
+ var documentPlugin = require_lib29().default;
163520
+ var notification = require_lib30().default;
163521
+ var tags = require_lib31().default;
163522
+ var task = require_lib34().default;
163523
+ var time3 = require_lib35().default;
163524
+ var tracker = require_lib36().default;
163587
163525
 
163588
163526
  // src/domain/schemas/task-management.ts
163589
- var StatusCategoryValues = ["backlog", "todo", "active", "done", "canceled"];
163527
+ var StatusCategoryBySdkKey = {
163528
+ UnStarted: task.statusCategory.UnStarted,
163529
+ ToDo: task.statusCategory.ToDo,
163530
+ Active: task.statusCategory.Active,
163531
+ Won: task.statusCategory.Won,
163532
+ Lost: task.statusCategory.Lost
163533
+ };
163534
+ var StatusCategoryKeys = [
163535
+ "UnStarted",
163536
+ "ToDo",
163537
+ "Active",
163538
+ "Won",
163539
+ "Lost"
163540
+ ];
163541
+ var exactStatusCategoryKeys = (value3) => value3;
163542
+ exactStatusCategoryKeys(true);
163543
+ var StatusCategoryEntries = [
163544
+ { key: "UnStarted", ref: StatusCategoryBySdkKey.UnStarted },
163545
+ { key: "ToDo", ref: StatusCategoryBySdkKey.ToDo },
163546
+ { key: "Active", ref: StatusCategoryBySdkKey.Active },
163547
+ { key: "Won", ref: StatusCategoryBySdkKey.Won },
163548
+ { key: "Lost", ref: StatusCategoryBySdkKey.Lost }
163549
+ ];
163550
+ var exactStatusCategoryEntries = (value3) => value3;
163551
+ exactStatusCategoryEntries(true);
163552
+ var StatusCategoryValues = StatusCategoryKeys;
163590
163553
  var UnknownStatusCategoryValue = "unknown";
163591
163554
  var StatusCategoryValueSchema = Schema_exports.Literal(...StatusCategoryValues, UnknownStatusCategoryValue);
163592
- var CreateStatusCategoryValueSchema = Schema_exports.Literal(...StatusCategoryValues);
163555
+ var KnownStatusCategoryValueLiteral = Schema_exports.Literal(...StatusCategoryValues);
163556
+ var normalizedStatusCategoryLookup = new Map(
163557
+ StatusCategoryValues.map((value3) => [value3.toLowerCase(), value3])
163558
+ );
163559
+ var KnownStatusCategoryValueSchema = Schema_exports.transformOrFail(
163560
+ Schema_exports.String,
163561
+ KnownStatusCategoryValueLiteral,
163562
+ {
163563
+ strict: true,
163564
+ decode: (input, _options, ast) => {
163565
+ const match16 = normalizedStatusCategoryLookup.get(input.toLowerCase());
163566
+ return match16 !== void 0 ? ParseResult_exports.succeed(match16) : ParseResult_exports.fail(
163567
+ new ParseResult_exports.Type(ast, input, `Expected one of: ${enumValuesDescription(StatusCategoryValues)}`)
163568
+ );
163569
+ },
163570
+ encode: ParseResult_exports.succeed
163571
+ }
163572
+ ).annotations({
163573
+ title: "KnownStatusCategoryValue",
163574
+ description: `Huly SDK task.statusCategory key: ${enumValuesDescription(StatusCategoryValues)}`,
163575
+ jsonSchema: { type: "string", enum: [...StatusCategoryValues] }
163576
+ });
163577
+ var CreateStatusCategoryValueSchema = KnownStatusCategoryValueSchema;
163593
163578
  var TaskTypeKindSchema = Schema_exports.Literal("task", "subtask", "both");
163594
163579
  var ProjectTypeRefSchema = NonEmptyString2.pipe(Schema_exports.brand("ProjectTypeRef"));
163595
163580
  var TaskTypeRefSchema = NonEmptyString2.pipe(Schema_exports.brand("TaskTypeRef"));
@@ -163663,7 +163648,7 @@ var CreateIssueStatusParamsSchema = Schema_exports.Struct({
163663
163648
  })),
163664
163649
  name: NonEmptyString2.annotations({ description: "Display name for the workflow status to add." }),
163665
163650
  category: CreateStatusCategoryValueSchema.annotations({
163666
- description: `Business category for the status: ${enumValuesDescription(StatusCategoryValues)}.`
163651
+ description: `Huly SDK task.statusCategory key: ${enumValuesDescription(StatusCategoryValues)}.`
163667
163652
  }),
163668
163653
  taskType: Schema_exports.optional(TaskTypeRefSchema.annotations({
163669
163654
  description: "Optional task type ID or display name to scope the status to. If omitted, the status is added to every task type in the project type."
@@ -163702,6 +163687,95 @@ var parseListTaskTypesParams = Schema_exports.decodeUnknown(ListTaskTypesParamsS
163702
163687
  var parseCreateTaskTypeParams = Schema_exports.decodeUnknown(CreateTaskTypeParamsSchema);
163703
163688
  var parseCreateIssueStatusParams = Schema_exports.decodeUnknown(CreateIssueStatusParamsSchema);
163704
163689
 
163690
+ // src/domain/schemas/projects.ts
163691
+ var ProjectSummarySchema = Schema_exports.Struct({
163692
+ identifier: ProjectIdentifier,
163693
+ name: NonEmptyString2,
163694
+ description: Schema_exports.optional(Schema_exports.String),
163695
+ archived: Schema_exports.Boolean
163696
+ }).annotations({
163697
+ title: "ProjectSummary",
163698
+ description: "Project summary for list operations"
163699
+ });
163700
+ var ListProjectsParamsSchema = Schema_exports.Struct({
163701
+ includeArchived: Schema_exports.optional(Schema_exports.Boolean.annotations({
163702
+ description: "Include archived projects in results (default: false, showing only active)"
163703
+ })),
163704
+ limit: Schema_exports.optional(
163705
+ LimitParam.annotations({
163706
+ description: "Maximum number of projects to return (default: 50)"
163707
+ })
163708
+ )
163709
+ }).annotations({
163710
+ title: "ListProjectsParams",
163711
+ description: "Parameters for listing projects"
163712
+ });
163713
+ var ProjectSchema = Schema_exports.Struct({
163714
+ identifier: ProjectIdentifier,
163715
+ name: NonEmptyString2,
163716
+ description: Schema_exports.optional(Schema_exports.String),
163717
+ archived: Schema_exports.Boolean,
163718
+ defaultStatus: Schema_exports.optional(StatusName),
163719
+ statuses: Schema_exports.optional(Schema_exports.Array(StatusName))
163720
+ }).annotations({
163721
+ title: "Project",
163722
+ description: "Full project with status information"
163723
+ });
163724
+ var GetProjectParamsSchema = Schema_exports.Struct({
163725
+ project: ProjectIdentifier.annotations({ description: "Project identifier (e.g., 'HULY')" })
163726
+ }).annotations({ title: "GetProjectParams", description: "Parameters for getting a project" });
163727
+ var CreateProjectParamsSchema = Schema_exports.Struct({
163728
+ name: NonEmptyString2.annotations({ description: "Project name" }),
163729
+ identifier: Schema_exports.String.pipe(
163730
+ Schema_exports.pattern(/^[A-Z][A-Z0-9_]{0,4}$/)
163731
+ ).annotations({
163732
+ description: "Unique project identifier, 1-5 uppercase alphanumeric chars starting with letter (e.g., 'HULY', 'QA')"
163733
+ }),
163734
+ description: Schema_exports.optional(Schema_exports.String.annotations({ description: "Project description" })),
163735
+ private: Schema_exports.optional(Schema_exports.Boolean.annotations({ description: "Whether project is private (default: false)" }))
163736
+ }).annotations({ title: "CreateProjectParams", description: "Parameters for creating a project" });
163737
+ var UPDATE_PROJECT_FIELDS = ["name", "description"];
163738
+ var UpdateProjectParamsSchema = Schema_exports.Struct({
163739
+ project: ProjectIdentifier.annotations({ description: "Project identifier to update" }),
163740
+ name: Schema_exports.optional(NonEmptyString2.annotations({ description: "New project name" })),
163741
+ description: Schema_exports.optional(
163742
+ Schema_exports.NullOr(Schema_exports.String).annotations({ description: "New description (null to clear)" })
163743
+ )
163744
+ }).annotations({
163745
+ title: "UpdateProjectParams",
163746
+ description: `Parameters for updating a project. ${atLeastOneUpdateFieldMessage(UPDATE_PROJECT_FIELDS)}`
163747
+ });
163748
+ var DeleteProjectParamsSchema = Schema_exports.Struct({
163749
+ project: ProjectIdentifier.annotations({ description: "Project identifier to delete" })
163750
+ }).annotations({ title: "DeleteProjectParams", description: "Parameters for deleting a project" });
163751
+ var ListStatusesParamsSchema = Schema_exports.Struct({
163752
+ project: ProjectIdentifier.annotations({ description: "Project identifier (e.g., 'HULY')" })
163753
+ }).annotations({ title: "ListStatusesParams", description: "Parameters for listing project statuses" });
163754
+ var StatusDetailSchema = Schema_exports.Struct({
163755
+ name: StatusName,
163756
+ category: StatusCategoryValueSchema,
163757
+ isDefault: Schema_exports.Boolean
163758
+ }).annotations({
163759
+ title: "StatusDetail",
163760
+ description: "Issue status with workflow category and default info"
163761
+ });
163762
+ var listProjectsParamsJsonSchema = JSONSchema_exports.make(ListProjectsParamsSchema);
163763
+ var listStatusesParamsJsonSchema = JSONSchema_exports.make(ListStatusesParamsSchema);
163764
+ var getProjectParamsJsonSchema = JSONSchema_exports.make(GetProjectParamsSchema);
163765
+ var createProjectParamsJsonSchema = JSONSchema_exports.make(CreateProjectParamsSchema);
163766
+ var updateProjectParamsJsonSchema = withAtLeastOneRequired(
163767
+ JSONSchema_exports.make(UpdateProjectParamsSchema),
163768
+ UPDATE_PROJECT_FIELDS
163769
+ );
163770
+ var deleteProjectParamsJsonSchema = JSONSchema_exports.make(DeleteProjectParamsSchema);
163771
+ var parseListProjectsParams = Schema_exports.decodeUnknown(ListProjectsParamsSchema);
163772
+ var parseListStatusesParams = Schema_exports.decodeUnknown(ListStatusesParamsSchema);
163773
+ var parseGetProjectParams = Schema_exports.decodeUnknown(GetProjectParamsSchema);
163774
+ var parseCreateProjectParams = Schema_exports.decodeUnknown(CreateProjectParamsSchema);
163775
+ var parseUpdateProjectParams = Schema_exports.decodeUnknown(UpdateProjectParamsSchema);
163776
+ var parseDeleteProjectParams = Schema_exports.decodeUnknown(DeleteProjectParamsSchema);
163777
+ var parseProject = Schema_exports.decodeUnknown(ProjectSchema);
163778
+
163705
163779
  // src/domain/schemas/cards.ts
163706
163780
  var ListCardSpacesParamsSchema = Schema_exports.Struct({
163707
163781
  includeArchived: Schema_exports.optional(Schema_exports.Boolean.annotations({
@@ -164081,7 +164155,10 @@ var ListIssuesParamsBase = Schema_exports.Struct({
164081
164155
  description: "Project identifier (e.g., 'HULY')"
164082
164156
  }),
164083
164157
  status: Schema_exports.optional(StatusName.annotations({
164084
- description: "Filter by status name"
164158
+ description: "Filter by exact workflow status name. Does not accept category aliases."
164159
+ })),
164160
+ statusCategory: Schema_exports.optional(KnownStatusCategoryValueSchema.annotations({
164161
+ description: `Filter by Huly SDK task.statusCategory key: ${enumValuesDescription(StatusCategoryValues)}. Use status for exact project-specific status names.`
164085
164162
  })),
164086
164163
  assignee: Schema_exports.optional(PersonRefInput.annotations({
164087
164164
  description: "Filter by assignee email or display name"
@@ -164124,6 +164201,9 @@ var ListIssuesParamsSchema = ListIssuesParamsBase.pipe(
164124
164201
  if (params.titleSearch !== void 0 && params.titleRegex !== void 0) {
164125
164202
  return "Cannot provide both 'titleSearch' and 'titleRegex'. Use one or the other.";
164126
164203
  }
164204
+ if (params.status !== void 0 && params.statusCategory !== void 0) {
164205
+ return "Cannot provide both 'status' and 'statusCategory'. Use status for exact workflow status names or statusCategory for Huly workflow categories.";
164206
+ }
164127
164207
  if (params.assignee !== void 0 && params.hasAssignee !== void 0) {
164128
164208
  return "Cannot provide both 'assignee' and 'hasAssignee'. Use one or the other.";
164129
164209
  }
@@ -167891,7 +167971,7 @@ var parseDeleteTestResultParams = Schema_exports.decodeUnknown(DeleteTestResultP
167891
167971
  var parseRunTestPlanParams = Schema_exports.decodeUnknown(RunTestPlanParamsSchema);
167892
167972
 
167893
167973
  // src/version.ts
167894
- var VERSION = true ? "0.17.1" : "0.0.0-dev";
167974
+ var VERSION = true ? "0.18.0" : "0.0.0-dev";
167895
167975
 
167896
167976
  // src/mcp/error-mapping.ts
167897
167977
  var McpErrorCode = {
@@ -168105,21 +168185,6 @@ var clampLimit = (limit) => Math.min(limit ?? DEFAULT_LIMIT, MAX_LIMIT);
168105
168185
  // src/huly/operations/update-guards.ts
168106
168186
  var requireUpdateFields = (operation, params, fields) => hasAtLeastOneDefined(params, fields) ? Effect_exports.void : Effect_exports.fail(new NoUpdateFieldsError({ operation, fields: fields.map(String) }));
168107
168187
 
168108
- // src/huly/huly-plugins.ts
168109
- var activity = require_lib23().default;
168110
- var attachment = require_lib24().default;
168111
- var calendar = require_lib25().default;
168112
- var cardPlugin = require_lib26().default;
168113
- var chunter = require_lib27().default;
168114
- var contact = require_lib28().default;
168115
- var core = require_lib4().default;
168116
- var documentPlugin = require_lib29().default;
168117
- var notification = require_lib30().default;
168118
- var tags = require_lib31().default;
168119
- var task = require_lib34().default;
168120
- var time3 = require_lib35().default;
168121
- var tracker = require_lib36().default;
168122
-
168123
168188
  // src/huly/operations/channel-messages-shared.ts
168124
168189
  var findChannelMessage = (params) => Effect_exports.gen(function* () {
168125
168190
  const { channel, client } = yield* findChannel(params.channel);
@@ -168203,7 +168268,7 @@ var buildSocialIdToPersonNameMap = (client, socialIds) => Effect_exports.gen(fun
168203
168268
  for (const si of socialIdentities) {
168204
168269
  const person = personById.get(si.attachedTo);
168205
168270
  if (person !== void 0) {
168206
- result.set(si._id, person.name);
168271
+ result.set(si._id, PersonName.make(person.name));
168207
168272
  }
168208
168273
  }
168209
168274
  return result;
@@ -168219,7 +168284,7 @@ var buildAccountUuidToNameMap = (client, accountUuids) => Effect_exports.gen(fun
168219
168284
  const result = /* @__PURE__ */ new Map();
168220
168285
  for (const emp of employees) {
168221
168286
  if (emp.personUuid !== void 0) {
168222
- result.set(emp.personUuid, emp.name);
168287
+ result.set(emp.personUuid, PersonName.make(emp.name));
168223
168288
  }
168224
168289
  }
168225
168290
  return result;
@@ -168275,7 +168340,7 @@ var getChannel = (params) => Effect_exports.gen(function* () {
168275
168340
  description: channel.description || void 0,
168276
168341
  private: channel.private,
168277
168342
  archived: channel.archived,
168278
- members: memberNames?.map((m) => PersonName.make(m)),
168343
+ members: memberNames,
168279
168344
  messages: channel.messages,
168280
168345
  modifiedOn: channel.modifiedOn,
168281
168346
  createdOn: channel.createdOn
@@ -168357,7 +168422,7 @@ var listChannelMessages = (params) => Effect_exports.gen(function* () {
168357
168422
  return {
168358
168423
  id: MessageId.make(msg._id),
168359
168424
  body: markupToMarkdownString(msg.message, markupUrlConfig),
168360
- sender: senderName !== void 0 ? PersonName.make(senderName) : void 0,
168425
+ sender: senderName,
168361
168426
  senderId: msg.modifiedBy,
168362
168427
  createdOn: msg.createdOn,
168363
168428
  modifiedOn: msg.modifiedOn,
@@ -168408,7 +168473,7 @@ var listDirectMessages = (params) => Effect_exports.gen(function* () {
168408
168473
  ];
168409
168474
  const accountUuidToName = yield* buildAccountUuidToNameMap(client, uniqueAccountUuids);
168410
168475
  const summaries = dms.map((dm) => {
168411
- const participants = dm.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0).map((n) => PersonName.make(n));
168476
+ const participants = dm.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0);
168412
168477
  const participantIds = dm.members.map((m) => AccountUuid.make(m));
168413
168478
  return {
168414
168479
  id: ChannelId.make(dm._id),
@@ -168904,6 +168969,31 @@ var findProject = (projectIdentifier) => Effect_exports.gen(function* () {
168904
168969
  );
168905
168970
  return { client, project: project3 };
168906
168971
  });
168972
+ var statusCategoryValueFromRef = (category) => category === void 0 ? "unknown" : StatusCategoryEntries.find((entry) => entry.ref === category)?.key ?? "unknown";
168973
+ var workflowStatusFromDoc = (doc) => {
168974
+ return {
168975
+ _id: doc._id,
168976
+ name: doc.name,
168977
+ category: statusCategoryValueFromRef(doc.category)
168978
+ };
168979
+ };
168980
+ var workflowStatusFromRef = (statusRef) => {
168981
+ const name = statusRef.includes(":") ? statusRef.slice(statusRef.lastIndexOf(":") + 1) : statusRef;
168982
+ return {
168983
+ _id: statusRef,
168984
+ name,
168985
+ category: "unknown"
168986
+ };
168987
+ };
168988
+ var uniqueStatusRefs = (refs) => refs.reduce(
168989
+ (unique, ref) => unique.includes(ref) ? unique : [...unique, ref],
168990
+ []
168991
+ );
168992
+ var uniqueStatusDocs = (statuses) => Array.from(statuses).reduce(
168993
+ (unique, status) => unique.some((existing) => existing._id === status._id) ? unique : [...unique, status],
168994
+ []
168995
+ );
168996
+ var uniqueProjectTypeStatusRefs = (statuses) => uniqueStatusRefs(statuses.map((status) => status._id));
168907
168997
  var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function* () {
168908
168998
  const client = yield* HulyClient;
168909
168999
  const project3 = yield* findOneOrFail(
@@ -168914,45 +169004,25 @@ var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function
168914
169004
  { lookup: { type: task.class.ProjectType } }
168915
169005
  );
168916
169006
  const projectType = project3.$lookup?.type;
168917
- const statuses = [];
168918
- if (projectType?.statuses) {
168919
- const statusRefs = projectType.statuses.map((s) => s._id);
168920
- if (statusRefs.length > 0) {
168921
- const statusDocsResult = yield* Effect_exports.either(
168922
- client.findAll(
168923
- core.class.Status,
168924
- hulyQuery({ _id: { $in: statusRefs } })
168925
- )
168926
- );
168927
- if (statusDocsResult._tag === "Right") {
168928
- for (const doc of statusDocsResult.right) {
168929
- const categoryStr = doc.category ? doc.category : "";
168930
- statuses.push({
168931
- _id: doc._id,
168932
- name: doc.name,
168933
- isDone: categoryStr === task.statusCategory.Won,
168934
- isCanceled: categoryStr === task.statusCategory.Lost
168935
- });
168936
- }
168937
- } else {
168938
- yield* Effect_exports.logWarning(
168939
- `Status query failed for project ${projectIdentifier}, using fallback. Category-based filtering (open/done/canceled) will use name heuristics. Error: ${statusDocsResult.left.message}`
168940
- );
168941
- for (const ps of projectType.statuses) {
168942
- const name = ps._id.split(":").pop() ?? "Unknown";
168943
- const nameLower = name.toLowerCase();
168944
- const isDone5 = nameLower.includes("done") || nameLower.includes("complete") || nameLower.includes("finished") || nameLower.includes("resolved") || nameLower.includes("closed");
168945
- const isCanceled = nameLower.includes("cancel") || nameLower.includes("reject") || nameLower.includes("abort") || nameLower.includes("wontfix") || nameLower.includes("invalid");
168946
- statuses.push({
168947
- _id: ps._id,
168948
- name,
168949
- isDone: isDone5,
168950
- isCanceled
168951
- });
168952
- }
168953
- }
169007
+ const statuses = projectType?.statuses ? yield* Effect_exports.gen(function* () {
169008
+ const statusRefs = uniqueProjectTypeStatusRefs(projectType.statuses);
169009
+ if (statusRefs.length === 0) {
169010
+ return [];
168954
169011
  }
168955
- }
169012
+ const statusDocsResult = yield* Effect_exports.either(
169013
+ client.findAll(
169014
+ core.class.Status,
169015
+ hulyQuery({ _id: { $in: statusRefs } })
169016
+ )
169017
+ );
169018
+ if (statusDocsResult._tag === "Right") {
169019
+ return uniqueStatusDocs(statusDocsResult.right).map(workflowStatusFromDoc);
169020
+ }
169021
+ yield* Effect_exports.logWarning(
169022
+ `Status query failed for project ${projectIdentifier}, using fallback. statusCategory filtering is unavailable until Huly returns status metadata. Error: ${statusDocsResult.left.message}`
169023
+ );
169024
+ return statusRefs.map(workflowStatusFromRef);
169025
+ }) : [];
168956
169026
  const defaultStatusId = project3.defaultIssueStatus || statuses[0]?._id;
168957
169027
  return { client, defaultStatusId, project: project3, projectType, statuses };
168958
169028
  });
@@ -170866,7 +170936,7 @@ var findDirectMessage = (identifier2) => Effect_exports.gen(function* () {
170866
170936
  const accountUuid = client.getAccountUuid();
170867
170937
  const accountUuids = [
170868
170938
  ...new Set(
170869
- employees.map((e) => e.personUuid).filter((u) => u !== void 0 && u !== accountUuid)
170939
+ employees.map((e) => e.personUuid).filter((u) => u !== void 0).filter((u) => u !== accountUuid)
170870
170940
  )
170871
170941
  ];
170872
170942
  if (accountUuids.length === 0) {
@@ -170925,7 +170995,7 @@ var listDirectMessageMessages = (params) => Effect_exports.gen(function* () {
170925
170995
  return {
170926
170996
  id: MessageId.make(msg._id),
170927
170997
  body: markupToMarkdownString(msg.message, markupUrlConfig),
170928
- sender: senderName !== void 0 ? PersonName.make(senderName) : void 0,
170998
+ sender: senderName,
170929
170999
  senderId: msg.modifiedBy,
170930
171000
  createdOn: msg.createdOn,
170931
171001
  modifiedOn: msg.modifiedOn,
@@ -171077,7 +171147,7 @@ var listThreadReplies = (params) => Effect_exports.gen(function* () {
171077
171147
  return {
171078
171148
  id: ThreadReplyId.make(msg._id),
171079
171149
  body: markupToMarkdownString(msg.message, markupUrlConfig),
171080
- sender: senderName !== void 0 ? PersonName.make(senderName) : void 0,
171150
+ sender: senderName,
171081
171151
  senderId: msg.modifiedBy,
171082
171152
  createdOn: msg.createdOn,
171083
171153
  modifiedOn: msg.modifiedOn,
@@ -173546,6 +173616,90 @@ var resolveDocumentWithoutTeamspace = (client, identifier2, field) => Effect_exp
173546
173616
  }
173547
173617
  return resolvedSummary(byTitle[0], "document");
173548
173618
  });
173619
+ var findCardById = (client, identifier2) => client.findOne(
173620
+ cardPlugin.class.Card,
173621
+ hulyQuery({ _id: toRef(identifier2) })
173622
+ );
173623
+ var findCardSpace2 = (client, identifier2, field) => Effect_exports.gen(function* () {
173624
+ const byId = yield* client.findOne(
173625
+ cardPlugin.class.CardSpace,
173626
+ hulyQuery({ _id: toRef(identifier2) })
173627
+ );
173628
+ if (byId !== void 0) {
173629
+ return byId;
173630
+ }
173631
+ const byName = yield* client.findAll(
173632
+ cardPlugin.class.CardSpace,
173633
+ hulyQuery({ name: identifier2, archived: false }),
173634
+ { limit: 2 }
173635
+ );
173636
+ if (byName.length === 0) {
173637
+ return yield* new GenericObjectNotFoundError({
173638
+ field,
173639
+ identifier: identifier2,
173640
+ class: cardPlugin.class.CardSpace
173641
+ });
173642
+ }
173643
+ if (byName.length > 1) {
173644
+ return yield* new GenericObjectIdentifierAmbiguousError({
173645
+ field,
173646
+ identifier: identifier2,
173647
+ candidates: byName.map((space) => ({
173648
+ id: DocId.make(space._id),
173649
+ class: ObjectClassName.make(space._class),
173650
+ display: space.name
173651
+ }))
173652
+ });
173653
+ }
173654
+ return byName[0];
173655
+ });
173656
+ var resolveCardInSpace = (client, identifier2, cardSpace, field) => Effect_exports.gen(function* () {
173657
+ const byId = yield* client.findOne(
173658
+ cardPlugin.class.Card,
173659
+ hulyQuery({ _id: toRef(identifier2), space: cardSpace._id })
173660
+ );
173661
+ if (byId !== void 0) {
173662
+ return resolvedSummary(byId, "card");
173663
+ }
173664
+ const byTitle = yield* client.findAll(
173665
+ cardPlugin.class.Card,
173666
+ hulyQuery({ title: identifier2, space: cardSpace._id }),
173667
+ { limit: 2 }
173668
+ );
173669
+ if (byTitle.length === 0) {
173670
+ return yield* new GenericObjectNotFoundError({
173671
+ field,
173672
+ identifier: identifier2,
173673
+ class: cardPlugin.class.Card
173674
+ });
173675
+ }
173676
+ if (byTitle.length > 1) {
173677
+ return yield* new GenericObjectIdentifierAmbiguousError({
173678
+ field,
173679
+ identifier: identifier2,
173680
+ candidates: byTitle.map((card) => ({
173681
+ id: DocId.make(card._id),
173682
+ class: ObjectClassName.make(card._class),
173683
+ display: card.title
173684
+ }))
173685
+ });
173686
+ }
173687
+ return resolvedSummary(byTitle[0], "card");
173688
+ });
173689
+ var resolveCardLocator = (client, locator, field) => Effect_exports.gen(function* () {
173690
+ if (locator.cardSpace !== void 0) {
173691
+ const cardSpace = yield* findCardSpace2(client, locator.cardSpace, field);
173692
+ return yield* resolveCardInSpace(client, locator.card, cardSpace, field);
173693
+ }
173694
+ const byId = yield* findCardById(client, locator.card);
173695
+ if (byId !== void 0) {
173696
+ return resolvedSummary(byId, "card");
173697
+ }
173698
+ return yield* new GenericObjectLocatorInvalidError({
173699
+ field,
173700
+ reason: `card '${locator.card}' was not found by ID; exact card title lookup requires cardSpace`
173701
+ });
173702
+ });
173549
173703
  var resolveGenericObject = (client, locator, expectedClass, field) => Effect_exports.gen(function* () {
173550
173704
  switch (locator.kind) {
173551
173705
  case "raw": {
@@ -173584,6 +173738,11 @@ var resolveGenericObject = (client, locator, expectedClass, field) => Effect_exp
173584
173738
  yield* validateExpectedClass(summary5, expectedClass, field);
173585
173739
  return summary5;
173586
173740
  }
173741
+ case "card": {
173742
+ const summary5 = yield* resolveCardLocator(client, locator, field);
173743
+ yield* validateExpectedClass(summary5, expectedClass, field);
173744
+ return summary5;
173745
+ }
173587
173746
  }
173588
173747
  });
173589
173748
  var unresolvedRelationEndpoint = (id, className, warning) => ({
@@ -174069,7 +174228,7 @@ var genericAssociationTools = [
174069
174228
  },
174070
174229
  {
174071
174230
  name: "list_relations",
174072
- description: "List concrete Huly relation instances under an association, optionally filtered by source and target documents. Requires at least one filter to avoid broad workspace scans.",
174231
+ description: "List concrete Huly relation instances under an association, optionally filtered by source and target documents. Endpoint locators support raw, issue, document, and card. Requires at least one filter to avoid broad workspace scans.",
174073
174232
  category: CATEGORY11,
174074
174233
  inputSchema: listRelationsParamsJsonSchema,
174075
174234
  handler: createEncodedToolHandler(
@@ -174081,7 +174240,7 @@ var genericAssociationTools = [
174081
174240
  },
174082
174241
  {
174083
174242
  name: "create_relation",
174084
- description: "Idempotently create one concrete relation between two resolved documents for a writable association. Enforces association endpoint classes, direction, duplicate handling, automation-only restrictions, and cardinality.",
174243
+ description: "Idempotently create one concrete relation between two resolved documents for a writable association. Endpoint locators support raw, issue, document, and card. Enforces association endpoint classes, direction, duplicate handling, automation-only restrictions, and cardinality.",
174085
174244
  category: CATEGORY11,
174086
174245
  inputSchema: createRelationParamsJsonSchema,
174087
174246
  annotations: {
@@ -174099,7 +174258,7 @@ var genericAssociationTools = [
174099
174258
  },
174100
174259
  {
174101
174260
  name: "delete_relation",
174102
- description: "Idempotently delete one concrete relation by relation ID or by exact association/source/target triple. Triple deletes use the same direction semantics as create_relation and fail if the selector is ambiguous.",
174261
+ description: "Idempotently delete one concrete relation by relation ID or by exact association/source/target triple. Triple endpoint locators support raw, issue, document, and card. Triple deletes use the same direction semantics as create_relation and fail if the selector is ambiguous.",
174103
174262
  category: CATEGORY11,
174104
174263
  inputSchema: deleteRelationParamsJsonSchema,
174105
174264
  annotations: {
@@ -174576,36 +174735,30 @@ var resolveStatusName = (statuses, statusId) => {
174576
174735
  const statusDoc = statuses.find((s) => s._id === statusId);
174577
174736
  return statusDoc?.name ?? "Unknown";
174578
174737
  };
174738
+ var hasUnknownStatusCategory = (statuses) => statuses.some((status) => status.category === "unknown");
174739
+ var requireKnownStatusCategories = (statuses, category, project3) => hasUnknownStatusCategory(statuses) ? Effect_exports.fail(
174740
+ new HulyConnectionError({
174741
+ message: `Cannot filter project '${project3}' issues by status category '${category}' because Huly did not return complete status category metadata. Use an exact status name instead.`
174742
+ })
174743
+ ) : Effect_exports.void;
174744
+ var statusIdsByCategory = (statuses, category) => statuses.filter((status) => status.category === category).map((status) => status._id);
174579
174745
  var listIssues = (params) => Effect_exports.gen(function* () {
174580
174746
  const { client, project: project3, statuses } = yield* findProjectWithStatuses(params.project);
174581
174747
  const query = {
174582
174748
  space: project3._id
174583
174749
  };
174584
- if (params.status !== void 0) {
174585
- const statusFilter = normalizeForComparison(params.status);
174586
- if (statusFilter === "open") {
174587
- const doneAndCanceledStatuses = statuses.filter((s) => s.isDone || s.isCanceled).map((s) => s._id);
174588
- if (doneAndCanceledStatuses.length > 0) {
174589
- query.status = { $nin: doneAndCanceledStatuses };
174590
- }
174591
- } else if (statusFilter === "done") {
174592
- const doneStatuses = statuses.filter((s) => s.isDone).map((s) => s._id);
174593
- if (doneStatuses.length > 0) {
174594
- query.status = { $in: doneStatuses };
174595
- } else {
174596
- return [];
174597
- }
174598
- } else if (statusFilter === "canceled") {
174599
- const canceledStatuses = statuses.filter((s) => s.isCanceled).map((s) => s._id);
174600
- if (canceledStatuses.length > 0) {
174601
- query.status = { $in: canceledStatuses };
174602
- } else {
174603
- return [];
174604
- }
174750
+ if (params.statusCategory !== void 0) {
174751
+ yield* requireKnownStatusCategories(statuses, params.statusCategory, params.project);
174752
+ const matchingStatuses = statusIdsByCategory(statuses, params.statusCategory);
174753
+ if (matchingStatuses.length > 0) {
174754
+ query.status = { $in: matchingStatuses };
174605
174755
  } else {
174606
- query.status = yield* resolveStatusByName(statuses, params.status, params.project);
174756
+ return [];
174607
174757
  }
174608
174758
  }
174759
+ if (params.status !== void 0) {
174760
+ query.status = yield* resolveStatusByName(statuses, params.status, params.project);
174761
+ }
174609
174762
  if (params.assignee !== void 0) {
174610
174763
  const assigneePerson = yield* findPersonByEmailOrName(client, params.assignee);
174611
174764
  if (assigneePerson !== void 0) {
@@ -175635,7 +175788,7 @@ var CATEGORY12 = "issues";
175635
175788
  var issueTools = [
175636
175789
  {
175637
175790
  name: "list_issues",
175638
- description: "Query Huly issues with optional filters. Returns issues sorted by modification date (newest first). Supports filtering by project, status, assignee, component, and parentIssue (to list children of a specific issue). Supports searching by title substring (titleSearch) and description content (descriptionSearch).",
175791
+ description: `Query Huly issues with optional filters. Returns issues sorted by modification date (newest first). Supports filtering by project, exact workflow status name (status), Huly SDK task.statusCategory key (statusCategory: ${enumValuesDescription(StatusCategoryValues)}), assignee, component, and parentIssue (to list children of a specific issue). Supports searching by title substring (titleSearch) and description content (descriptionSearch).`,
175639
175792
  category: CATEGORY12,
175640
175793
  inputSchema: listIssuesParamsJsonSchema,
175641
175794
  handler: createToolHandler(
@@ -177397,8 +177550,7 @@ var listStatuses = (params) => Effect_exports.gen(function* () {
177397
177550
  const { defaultStatusId, statuses } = yield* findProjectWithStatuses(params.project);
177398
177551
  const details = statuses.map((s) => ({
177399
177552
  name: StatusName.make(s.name),
177400
- isDone: s.isDone,
177401
- isCanceled: s.isCanceled,
177553
+ category: s.category,
177402
177554
  isDefault: s._id === defaultStatusId
177403
177555
  }));
177404
177556
  return { statuses: details, total: details.length };
@@ -177502,7 +177654,7 @@ var projectTools = [
177502
177654
  },
177503
177655
  {
177504
177656
  name: "list_statuses",
177505
- description: "List all issue statuses for a Huly project with category info. Returns status name, isDone, isCanceled, and isDefault flags. Use this to discover valid statuses before creating or updating issues.",
177657
+ description: "List all issue statuses for a Huly project with workflow category and default info. Returns status name, category, and isDefault. Use this to discover valid statuses before creating or updating issues.",
177506
177658
  category: CATEGORY18,
177507
177659
  inputSchema: listStatusesParamsJsonSchema,
177508
177660
  handler: createToolHandler(
@@ -177675,20 +177827,20 @@ var tagCategoryTools = [
177675
177827
  var import_core38 = __toESM(require_lib4(), 1);
177676
177828
  var import_platform3 = __toESM(require_lib(), 1);
177677
177829
  var STATUS_CATEGORY_BY_SDK_KEY = {
177678
- UnStarted: { value: "backlog", ref: task.statusCategory.UnStarted, name: "Backlog" },
177679
- ToDo: { value: "todo", ref: task.statusCategory.ToDo, name: "Todo" },
177680
- Active: { value: "active", ref: task.statusCategory.Active, name: "Active" },
177681
- Won: { value: "done", ref: task.statusCategory.Won, name: "Done" },
177682
- Lost: { value: "canceled", ref: task.statusCategory.Lost, name: "Canceled" }
177830
+ UnStarted: { value: "UnStarted", ref: StatusCategoryBySdkKey.UnStarted, name: "UnStarted" },
177831
+ ToDo: { value: "ToDo", ref: StatusCategoryBySdkKey.ToDo, name: "ToDo" },
177832
+ Active: { value: "Active", ref: StatusCategoryBySdkKey.Active, name: "Active" },
177833
+ Won: { value: "Won", ref: StatusCategoryBySdkKey.Won, name: "Won" },
177834
+ Lost: { value: "Lost", ref: StatusCategoryBySdkKey.Lost, name: "Lost" }
177683
177835
  };
177684
177836
  var exactStatusCategoryMapping = (value3) => value3;
177685
177837
  exactStatusCategoryMapping(true);
177686
177838
  var CATEGORY_TO_REF = {
177687
- backlog: STATUS_CATEGORY_BY_SDK_KEY.UnStarted.ref,
177688
- todo: STATUS_CATEGORY_BY_SDK_KEY.ToDo.ref,
177689
- active: STATUS_CATEGORY_BY_SDK_KEY.Active.ref,
177690
- done: STATUS_CATEGORY_BY_SDK_KEY.Won.ref,
177691
- canceled: STATUS_CATEGORY_BY_SDK_KEY.Lost.ref
177839
+ UnStarted: STATUS_CATEGORY_BY_SDK_KEY.UnStarted.ref,
177840
+ ToDo: STATUS_CATEGORY_BY_SDK_KEY.ToDo.ref,
177841
+ Active: STATUS_CATEGORY_BY_SDK_KEY.Active.ref,
177842
+ Won: STATUS_CATEGORY_BY_SDK_KEY.Won.ref,
177843
+ Lost: STATUS_CATEGORY_BY_SDK_KEY.Lost.ref
177692
177844
  };
177693
177845
  var REF_TO_CATEGORY = new Map(
177694
177846
  Object.values(STATUS_CATEGORY_BY_SDK_KEY).map((entry) => [entry.ref, entry.value])
@@ -177709,9 +177861,15 @@ var encodeOrConnectionError2 = (schema, value3, operation) => Schema_exports.enc
177709
177861
  })
177710
177862
  )
177711
177863
  );
177712
- var uniqueStatusIds = (projectType) => Array.from(new Set(projectType.statuses.map((status) => status._id)));
177864
+ var uniqueTaskTypeRefs = (refs) => refs.reduce((unique, ref) => unique.includes(ref) ? unique : [...unique, ref], []);
177865
+ var uniqueStatusIds = (projectType) => uniqueStatusRefs(projectType.statuses.map((status) => status._id));
177866
+ var sameProjectStatus = (left3, right3) => left3._id === right3._id && left3.taskType === right3.taskType;
177867
+ var uniqueProjectStatuses = (statuses) => statuses.reduce(
177868
+ (unique, status) => unique.some((existing) => sameProjectStatus(existing, status)) ? unique : [...unique, status],
177869
+ []
177870
+ );
177713
177871
  var getStatusDocs = (client, statusIds) => statusIds.length === 0 ? Effect_exports.succeed([]) : client.findAll(core.class.Status, hulyQuery({ _id: { $in: [...statusIds] } })).pipe(
177714
- Effect_exports.map((result) => [...result])
177872
+ Effect_exports.map(uniqueStatusDocs)
177715
177873
  );
177716
177874
  var getTaskTypes = (client, taskTypeIds) => taskTypeIds.length === 0 ? Effect_exports.succeed([]) : client.findAll(task.class.TaskType, hulyQuery({ _id: { $in: [...taskTypeIds] } })).pipe(
177717
177875
  Effect_exports.map((result) => [...result])
@@ -177743,7 +177901,11 @@ var projectTypeSummary = (data) => ({
177743
177901
  statusCount: uniqueStatusIds(data.projectType).length,
177744
177902
  isDefaultClassic: isDefaultClassicProjectType(data.projectType)
177745
177903
  });
177746
- var statusTaskTypeIds = (projectType, statusId) => projectType.statuses.filter((status) => status._id === statusId).map((status) => status.taskType);
177904
+ var statusTaskTypeIds = (projectType, statusId) => uniqueTaskTypeRefs(
177905
+ uniqueProjectStatuses(projectType.statuses).filter((status) => status._id === statusId).map(
177906
+ (status) => status.taskType
177907
+ )
177908
+ );
177747
177909
  var statusSummary = (projectType, status) => ({
177748
177910
  id: IssueStatusId.make(status._id),
177749
177911
  name: status.name,
@@ -177757,7 +177919,7 @@ var taskTypeSummary = (projectType, taskType) => ({
177757
177919
  projectTypeName: projectType.name,
177758
177920
  kind: taskType.kind,
177759
177921
  issueClass: taskType.ofClass,
177760
- statusCount: taskType.statuses.length
177922
+ statusCount: uniqueStatusRefs(taskType.statuses).length
177761
177923
  });
177762
177924
  var projectTypeDetail = (data) => ({
177763
177925
  ...projectTypeSummary(data),
@@ -177769,7 +177931,7 @@ var projectTypeDetail = (data) => ({
177769
177931
  taskTypeStatuses: data.taskTypes.map((taskType) => ({
177770
177932
  taskTypeId: TaskTypeId.make(taskType._id),
177771
177933
  taskTypeName: taskType.name,
177772
- statusIds: taskType.statuses.map((statusId) => IssueStatusId.make(statusId))
177934
+ statusIds: uniqueStatusRefs(taskType.statuses).map((statusId) => IssueStatusId.make(statusId))
177773
177935
  }))
177774
177936
  });
177775
177937
  var listAllProjectTypes = (client) => client.findAll(
@@ -177809,7 +177971,12 @@ var resolveStatusClass = (taskTypes) => {
177809
177971
  const statusClass = statusClasses.at(0);
177810
177972
  return statusClasses.length === 1 && statusClass !== void 0 ? Effect_exports.succeed(statusClass) : Effect_exports.fail(new HulyError({ message: "Target task types do not share one issue status class." }));
177811
177973
  };
177812
- var replaceOrAppendProjectStatus = (statuses, statusId, taskTypeId) => statuses.some((status) => status._id === statusId && status.taskType === taskTypeId) ? statuses : [...statuses, { _id: statusId, taskType: taskTypeId }];
177974
+ var replaceOrAppendProjectStatus = (statuses, statusId, taskTypeId) => statuses.some((status) => status._id === statusId && status.taskType === taskTypeId) ? [...statuses] : [...statuses, { _id: statusId, taskType: taskTypeId }];
177975
+ var sameStatusRefList = (left3, right3) => left3.length === right3.length && left3.every((value3, index) => value3 === right3[index]);
177976
+ var sameProjectStatusList = (left3, right3) => left3.length === right3.length && left3.every((value3, index) => {
177977
+ const rightValue = right3[index];
177978
+ return sameProjectStatus(value3, rightValue);
177979
+ });
177813
177980
  var listProjectTypes = (_params) => Effect_exports.gen(function* () {
177814
177981
  const client = yield* HulyClient;
177815
177982
  const projectTypes = yield* listAllProjectTypes(client);
@@ -177842,29 +178009,42 @@ var createTaskType = (params) => Effect_exports.gen(function* () {
177842
178009
  const workflowData = yield* loadWorkflowData(client, projectType);
177843
178010
  const allProjectTaskTypes = yield* getTaskTypesByProjectType(client, projectType._id);
177844
178011
  const existing = existingTaskTypeByName(allProjectTaskTypes, params.name);
178012
+ const normalizedProjectStatuses = uniqueProjectStatuses(projectType.statuses);
177845
178013
  if (existing !== void 0) {
178014
+ const existingTaskTypeStatuses = uniqueStatusRefs(existing.statuses);
178015
+ const taskTypeChanged = !sameStatusRefList(existingTaskTypeStatuses, existing.statuses);
177846
178016
  const projectTypeTasks = projectType.tasks.includes(existing._id) ? projectType.tasks : [...projectType.tasks, existing._id];
177847
- const existingProjectStatuses = existing.statuses.reduce(
178017
+ const existingProjectStatuses = existingTaskTypeStatuses.reduce(
177848
178018
  (statuses, statusId) => replaceOrAppendProjectStatus(statuses, statusId, existing._id),
177849
- [...projectType.statuses]
178019
+ normalizedProjectStatuses
177850
178020
  );
177851
- const projectTypeChanged = projectTypeTasks.length !== projectType.tasks.length || existingProjectStatuses.length !== projectType.statuses.length;
178021
+ const projectTypeChanged = projectTypeTasks.length !== projectType.tasks.length || !sameProjectStatusList(existingProjectStatuses, projectType.statuses);
178022
+ if (taskTypeChanged) {
178023
+ yield* client.updateDoc(
178024
+ task.class.TaskType,
178025
+ core.space.Model,
178026
+ existing._id,
178027
+ { statuses: [...existingTaskTypeStatuses] }
178028
+ );
178029
+ }
177852
178030
  if (projectTypeChanged) {
177853
178031
  yield* client.updateDoc(
177854
178032
  task.class.ProjectType,
177855
178033
  core.space.Model,
177856
178034
  projectType._id,
177857
- { tasks: projectTypeTasks, statuses: existingProjectStatuses }
178035
+ { tasks: projectTypeTasks, statuses: [...existingProjectStatuses] }
177858
178036
  );
177859
178037
  }
177860
178038
  const result2 = {
177861
- created: projectTypeChanged,
178039
+ created: taskTypeChanged || projectTypeChanged,
177862
178040
  projectType: projectTypeSummary({
177863
178041
  projectType: { ...projectType, tasks: projectTypeTasks, statuses: existingProjectStatuses },
177864
- taskTypes: workflowData.taskTypes.some((taskType) => taskType._id === existing._id) ? workflowData.taskTypes : [...workflowData.taskTypes, existing],
178042
+ taskTypes: workflowData.taskTypes.some((taskType) => taskType._id === existing._id) ? workflowData.taskTypes.map(
178043
+ (taskType) => taskType._id === existing._id ? { ...taskType, statuses: existingTaskTypeStatuses } : taskType
178044
+ ) : [...workflowData.taskTypes, { ...existing, statuses: existingTaskTypeStatuses }],
177865
178045
  statuses: workflowData.statuses
177866
178046
  }),
177867
- taskType: taskTypeSummary(projectType, existing),
178047
+ taskType: taskTypeSummary(projectType, { ...existing, statuses: existingTaskTypeStatuses }),
177868
178048
  affectedTaskTypeIds: [TaskTypeId.make(existing._id)],
177869
178049
  warning: WORKFLOW_WARNING
177870
178050
  };
@@ -177879,6 +178059,7 @@ var createTaskType = (params) => Effect_exports.gen(function* () {
177879
178059
  const taskTypeId = (0, import_core38.generateId)();
177880
178060
  const targetClassId = `${taskTypeId}:type:mixin`;
177881
178061
  const targetClassRef = toRef(targetClassId);
178062
+ const templateStatusIds = uniqueStatusRefs(template.statuses);
177882
178063
  yield* client.createDoc(
177883
178064
  core.class.Mixin,
177884
178065
  core.space.Model,
@@ -177907,7 +178088,7 @@ var createTaskType = (params) => Effect_exports.gen(function* () {
177907
178088
  kind: template.kind,
177908
178089
  ofClass: template.ofClass,
177909
178090
  targetClass: targetClassRef,
177910
- statuses: [...template.statuses],
178091
+ statuses: templateStatusIds,
177911
178092
  statusClass: template.statusClass,
177912
178093
  statusCategories: [...template.statusCategories],
177913
178094
  ...template.allowedAsChildOf === void 0 ? {} : { allowedAsChildOf: template.allowedAsChildOf },
@@ -177922,18 +178103,23 @@ var createTaskType = (params) => Effect_exports.gen(function* () {
177922
178103
  {
177923
178104
  tasks: [...projectType.tasks, taskTypeId],
177924
178105
  statuses: [
177925
- ...projectType.statuses,
177926
- ...template.statuses.map((statusId) => ({ _id: statusId, taskType: taskTypeId }))
178106
+ ...normalizedProjectStatuses,
178107
+ ...templateStatusIds.map((statusId) => ({ _id: statusId, taskType: taskTypeId }))
177927
178108
  ]
177928
178109
  }
177929
178110
  );
178111
+ const createdProjectStatuses = [
178112
+ ...normalizedProjectStatuses,
178113
+ ...templateStatusIds.map((statusId) => ({ _id: statusId, taskType: taskTypeId }))
178114
+ ];
177930
178115
  const createdTaskType = {
177931
178116
  ...template,
177932
178117
  _id: taskTypeId,
177933
178118
  parent: projectType._id,
177934
178119
  name: params.name,
177935
178120
  kind: template.kind,
177936
- targetClass: targetClassRef
178121
+ targetClass: targetClassRef,
178122
+ statuses: templateStatusIds
177937
178123
  };
177938
178124
  const result = {
177939
178125
  created: true,
@@ -177941,10 +178127,7 @@ var createTaskType = (params) => Effect_exports.gen(function* () {
177941
178127
  projectType: {
177942
178128
  ...projectType,
177943
178129
  tasks: [...projectType.tasks, taskTypeId],
177944
- statuses: [
177945
- ...projectType.statuses,
177946
- ...template.statuses.map((statusId) => ({ _id: statusId, taskType: taskTypeId }))
177947
- ]
178130
+ statuses: createdProjectStatuses
177948
178131
  },
177949
178132
  taskTypes: [...workflowData.taskTypes, createdTaskType],
177950
178133
  statuses: workflowData.statuses
@@ -177959,6 +178142,7 @@ var createIssueStatus = (params) => Effect_exports.gen(function* () {
177959
178142
  const client = yield* HulyClient;
177960
178143
  const projectType = yield* resolveProjectType(client, params.projectType);
177961
178144
  const workflowData = yield* loadWorkflowData(client, projectType);
178145
+ const normalizedProjectStatuses = uniqueProjectStatuses(projectType.statuses);
177962
178146
  const targetTaskTypes = params.taskType === void 0 ? workflowData.taskTypes : [yield* resolveTaskType(workflowData.taskTypes, params.taskType)];
177963
178147
  const statusClass = yield* resolveStatusClass(targetTaskTypes);
177964
178148
  const statusesByName = yield* getRecoverableStatusesByName(client, params.name);
@@ -177982,28 +178166,33 @@ var createIssueStatus = (params) => Effect_exports.gen(function* () {
177982
178166
  statusId
177983
178167
  );
177984
178168
  }
177985
- const taskTypesMissingStatus = targetTaskTypes.filter((taskType) => !taskType.statuses.includes(statusId));
178169
+ const taskTypesNeedingStatusUpdate = targetTaskTypes.filter((taskType) => {
178170
+ const normalizedStatuses = uniqueStatusRefs(taskType.statuses);
178171
+ return !normalizedStatuses.includes(statusId) || !sameStatusRefList(normalizedStatuses, taskType.statuses);
178172
+ });
177986
178173
  yield* Effect_exports.all(
177987
- taskTypesMissingStatus.map(
177988
- (taskType) => client.updateDoc(
178174
+ taskTypesNeedingStatusUpdate.map((taskType) => {
178175
+ const normalizedStatuses = uniqueStatusRefs(taskType.statuses);
178176
+ const updatedStatuses = normalizedStatuses.includes(statusId) ? normalizedStatuses : [...normalizedStatuses, statusId];
178177
+ return client.updateDoc(
177989
178178
  task.class.TaskType,
177990
178179
  core.space.Model,
177991
178180
  taskType._id,
177992
- { statuses: [...taskType.statuses, statusId] }
177993
- )
177994
- )
178181
+ { statuses: [...updatedStatuses] }
178182
+ );
178183
+ })
177995
178184
  );
177996
178185
  const updatedProjectStatuses = targetTaskTypes.reduce(
177997
178186
  (statuses, taskType) => replaceOrAppendProjectStatus(statuses, statusId, taskType._id),
177998
- [...projectType.statuses]
178187
+ normalizedProjectStatuses
177999
178188
  );
178000
- const projectTypeChanged = updatedProjectStatuses.length !== projectType.statuses.length;
178189
+ const projectTypeChanged = !sameProjectStatusList(updatedProjectStatuses, projectType.statuses);
178001
178190
  if (projectTypeChanged) {
178002
178191
  yield* client.updateDoc(
178003
178192
  task.class.ProjectType,
178004
178193
  core.space.Model,
178005
178194
  projectType._id,
178006
- { statuses: updatedProjectStatuses }
178195
+ { statuses: [...updatedProjectStatuses] }
178007
178196
  );
178008
178197
  }
178009
178198
  const statusDoc = existingStatus ?? {
@@ -178017,7 +178206,7 @@ var createIssueStatus = (params) => Effect_exports.gen(function* () {
178017
178206
  category: CATEGORY_TO_REF[params.category]
178018
178207
  };
178019
178208
  const result = {
178020
- created: existingStatus === void 0 || taskTypesMissingStatus.length > 0 || projectTypeChanged,
178209
+ created: existingStatus === void 0 || taskTypesNeedingStatusUpdate.length > 0 || projectTypeChanged,
178021
178210
  projectType: projectTypeSummary({
178022
178211
  projectType: { ...projectType, statuses: updatedProjectStatuses },
178023
178212
  taskTypes: workflowData.taskTypes,
@@ -178064,7 +178253,7 @@ var taskManagementTools = [
178064
178253
  },
178065
178254
  {
178066
178255
  name: "create_issue_status",
178067
- description: "Add a Huly issue workflow status idempotently by normalized name within a project type and task type scope. Accepts category as backlog, todo, active, done, or canceled; taskType may be ID or display name, and omission applies the status to every task type in the project type.",
178256
+ description: `Add a Huly issue workflow status idempotently by normalized name within a project type and task type scope. Accepts category as a Huly SDK task.statusCategory key: ${enumValuesDescription(StatusCategoryValues)}; taskType may be ID or display name, and omission applies the status to every task type in the project type.`,
178068
178257
  category: CATEGORY22,
178069
178258
  inputSchema: createIssueStatusParamsJsonSchema,
178070
178259
  annotations: { idempotentHint: true },
@@ -190246,6 +190435,37 @@ var McpServerService = class _McpServerService extends Context_exports.Tag("@hul
190246
190435
  }
190247
190436
  };
190248
190437
 
190438
+ // src/mcp/stdio-output.ts
190439
+ var redirectedMethods = [
190440
+ "debug",
190441
+ "info",
190442
+ "log",
190443
+ "warn",
190444
+ "error"
190445
+ ];
190446
+ var redirectConsoleToStderr = (target = console) => {
190447
+ const original = {
190448
+ debug: target.debug,
190449
+ error: target.error,
190450
+ info: target.info,
190451
+ log: target.log,
190452
+ warn: target.warn
190453
+ };
190454
+ const writeToStderr = original.error.bind(target);
190455
+ for (const method of redirectedMethods) {
190456
+ target[method] = writeToStderr;
190457
+ }
190458
+ return {
190459
+ restore: () => {
190460
+ target.debug = original.debug;
190461
+ target.error = original.error;
190462
+ target.info = original.info;
190463
+ target.log = original.log;
190464
+ target.warn = original.warn;
190465
+ }
190466
+ };
190467
+ };
190468
+
190249
190469
  // src/index.ts
190250
190470
  var getTransportType = Config_exports.string("MCP_TRANSPORT").pipe(
190251
190471
  Config_exports.withDefault("stdio"),
@@ -190273,6 +190493,9 @@ var getLazyEnvs = Config_exports.string("LAZY_ENVS").pipe(
190273
190493
  Config_exports.withDefault("false"),
190274
190494
  Effect_exports.map((v) => v.toLowerCase() === "true")
190275
190495
  );
190496
+ var restoreConsoleRedirect = (redirect) => Effect_exports.sync(() => {
190497
+ redirect?.restore();
190498
+ });
190276
190499
  var buildCombinedClientLayer = () => {
190277
190500
  const configLayer = HulyConfigService.layer;
190278
190501
  const hulyClientLayer = HulyClient.layer.pipe(
@@ -190364,8 +190587,7 @@ var buildAppLayer = (transport, httpPort, httpHost, mcpAuthToken, autoExit, auth
190364
190587
  const mcpServerLayer = McpServerService.layer(mcpServerConfig).pipe(Layer_exports.provide(TelemetryService.layer));
190365
190588
  return Layer_exports.merge(mcpServerLayer, HttpServerFactoryService.defaultLayer);
190366
190589
  };
190367
- var main = Effect_exports.gen(function* () {
190368
- const transport = yield* getTransportType;
190590
+ var runConfiguredServer = (transport) => Effect_exports.gen(function* () {
190369
190591
  const httpPort = yield* getHttpPort;
190370
190592
  const httpHost = yield* getHttpHost;
190371
190593
  const mcpAuthToken = transport === "http" ? Option_exports.map(yield* getMcpAuthToken, Redacted_exports.value).pipe(Option_exports.getOrUndefined) : void 0;
@@ -190399,6 +190621,13 @@ var main = Effect_exports.gen(function* () {
190399
190621
  Effect_exports.scoped
190400
190622
  );
190401
190623
  });
190624
+ var main = Effect_exports.gen(function* () {
190625
+ const transport = yield* getTransportType;
190626
+ const consoleRedirect = yield* Effect_exports.sync(() => transport === "stdio" ? redirectConsoleToStderr() : void 0);
190627
+ yield* runConfiguredServer(transport).pipe(
190628
+ Effect_exports.ensuring(restoreConsoleRedirect(consoleRedirect))
190629
+ );
190630
+ });
190402
190631
  var isMainModule = (() => {
190403
190632
  if (typeof require !== "undefined" && require.main === module) return true;
190404
190633
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firfi/huly-mcp",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "MCP server for Huly integration",
5
5
  "mcpName": "io.github.dearlordylord/huly-mcp",
6
6
  "type": "module",
@@ -111,6 +111,6 @@
111
111
  "verify-version": "node -e \"const v=require('./package.json').version; const d=require('fs').readFileSync('dist/index.cjs','utf8'); if(!d.includes('\\\"'+v+'\\\"'))throw new Error('dist version mismatch: expected '+v)\"",
112
112
  "verify-registry-metadata": "node scripts/sync-registry-metadata.mjs --check",
113
113
  "sync-registry-metadata": "node scripts/sync-registry-metadata.mjs",
114
- "update-readme": "node scripts/update-readme-tools.mjs"
114
+ "update-readme": "tsx scripts/update-readme-tools.mjs"
115
115
  }
116
116
  }