@daghis/teamcity-mcp 2.11.0 → 2.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.12.1](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.12.0...teamcity-mcp-v2.12.1) (2026-05-12)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **tools:** mark download_* as readOnly and idempotent ([#507](https://github.com/Daghis/teamcity-mcp/issues/507)) ([0a09663](https://github.com/Daghis/teamcity-mcp/commit/0a09663a5ff39e82f9b471e1aa7102ffc4d68163))
9
+
10
+ ## [2.12.0](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.11.0...teamcity-mcp-v2.12.0) (2026-05-03)
11
+
12
+
13
+ ### Features
14
+
15
+ * **http:** forward TEAMCITY_HEADER_* env vars on every request ([#492](https://github.com/Daghis/teamcity-mcp/issues/492)) ([c406511](https://github.com/Daghis/teamcity-mcp/commit/c4065111e2e8c6e807ec9a4383cbbe8d280ca00e))
16
+
3
17
  ## [2.11.0](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.10.0...teamcity-mcp-v2.11.0) (2026-05-03)
4
18
 
5
19
 
package/README.md CHANGED
@@ -47,6 +47,24 @@ See the [Tools Mode Matrix](docs/mcp-tools-mode-matrix.md) for the complete list
47
47
  - Performance-conscious: fast startup with minimal overhead
48
48
  - Clean codebase with clear module boundaries
49
49
 
50
+ ## Choosing between teamcity-mcp and the built-in MCP
51
+
52
+ TeamCity 2026.1 ships with a built-in MCP endpoint at `<server-url>/app/mcp` exposing three tools: build log retrieval, a generic REST GET, and a build trigger (forced to `personal=true`). It is server-resident, requires no install, and is a sensible default for read-and-rerun workflows.
53
+
54
+ teamcity-mcp is a different shape: an 87-tool typed surface focused on AI-driven workflows that need writes, multi-server support, or pre-2026.1 compatibility.
55
+
56
+ | Use case | Recommendation |
57
+ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
58
+ | Read build logs, trigger builds, simple read flows | Built-in (TeamCity 2026.1+) — zero install |
59
+ | Manage parameters, agents, queue, mutes, build configs, VCS roots | teamcity-mcp |
60
+ | TeamCity server older than 2026.1 | teamcity-mcp |
61
+ | Multi-server / multi-tenant deployment | teamcity-mcp (HTTP transport — [PR #491](https://github.com/Daghis/teamcity-mcp/pull/491)) |
62
+ | Typed tool surface for better agent reliability on chained operations | teamcity-mcp |
63
+
64
+ Both can coexist. The built-in is a good first stop; teamcity-mcp is the power tool for everything the built-in doesn't reach.
65
+
66
+ For the design reasoning, see [docs/strategy.md](docs/strategy.md) and [docs/non-goals.md](docs/non-goals.md).
67
+
50
68
  ## Installation
51
69
 
52
70
  ### Prerequisites
@@ -110,7 +128,14 @@ On Windows, Claude Code's MCP configuration [may not properly merge environment
110
128
  "mcpServers": {
111
129
  "teamcity": {
112
130
  "command": "npx",
113
- "args": ["-y", "@daghis/teamcity-mcp", "--url", "https://teamcity.example.com", "--token", "YOUR_TOKEN"]
131
+ "args": [
132
+ "-y",
133
+ "@daghis/teamcity-mcp",
134
+ "--url",
135
+ "https://teamcity.example.com",
136
+ "--token",
137
+ "YOUR_TOKEN"
138
+ ]
114
139
  }
115
140
  }
116
141
  }
@@ -156,6 +181,14 @@ MCP_MODE=dev
156
181
  # TEAMCITY_KEEP_ALIVE=true
157
182
  # TEAMCITY_COMPRESSION=true
158
183
 
184
+ # Extra headers attached to every TeamCity request — useful when TeamCity
185
+ # sits behind a reverse proxy that gates access on custom headers (e.g.
186
+ # Cloudflare Zero Trust service tokens). One env var per header; the part
187
+ # after `TEAMCITY_HEADER_` is used verbatim as the HTTP header name.
188
+ # Example (note the literal hyphens — most shells need quoting):
189
+ # TEAMCITY_HEADER_CF-Access-Client-Id=<id>
190
+ # TEAMCITY_HEADER_CF-Access-Client-Secret=<secret>
191
+
159
192
  # Retry
160
193
  # TEAMCITY_RETRY_ENABLED=true
161
194
  # TEAMCITY_MAX_RETRIES=3
@@ -351,4 +384,4 @@ This repository has GitHub secret scanning and push protection enabled. See [SEC
351
384
 
352
385
  ---
353
386
 
354
- Built with ❤️ for developers who love efficient CI/CD workflows
387
+ Built with ❤️ for developers who love efficient CI/CD workflows
package/dist/index.js CHANGED
@@ -691,6 +691,17 @@ function setServerInstance(server) {
691
691
  function getServerInstance() {
692
692
  return serverInstance;
693
693
  }
694
+ var HEADER_ENV_PREFIX = "TEAMCITY_HEADER_";
695
+ function getTeamCityExtraHeaders() {
696
+ const headers = {};
697
+ for (const [key, value] of Object.entries(process.env)) {
698
+ if (!key.startsWith(HEADER_ENV_PREFIX) || value === void 0) continue;
699
+ const headerName = key.slice(HEADER_ENV_PREFIX.length);
700
+ if (headerName === "") continue;
701
+ headers[headerName] = value;
702
+ }
703
+ return Object.keys(headers).length > 0 ? headers : void 0;
704
+ }
694
705
  function getTeamCityUrl() {
695
706
  const config2 = getConfig();
696
707
  if (!config2.teamcity?.url || config2.teamcity.url.length === 0) {
@@ -1205,7 +1216,7 @@ function debug2(message, meta) {
1205
1216
  // package.json
1206
1217
  var package_default = {
1207
1218
  name: "@daghis/teamcity-mcp",
1208
- version: "2.11.0",
1219
+ version: "2.12.1",
1209
1220
  description: "Model Control Protocol server for TeamCity CI/CD integration with AI coding assistants",
1210
1221
  mcpName: "io.github.Daghis/teamcity",
1211
1222
  main: "dist/index.js",
@@ -1269,7 +1280,7 @@ var package_default = {
1269
1280
  url: "https://github.com/Daghis/teamcity-mcp/issues"
1270
1281
  },
1271
1282
  dependencies: {
1272
- "@modelcontextprotocol/sdk": "^1.27.0",
1283
+ "@modelcontextprotocol/sdk": "^1.29.0",
1273
1284
  axios: "^1.15.0",
1274
1285
  "axios-retry": "^4.5.0",
1275
1286
  dotenv: "17.4.2",
@@ -38459,6 +38470,7 @@ var TeamCityAPI = class _TeamCityAPI {
38459
38470
  baseURL: basePath,
38460
38471
  timeout,
38461
38472
  headers: {
38473
+ ...config2.extraHeaders ?? {},
38462
38474
  Authorization: `Bearer ${config2.token}`,
38463
38475
  Accept: "application/json",
38464
38476
  "Content-Type": "application/json"
@@ -38487,6 +38499,7 @@ var TeamCityAPI = class _TeamCityAPI {
38487
38499
  baseOptions: {
38488
38500
  timeout,
38489
38501
  headers: {
38502
+ ...config2.extraHeaders ?? {},
38490
38503
  Authorization: `Bearer ${config2.token}`,
38491
38504
  Accept: "application/json"
38492
38505
  }
@@ -38569,7 +38582,8 @@ var TeamCityAPI = class _TeamCityAPI {
38569
38582
  if (this.instance == null) {
38570
38583
  const envConfig = this.normalizeConfig({
38571
38584
  baseUrl: getTeamCityUrl(),
38572
- token: getTeamCityToken()
38585
+ token: getTeamCityToken(),
38586
+ extraHeaders: getTeamCityExtraHeaders()
38573
38587
  });
38574
38588
  this.instance = new _TeamCityAPI(envConfig);
38575
38589
  this.instanceConfig = envConfig;
@@ -38800,15 +38814,34 @@ var TeamCityAPI = class _TeamCityAPI {
38800
38814
  return {
38801
38815
  baseUrl: config2.baseUrl.replace(/\/$/, ""),
38802
38816
  token: config2.token,
38803
- timeout: config2.timeout
38817
+ timeout: config2.timeout,
38818
+ extraHeaders: normalizeExtraHeaders(config2.extraHeaders)
38804
38819
  };
38805
38820
  }
38806
38821
  static configsEqual(a, b) {
38807
38822
  if (a == null || b == null) {
38808
38823
  return false;
38809
38824
  }
38810
- return a.baseUrl === b.baseUrl && a.token === b.token && a.timeout === b.timeout;
38825
+ return a.baseUrl === b.baseUrl && a.token === b.token && a.timeout === b.timeout && extraHeadersEqual(a.extraHeaders, b.extraHeaders);
38826
+ }
38827
+ };
38828
+ var normalizeExtraHeaders = (headers) => {
38829
+ if (headers == null) {
38830
+ return void 0;
38811
38831
  }
38832
+ const entries = Object.entries(headers);
38833
+ if (entries.length === 0) {
38834
+ return void 0;
38835
+ }
38836
+ return Object.fromEntries(entries.sort(([a], [b]) => a.localeCompare(b)));
38837
+ };
38838
+ var extraHeadersEqual = (a, b) => {
38839
+ if (a === b) return true;
38840
+ if (a == null || b == null) return a == null && b == null;
38841
+ const keysA = Object.keys(a);
38842
+ const keysB = Object.keys(b);
38843
+ if (keysA.length !== keysB.length) return false;
38844
+ return keysA.every((key) => a[key] === b[key]);
38812
38845
  };
38813
38846
 
38814
38847
  // src/tools.ts
@@ -41511,9 +41544,9 @@ var DEV_TOOLS = [
41511
41544
  {
41512
41545
  name: "download_build_artifact",
41513
41546
  annotations: {
41514
- readOnlyHint: false,
41547
+ readOnlyHint: true,
41515
41548
  destructiveHint: false,
41516
- idempotentHint: false,
41549
+ idempotentHint: true,
41517
41550
  openWorldHint: true
41518
41551
  },
41519
41552
  description: "Download a single build artifact, with base64, text, or streaming output. Returns the artifact bytes or stream metadata; returns 404 if the build or path is unknown.",
@@ -41579,9 +41612,9 @@ var DEV_TOOLS = [
41579
41612
  {
41580
41613
  name: "download_build_artifacts",
41581
41614
  annotations: {
41582
- readOnlyHint: false,
41615
+ readOnlyHint: true,
41583
41616
  destructiveHint: false,
41584
- idempotentHint: false,
41617
+ idempotentHint: true,
41585
41618
  openWorldHint: true
41586
41619
  },
41587
41620
  description: "Download multiple build artifacts, with base64, text, or streaming output. Returns per-artifact payloads or stream metadata; returns 404 if the build or any path is unknown.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daghis/teamcity-mcp",
3
- "version": "2.11.0",
3
+ "version": "2.12.1",
4
4
  "description": "Model Control Protocol server for TeamCity CI/CD integration with AI coding assistants",
5
5
  "mcpName": "io.github.Daghis/teamcity",
6
6
  "main": "dist/index.js",
@@ -64,7 +64,7 @@
64
64
  "url": "https://github.com/Daghis/teamcity-mcp/issues"
65
65
  },
66
66
  "dependencies": {
67
- "@modelcontextprotocol/sdk": "^1.27.0",
67
+ "@modelcontextprotocol/sdk": "^1.29.0",
68
68
  "axios": "^1.15.0",
69
69
  "axios-retry": "^4.5.0",
70
70
  "dotenv": "17.4.2",
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.11.0",
10
+ "version": "2.12.1",
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.11.0",
16
+ "version": "2.12.1",
17
17
  "runtimeHint": "npx",
18
18
  "runtimeArguments": [
19
19
  {