Skip to main content
Glama

Git MCP Server

requestContext.ts8.08 kB
/** * @fileoverview Utilities for creating and managing request contexts. * A request context is an object carrying a unique ID, timestamp, and other * relevant data for logging, tracing, and processing. It supports context * propagation for distributed tracing. * @module src/utils/internal/requestContext */ import { trace } from '@opentelemetry/api'; import { authContext as alsAuthContext } from '@/mcp-server/transports/auth/lib/authContext.js'; import { generateRequestContextId } from '@/utils/index.js'; import { logger } from '@/utils/internal/logger.js'; /** * Defines the structure of the authentication-related context, typically * decoded from a JWT. */ export interface AuthContext { /** The subject (user) identifier. */ sub: string; /** An array of granted permissions (scopes). */ scopes: string[]; /** Other properties from the token payload. */ [key: string]: unknown; } /** * Defines the core structure for context information associated with a request or operation. * This is fundamental for logging, tracing, and passing operational data. */ export interface RequestContext { /** * Unique ID for the context instance. * Used for log correlation and request tracing. */ requestId: string; /** * ISO 8601 timestamp indicating when the context was created. */ timestamp: string; /** * The unique identifier for the tenant making the request. * This is essential for multi-tenancy and data isolation. */ tenantId?: string; /** * Optional authentication context, present if the request was authenticated. */ auth?: AuthContext; /** * Allows arbitrary key-value pairs for specific context needs. * Using `unknown` promotes type-safe access. * Consumers must type-check/assert when accessing extended properties. */ [key: string]: unknown; } /** * Configuration for the {@link requestContextService}. * Allows for future extensibility of service-wide settings. */ export interface ContextConfig { /** Custom configuration properties. Allows for arbitrary key-value pairs. */ [key: string]: unknown; } /** * Represents a broader context for a specific operation or task. * It can optionally include a base {@link RequestContext} and other custom properties * relevant to the operation. */ export interface OperationContext { /** Optional base request context data, adhering to the `RequestContext` structure. */ requestContext?: RequestContext; /** Allows for additional, custom properties specific to the operation. */ [key: string]: unknown; } /** * Parameters for creating a new request context. */ export interface CreateRequestContextParams { /** * An optional parent context to inherit properties from, such as `requestId`. * This is key for propagating context in distributed systems. */ parentContext?: Record<string, unknown> | RequestContext; /** * An optional record of key-value pairs to be merged into the new context. * These will override any properties inherited from the parent context. */ additionalContext?: Record<string, unknown>; /** * A descriptive name for the operation creating this context. * Useful for debugging and tracing. */ operation?: string; } /** * Singleton-like service object for managing request context operations. * @private */ const requestContextServiceInstance = { /** * Internal configuration store for the service. */ config: {} as ContextConfig, /** * Configures the request context service with new settings. * Merges the provided partial configuration with existing settings. * * @param config - A partial `ContextConfig` object containing settings to update or add. * @returns A shallow copy of the newly updated configuration. */ configure(config: Partial<ContextConfig>): ContextConfig { this.config = { ...this.config, ...config, }; const logContext = this.createRequestContext({ operation: 'RequestContextService.configure', additionalContext: { newConfigState: { ...this.config } }, }); logger.debug('RequestContextService configuration updated', logContext); return { ...this.config }; }, /** * Retrieves a shallow copy of the current service configuration. * This prevents direct mutation of the internal configuration state. * * @returns A shallow copy of the current `ContextConfig`. */ getConfig(): ContextConfig { return { ...this.config }; }, /** * Creates a new {@link RequestContext} instance, supporting context propagation. * This function robustly handles two calling patterns: * 1. Passing a `CreateRequestContextParams` object: `createRequestContext({ parentContext: ..., additionalContext: ... })` * 2. Passing a plain object to be used as the context: `createRequestContext({ userId: '123', operation: '...' })` * * OpenTelemetry trace and span IDs are automatically injected if an active span exists. * * @param params - Parameters for creating the context. * @returns A new `RequestContext` object. */ createRequestContext( params: CreateRequestContextParams | Record<string, unknown> = {}, ): RequestContext { // Destructure known CreateRequestContextParams keys and capture the rest. // The 'rest' object will contain all properties that are NOT the special keys, // effectively capturing the direct context object when passed. const { parentContext, additionalContext, operation, ...rest } = params as CreateRequestContextParams; const inheritedContext = parentContext && typeof parentContext === 'object' ? { ...parentContext } : {}; let inheritedTenantId: string | undefined; if ( inheritedContext && typeof inheritedContext === 'object' && 'tenantId' in inheritedContext && typeof (inheritedContext as { tenantId?: unknown }).tenantId === 'string' ) { inheritedTenantId = (inheritedContext as { tenantId: string }).tenantId; } const authStore = alsAuthContext.getStore(); const tenantIdFromAuth = authStore?.authInfo?.tenantId; const requestId = typeof inheritedContext.requestId === 'string' && inheritedContext.requestId ? inheritedContext.requestId : generateRequestContextId(); const timestamp = new Date().toISOString(); const restTenantId = typeof (rest as { tenantId?: unknown }).tenantId === 'string' ? (rest as { tenantId: string }).tenantId : undefined; const additionalTenantId = additionalContext && typeof additionalContext === 'object' && typeof (additionalContext as { tenantId?: unknown }).tenantId === 'string' ? (additionalContext as { tenantId: string }).tenantId : undefined; const resolvedTenantId = additionalTenantId ?? restTenantId ?? inheritedTenantId ?? tenantIdFromAuth; const context: RequestContext = { ...inheritedContext, ...rest, // Spread any other properties from the params object requestId, timestamp, ...(resolvedTenantId ? { tenantId: resolvedTenantId } : {}), ...(additionalContext && typeof additionalContext === 'object' ? additionalContext : {}), ...(operation && typeof operation === 'string' ? { operation } : {}), }; // --- OpenTelemetry Integration --- const activeSpan = trace.getActiveSpan(); if (activeSpan && typeof activeSpan.spanContext === 'function') { const spanContext = activeSpan.spanContext(); if (spanContext) { context.traceId = spanContext.traceId; context.spanId = spanContext.spanId; } } // --- End OpenTelemetry Integration --- return context; }, }; /** * Primary export for request context functionalities. * This service provides methods to create and manage {@link RequestContext} instances, * which are essential for logging, tracing, and correlating operations. */ export const requestContextService = requestContextServiceInstance;

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/git-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server