import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import { GitLabService } from './services/gitlab.js';
import { startHttpServer } from './transports/http.js';
export interface ServerConfig {
name: string;
version: string;
gitlabUrl: string;
gitlabProjectId: string;
gitlabToken: string;
}
export class GitLabMCPServer {
private mcpServer: McpServer;
private gitlabService: GitLabService;
private config: ServerConfig;
constructor(config: ServerConfig) {
this.config = config;
this.gitlabService = new GitLabService();
this.mcpServer = new McpServer({
name: config.name,
version: config.version
});
this.registerTools();
}
private registerTools() {
// 注册触发流水线工具
this.mcpServer.registerTool(
'trigger_pipeline',
{
description: '触发 GitLab 流水线',
inputSchema: {
ref: z.string().describe('分支或标签名称'),
variables: z.record(z.string()).optional().describe('流水线变量对象')
}
},
async ({ ref, variables }) => {
try {
const result = await this.gitlabService.triggerPipeline(
this.config.gitlabUrl,
this.config.gitlabProjectId,
ref,
this.config.gitlabToken,
variables
);
return {
content: [{
type: 'text' as const,
text: `流水线触发成功: ${JSON.stringify(result, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `触发流水线失败: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
// 注册获取流水线状态工具
this.mcpServer.registerTool(
'get_pipeline_status',
{
description: '获取 GitLab 流水线状态',
inputSchema: {
pipeline_id: z.string().describe('流水线ID')
}
},
async ({ pipeline_id }) => {
try {
const result = await this.gitlabService.getPipelineStatus(
this.config.gitlabUrl,
this.config.gitlabProjectId,
pipeline_id,
this.config.gitlabToken
);
return {
content: [{
type: 'text' as const,
text: `流水线状态: ${JSON.stringify(result, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `获取流水线状态失败: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
// 注册列出流水线工具
this.mcpServer.registerTool(
'list_pipelines',
{
description: '列出 GitLab 流水线',
inputSchema: {
ref: z.string().optional().describe('分支名称'),
status: z.string().optional().describe('流水线状态'),
per_page: z.number().optional().describe('每页数量'),
page: z.number().optional().describe('页码')
}
},
async ({ ref, status, per_page, page }) => {
try {
const result = await this.gitlabService.listPipelines(
this.config.gitlabUrl,
this.config.gitlabProjectId,
this.config.gitlabToken,
{ ref, status, per_page, page }
);
return {
content: [{
type: 'text' as const,
text: `流水线列表: ${JSON.stringify(result, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `获取流水线列表失败: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
// 注册获取流水线作业工具
this.mcpServer.registerTool(
'get_pipeline_jobs',
{
description: '获取 GitLab 流水线作业',
inputSchema: {
pipeline_id: z.string().describe('流水线ID')
}
},
async ({ pipeline_id }) => {
try {
const result = await this.gitlabService.getPipelineJobs(
this.config.gitlabUrl,
this.config.gitlabProjectId,
pipeline_id,
this.config.gitlabToken
);
return {
content: [{
type: 'text' as const,
text: `流水线作业: ${JSON.stringify(result, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `获取流水线作业失败: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
// 注册取消流水线工具
this.mcpServer.registerTool(
'cancel_pipeline',
{
description: '取消 GitLab 流水线',
inputSchema: {
pipeline_id: z.string().describe('流水线ID')
}
},
async ({ pipeline_id }) => {
try {
const result = await this.gitlabService.cancelPipeline(
this.config.gitlabUrl,
this.config.gitlabProjectId,
pipeline_id,
this.config.gitlabToken
);
return {
content: [{
type: 'text' as const,
text: `流水线已取消: ${JSON.stringify(result, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: 'text' as const,
text: `取消流水线失败: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
}
async startStdio() {
const transport = new StdioServerTransport();
await this.mcpServer.connect(transport);
console.error('='.repeat(50));
console.error('🚀 GitLab MCP 服务器已启动');
console.error('📋 模式: STDIO');
console.error('🔗 GitLab URL:', this.config.gitlabUrl);
console.error('📁 项目 ID:', this.config.gitlabProjectId);
console.error('🛠️ 可用工具: trigger_pipeline, get_pipeline_status, list_pipelines, get_pipeline_jobs, cancel_pipeline');
console.error('='.repeat(50));
}
// Streamable HTTP 模式
async startHttp(port: number = 3300, host: string = '127.0.0.1') {
const httpServerInstance = await startHttpServer(this.mcpServer, {
port,
host,
});
}
getMcpServer() {
return this.mcpServer;
}
}