@daghis/teamcity-mcp 2.2.3 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/index.js +128 -70
- package/package.json +1 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.3.0](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.2.3...teamcity-mcp-v2.3.0) (2026-03-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **tools:** accept buildNumber + buildTypeId across all build tools ([#410](https://github.com/Daghis/teamcity-mcp/issues/410)) ([9aa005d](https://github.com/Daghis/teamcity-mcp/commit/9aa005d01bf6db9e7ac53155680876dc36202da7))
|
|
9
|
+
|
|
3
10
|
## [2.2.3](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.2.2...teamcity-mcp-v2.2.3) (2026-03-09)
|
|
4
11
|
|
|
5
12
|
|
package/dist/index.js
CHANGED
|
@@ -1205,7 +1205,7 @@ function debug2(message, meta) {
|
|
|
1205
1205
|
// package.json
|
|
1206
1206
|
var package_default = {
|
|
1207
1207
|
name: "@daghis/teamcity-mcp",
|
|
1208
|
-
version: "2.
|
|
1208
|
+
version: "2.3.0",
|
|
1209
1209
|
description: "Model Control Protocol server for TeamCity CI/CD integration with AI coding assistants",
|
|
1210
1210
|
mcpName: "io.github.Daghis/teamcity",
|
|
1211
1211
|
main: "dist/index.js",
|
|
@@ -38826,6 +38826,55 @@ var TeamCityAPI = class _TeamCityAPI {
|
|
|
38826
38826
|
// src/tools.ts
|
|
38827
38827
|
var isReadableStream = (value) => typeof value === "object" && value !== null && typeof value.pipe === "function";
|
|
38828
38828
|
var isAxios4042 = (error3) => (0, import_axios36.isAxiosError)(error3) && error3.response?.status === 404;
|
|
38829
|
+
var buildIdentifierSchema = import_zod4.z.object({
|
|
38830
|
+
buildId: import_zod4.z.string().min(1).optional(),
|
|
38831
|
+
buildNumber: import_zod4.z.union([import_zod4.z.string().min(1), import_zod4.z.number().int()]).optional(),
|
|
38832
|
+
buildTypeId: import_zod4.z.string().min(1).optional()
|
|
38833
|
+
}).superRefine((value, ctx) => {
|
|
38834
|
+
if (!value.buildId && value.buildNumber === void 0) {
|
|
38835
|
+
ctx.addIssue({
|
|
38836
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
38837
|
+
path: ["buildId"],
|
|
38838
|
+
message: "Either buildId or (buildNumber + buildTypeId) must be provided"
|
|
38839
|
+
});
|
|
38840
|
+
}
|
|
38841
|
+
if (value.buildNumber !== void 0 && !value.buildTypeId) {
|
|
38842
|
+
ctx.addIssue({
|
|
38843
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
38844
|
+
path: ["buildTypeId"],
|
|
38845
|
+
message: "buildTypeId is required when querying by buildNumber"
|
|
38846
|
+
});
|
|
38847
|
+
}
|
|
38848
|
+
});
|
|
38849
|
+
function resolveBuildLocator(input) {
|
|
38850
|
+
const trimmedBuildId = typeof input.buildId === "string" ? input.buildId.trim() : void 0;
|
|
38851
|
+
if (trimmedBuildId && trimmedBuildId.length > 0) {
|
|
38852
|
+
return { locator: `id:${trimmedBuildId}`, friendlyId: `ID '${trimmedBuildId}'` };
|
|
38853
|
+
}
|
|
38854
|
+
const buildNumber = input.buildNumber !== void 0 ? String(input.buildNumber).trim() : void 0;
|
|
38855
|
+
const buildTypeId = input.buildTypeId?.trim();
|
|
38856
|
+
if (buildTypeId && buildNumber) {
|
|
38857
|
+
return {
|
|
38858
|
+
locator: `buildType:(id:${buildTypeId}),number:${buildNumber}`,
|
|
38859
|
+
friendlyId: `build type '${buildTypeId}' #${buildNumber}`
|
|
38860
|
+
};
|
|
38861
|
+
}
|
|
38862
|
+
throw new TeamCityAPIError("Unable to resolve build identifier", "INVALID_BUILD_IDENTIFIER");
|
|
38863
|
+
}
|
|
38864
|
+
var buildIdentifierInputProperties = {
|
|
38865
|
+
buildId: { type: "string", description: "Build ID (internal TeamCity ID)" },
|
|
38866
|
+
buildNumber: {
|
|
38867
|
+
oneOf: [
|
|
38868
|
+
{ type: "string", description: 'Build number as TeamCity displays it (e.g. "886")' },
|
|
38869
|
+
{ type: "number", description: "Numeric build number" }
|
|
38870
|
+
],
|
|
38871
|
+
description: "Human-readable build number (requires buildTypeId)"
|
|
38872
|
+
},
|
|
38873
|
+
buildTypeId: {
|
|
38874
|
+
type: "string",
|
|
38875
|
+
description: "Build configuration ID (required when using buildNumber)"
|
|
38876
|
+
}
|
|
38877
|
+
};
|
|
38829
38878
|
var sanitizeFileName = (artifactName) => {
|
|
38830
38879
|
const base = (0, import_node_path.basename)(artifactName || "artifact");
|
|
38831
38880
|
const safeBase = base.replace(/[^a-zA-Z0-9._-]/g, "_") || "artifact";
|
|
@@ -39316,31 +39365,34 @@ var DEV_TOOLS = [
|
|
|
39316
39365
|
inputSchema: {
|
|
39317
39366
|
type: "object",
|
|
39318
39367
|
properties: {
|
|
39319
|
-
|
|
39320
|
-
}
|
|
39321
|
-
required: ["buildId"]
|
|
39368
|
+
...buildIdentifierInputProperties
|
|
39369
|
+
}
|
|
39322
39370
|
},
|
|
39323
39371
|
handler: async (args) => {
|
|
39324
|
-
const schema =
|
|
39372
|
+
const schema = buildIdentifierSchema;
|
|
39325
39373
|
return runTool(
|
|
39326
39374
|
"get_build",
|
|
39327
39375
|
schema,
|
|
39328
39376
|
async (typed) => {
|
|
39329
39377
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
39378
|
+
const { locator, friendlyId } = resolveBuildLocator(typed);
|
|
39330
39379
|
try {
|
|
39331
|
-
const
|
|
39332
|
-
return json(
|
|
39380
|
+
const build = await adapter.getBuild(locator);
|
|
39381
|
+
return json(build);
|
|
39333
39382
|
} catch (error3) {
|
|
39334
39383
|
if (!isAxios4042(error3)) throw error3;
|
|
39335
39384
|
}
|
|
39336
|
-
|
|
39337
|
-
|
|
39338
|
-
|
|
39339
|
-
|
|
39340
|
-
|
|
39385
|
+
if (typed.buildId) {
|
|
39386
|
+
try {
|
|
39387
|
+
const qb = await adapter.modules.buildQueue.getQueuedBuild(`id:${typed.buildId}`);
|
|
39388
|
+
return json({ ...qb.data, state: "queued" });
|
|
39389
|
+
} catch (queueError) {
|
|
39390
|
+
if (!isAxios4042(queueError)) throw queueError;
|
|
39391
|
+
}
|
|
39392
|
+
const build = await adapter.getBuild(locator);
|
|
39393
|
+
return json(build);
|
|
39341
39394
|
}
|
|
39342
|
-
|
|
39343
|
-
return json(build);
|
|
39395
|
+
throw new TeamCityNotFoundError(`Build not found for ${friendlyId}`);
|
|
39344
39396
|
},
|
|
39345
39397
|
args
|
|
39346
39398
|
);
|
|
@@ -39980,7 +40032,7 @@ var DEV_TOOLS = [
|
|
|
39980
40032
|
inputSchema: {
|
|
39981
40033
|
type: "object",
|
|
39982
40034
|
properties: {
|
|
39983
|
-
|
|
40035
|
+
...buildIdentifierInputProperties,
|
|
39984
40036
|
pageSize: { type: "number", description: "Items per page (default 100)" },
|
|
39985
40037
|
maxPages: { type: "number", description: "Max pages to fetch (when all=true)" },
|
|
39986
40038
|
all: { type: "boolean", description: "Fetch all pages up to maxPages" },
|
|
@@ -39988,25 +40040,26 @@ var DEV_TOOLS = [
|
|
|
39988
40040
|
type: "string",
|
|
39989
40041
|
description: "Optional fields selector for server-side projection"
|
|
39990
40042
|
}
|
|
39991
|
-
}
|
|
39992
|
-
required: ["buildId"]
|
|
40043
|
+
}
|
|
39993
40044
|
},
|
|
39994
40045
|
handler: async (args) => {
|
|
39995
|
-
const schema =
|
|
39996
|
-
|
|
39997
|
-
|
|
39998
|
-
|
|
39999
|
-
|
|
40000
|
-
|
|
40001
|
-
|
|
40046
|
+
const schema = buildIdentifierSchema.and(
|
|
40047
|
+
import_zod4.z.object({
|
|
40048
|
+
pageSize: import_zod4.z.number().int().min(1).max(1e3).optional(),
|
|
40049
|
+
maxPages: import_zod4.z.number().int().min(1).max(1e3).optional(),
|
|
40050
|
+
all: import_zod4.z.boolean().optional(),
|
|
40051
|
+
fields: import_zod4.z.string().min(1).optional()
|
|
40052
|
+
})
|
|
40053
|
+
);
|
|
40002
40054
|
return runTool(
|
|
40003
40055
|
"list_test_failures",
|
|
40004
40056
|
schema,
|
|
40005
40057
|
async (typed) => {
|
|
40006
40058
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
40059
|
+
const { locator: buildLocator } = resolveBuildLocator(typed);
|
|
40007
40060
|
const pageSize = typed.pageSize ?? 100;
|
|
40008
40061
|
const baseFetch = async ({ count, start }) => {
|
|
40009
|
-
const parts = [`build:(
|
|
40062
|
+
const parts = [`build:(${buildLocator})`, "status:FAILURE"];
|
|
40010
40063
|
if (typeof count === "number") parts.push(`count:${count}`);
|
|
40011
40064
|
if (typeof start === "number") parts.push(`start:${start}`);
|
|
40012
40065
|
const locator = parts.join(",");
|
|
@@ -40930,7 +40983,7 @@ var DEV_TOOLS = [
|
|
|
40930
40983
|
inputSchema: {
|
|
40931
40984
|
type: "object",
|
|
40932
40985
|
properties: {
|
|
40933
|
-
|
|
40986
|
+
...buildIdentifierInputProperties,
|
|
40934
40987
|
artifactPath: { type: "string", description: "Artifact path or name" },
|
|
40935
40988
|
encoding: {
|
|
40936
40989
|
type: "string",
|
|
@@ -40947,31 +41000,33 @@ var DEV_TOOLS = [
|
|
|
40947
41000
|
description: "Optional absolute path to write streamed content; defaults to a temp file when streaming"
|
|
40948
41001
|
}
|
|
40949
41002
|
},
|
|
40950
|
-
required: ["
|
|
41003
|
+
required: ["artifactPath"]
|
|
40951
41004
|
},
|
|
40952
41005
|
handler: async (args) => {
|
|
40953
|
-
const schema =
|
|
40954
|
-
|
|
40955
|
-
|
|
40956
|
-
|
|
40957
|
-
|
|
40958
|
-
|
|
40959
|
-
|
|
41006
|
+
const schema = buildIdentifierSchema.and(
|
|
41007
|
+
import_zod4.z.object({
|
|
41008
|
+
artifactPath: import_zod4.z.string().min(1),
|
|
41009
|
+
encoding: import_zod4.z.enum(["base64", "text", "stream"]).default("base64"),
|
|
41010
|
+
maxSize: import_zod4.z.number().int().positive().optional(),
|
|
41011
|
+
outputPath: import_zod4.z.string().min(1).optional()
|
|
41012
|
+
})
|
|
41013
|
+
);
|
|
40960
41014
|
return runTool(
|
|
40961
41015
|
"download_build_artifact",
|
|
40962
41016
|
schema,
|
|
40963
41017
|
async (typed) => {
|
|
40964
41018
|
const encoding = typed.encoding ?? "base64";
|
|
40965
41019
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41020
|
+
const { locator: buildLocator } = resolveBuildLocator(typed);
|
|
40966
41021
|
debug2("tools.download_build_artifact.start", {
|
|
40967
|
-
|
|
41022
|
+
buildLocator,
|
|
40968
41023
|
encoding,
|
|
40969
41024
|
artifactPath: typed.artifactPath,
|
|
40970
41025
|
maxSize: typed.maxSize,
|
|
40971
41026
|
outputPath: typed.outputPath
|
|
40972
41027
|
});
|
|
40973
41028
|
const manager = new ArtifactManager(adapter);
|
|
40974
|
-
const artifact = await manager.downloadArtifact(
|
|
41029
|
+
const artifact = await manager.downloadArtifact(buildLocator, typed.artifactPath, {
|
|
40975
41030
|
encoding,
|
|
40976
41031
|
maxSize: typed.maxSize
|
|
40977
41032
|
});
|
|
@@ -40990,7 +41045,7 @@ var DEV_TOOLS = [
|
|
|
40990
41045
|
inputSchema: {
|
|
40991
41046
|
type: "object",
|
|
40992
41047
|
properties: {
|
|
40993
|
-
|
|
41048
|
+
...buildIdentifierInputProperties,
|
|
40994
41049
|
artifactPaths: {
|
|
40995
41050
|
type: "array",
|
|
40996
41051
|
description: "Artifact paths or names to download",
|
|
@@ -41024,7 +41079,7 @@ var DEV_TOOLS = [
|
|
|
41024
41079
|
description: "Optional absolute directory to write streamed artifacts; defaults to temp files when streaming"
|
|
41025
41080
|
}
|
|
41026
41081
|
},
|
|
41027
|
-
required: ["
|
|
41082
|
+
required: ["artifactPaths"]
|
|
41028
41083
|
},
|
|
41029
41084
|
handler: async (args) => {
|
|
41030
41085
|
const artifactInputSchema = import_zod4.z.union([
|
|
@@ -41035,31 +41090,33 @@ var DEV_TOOLS = [
|
|
|
41035
41090
|
downloadUrl: import_zod4.z.string().url().optional()
|
|
41036
41091
|
})
|
|
41037
41092
|
]);
|
|
41038
|
-
const schema =
|
|
41039
|
-
|
|
41040
|
-
|
|
41041
|
-
|
|
41042
|
-
|
|
41043
|
-
|
|
41044
|
-
|
|
41093
|
+
const schema = buildIdentifierSchema.and(
|
|
41094
|
+
import_zod4.z.object({
|
|
41095
|
+
artifactPaths: import_zod4.z.array(artifactInputSchema).min(1),
|
|
41096
|
+
encoding: import_zod4.z.enum(["base64", "text", "stream"]).default("base64"),
|
|
41097
|
+
maxSize: import_zod4.z.number().int().positive().optional(),
|
|
41098
|
+
outputDir: import_zod4.z.string().min(1).optional().refine((value) => value == null || (0, import_node_path.isAbsolute)(value), {
|
|
41099
|
+
message: "outputDir must be an absolute path"
|
|
41100
|
+
})
|
|
41101
|
+
}).superRefine((value, ctx) => {
|
|
41102
|
+
if (value.encoding !== "stream" && value.outputDir) {
|
|
41103
|
+
ctx.addIssue({
|
|
41104
|
+
code: import_zod4.z.ZodIssueCode.custom,
|
|
41105
|
+
message: 'outputDir can only be provided when encoding is set to "stream"',
|
|
41106
|
+
path: ["outputDir"]
|
|
41107
|
+
});
|
|
41108
|
+
}
|
|
41045
41109
|
})
|
|
41046
|
-
|
|
41047
|
-
if (value.encoding !== "stream" && value.outputDir) {
|
|
41048
|
-
ctx.addIssue({
|
|
41049
|
-
code: import_zod4.z.ZodIssueCode.custom,
|
|
41050
|
-
message: 'outputDir can only be provided when encoding is set to "stream"',
|
|
41051
|
-
path: ["outputDir"]
|
|
41052
|
-
});
|
|
41053
|
-
}
|
|
41054
|
-
});
|
|
41110
|
+
);
|
|
41055
41111
|
return runTool(
|
|
41056
41112
|
"download_build_artifacts",
|
|
41057
41113
|
schema,
|
|
41058
41114
|
async (typed) => {
|
|
41059
41115
|
const encoding = typed.encoding ?? "base64";
|
|
41060
41116
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41117
|
+
const { locator: buildLocator } = resolveBuildLocator(typed);
|
|
41061
41118
|
const manager = new ArtifactManager(adapter);
|
|
41062
|
-
const requests = toNormalizedArtifactRequests(typed.artifactPaths,
|
|
41119
|
+
const requests = toNormalizedArtifactRequests(typed.artifactPaths, buildLocator);
|
|
41063
41120
|
const results = [];
|
|
41064
41121
|
for (const request of requests) {
|
|
41065
41122
|
try {
|
|
@@ -41148,22 +41205,23 @@ var DEV_TOOLS = [
|
|
|
41148
41205
|
inputSchema: {
|
|
41149
41206
|
type: "object",
|
|
41150
41207
|
properties: {
|
|
41151
|
-
|
|
41208
|
+
...buildIdentifierInputProperties,
|
|
41152
41209
|
testNameId: { type: "string", description: "Test name ID (optional)" }
|
|
41153
|
-
}
|
|
41154
|
-
required: ["buildId"]
|
|
41210
|
+
}
|
|
41155
41211
|
},
|
|
41156
41212
|
handler: async (args) => {
|
|
41157
|
-
const schema =
|
|
41158
|
-
|
|
41159
|
-
|
|
41160
|
-
|
|
41213
|
+
const schema = buildIdentifierSchema.and(
|
|
41214
|
+
import_zod4.z.object({
|
|
41215
|
+
testNameId: import_zod4.z.string().min(1).optional()
|
|
41216
|
+
})
|
|
41217
|
+
);
|
|
41161
41218
|
return runTool(
|
|
41162
41219
|
"get_test_details",
|
|
41163
41220
|
schema,
|
|
41164
41221
|
async (typed) => {
|
|
41165
41222
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41166
|
-
|
|
41223
|
+
const { locator: buildLocator } = resolveBuildLocator(typed);
|
|
41224
|
+
let locator = `build:(${buildLocator})`;
|
|
41167
41225
|
if (typed.testNameId) locator += `,test:(id:${typed.testNameId})`;
|
|
41168
41226
|
const response = await adapter.modules.tests.getAllTestOccurrences(locator);
|
|
41169
41227
|
return json(response.data);
|
|
@@ -41178,20 +41236,20 @@ var DEV_TOOLS = [
|
|
|
41178
41236
|
inputSchema: {
|
|
41179
41237
|
type: "object",
|
|
41180
41238
|
properties: {
|
|
41181
|
-
|
|
41182
|
-
}
|
|
41183
|
-
required: ["buildId"]
|
|
41239
|
+
...buildIdentifierInputProperties
|
|
41240
|
+
}
|
|
41184
41241
|
},
|
|
41185
41242
|
handler: async (args) => {
|
|
41186
|
-
const schema =
|
|
41243
|
+
const schema = buildIdentifierSchema;
|
|
41187
41244
|
return runTool(
|
|
41188
41245
|
"analyze_build_problems",
|
|
41189
41246
|
schema,
|
|
41190
41247
|
async (typed) => {
|
|
41191
41248
|
const adapter = createAdapterFromTeamCityAPI(TeamCityAPI.getInstance());
|
|
41192
|
-
const
|
|
41193
|
-
const
|
|
41194
|
-
const
|
|
41249
|
+
const { locator: buildLocator } = resolveBuildLocator(typed);
|
|
41250
|
+
const build = await adapter.getBuild(buildLocator);
|
|
41251
|
+
const problems = await adapter.modules.builds.getBuildProblems(buildLocator);
|
|
41252
|
+
const failures = await adapter.listTestFailures(buildLocator);
|
|
41195
41253
|
return json({
|
|
41196
41254
|
buildStatus: build.status,
|
|
41197
41255
|
statusText: build.statusText,
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
9
|
"websiteUrl": "https://github.com/Daghis/teamcity-mcp",
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.3.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
15
15
|
"identifier": "@daghis/teamcity-mcp",
|
|
16
|
-
"version": "2.
|
|
16
|
+
"version": "2.3.0",
|
|
17
17
|
"runtimeHint": "npx",
|
|
18
18
|
"runtimeArguments": [
|
|
19
19
|
{
|