All files / src config.ts

100% Statements 59/59
93.75% Branches 30/32
100% Functions 4/4
100% Lines 58/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 12051x 51x   51x     51x 51x 51x 51x 51x     51x 51x 51x 51x 51x 51x 51x 51x 51x 51x     51x             51x     51x 51x 51x 51x       51x 45x     6x 2x       6x 2x     6x     51x 51x 51x 51x 12x   51x 5x 2x     3x 2x 1x           2x       51x 51x   51x 51x       11x 11x         51x             51x 14x 14x     14x 1948x     26x   26x       14x    
import * as path from "path";
import * as fs from "fs";
// Get package.json path
const packageJsonPath = path.resolve(process.cwd(), "package.json");
 
// Environment variables
export const GITLAB_TOKEN = process.env.GITLAB_TOKEN;
export const GITLAB_AUTH_COOKIE_PATH = process.env.GITLAB_AUTH_COOKIE_PATH;
export const IS_OLD = process.env.GITLAB_IS_OLD === "true";
export const GITLAB_READ_ONLY_MODE = process.env.GITLAB_READ_ONLY_MODE === "true";
export const GITLAB_DENIED_TOOLS_REGEX = process.env.GITLAB_DENIED_TOOLS_REGEX
  ? new RegExp(process.env.GITLAB_DENIED_TOOLS_REGEX)
  : undefined;
export const USE_GITLAB_WIKI = process.env.USE_GITLAB_WIKI !== "false";
export const USE_MILESTONE = process.env.USE_MILESTONE !== "false";
export const USE_PIPELINE = process.env.USE_PIPELINE !== "false";
export const USE_WORKITEMS = process.env.USE_WORKITEMS !== "false";
export const USE_LABELS = process.env.USE_LABELS !== "false";
export const USE_MRS = process.env.USE_MRS !== "false";
export const USE_FILES = process.env.USE_FILES !== "false";
export const USE_VARIABLES = process.env.USE_VARIABLES !== "false";
export const HOST = process.env.HOST ?? "0.0.0.0";
export const PORT = process.env.PORT ?? 3002;
 
// API timeout configuration (in milliseconds)
export const API_TIMEOUT_MS = parseInt(process.env.GITLAB_API_TIMEOUT_MS ?? "20000", 10);
 
// Transport mode selection:
// - If PORT env var is present: HTTP mode with dual transport (SSE + StreamableHTTP)
// - If no PORT env var: stdio mode for direct MCP communication
 
// TLS/SSL configuration
export const SKIP_TLS_VERIFY = process.env.SKIP_TLS_VERIFY === "true";
 
// Proxy configuration
export const HTTP_PROXY = process.env.HTTP_PROXY;
export const HTTPS_PROXY = process.env.HTTPS_PROXY;
export const NODE_TLS_REJECT_UNAUTHORIZED = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
export const GITLAB_CA_CERT_PATH = process.env.GITLAB_CA_CERT_PATH;
 
// GitLab base URL configuration (without /api/v4)
function normalizeGitLabBaseUrl(url?: string): string {
  if (!url) {
    return "https://gitlab.com";
  }
 
  if (url.endsWith("/")) {
    url = url.slice(0, -1);
  }
 
  // Remove /api/v4 if user accidentally added it
  if (url.endsWith("/api/v4")) {
    url = url.slice(0, -7);
  }
 
  return url;
}
 
export const GITLAB_BASE_URL = normalizeGitLabBaseUrl(process.env.GITLAB_API_URL ?? "");
export const GITLAB_API_URL = `${GITLAB_BASE_URL}/api/v4`;
export const GITLAB_PROJECT_ID = process.env.GITLAB_PROJECT_ID;
export const GITLAB_ALLOWED_PROJECT_IDS =
  process.env.GITLAB_ALLOWED_PROJECT_IDS?.split(",").map(id => id.trim()) ?? [];
 
export function getEffectiveProjectId(projectId: string): string {
  if (GITLAB_PROJECT_ID) {
    return GITLAB_PROJECT_ID;
  }
 
  if (GITLAB_ALLOWED_PROJECT_IDS.length > 0) {
    if (!GITLAB_ALLOWED_PROJECT_IDS.includes(projectId)) {
      throw new Error(
        `Project ID ${projectId} is not allowed. Allowed project IDs: ${GITLAB_ALLOWED_PROJECT_IDS.join(", ")}`
      );
    }
  }
 
  return projectId;
}
 
// Package info
let packageName = "gitlab-mcp";
let packageVersion = "unknown";
 
try {
  const packageInfo = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) as {
    name?: string;
    version?: string;
  };
  packageName = packageInfo.name ?? packageName;
  packageVersion = packageInfo.version ?? packageVersion;
} catch {
  // Ignore errors when reading package.json
}
 
export { packageName, packageVersion };
 
/**
 * Parse tool description overrides from environment variables
 * Environment variables should follow the pattern: GITLAB_TOOL_{TOOL_NAME}="Custom description"
 * @returns Map of tool name to custom description
 */
export function getToolDescriptionOverrides(): Map<string, string> {
  const overrides = new Map<string, string>();
  const prefix = "GITLAB_TOOL_";
 
  // Scan all environment variables for tool description overrides
  for (const [key, value] of Object.entries(process.env)) {
    if (key.startsWith(prefix) && value) {
      // Extract tool name from environment variable
      // Convert from GITLAB_TOOL_LIST_PROJECTS to list_projects
      const toolName = key.substring(prefix.length).toLowerCase();
 
      overrides.set(toolName, value);
    }
  }
 
  return overrides;
}