@daghis/teamcity-mcp 2.3.2 → 2.4.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 +107 -9
- 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.4.0](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.3.2...teamcity-mcp-v2.4.0) (2026-03-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add SSH key management tools for projects ([#407](https://github.com/Daghis/teamcity-mcp/issues/407)) ([#421](https://github.com/Daghis/teamcity-mcp/issues/421)) ([e00955c](https://github.com/Daghis/teamcity-mcp/commit/e00955c1d4c43955a734c806e42bd8ac4296d21d))
|
|
9
|
+
|
|
3
10
|
## [2.3.2](https://github.com/Daghis/teamcity-mcp/compare/teamcity-mcp-v2.3.1...teamcity-mcp-v2.3.2) (2026-03-10)
|
|
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.4.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",
|
|
@@ -4548,6 +4548,13 @@ var globalErrorHandler = GlobalErrorHandler.getInstance();
|
|
|
4548
4548
|
function json(data) {
|
|
4549
4549
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], success: true };
|
|
4550
4550
|
}
|
|
4551
|
+
var SECRET_KEY_PATTERN = /token|authorization|password|privateKey/i;
|
|
4552
|
+
var maskSecrets = (args) => typeof args === "object" && args != null ? Object.fromEntries(
|
|
4553
|
+
Object.entries(args).map(([k, v]) => [
|
|
4554
|
+
k,
|
|
4555
|
+
SECRET_KEY_PATTERN.test(k) ? "***" : v
|
|
4556
|
+
])
|
|
4557
|
+
) : {};
|
|
4551
4558
|
async function runTool(toolName, schema, handler, rawArgs, context) {
|
|
4552
4559
|
const logger2 = getLogger();
|
|
4553
4560
|
const reqId = context?.requestId ?? logger2.generateRequestId();
|
|
@@ -4559,13 +4566,7 @@ async function runTool(toolName, schema, handler, rawArgs, context) {
|
|
|
4559
4566
|
const success = result?.success !== false;
|
|
4560
4567
|
logger2.logToolExecution(
|
|
4561
4568
|
toolName,
|
|
4562
|
-
|
|
4563
|
-
typeof args === "object" && args != null ? Object.fromEntries(
|
|
4564
|
-
Object.entries(args).map(([k, v]) => [
|
|
4565
|
-
k,
|
|
4566
|
-
/token|authorization|password/i.test(k) ? "***" : v
|
|
4567
|
-
])
|
|
4568
|
-
) : {},
|
|
4569
|
+
maskSecrets(args),
|
|
4569
4570
|
{ success, error: result?.error },
|
|
4570
4571
|
duration,
|
|
4571
4572
|
{ requestId: reqId }
|
|
@@ -4576,7 +4577,7 @@ async function runTool(toolName, schema, handler, rawArgs, context) {
|
|
|
4576
4577
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4577
4578
|
logger2.logToolExecution(
|
|
4578
4579
|
toolName,
|
|
4579
|
-
|
|
4580
|
+
maskSecrets(rawArgs),
|
|
4580
4581
|
{ success: false, error: msg },
|
|
4581
4582
|
duration,
|
|
4582
4583
|
{ requestId: reqId }
|
|
@@ -43915,6 +43916,103 @@ var FULL_MODE_TOOLS = [
|
|
|
43915
43916
|
);
|
|
43916
43917
|
},
|
|
43917
43918
|
mode: "full"
|
|
43919
|
+
},
|
|
43920
|
+
// === SSH Key Management ===
|
|
43921
|
+
{
|
|
43922
|
+
name: "list_project_ssh_keys",
|
|
43923
|
+
description: "List SSH keys configured for a project",
|
|
43924
|
+
inputSchema: {
|
|
43925
|
+
type: "object",
|
|
43926
|
+
properties: {
|
|
43927
|
+
projectId: { type: "string", description: "Project ID" }
|
|
43928
|
+
},
|
|
43929
|
+
required: ["projectId"]
|
|
43930
|
+
},
|
|
43931
|
+
handler: async (args) => {
|
|
43932
|
+
const typedArgs = args;
|
|
43933
|
+
const api = TeamCityAPI.getInstance();
|
|
43934
|
+
const response = await api.http.get(
|
|
43935
|
+
`/app/rest/projects/${encodeURIComponent(typedArgs.projectId)}/sshKeys`,
|
|
43936
|
+
{ headers: { Accept: "application/json" } }
|
|
43937
|
+
);
|
|
43938
|
+
return json({
|
|
43939
|
+
success: true,
|
|
43940
|
+
action: "list_project_ssh_keys",
|
|
43941
|
+
projectId: typedArgs.projectId,
|
|
43942
|
+
sshKeys: response.data
|
|
43943
|
+
});
|
|
43944
|
+
},
|
|
43945
|
+
mode: "full"
|
|
43946
|
+
},
|
|
43947
|
+
{
|
|
43948
|
+
name: "upload_project_ssh_key",
|
|
43949
|
+
description: "Upload an SSH key to a project. Provide either privateKeyContent (raw PEM string) or privateKeyPath (path to key file), but not both.",
|
|
43950
|
+
inputSchema: {
|
|
43951
|
+
type: "object",
|
|
43952
|
+
properties: {
|
|
43953
|
+
projectId: { type: "string", description: "Project ID" },
|
|
43954
|
+
keyName: { type: "string", description: "Name for the SSH key" },
|
|
43955
|
+
privateKeyContent: {
|
|
43956
|
+
type: "string",
|
|
43957
|
+
description: "Raw private key content (PEM format)"
|
|
43958
|
+
},
|
|
43959
|
+
privateKeyPath: {
|
|
43960
|
+
type: "string",
|
|
43961
|
+
description: "Path to the private key file"
|
|
43962
|
+
}
|
|
43963
|
+
},
|
|
43964
|
+
required: ["projectId", "keyName"]
|
|
43965
|
+
},
|
|
43966
|
+
handler: async (args) => {
|
|
43967
|
+
const typedArgs = args;
|
|
43968
|
+
if (!typedArgs.privateKeyContent && !typedArgs.privateKeyPath) {
|
|
43969
|
+
throw new Error("Either privateKeyContent or privateKeyPath must be provided");
|
|
43970
|
+
}
|
|
43971
|
+
if (typedArgs.privateKeyContent && typedArgs.privateKeyPath) {
|
|
43972
|
+
throw new Error("Provide only one of privateKeyContent or privateKeyPath, not both");
|
|
43973
|
+
}
|
|
43974
|
+
const keyContent = typedArgs.privateKeyPath ? await import_node_fs2.promises.readFile(typedArgs.privateKeyPath, "utf-8") : typedArgs.privateKeyContent;
|
|
43975
|
+
const formData = new FormData();
|
|
43976
|
+
formData.append("privateKey", new Blob([keyContent]), "key");
|
|
43977
|
+
const api = TeamCityAPI.getInstance();
|
|
43978
|
+
await api.http.post(
|
|
43979
|
+
`/app/rest/projects/${encodeURIComponent(typedArgs.projectId)}/sshKeys?${new URLSearchParams({ name: typedArgs.keyName })}`,
|
|
43980
|
+
formData
|
|
43981
|
+
);
|
|
43982
|
+
return json({
|
|
43983
|
+
success: true,
|
|
43984
|
+
action: "upload_project_ssh_key",
|
|
43985
|
+
projectId: typedArgs.projectId,
|
|
43986
|
+
keyName: typedArgs.keyName
|
|
43987
|
+
});
|
|
43988
|
+
},
|
|
43989
|
+
mode: "full"
|
|
43990
|
+
},
|
|
43991
|
+
{
|
|
43992
|
+
name: "delete_project_ssh_key",
|
|
43993
|
+
description: "Delete an SSH key from a project",
|
|
43994
|
+
inputSchema: {
|
|
43995
|
+
type: "object",
|
|
43996
|
+
properties: {
|
|
43997
|
+
projectId: { type: "string", description: "Project ID" },
|
|
43998
|
+
keyName: { type: "string", description: "Name of the SSH key to delete" }
|
|
43999
|
+
},
|
|
44000
|
+
required: ["projectId", "keyName"]
|
|
44001
|
+
},
|
|
44002
|
+
handler: async (args) => {
|
|
44003
|
+
const typedArgs = args;
|
|
44004
|
+
const api = TeamCityAPI.getInstance();
|
|
44005
|
+
await api.http.delete(
|
|
44006
|
+
`/app/rest/projects/${encodeURIComponent(typedArgs.projectId)}/sshKeys?${new URLSearchParams({ name: typedArgs.keyName })}`
|
|
44007
|
+
);
|
|
44008
|
+
return json({
|
|
44009
|
+
success: true,
|
|
44010
|
+
action: "delete_project_ssh_key",
|
|
44011
|
+
projectId: typedArgs.projectId,
|
|
44012
|
+
keyName: typedArgs.keyName
|
|
44013
|
+
});
|
|
44014
|
+
},
|
|
44015
|
+
mode: "full"
|
|
43918
44016
|
}
|
|
43919
44017
|
];
|
|
43920
44018
|
function getAvailableTools() {
|
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.4.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.4.0",
|
|
17
17
|
"runtimeHint": "npx",
|
|
18
18
|
"runtimeArguments": [
|
|
19
19
|
{
|