Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ const authBySession: Record<string, AuthData> = {};
const BASE_HEADERS: Record<string, string> = {
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent": `gitlab-mcp-server/${SERVER_VERSION} (node-fetch)`,
};

/**
Expand Down
92 changes: 92 additions & 0 deletions test-results-oauth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[
{
"name": "OAuth class instantiation",
"status": "passed",
"duration": 0
},
{
"name": "Token storage path configuration",
"status": "passed",
"duration": 0
},
{
"name": "Scope configuration with api only",
"status": "passed",
"duration": 0
},
{
"name": "Multiple scopes configuration (redundant)",
"status": "passed",
"duration": 1
},
{
"name": "hasValidToken returns false without token",
"status": "passed",
"duration": 0
},
{
"name": "hasValidToken returns true with valid token",
"status": "passed",
"duration": 1
},
{
"name": "hasValidToken returns false with expired token",
"status": "passed",
"duration": 0
},
{
"name": "clearToken removes token file",
"status": "passed",
"duration": 1
},
{
"name": "Token file has correct permissions",
"status": "passed",
"duration": 0
},
{
"name": "Port availability check",
"status": "passed",
"duration": 3
},
{
"name": "OAuth redirect URI parsing",
"status": "passed",
"duration": 0
},
{
"name": "Token expiration calculation",
"status": "passed",
"duration": 0
},
{
"name": "Shared server concept",
"status": "passed",
"duration": 2
},
{
"name": "Environment variable configuration",
"status": "passed",
"duration": 0
},
{
"name": "Token data structure validation",
"status": "passed",
"duration": 0
},
{
"name": "Invalid token storage path handling",
"status": "passed",
"duration": 0
},
{
"name": "Self-hosted GitLab URL configuration",
"status": "passed",
"duration": 0
},
{
"name": "Custom port in redirect URI",
"status": "passed",
"duration": 0
}
]
54 changes: 54 additions & 0 deletions test/test-user-agent-header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { describe, test, before, after } from 'node:test';
import assert from 'node:assert';
import { MockGitLabServer, findMockServerPort } from './utils/mock-gitlab-server.js';

const MOCK_TOKEN = 'glpat-mock-token-12345';

describe('User-Agent Header Tests', () => {
let mockServer: MockGitLabServer;
let mockPort: number;

before(async () => {
mockPort = await findMockServerPort();
mockServer = new MockGitLabServer({
port: mockPort,
validTokens: [MOCK_TOKEN]
});
await mockServer.start();

// Add custom route to capture User-Agent header
mockServer.addMockHandler('get', '/user', (req, res) => {
const userAgent = req.headers['user-agent'];
res.json({
id: 1,
username: 'test_user',
name: 'Test User',
user_agent: userAgent
});
});
});

after(async () => {
if (mockServer) {
await mockServer.stop();
}
});

test('User-Agent header should be set in API requests', async () => {
// Import node-fetch to make a test request
const fetch = (await import('node-fetch')).default;

// Make a request to the mock server to verify User-Agent is set
const response = await fetch(`http://127.0.0.1:${mockPort}/api/v4/user`, {
headers: {
'Authorization': `Bearer ${MOCK_TOKEN}`,
'User-Agent': 'gitlab-mcp-server/2.0.23 (node-fetch)'
}
});

const data = await response.json() as any;
assert.ok(data.user_agent, 'User-Agent header should be present');
assert.ok(data.user_agent.includes('gitlab-mcp-server'), 'User-Agent should include "gitlab-mcp-server"');
assert.ok(data.user_agent.includes('node-fetch'), 'User-Agent should include "node-fetch"');
});
});