gitlab-mcp-agent-server 0.2.5 → 0.2.7
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.
|
@@ -54,6 +54,13 @@ class GitLabOAuthManager {
|
|
|
54
54
|
try {
|
|
55
55
|
return await this.loginInteractively();
|
|
56
56
|
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof OAuthCallbackPortBusyError) {
|
|
59
|
+
console.error(error.message);
|
|
60
|
+
return this.waitForTokenFromOtherProcess(lockFilePath);
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
57
64
|
finally {
|
|
58
65
|
lock.release();
|
|
59
66
|
}
|
|
@@ -190,6 +197,11 @@ class GitLabOAuthManager {
|
|
|
190
197
|
});
|
|
191
198
|
server.on('error', (error) => {
|
|
192
199
|
settled = true;
|
|
200
|
+
const errno = error;
|
|
201
|
+
if (errno.code === 'EADDRINUSE') {
|
|
202
|
+
reject(new OAuthCallbackPortBusyError(`OAuth callback port is busy (${redirect.hostname}:${resolvePort(redirect)}). If another OAuth flow is active, finish it and retry.`));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
193
205
|
reject(new Error(`OAuth callback server failed on ${redirect.hostname}:${resolvePort(redirect)}: ${error.message}`));
|
|
194
206
|
});
|
|
195
207
|
server.listen(resolvePort(redirect), redirect.hostname, () => {
|
|
@@ -201,7 +213,7 @@ class GitLabOAuthManager {
|
|
|
201
213
|
console.error(authorizeUrl.toString());
|
|
202
214
|
}
|
|
203
215
|
});
|
|
204
|
-
const timeoutMs =
|
|
216
|
+
const timeoutMs = this.options.callbackTimeoutMs ?? 180_000;
|
|
205
217
|
setTimeout(() => {
|
|
206
218
|
if (settled) {
|
|
207
219
|
return;
|
|
@@ -315,6 +327,12 @@ class OAuthRefreshError extends Error {
|
|
|
315
327
|
this.name = 'OAuthRefreshError';
|
|
316
328
|
}
|
|
317
329
|
}
|
|
330
|
+
class OAuthCallbackPortBusyError extends Error {
|
|
331
|
+
constructor(message) {
|
|
332
|
+
super(message);
|
|
333
|
+
this.name = 'OAuthCallbackPortBusyError';
|
|
334
|
+
}
|
|
335
|
+
}
|
|
318
336
|
function shouldReloginOnRefreshFailure(error) {
|
|
319
337
|
if (!(error instanceof OAuthRefreshError)) {
|
|
320
338
|
return false;
|
|
@@ -375,6 +393,15 @@ function isStaleLock(lockFilePath) {
|
|
|
375
393
|
try {
|
|
376
394
|
const raw = (0, node_fs_1.readFileSync)(lockFilePath, 'utf8');
|
|
377
395
|
const parsed = JSON.parse(raw);
|
|
396
|
+
if (parsed.startedAt) {
|
|
397
|
+
const startedAtMs = new Date(parsed.startedAt).getTime();
|
|
398
|
+
if (!Number.isNaN(startedAtMs)) {
|
|
399
|
+
const ageMs = Date.now() - startedAtMs;
|
|
400
|
+
if (ageMs > 10 * 60 * 1000) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
378
405
|
if (!parsed.pid || !Number.isInteger(parsed.pid)) {
|
|
379
406
|
return true;
|
|
380
407
|
}
|
|
@@ -28,6 +28,7 @@ function createMcpServer() {
|
|
|
28
28
|
scopes: config.gitlab.oauth.scopes,
|
|
29
29
|
bootstrapAccessToken: config.gitlab.accessToken,
|
|
30
30
|
tokenStorePath: config.gitlab.oauth.tokenStorePath,
|
|
31
|
+
callbackTimeoutMs: config.gitlab.oauth.callbackTimeoutMs,
|
|
31
32
|
autoLogin: config.gitlab.oauth.autoLogin,
|
|
32
33
|
openBrowser: config.gitlab.oauth.openBrowser
|
|
33
34
|
})
|
|
@@ -15,6 +15,7 @@ const EnvSchema = zod_1.z.object({
|
|
|
15
15
|
GITLAB_OAUTH_REDIRECT_URI: zod_1.z.string().optional(),
|
|
16
16
|
GITLAB_OAUTH_SCOPES: zod_1.z.string().default('api'),
|
|
17
17
|
GITLAB_OAUTH_TOKEN_STORE_PATH: zod_1.z.string().optional(),
|
|
18
|
+
GITLAB_OAUTH_CALLBACK_TIMEOUT_MS: zod_1.z.coerce.number().int().positive().optional(),
|
|
18
19
|
GITLAB_OAUTH_AUTO_LOGIN: zod_1.z
|
|
19
20
|
.enum(['true', 'false'])
|
|
20
21
|
.optional()
|
|
@@ -68,6 +69,7 @@ function loadConfig() {
|
|
|
68
69
|
redirectUri: env.GITLAB_OAUTH_REDIRECT_URI,
|
|
69
70
|
scopes: splitCsv(env.GITLAB_OAUTH_SCOPES),
|
|
70
71
|
tokenStorePath: defaultTokenStorePath,
|
|
72
|
+
callbackTimeoutMs: env.GITLAB_OAUTH_CALLBACK_TIMEOUT_MS ?? 180_000,
|
|
71
73
|
autoLogin: env.GITLAB_OAUTH_AUTO_LOGIN,
|
|
72
74
|
openBrowser: env.GITLAB_OAUTH_OPEN_BROWSER
|
|
73
75
|
},
|
package/docs/USER_GUIDE.md
CHANGED
|
@@ -60,6 +60,7 @@ export GITLAB_AUTH_MODE="oauth";
|
|
|
60
60
|
export GITLAB_OAUTH_CLIENT_ID="<GITLAB_COM_APP_ID>";
|
|
61
61
|
export GITLAB_OAUTH_CLIENT_SECRET="<GITLAB_COM_APP_SECRET>";
|
|
62
62
|
export GITLAB_OAUTH_REDIRECT_URI="http://127.0.0.1:8787/oauth/callback";
|
|
63
|
+
export GITLAB_OAUTH_CALLBACK_TIMEOUT_MS="180000";
|
|
63
64
|
export GITLAB_OAUTH_AUTO_LOGIN="true";
|
|
64
65
|
export GITLAB_OAUTH_OPEN_BROWSER="true";
|
|
65
66
|
|
|
@@ -77,6 +78,7 @@ export GITLAB_AUTH_MODE="oauth";
|
|
|
77
78
|
export GITLAB_OAUTH_CLIENT_ID="<WORK_APP_ID>";
|
|
78
79
|
export GITLAB_OAUTH_CLIENT_SECRET="<WORK_APP_SECRET>";
|
|
79
80
|
export GITLAB_OAUTH_REDIRECT_URI="http://127.0.0.1:8788/oauth/callback";
|
|
81
|
+
export GITLAB_OAUTH_CALLBACK_TIMEOUT_MS="180000";
|
|
80
82
|
export GITLAB_OAUTH_AUTO_LOGIN="true";
|
|
81
83
|
export GITLAB_OAUTH_OPEN_BROWSER="true";
|
|
82
84
|
|
|
@@ -121,6 +123,8 @@ npx -y gitlab-mcp-agent-server
|
|
|
121
123
|
2. Ограничь права файла:
|
|
122
124
|
- `chmod 600 /home/<user>/.config/gitlab-mcp/gitlab.com/token.json`
|
|
123
125
|
3. Для headless окружений ставь `GITLAB_OAUTH_OPEN_BROWSER=false`.
|
|
126
|
+
4. При медленном интерактивном flow увеличь окно ожидания callback:
|
|
127
|
+
- `GITLAB_OAUTH_CALLBACK_TIMEOUT_MS=180000` (или выше).
|
|
124
128
|
|
|
125
129
|
## 7. Сценарий пользовательского запроса
|
|
126
130
|
|