@therealchristhomas/gitlab-mcp-server
Version:
MCP Server for GitLab API operations
105 lines (104 loc) • 3.54 kB
JavaScript
import fetch from "node-fetch";
import { GITLAB_API_URL, DEFAULT_HEADERS, AUTH_HEADERS } from "./constants.js";
export class GitLabApiError extends Error {
constructor(message, status, details) {
super(`GitLab API error: ${message}`);
this.status = status;
this.details = details;
this.name = "GitLabApiError";
}
}
export async function gitlabGetWithHeaders(endpoint, searchParams) {
const url = new URL(`${GITLAB_API_URL}${endpoint}`);
if (searchParams) {
url.search = searchParams.toString();
}
const response = await fetch(url.toString(), {
headers: AUTH_HEADERS
});
if (!response.ok) {
let errorDetails;
try {
errorDetails = await response.json();
}
catch {
// If response body isn't JSON, ignore
}
throw new GitLabApiError(response.statusText, response.status, errorDetails);
}
const data = (await response.json());
const headers = {
"x-next-page": response.headers.get("x-next-page") || undefined,
"x-prev-page": response.headers.get("x-prev-page") || undefined,
"x-total": response.headers.get("x-total") || undefined,
"x-total-pages": response.headers.get("x-total-pages") || undefined,
"x-per-page": response.headers.get("x-per-page") || undefined,
"x-page": response.headers.get("x-page") || undefined,
link: response.headers.get("link") || undefined
};
return { data, headers };
}
export async function gitlabGet(endpoint, searchParams) {
const response = await gitlabGetWithHeaders(endpoint, searchParams);
return response.data;
}
export async function gitlabPost(endpoint, body) {
const response = await fetch(`${GITLAB_API_URL}${endpoint}`, {
method: "POST",
headers: DEFAULT_HEADERS,
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
let errorDetails;
try {
errorDetails = await response.json();
}
catch {
// If response body isn't JSON, ignore
}
throw new GitLabApiError(response.statusText, response.status, errorDetails);
}
return (await response.json());
}
export async function gitlabPut(endpoint, body) {
const response = await fetch(`${GITLAB_API_URL}${endpoint}`, {
method: "PUT",
headers: DEFAULT_HEADERS,
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
let errorDetails;
try {
errorDetails = await response.json();
}
catch {
// If response body isn't JSON, ignore
}
throw new GitLabApiError(response.statusText, response.status, errorDetails);
}
return (await response.json());
}
export async function gitlabDelete(endpoint) {
const response = await fetch(`${GITLAB_API_URL}${endpoint}`, {
method: "DELETE",
headers: AUTH_HEADERS
});
if (!response.ok) {
throw new GitLabApiError(response.statusText, response.status);
}
}
export function encodeProjectId(projectId) {
return encodeURIComponent(projectId);
}
export function encodeFilePath(filePath) {
return encodeURIComponent(filePath);
}
export function buildSearchParams(options) {
const params = new URLSearchParams();
Object.entries(options).forEach(([key, value]) => {
if (value !== undefined) {
params.append(key, value.toString());
}
});
return params;
}