@zereight/mcp-gitlab 2.2.1 → 2.2.3
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/README.ko.md +49 -21
- package/README.md +110 -76
- package/README.pt-BR.md +48 -20
- package/README.zh-CN.md +48 -20
- package/build/auth-cli.js +15 -5
- package/build/cli-boolean-flags.js +34 -0
- package/build/config.js +12 -30
- package/build/deprecated-env.js +158 -28
- package/build/index.js +328 -42
- package/build/oauth-proxy.js +2 -1
- package/build/oauth.js +5 -4
- package/build/schemas.js +97 -0
- package/build/tools/registry.js +54 -3
- package/build/tools/tool-descriptions.js +5 -1
- package/build/utils/health-check-transport-error.js +115 -0
- package/build/utils/logger.js +92 -16
- package/build/utils/redact-sensitive.js +18 -8
- package/build/utils/redact-url.js +141 -0
- package/package.json +1 -1
package/build/deprecated-env.js
CHANGED
|
@@ -5,31 +5,116 @@ function shownEnvValue(rawValue) {
|
|
|
5
5
|
}
|
|
6
6
|
return `${singleLine.slice(0, 77)}...`;
|
|
7
7
|
}
|
|
8
|
+
const REMOVAL_VERSION = "v3.0.0";
|
|
9
|
+
const DEPRECATION_NOTICE_URL = "https://github.com/zereight/gitlab-mcp/issues/815";
|
|
8
10
|
// USE_PIPELINE exposes these two tools, but they live in the `ci` toolset, not `pipelines`.
|
|
9
11
|
// Suggesting `ci` would also turn on catalog tools the flag does not expose.
|
|
10
12
|
const LEGACY_TOOLS_OUTSIDE_NAMED_TOOLSET = {
|
|
11
13
|
pipelines: "validate_ci_lint,validate_project_ci_lint",
|
|
12
14
|
};
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
+
function explicitToolsets(raw) {
|
|
16
|
+
if (raw === undefined) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const trimmed = raw.trim();
|
|
20
|
+
if (trimmed === "") {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return trimmed;
|
|
24
|
+
}
|
|
25
|
+
function isAllToolsets(raw) {
|
|
26
|
+
return raw.trim().toLowerCase() === "all";
|
|
27
|
+
}
|
|
28
|
+
function settingName(envName, cliFlag, fromCli) {
|
|
29
|
+
if (fromCli) {
|
|
30
|
+
return `\`--${cliFlag}\` (${envName})`;
|
|
31
|
+
}
|
|
32
|
+
return envName;
|
|
33
|
+
}
|
|
34
|
+
function gitlabToolsAssignment(extraTools, toolsRaw, toolsFromCli) {
|
|
35
|
+
const prefix = toolsFromCli ? "--tools=" : "GITLAB_TOOLS=";
|
|
36
|
+
const existing = explicitToolsets(toolsRaw);
|
|
37
|
+
if (existing === undefined) {
|
|
38
|
+
return `${prefix}${extraTools}`;
|
|
39
|
+
}
|
|
40
|
+
const names = existing
|
|
41
|
+
.split(",")
|
|
42
|
+
.map(part => part.trim())
|
|
43
|
+
.filter(part => part.length > 0);
|
|
44
|
+
const merged = extraTools.split(",").reduce((current, tool) => {
|
|
45
|
+
if (current.includes(tool)) {
|
|
46
|
+
return current;
|
|
47
|
+
}
|
|
48
|
+
return [...current, tool];
|
|
49
|
+
}, names);
|
|
50
|
+
return `${prefix}${merged.join(",")}`;
|
|
51
|
+
}
|
|
52
|
+
function legacyToolsetHint(toolset, toolsetsRaw, toolsetsFromCli, toolsRaw, toolsFromCli, optional) {
|
|
15
53
|
const extraTools = LEGACY_TOOLS_OUTSIDE_NAMED_TOOLSET[toolset];
|
|
16
|
-
|
|
17
|
-
|
|
54
|
+
const toolsAssignment = extraTools === undefined
|
|
55
|
+
? undefined
|
|
56
|
+
: gitlabToolsAssignment(extraTools, toolsRaw, toolsFromCli);
|
|
57
|
+
const listed = explicitToolsets(toolsetsRaw);
|
|
58
|
+
const toolsetsLabel = toolsetsFromCli && listed !== undefined ? "--toolsets" : "GITLAB_TOOLSETS";
|
|
59
|
+
if (listed !== undefined) {
|
|
60
|
+
const shown = shownEnvValue(listed);
|
|
61
|
+
// parseEnabledToolsets treats only the exact value "all" as every toolset.
|
|
62
|
+
// "all,pipelines" is not "all"; unknown token "all" is dropped and pipelines remains.
|
|
63
|
+
if (isAllToolsets(listed)) {
|
|
64
|
+
return `Keep the existing ${toolsetsLabel} value ("${shown}") and remove the deprecated setting`;
|
|
65
|
+
}
|
|
66
|
+
const extra = toolsAssignment === undefined ? "" : ` and set ${toolsAssignment}`;
|
|
67
|
+
if (optional) {
|
|
68
|
+
return (`Add \`${toolset}\` to the existing ${toolsetsLabel} list ("${shown}")${extra} ` +
|
|
69
|
+
"only if you want those tools");
|
|
70
|
+
}
|
|
71
|
+
return `Add \`${toolset}\` to the existing ${toolsetsLabel} list ("${shown}")${extra} instead`;
|
|
72
|
+
}
|
|
73
|
+
// An explicit toolset list replaces the default toolsets; it does not merge.
|
|
74
|
+
// Legacy USE_* flags add tools on top of defaults, so the hint must keep `core`
|
|
75
|
+
// only when the user has not set a toolset list.
|
|
76
|
+
const toolsets = `GITLAB_TOOLSETS=core,${toolset}`;
|
|
77
|
+
const replacement = toolsAssignment === undefined ? toolsets : `${toolsets} and ${toolsAssignment}`;
|
|
78
|
+
if (optional) {
|
|
79
|
+
return `Set ${replacement} only if you want those tools in addition to core`;
|
|
18
80
|
}
|
|
19
|
-
return
|
|
81
|
+
return `Use ${replacement} instead`;
|
|
20
82
|
}
|
|
21
|
-
function legacyToolsetWarning(envName, rawValue, toolset) {
|
|
22
|
-
|
|
23
|
-
// Legacy USE_* flags add tools on top of defaults, so the hint must keep `core`.
|
|
24
|
-
const replacement = legacyToolsetReplacement(toolset);
|
|
83
|
+
function legacyToolsetWarning(envName, cliFlag, fromCli, rawValue, toolset, toolsetsRaw, toolsetsFromCli, toolsRaw, toolsFromCli) {
|
|
84
|
+
const name = settingName(envName, cliFlag, fromCli);
|
|
25
85
|
if (rawValue === "true") {
|
|
26
|
-
return (`${
|
|
27
|
-
|
|
86
|
+
return (`${name} is deprecated and will be removed in ${REMOVAL_VERSION}. ` +
|
|
87
|
+
`${legacyToolsetHint(toolset, toolsetsRaw, toolsetsFromCli, toolsRaw, toolsFromCli, false)}.`);
|
|
28
88
|
}
|
|
29
89
|
const shown = shownEnvValue(rawValue);
|
|
30
|
-
return (`${
|
|
90
|
+
return (`${name} is set to "${shown}" and is deprecated and will be removed in ${REMOVAL_VERSION}. ` +
|
|
31
91
|
`This value does not enable the ${toolset} toolset. Remove it. ` +
|
|
32
|
-
|
|
92
|
+
`${legacyToolsetHint(toolset, toolsetsRaw, toolsetsFromCli, toolsRaw, toolsFromCli, true)}.`);
|
|
93
|
+
}
|
|
94
|
+
function readOnlyRawValue(input) {
|
|
95
|
+
if (input.readOnlyRaw !== undefined && input.readOnlyRaw !== "") {
|
|
96
|
+
return input.readOnlyRaw;
|
|
97
|
+
}
|
|
98
|
+
if (input.readOnlyMode) {
|
|
99
|
+
return "true";
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
function readOnlyWarning(input) {
|
|
104
|
+
const raw = readOnlyRawValue(input);
|
|
105
|
+
if (raw === undefined) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const name = settingName("GITLAB_READ_ONLY_MODE", "read-only", input.readOnlyFromCli === true);
|
|
109
|
+
if (raw === "true") {
|
|
110
|
+
const conflict = input.permissionModeRaw !== undefined && input.permissionModeRaw !== "readonly"
|
|
111
|
+
? ` It OVERRIDES the configured permission mode "${input.permissionModeRaw}"; the server runs as "readonly".`
|
|
112
|
+
: "";
|
|
113
|
+
return (`${name} is deprecated and will be removed in ${REMOVAL_VERSION}. ` +
|
|
114
|
+
`Use GITLAB_PERMISSION_MODE=readonly or --permission-mode=readonly instead.${conflict}`);
|
|
115
|
+
}
|
|
116
|
+
return (`${name} is set to "${shownEnvValue(raw)}" and is deprecated and will be removed in ${REMOVAL_VERSION}. ` +
|
|
117
|
+
"This value does not enable legacy read-only mode. The effective permission mode comes from GITLAB_PERMISSION_MODE or --permission-mode. Remove it.");
|
|
33
118
|
}
|
|
34
119
|
/**
|
|
35
120
|
* Builds startup warnings for deprecated env vars / CLI flags.
|
|
@@ -37,27 +122,72 @@ function legacyToolsetWarning(envName, rawValue, toolset) {
|
|
|
37
122
|
*/
|
|
38
123
|
export function getDeprecatedEnvWarnings(input) {
|
|
39
124
|
const warnings = [];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
: "";
|
|
44
|
-
warnings.push("GITLAB_READ_ONLY_MODE is deprecated and will be removed in the next major version. " +
|
|
45
|
-
`Use GITLAB_PERMISSION_MODE=readonly or --permission-mode=readonly instead.${conflict}`);
|
|
125
|
+
const readOnly = readOnlyWarning(input);
|
|
126
|
+
if (readOnly !== undefined) {
|
|
127
|
+
warnings.push(readOnly);
|
|
46
128
|
}
|
|
47
129
|
if (input.allowedGroupsRaw) {
|
|
130
|
+
const name = settingName("GITLAB_ALLOWED_GROUPS", "allowed-groups", input.allowedGroupsFromCli === true);
|
|
48
131
|
warnings.push(input.oauthAllowedGroupsRaw
|
|
49
|
-
?
|
|
50
|
-
:
|
|
132
|
+
? `${name} is deprecated and ignored because GITLAB_OAUTH_ALLOWED_GROUPS is set. Remove it. It will be removed in ${REMOVAL_VERSION}.`
|
|
133
|
+
: `${name} is deprecated and will be removed in ${REMOVAL_VERSION}. Use GITLAB_OAUTH_ALLOWED_GROUPS instead.`);
|
|
51
134
|
}
|
|
52
135
|
const legacyToolsetFlags = [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
136
|
+
{
|
|
137
|
+
rawValue: input.useWikiRaw,
|
|
138
|
+
envName: "USE_GITLAB_WIKI",
|
|
139
|
+
cliFlag: "use-wiki",
|
|
140
|
+
fromCli: input.useWikiFromCli === true,
|
|
141
|
+
toolset: "wiki",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
rawValue: input.useMilestoneRaw,
|
|
145
|
+
envName: "USE_MILESTONE",
|
|
146
|
+
cliFlag: "use-milestone",
|
|
147
|
+
fromCli: input.useMilestoneFromCli === true,
|
|
148
|
+
toolset: "milestones",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
rawValue: input.usePipelineRaw,
|
|
152
|
+
envName: "USE_PIPELINE",
|
|
153
|
+
cliFlag: "use-pipeline",
|
|
154
|
+
fromCli: input.usePipelineFromCli === true,
|
|
155
|
+
toolset: "pipelines",
|
|
156
|
+
},
|
|
56
157
|
];
|
|
57
|
-
for (const
|
|
58
|
-
if (rawValue !== undefined) {
|
|
59
|
-
warnings.push(legacyToolsetWarning(envName, rawValue, toolset));
|
|
158
|
+
for (const flag of legacyToolsetFlags) {
|
|
159
|
+
if (flag.rawValue !== undefined) {
|
|
160
|
+
warnings.push(legacyToolsetWarning(flag.envName, flag.cliFlag, flag.fromCli, flag.rawValue, flag.toolset, input.toolsetsRaw, input.toolsetsFromCli === true, input.toolsRaw, input.toolsFromCli === true));
|
|
60
161
|
}
|
|
61
162
|
}
|
|
62
|
-
return warnings;
|
|
163
|
+
return warnings.map(warning => `${warning} See ${DEPRECATION_NOTICE_URL} for migration details.`);
|
|
164
|
+
}
|
|
165
|
+
function readSuppliedSetting(parsedArgs, env, cliKey, envKey) {
|
|
166
|
+
return parsedArgs[cliKey] || env[envKey];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Warning snapshot for one command. CLI flags in `parsedArgs` win over `env`,
|
|
170
|
+
* matching getConfig, and neither source is read from the process globals.
|
|
171
|
+
*/
|
|
172
|
+
export function deprecatedEnvInputFromSources(parsedArgs, env) {
|
|
173
|
+
const readOnlyRaw = readSuppliedSetting(parsedArgs, env, "read-only", "GITLAB_READ_ONLY_MODE");
|
|
174
|
+
return {
|
|
175
|
+
readOnlyMode: readOnlyRaw === "true",
|
|
176
|
+
readOnlyRaw,
|
|
177
|
+
readOnlyFromCli: Boolean(parsedArgs["read-only"]),
|
|
178
|
+
permissionModeRaw: readSuppliedSetting(parsedArgs, env, "permission-mode", "GITLAB_PERMISSION_MODE"),
|
|
179
|
+
allowedGroupsRaw: readSuppliedSetting(parsedArgs, env, "allowed-groups", "GITLAB_ALLOWED_GROUPS"),
|
|
180
|
+
allowedGroupsFromCli: Boolean(parsedArgs["allowed-groups"]),
|
|
181
|
+
oauthAllowedGroupsRaw: readSuppliedSetting(parsedArgs, env, "oauth-allowed-groups", "GITLAB_OAUTH_ALLOWED_GROUPS"),
|
|
182
|
+
useWikiRaw: readSuppliedSetting(parsedArgs, env, "use-wiki", "USE_GITLAB_WIKI"),
|
|
183
|
+
useWikiFromCli: Boolean(parsedArgs["use-wiki"]),
|
|
184
|
+
useMilestoneRaw: readSuppliedSetting(parsedArgs, env, "use-milestone", "USE_MILESTONE"),
|
|
185
|
+
useMilestoneFromCli: Boolean(parsedArgs["use-milestone"]),
|
|
186
|
+
usePipelineRaw: readSuppliedSetting(parsedArgs, env, "use-pipeline", "USE_PIPELINE"),
|
|
187
|
+
usePipelineFromCli: Boolean(parsedArgs["use-pipeline"]),
|
|
188
|
+
toolsetsRaw: readSuppliedSetting(parsedArgs, env, "toolsets", "GITLAB_TOOLSETS"),
|
|
189
|
+
toolsetsFromCli: Boolean(parsedArgs["toolsets"]),
|
|
190
|
+
toolsRaw: readSuppliedSetting(parsedArgs, env, "tools", "GITLAB_TOOLS"),
|
|
191
|
+
toolsFromCli: Boolean(parsedArgs["tools"]),
|
|
192
|
+
};
|
|
63
193
|
}
|