MCPcopy
hub / github.com/coder/mux / MCPServerManager

Class MCPServerManager

src/node/services/mcpServerManager.ts:599–2022  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

597}
598
599export class MCPServerManager {
600 private readonly workspaceServers = new Map<string, WorkspaceServers>();
601 private readonly workspaceLeases = new Map<string, number>();
602 private readonly idleCheckInterval: ReturnType<typeof setInterval>;
603 private inlineServers: Record<string, string> = {};
604 private readonly policyService: PolicyService | null;
605 private mcpOauthService: McpOauthService | null = null;
606 private ignoreConfigFile = false;
607
608 setMcpOauthService(service: McpOauthService): void {
609 this.mcpOauthService = service;
610 }
611 constructor(
612 private readonly configService: MCPConfigService,
613 options?: MCPServerManagerOptions,
614 policyService?: PolicyService
615 ) {
616 this.policyService = policyService ?? null;
617 this.idleCheckInterval = setInterval(() => this.cleanupIdleServers(), IDLE_CHECK_INTERVAL_MS);
618 this.idleCheckInterval.unref?.();
619 if (options?.inlineServers) {
620 this.inlineServers = options.inlineServers;
621 }
622 if (options?.ignoreConfigFile) {
623 this.ignoreConfigFile = options.ignoreConfigFile;
624 }
625 }
626
627 /**
628 * Stop the idle cleanup interval. Call when shutting down.
629 */
630 dispose(): void {
631 clearInterval(this.idleCheckInterval);
632 }
633
634 private getLeaseCount(workspaceId: string): number {
635 return this.workspaceLeases.get(workspaceId) ?? 0;
636 }
637
638 /**
639 * Mark a workspace's MCP servers as actively in-use.
640 *
641 * This prevents idle cleanup from shutting down MCP clients while a stream is
642 * still running (which can otherwise surface as "Attempted to send a request
643 * from a closed client").
644 */
645 acquireLease(workspaceId: string): void {
646 const current = this.workspaceLeases.get(workspaceId) ?? 0;
647 this.workspaceLeases.set(workspaceId, current + 1);
648 this.markActivity(workspaceId);
649 }
650
651 /**
652 * Release a previously-acquired lease.
653 */
654 releaseLease(workspaceId: string): void {
655 const current = this.workspaceLeases.get(workspaceId) ?? 0;
656 if (current <= 0) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected