@daghis/teamcity-mcp 1.9.0 → 1.9.2

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.9.2](https://github.com/Daghis/teamcity-mcp/compare/v1.9.1...v1.9.2) (2025-09-21)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **teamcity:** restore artifact rules update compatibility ([#185](https://github.com/Daghis/teamcity-mcp/issues/185)) ([1d67268](https://github.com/Daghis/teamcity-mcp/commit/1d67268e6ee837db38ab9be27a94a5f3e072ab83))
9
+
10
+ ## [1.9.1](https://github.com/Daghis/teamcity-mcp/compare/v1.9.0...v1.9.1) (2025-09-20)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **tools:** allow manage_build_steps updates ([#182](https://github.com/Daghis/teamcity-mcp/issues/182)) ([2c6bea0](https://github.com/Daghis/teamcity-mcp/commit/2c6bea0cf6770d22068b9e4b733542a056399148))
16
+
3
17
  ## [1.9.0](https://github.com/Daghis/teamcity-mcp/compare/v1.8.2...v1.9.0) (2025-09-20)
4
18
 
5
19
 
package/dist/index.js CHANGED
@@ -1346,6 +1346,38 @@ var ArtifactManager = class _ArtifactManager {
1346
1346
  };
1347
1347
 
1348
1348
  // src/teamcity/build-configuration-update-manager.ts
1349
+ var ARTIFACT_RULES_SETTINGS_FIELD = "settings/artifactRules";
1350
+ var ARTIFACT_RULES_LEGACY_FIELD = "artifactRules";
1351
+ var isArtifactRulesRetryableError = (error2) => {
1352
+ if (error2 == null || typeof error2 !== "object") return false;
1353
+ if (!("response" in error2)) return false;
1354
+ const response = error2.response;
1355
+ const status = response?.status;
1356
+ return status === 400 || status === 404;
1357
+ };
1358
+ var setArtifactRulesWithFallback = async (api, buildTypeId, artifactRules) => {
1359
+ try {
1360
+ await api.setBuildTypeField(buildTypeId, ARTIFACT_RULES_SETTINGS_FIELD, artifactRules);
1361
+ } catch (err) {
1362
+ if (!isArtifactRulesRetryableError(err)) {
1363
+ throw err;
1364
+ }
1365
+ const status = err.response?.status;
1366
+ debug("Retrying artifact rules update via legacy field", {
1367
+ buildTypeId,
1368
+ status
1369
+ });
1370
+ try {
1371
+ await api.setBuildTypeField(buildTypeId, ARTIFACT_RULES_LEGACY_FIELD, artifactRules);
1372
+ } catch (fallbackError) {
1373
+ debug("Legacy artifact rules update failed", {
1374
+ buildTypeId,
1375
+ status: fallbackError.response?.status
1376
+ });
1377
+ throw fallbackError;
1378
+ }
1379
+ }
1380
+ };
1349
1381
  var BuildConfigurationUpdateManager = class {
1350
1382
  client;
1351
1383
  constructor(client) {
@@ -1555,6 +1587,14 @@ var BuildConfigurationUpdateManager = class {
1555
1587
  }
1556
1588
  if (settings.length > 0) {
1557
1589
  for (const setting of settings) {
1590
+ if (setting.name === "artifactRules") {
1591
+ await setArtifactRulesWithFallback(
1592
+ this.client.modules.buildTypes,
1593
+ currentConfig.id,
1594
+ setting.value
1595
+ );
1596
+ continue;
1597
+ }
1558
1598
  await this.client.modules.buildTypes.setBuildTypeField(
1559
1599
  currentConfig.id,
1560
1600
  `settings/${setting.name}`,
@@ -40100,9 +40140,9 @@ var FULL_MODE_TOOLS = [
40100
40140
  );
40101
40141
  }
40102
40142
  if (typedArgs.artifactRules !== void 0) {
40103
- await adapter.modules.buildTypes.setBuildTypeField(
40143
+ await setArtifactRulesWithFallback(
40144
+ adapter.modules.buildTypes,
40104
40145
  typedArgs.buildTypeId,
40105
- "settings/artifactRules",
40106
40146
  typedArgs.artifactRules
40107
40147
  );
40108
40148
  }
@@ -40123,9 +40163,9 @@ var FULL_MODE_TOOLS = [
40123
40163
  );
40124
40164
  }
40125
40165
  if (typedArgs.artifactRules !== void 0) {
40126
- await adapter.modules.buildTypes.setBuildTypeField(
40166
+ await setArtifactRulesWithFallback(
40167
+ adapter.modules.buildTypes,
40127
40168
  typedArgs.buildTypeId,
40128
- "settings/artifactRules",
40129
40169
  typedArgs.artifactRules
40130
40170
  );
40131
40171
  }
@@ -40400,103 +40440,122 @@ var FULL_MODE_TOOLS = [
40400
40440
  required: ["buildTypeId", "action"]
40401
40441
  },
40402
40442
  handler: async (args) => {
40403
- const typedArgs = args;
40404
- const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
40405
- switch (typedArgs.action) {
40406
- case "add": {
40407
- const stepProps = Object.fromEntries(
40408
- Object.entries(typedArgs.properties ?? {}).map(([k, v]) => [k, String(v)])
40409
- );
40410
- if (typedArgs.type === "simpleRunner" && stepProps["script.content"]) {
40411
- stepProps["use.custom.script"] = stepProps["use.custom.script"] ?? "true";
40412
- }
40413
- const step = {
40414
- name: typedArgs.name,
40415
- type: typedArgs.type,
40416
- properties: {
40417
- property: Object.entries(stepProps).map(([k, v]) => ({ name: k, value: v }))
40418
- }
40419
- };
40420
- await adapter.modules.buildTypes.addBuildStepToBuildType(
40421
- typedArgs.buildTypeId,
40422
- void 0,
40423
- step,
40424
- {
40425
- headers: { "Content-Type": "application/json", Accept: "application/json" }
40426
- }
40427
- );
40428
- return json({
40429
- success: true,
40430
- action: "add_build_step",
40431
- buildTypeId: typedArgs.buildTypeId
40432
- });
40433
- }
40434
- case "update": {
40435
- if (typedArgs.stepId == null || typedArgs.stepId === "") {
40436
- return json({
40437
- success: false,
40438
- action: "update_build_step",
40439
- error: "Step ID is required for update action"
40440
- });
40441
- }
40442
- const updatePayload = {};
40443
- if (typedArgs.name != null) {
40444
- updatePayload["name"] = typedArgs.name;
40445
- }
40446
- if (typedArgs.type != null) {
40447
- updatePayload["type"] = typedArgs.type;
40448
- }
40449
- const rawProps = typedArgs.properties ?? {};
40450
- const stepProps = Object.fromEntries(
40451
- Object.entries(rawProps).map(([k, v]) => [k, String(v)])
40452
- );
40453
- if (stepProps["script.content"]) {
40454
- stepProps["use.custom.script"] = stepProps["use.custom.script"] ?? "true";
40455
- stepProps["script.type"] = stepProps["script.type"] ?? "customScript";
40456
- }
40457
- if (Object.keys(stepProps).length > 0) {
40458
- updatePayload["properties"] = {
40459
- property: Object.entries(stepProps).map(([name, value]) => ({ name, value }))
40460
- };
40461
- }
40462
- if (Object.keys(updatePayload).length === 0) {
40463
- return json({
40464
- success: false,
40465
- action: "update_build_step",
40466
- error: "No update fields provided"
40443
+ const schema = import_zod4.z.object({
40444
+ buildTypeId: import_zod4.z.string().min(1, "buildTypeId is required"),
40445
+ action: import_zod4.z.enum(["add", "update", "delete"]),
40446
+ stepId: import_zod4.z.string().min(1).optional(),
40447
+ name: import_zod4.z.string().optional(),
40448
+ type: import_zod4.z.string().optional(),
40449
+ properties: import_zod4.z.record(import_zod4.z.unknown()).optional()
40450
+ }).superRefine((value, ctx) => {
40451
+ if (value.action === "update" || value.action === "delete") {
40452
+ if (!value.stepId || value.stepId.trim() === "") {
40453
+ ctx.addIssue({
40454
+ code: import_zod4.z.ZodIssueCode.custom,
40455
+ message: "stepId is required for update or delete actions",
40456
+ path: ["stepId"]
40467
40457
  });
40468
40458
  }
40469
- await adapter.modules.buildTypes.replaceBuildStep(
40470
- typedArgs.buildTypeId,
40471
- typedArgs.stepId,
40472
- void 0,
40473
- updatePayload
40474
- );
40475
- return json({
40476
- success: true,
40477
- action: "update_build_step",
40478
- buildTypeId: typedArgs.buildTypeId,
40479
- stepId: typedArgs.stepId
40480
- });
40481
40459
  }
40482
- case "delete":
40483
- if (typedArgs.stepId == null || typedArgs.stepId === "") {
40484
- return json({
40485
- success: false,
40486
- action: "delete_build_step",
40487
- error: "Step ID is required for delete action"
40488
- });
40460
+ });
40461
+ return runTool(
40462
+ "manage_build_steps",
40463
+ schema,
40464
+ async (typedArgs) => {
40465
+ const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
40466
+ switch (typedArgs.action) {
40467
+ case "add": {
40468
+ const stepProps = Object.fromEntries(
40469
+ Object.entries(typedArgs.properties ?? {}).map(([k, v]) => [k, String(v)])
40470
+ );
40471
+ if (typedArgs.type === "simpleRunner" && stepProps["script.content"]) {
40472
+ stepProps["use.custom.script"] = stepProps["use.custom.script"] ?? "true";
40473
+ }
40474
+ const step = {
40475
+ name: typedArgs.name,
40476
+ type: typedArgs.type,
40477
+ properties: {
40478
+ property: Object.entries(stepProps).map(([k, v]) => ({ name: k, value: v }))
40479
+ }
40480
+ };
40481
+ await adapter.modules.buildTypes.addBuildStepToBuildType(
40482
+ typedArgs.buildTypeId,
40483
+ void 0,
40484
+ step,
40485
+ {
40486
+ headers: { "Content-Type": "application/json", Accept: "application/json" }
40487
+ }
40488
+ );
40489
+ return json({
40490
+ success: true,
40491
+ action: "add_build_step",
40492
+ buildTypeId: typedArgs.buildTypeId
40493
+ });
40494
+ }
40495
+ case "update": {
40496
+ const updatePayload = {};
40497
+ if (typedArgs.name != null) {
40498
+ updatePayload["name"] = typedArgs.name;
40499
+ }
40500
+ if (typedArgs.type != null) {
40501
+ updatePayload["type"] = typedArgs.type;
40502
+ }
40503
+ const rawProps = typedArgs.properties ?? {};
40504
+ const stepProps = Object.fromEntries(
40505
+ Object.entries(rawProps).map(([k, v]) => [k, String(v)])
40506
+ );
40507
+ if (stepProps["script.content"]) {
40508
+ stepProps["use.custom.script"] = stepProps["use.custom.script"] ?? "true";
40509
+ stepProps["script.type"] = stepProps["script.type"] ?? "customScript";
40510
+ }
40511
+ if (Object.keys(stepProps).length > 0) {
40512
+ updatePayload["properties"] = {
40513
+ property: Object.entries(stepProps).map(([name, value]) => ({ name, value }))
40514
+ };
40515
+ }
40516
+ if (Object.keys(updatePayload).length === 0) {
40517
+ return json({
40518
+ success: false,
40519
+ action: "update_build_step",
40520
+ error: "No update fields provided"
40521
+ });
40522
+ }
40523
+ await adapter.modules.buildTypes.replaceBuildStep(
40524
+ typedArgs.buildTypeId,
40525
+ typedArgs.stepId,
40526
+ void 0,
40527
+ updatePayload,
40528
+ {
40529
+ headers: {
40530
+ "Content-Type": "application/json",
40531
+ Accept: "application/json"
40532
+ }
40533
+ }
40534
+ );
40535
+ return json({
40536
+ success: true,
40537
+ action: "update_build_step",
40538
+ buildTypeId: typedArgs.buildTypeId,
40539
+ stepId: typedArgs.stepId
40540
+ });
40541
+ }
40542
+ case "delete":
40543
+ await adapter.modules.buildTypes.deleteBuildStep(
40544
+ typedArgs.buildTypeId,
40545
+ typedArgs.stepId
40546
+ );
40547
+ return json({
40548
+ success: true,
40549
+ action: "delete_build_step",
40550
+ buildTypeId: typedArgs.buildTypeId,
40551
+ stepId: typedArgs.stepId
40552
+ });
40553
+ default:
40554
+ return json({ success: false, error: "Invalid action" });
40489
40555
  }
40490
- await adapter.modules.buildTypes.deleteBuildStep(typedArgs.buildTypeId, typedArgs.stepId);
40491
- return json({
40492
- success: true,
40493
- action: "delete_build_step",
40494
- buildTypeId: typedArgs.buildTypeId,
40495
- stepId: typedArgs.stepId
40496
- });
40497
- default:
40498
- return json({ success: false, error: "Invalid action" });
40499
- }
40556
+ },
40557
+ args
40558
+ );
40500
40559
  },
40501
40560
  mode: "full"
40502
40561
  },