@daghis/teamcity-mcp 1.10.6 → 1.10.8
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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/index.js +210 -16
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.10.8](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v1.10.7...teamcity-mcp-v1.10.8) (2025-10-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **teamcity:** send snapshot options separately (238) ([fc9b313](https://github.com/Daghis/teamcity-mcp/commit/fc9b31379feccded78db5a35e1dc6f5ad13dccbd))
|
|
9
|
+
* **teamcity:** send snapshot options separately (238) ([6af8ea6](https://github.com/Daghis/teamcity-mcp/commit/6af8ea63dcc7dfae915a55287f3e1bc31e0a5c03))
|
|
10
|
+
|
|
11
|
+
## [1.10.7](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v1.10.6...teamcity-mcp-v1.10.7) (2025-10-06)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **teamcity:** serialize snapshot dependencies as xml ([#235](https://github.com/Daghis/teamcity-mcp/issues/235)) ([#236](https://github.com/Daghis/teamcity-mcp/issues/236)) ([9cec149](https://github.com/Daghis/teamcity-mcp/commit/9cec14934783f135b408211fefa41ba6a38391c8))
|
|
17
|
+
|
|
3
18
|
## [1.10.6](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v1.10.5...teamcity-mcp-v1.10.6) (2025-10-04)
|
|
4
19
|
|
|
5
20
|
|
package/dist/index.js
CHANGED
|
@@ -2321,6 +2321,12 @@ var JSON_HEADERS2 = {
|
|
|
2321
2321
|
Accept: "application/json"
|
|
2322
2322
|
}
|
|
2323
2323
|
};
|
|
2324
|
+
var XML_HEADERS = {
|
|
2325
|
+
headers: {
|
|
2326
|
+
"Content-Type": "application/xml",
|
|
2327
|
+
Accept: "application/json"
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2324
2330
|
var JSON_GET_HEADERS2 = {
|
|
2325
2331
|
headers: {
|
|
2326
2332
|
Accept: "application/json"
|
|
@@ -2336,6 +2342,13 @@ var defaultTypeFor = (dependencyType) => {
|
|
|
2336
2342
|
return void 0;
|
|
2337
2343
|
}
|
|
2338
2344
|
};
|
|
2345
|
+
var SNAPSHOT_DEPENDENCY_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
2346
|
+
"run-build-on-the-same-agent",
|
|
2347
|
+
"sync-revisions",
|
|
2348
|
+
"take-successful-builds-only",
|
|
2349
|
+
"take-started-build-with-same-revisions",
|
|
2350
|
+
"do-not-run-new-build-if-there-is-a-suitable-one"
|
|
2351
|
+
]);
|
|
2339
2352
|
var toStringRecord2 = (input) => {
|
|
2340
2353
|
if (!input) {
|
|
2341
2354
|
return {};
|
|
@@ -2375,6 +2388,30 @@ var recordToProperties2 = (record) => {
|
|
|
2375
2388
|
property: entries.map(([name, value]) => ({ name, value }))
|
|
2376
2389
|
};
|
|
2377
2390
|
};
|
|
2391
|
+
var optionsToRecord = (options) => {
|
|
2392
|
+
if (!options) {
|
|
2393
|
+
return {};
|
|
2394
|
+
}
|
|
2395
|
+
const optionEntries = options?.option;
|
|
2396
|
+
const collection = Array.isArray(optionEntries) ? optionEntries : optionEntries != null ? [optionEntries] : [];
|
|
2397
|
+
const map = {};
|
|
2398
|
+
for (const item of collection) {
|
|
2399
|
+
if (!item?.name) {
|
|
2400
|
+
continue;
|
|
2401
|
+
}
|
|
2402
|
+
map[item.name] = item.value != null ? String(item.value) : "";
|
|
2403
|
+
}
|
|
2404
|
+
return map;
|
|
2405
|
+
};
|
|
2406
|
+
var recordToOptions = (record) => {
|
|
2407
|
+
const entries = Object.entries(record);
|
|
2408
|
+
if (entries.length === 0) {
|
|
2409
|
+
return void 0;
|
|
2410
|
+
}
|
|
2411
|
+
return {
|
|
2412
|
+
option: entries.map(([name, value]) => ({ name, value }))
|
|
2413
|
+
};
|
|
2414
|
+
};
|
|
2378
2415
|
var mergeRecords2 = (base, override) => {
|
|
2379
2416
|
const merged = { ...base };
|
|
2380
2417
|
for (const [key, value] of Object.entries(override)) {
|
|
@@ -2382,6 +2419,109 @@ var mergeRecords2 = (base, override) => {
|
|
|
2382
2419
|
}
|
|
2383
2420
|
return merged;
|
|
2384
2421
|
};
|
|
2422
|
+
var escapeXml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
2423
|
+
var attributesToString = (attributes) => {
|
|
2424
|
+
const parts = Object.entries(attributes).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}="${escapeXml(value)}"`);
|
|
2425
|
+
return parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
2426
|
+
};
|
|
2427
|
+
var propertiesToXml = (properties) => {
|
|
2428
|
+
if (!properties) {
|
|
2429
|
+
return void 0;
|
|
2430
|
+
}
|
|
2431
|
+
const entries = properties.property;
|
|
2432
|
+
const list = Array.isArray(entries) ? entries : entries != null ? [entries] : [];
|
|
2433
|
+
if (list.length === 0) {
|
|
2434
|
+
return void 0;
|
|
2435
|
+
}
|
|
2436
|
+
const nodes = list.filter((item) => item?.name).map((item) => {
|
|
2437
|
+
const name = item?.name ?? "";
|
|
2438
|
+
const value = item?.value != null ? String(item.value) : "";
|
|
2439
|
+
return `<property name="${escapeXml(name)}" value="${escapeXml(value)}"/>`;
|
|
2440
|
+
});
|
|
2441
|
+
if (nodes.length === 0) {
|
|
2442
|
+
return void 0;
|
|
2443
|
+
}
|
|
2444
|
+
return `<properties>${nodes.join("")}</properties>`;
|
|
2445
|
+
};
|
|
2446
|
+
var optionsToXml = (options) => {
|
|
2447
|
+
if (!options) {
|
|
2448
|
+
return void 0;
|
|
2449
|
+
}
|
|
2450
|
+
const entries = options.option;
|
|
2451
|
+
const list = Array.isArray(entries) ? entries : entries != null ? [entries] : [];
|
|
2452
|
+
if (list.length === 0) {
|
|
2453
|
+
return void 0;
|
|
2454
|
+
}
|
|
2455
|
+
const nodes = list.filter((item) => item?.name).map((item) => {
|
|
2456
|
+
const name = item?.name ?? "";
|
|
2457
|
+
const value = item?.value != null ? String(item.value) : "";
|
|
2458
|
+
return `<option name="${escapeXml(name)}" value="${escapeXml(value)}"/>`;
|
|
2459
|
+
});
|
|
2460
|
+
if (nodes.length === 0) {
|
|
2461
|
+
return void 0;
|
|
2462
|
+
}
|
|
2463
|
+
return `<options>${nodes.join("")}</options>`;
|
|
2464
|
+
};
|
|
2465
|
+
var sourceBuildTypeToXml = (source) => {
|
|
2466
|
+
if (!source || typeof source !== "object") {
|
|
2467
|
+
return void 0;
|
|
2468
|
+
}
|
|
2469
|
+
const { id, name } = source;
|
|
2470
|
+
if (!id) {
|
|
2471
|
+
return void 0;
|
|
2472
|
+
}
|
|
2473
|
+
const attributes = {
|
|
2474
|
+
id,
|
|
2475
|
+
name
|
|
2476
|
+
};
|
|
2477
|
+
return `<source-buildType${attributesToString(attributes)}/>`;
|
|
2478
|
+
};
|
|
2479
|
+
var dependencyToXml = (dependencyType, payload) => {
|
|
2480
|
+
const root = dependencyType === "artifact" ? "artifact-dependency" : "snapshot-dependency";
|
|
2481
|
+
const normalizeTypeAttribute = (value) => {
|
|
2482
|
+
if (!value) {
|
|
2483
|
+
return void 0;
|
|
2484
|
+
}
|
|
2485
|
+
if (dependencyType === "snapshot" && value === "snapshotDependency") {
|
|
2486
|
+
return "snapshot_dependency";
|
|
2487
|
+
}
|
|
2488
|
+
if (dependencyType === "artifact" && value === "artifactDependency") {
|
|
2489
|
+
return "artifact_dependency";
|
|
2490
|
+
}
|
|
2491
|
+
return value;
|
|
2492
|
+
};
|
|
2493
|
+
const attributes = {
|
|
2494
|
+
id: typeof payload.id === "string" && payload.id.trim() !== "" ? payload.id : void 0,
|
|
2495
|
+
name: typeof payload.name === "string" && payload.name.trim() !== "" ? payload.name : void 0,
|
|
2496
|
+
type: typeof payload.type === "string" && payload.type.trim() !== "" ? normalizeTypeAttribute(payload.type) : void 0,
|
|
2497
|
+
disabled: typeof payload.disabled === "boolean" ? payload.disabled ? "true" : "false" : void 0,
|
|
2498
|
+
inherited: typeof payload.inherited === "boolean" ? payload.inherited ? "true" : "false" : void 0
|
|
2499
|
+
};
|
|
2500
|
+
const fragments = [];
|
|
2501
|
+
const sourceBuildTypeXml = sourceBuildTypeToXml(
|
|
2502
|
+
payload["source-buildType"]
|
|
2503
|
+
);
|
|
2504
|
+
if (sourceBuildTypeXml) {
|
|
2505
|
+
fragments.push(sourceBuildTypeXml);
|
|
2506
|
+
}
|
|
2507
|
+
const propertiesXml = propertiesToXml(payload.properties);
|
|
2508
|
+
if (propertiesXml) {
|
|
2509
|
+
fragments.push(propertiesXml);
|
|
2510
|
+
}
|
|
2511
|
+
const optionsXml = optionsToXml(payload.options);
|
|
2512
|
+
if (optionsXml) {
|
|
2513
|
+
fragments.push(optionsXml);
|
|
2514
|
+
}
|
|
2515
|
+
return `<${root}${attributesToString(attributes)}>${fragments.join("")}</${root}>`;
|
|
2516
|
+
};
|
|
2517
|
+
var prepareArtifactRequest = (payload) => ({
|
|
2518
|
+
body: payload,
|
|
2519
|
+
headers: JSON_HEADERS2
|
|
2520
|
+
});
|
|
2521
|
+
var prepareSnapshotRequest = (payload) => ({
|
|
2522
|
+
body: dependencyToXml("snapshot", payload),
|
|
2523
|
+
headers: XML_HEADERS
|
|
2524
|
+
});
|
|
2385
2525
|
var BuildDependencyManager = class {
|
|
2386
2526
|
constructor(client) {
|
|
2387
2527
|
this.client = client;
|
|
@@ -2436,36 +2576,40 @@ var BuildDependencyManager = class {
|
|
|
2436
2576
|
}
|
|
2437
2577
|
async createDependency(dependencyType, buildTypeId, payload) {
|
|
2438
2578
|
if (dependencyType === "artifact") {
|
|
2579
|
+
const { body: body2, headers: headers2 } = prepareArtifactRequest(payload);
|
|
2439
2580
|
return this.client.modules.buildTypes.addArtifactDependencyToBuildType(
|
|
2440
2581
|
buildTypeId,
|
|
2441
2582
|
void 0,
|
|
2442
|
-
|
|
2443
|
-
|
|
2583
|
+
body2,
|
|
2584
|
+
headers2
|
|
2444
2585
|
);
|
|
2445
2586
|
}
|
|
2587
|
+
const { body, headers } = prepareSnapshotRequest(payload);
|
|
2446
2588
|
return this.client.modules.buildTypes.addSnapshotDependencyToBuildType(
|
|
2447
2589
|
buildTypeId,
|
|
2448
2590
|
void 0,
|
|
2449
|
-
|
|
2450
|
-
|
|
2591
|
+
body,
|
|
2592
|
+
headers
|
|
2451
2593
|
);
|
|
2452
2594
|
}
|
|
2453
2595
|
async replaceDependency(dependencyType, buildTypeId, dependencyId, payload) {
|
|
2454
2596
|
if (dependencyType === "artifact") {
|
|
2597
|
+
const { body: body2, headers: headers2 } = prepareArtifactRequest(payload);
|
|
2455
2598
|
return this.client.modules.buildTypes.replaceArtifactDependency(
|
|
2456
2599
|
buildTypeId,
|
|
2457
2600
|
dependencyId,
|
|
2458
2601
|
void 0,
|
|
2459
|
-
|
|
2460
|
-
|
|
2602
|
+
body2,
|
|
2603
|
+
headers2
|
|
2461
2604
|
);
|
|
2462
2605
|
}
|
|
2606
|
+
const { body, headers } = prepareSnapshotRequest(payload);
|
|
2463
2607
|
return this.client.modules.buildTypes.replaceSnapshotDependency(
|
|
2464
2608
|
buildTypeId,
|
|
2465
2609
|
dependencyId,
|
|
2466
2610
|
void 0,
|
|
2467
|
-
|
|
2468
|
-
|
|
2611
|
+
body,
|
|
2612
|
+
headers
|
|
2469
2613
|
);
|
|
2470
2614
|
}
|
|
2471
2615
|
async fetchDependency(dependencyType, buildTypeId, dependencyId) {
|
|
@@ -2482,7 +2626,7 @@ var BuildDependencyManager = class {
|
|
|
2482
2626
|
const response = await this.client.modules.buildTypes.getSnapshotDependency(
|
|
2483
2627
|
buildTypeId,
|
|
2484
2628
|
dependencyId,
|
|
2485
|
-
"id,type,disabled,properties(property(name,value)),'source-buildType'(id)",
|
|
2629
|
+
"id,type,disabled,properties(property(name,value)),options(option(name,value)),'source-buildType'(id)",
|
|
2486
2630
|
JSON_GET_HEADERS2
|
|
2487
2631
|
);
|
|
2488
2632
|
return response.data;
|
|
@@ -2494,9 +2638,42 @@ var BuildDependencyManager = class {
|
|
|
2494
2638
|
}
|
|
2495
2639
|
}
|
|
2496
2640
|
buildPayload(dependencyType, existing, input) {
|
|
2497
|
-
const
|
|
2498
|
-
const
|
|
2641
|
+
const existingSnapshot = existing;
|
|
2642
|
+
const baseProperties = propertiesToRecord2(existing?.properties);
|
|
2643
|
+
const inputPropertyRecord = toStringRecord2(input.properties);
|
|
2644
|
+
const inputExplicitOptions = toStringRecord2(input.options);
|
|
2645
|
+
let optionOverrides = {};
|
|
2646
|
+
let propertyOverrides = inputPropertyRecord;
|
|
2647
|
+
let baseOptions = {};
|
|
2648
|
+
if (dependencyType === "snapshot") {
|
|
2649
|
+
baseOptions = optionsToRecord(existingSnapshot?.options);
|
|
2650
|
+
const knownOptionKeys = /* @__PURE__ */ new Set([
|
|
2651
|
+
...Object.keys(baseOptions),
|
|
2652
|
+
...Object.keys(inputExplicitOptions)
|
|
2653
|
+
]);
|
|
2654
|
+
for (const key of SNAPSHOT_DEPENDENCY_OPTION_KEYS) {
|
|
2655
|
+
knownOptionKeys.add(key);
|
|
2656
|
+
}
|
|
2657
|
+
const derivedOptionOverrides = { ...inputExplicitOptions };
|
|
2658
|
+
const derivedPropertyOverrides = {};
|
|
2659
|
+
for (const [key, value] of Object.entries(inputPropertyRecord)) {
|
|
2660
|
+
if (knownOptionKeys.has(key)) {
|
|
2661
|
+
derivedOptionOverrides[key] = value;
|
|
2662
|
+
} else {
|
|
2663
|
+
derivedPropertyOverrides[key] = value;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
optionOverrides = derivedOptionOverrides;
|
|
2667
|
+
propertyOverrides = derivedPropertyOverrides;
|
|
2668
|
+
} else if (Object.keys(inputExplicitOptions).length > 0) {
|
|
2669
|
+
optionOverrides = inputExplicitOptions;
|
|
2670
|
+
}
|
|
2671
|
+
const mergedProps = mergeRecords2(baseProperties, propertyOverrides);
|
|
2499
2672
|
const properties = recordToProperties2(mergedProps);
|
|
2673
|
+
let mergedOptions = {};
|
|
2674
|
+
if (dependencyType === "snapshot") {
|
|
2675
|
+
mergedOptions = mergeRecords2(baseOptions, optionOverrides);
|
|
2676
|
+
}
|
|
2500
2677
|
const resolvedType = input.type ?? existing?.type ?? defaultTypeFor(dependencyType);
|
|
2501
2678
|
const payload = {
|
|
2502
2679
|
...existing ?? {},
|
|
@@ -2507,6 +2684,16 @@ var BuildDependencyManager = class {
|
|
|
2507
2684
|
}
|
|
2508
2685
|
if (properties) {
|
|
2509
2686
|
payload.properties = properties;
|
|
2687
|
+
} else {
|
|
2688
|
+
delete payload.properties;
|
|
2689
|
+
}
|
|
2690
|
+
if (dependencyType === "snapshot") {
|
|
2691
|
+
const options = recordToOptions(mergedOptions);
|
|
2692
|
+
if (options) {
|
|
2693
|
+
payload.options = options;
|
|
2694
|
+
} else {
|
|
2695
|
+
delete payload.options;
|
|
2696
|
+
}
|
|
2510
2697
|
}
|
|
2511
2698
|
const dependsOn = input.dependsOn ?? existing?.["source-buildType"]?.id;
|
|
2512
2699
|
if (dependsOn) {
|
|
@@ -38706,13 +38893,13 @@ var DEV_TOOLS = [
|
|
|
38706
38893
|
buildRequest.properties = propertiesPayload;
|
|
38707
38894
|
}
|
|
38708
38895
|
const sendXmlFallback = async (error2) => {
|
|
38709
|
-
const
|
|
38710
|
-
const branchPart = branchName ? `<branchName>${
|
|
38711
|
-
const commentPart = commentText ? `<comment><text>${
|
|
38896
|
+
const escapeXml2 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
38897
|
+
const branchPart = branchName ? `<branchName>${escapeXml2(branchName)}</branchName>` : "";
|
|
38898
|
+
const commentPart = commentText ? `<comment><text>${escapeXml2(commentText)}</text></comment>` : "";
|
|
38712
38899
|
const propertiesPart = propertiesPayload ? `<properties>${propertiesPayload.property.map(
|
|
38713
|
-
(prop) => `<property name="${
|
|
38900
|
+
(prop) => `<property name="${escapeXml2(prop.name)}" value="${escapeXml2(prop.value)}"/>`
|
|
38714
38901
|
).join("")}</properties>` : "";
|
|
38715
|
-
const xml = `<?xml version="1.0" encoding="UTF-8"?><build><buildType id="${
|
|
38902
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?><build><buildType id="${escapeXml2(
|
|
38716
38903
|
typed.buildTypeId
|
|
38717
38904
|
)}"/>${branchPart}${commentPart}${propertiesPart}</build>`;
|
|
38718
38905
|
const response = await adapter.http.post("/app/rest/buildQueue", xml, {
|
|
@@ -41445,6 +41632,10 @@ var FULL_MODE_TOOLS = [
|
|
|
41445
41632
|
type: "object",
|
|
41446
41633
|
description: "Dependency properties (e.g. cleanDestinationDirectory, pathRules)"
|
|
41447
41634
|
},
|
|
41635
|
+
options: {
|
|
41636
|
+
type: "object",
|
|
41637
|
+
description: "Snapshot dependency options (e.g. run-build-on-the-same-agent)"
|
|
41638
|
+
},
|
|
41448
41639
|
type: {
|
|
41449
41640
|
type: "string",
|
|
41450
41641
|
description: "Override dependency type value sent to TeamCity"
|
|
@@ -41462,6 +41653,7 @@ var FULL_MODE_TOOLS = [
|
|
|
41462
41653
|
dependencyId: import_zod4.z.string().min(1).optional(),
|
|
41463
41654
|
dependsOn: import_zod4.z.string().min(1).optional(),
|
|
41464
41655
|
properties: import_zod4.z.record(import_zod4.z.string(), propertyValue).optional(),
|
|
41656
|
+
options: import_zod4.z.record(import_zod4.z.string(), propertyValue).optional(),
|
|
41465
41657
|
type: import_zod4.z.string().min(1).optional(),
|
|
41466
41658
|
disabled: import_zod4.z.boolean().optional()
|
|
41467
41659
|
}).superRefine((value, ctx) => {
|
|
@@ -41493,6 +41685,7 @@ var FULL_MODE_TOOLS = [
|
|
|
41493
41685
|
dependencyType: typed.dependencyType,
|
|
41494
41686
|
dependsOn: typed.dependsOn,
|
|
41495
41687
|
properties: typed.properties,
|
|
41688
|
+
options: typed.options,
|
|
41496
41689
|
type: typed.type,
|
|
41497
41690
|
disabled: typed.disabled
|
|
41498
41691
|
});
|
|
@@ -41511,6 +41704,7 @@ var FULL_MODE_TOOLS = [
|
|
|
41511
41704
|
dependencyType: typed.dependencyType,
|
|
41512
41705
|
dependsOn: typed.dependsOn,
|
|
41513
41706
|
properties: typed.properties,
|
|
41707
|
+
options: typed.options,
|
|
41514
41708
|
type: typed.type,
|
|
41515
41709
|
disabled: typed.disabled
|
|
41516
41710
|
});
|