refactor(mcp): trim internal server exports (#108076)

* refactor(mcp): remove dead internal exports

* chore(deadcode): refresh export baseline
This commit is contained in:
Peter Steinberger
2026-07-14 23:47:38 -07:00
committed by GitHub
parent c4cd643c1b
commit 92d06e51bb
8 changed files with 80 additions and 102 deletions

View File

@@ -24,6 +24,8 @@ const rootEntries = [
"src/plugins/runtime/index.ts!",
"src/plugins/source-display.ts!",
"src/mcp/codex-supervision-tools-serve.ts!",
// Spawned by generated system-agent MCP configs; this stdio entry is not statically imported.
"src/mcp/openclaw-tools-serve.ts!",
"scripts/qa/render-maturity-docs.ts!",
bundledPluginFile("telegram", "src/audit.ts", "!"),
bundledPluginFile("telegram", "src/token.ts", "!"),

View File

@@ -235,14 +235,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/logging/diagnostic-run-activity.ts: markDiagnosticToolStartedForTest",
"src/logging/redact-internal.ts: withFullContextToolPayloadRedaction",
"src/logging/secret-redaction-registry.ts: resetSecretRedactionRegistryForTest",
"src/mcp/channel-bridge.ts: shouldRetryInitialMcpGatewayConnect",
"src/mcp/channel-server.ts: createOpenClawChannelMcpServer",
"src/mcp/channel-server.ts: OpenClawChannelBridge",
"src/mcp/openclaw-tools-serve-config.ts: OPENCLAW_TOOLS_MCP_SYSTEM_AGENT_SURFACE_ENV",
"src/mcp/openclaw-tools-serve-config.ts: OpenClawToolsMcpToolId",
"src/mcp/openclaw-tools-serve-config.ts: resolveOpenClawToolsMcpSystemAgentApproval",
"src/mcp/openclaw-tools-serve-config.ts: resolveOpenClawToolsMcpSystemAgentSurface",
"src/mcp/openclaw-tools-serve-config.ts: resolveOpenClawToolsMcpToolSelection",
"src/music-generation/capabilities.ts: resolveMusicGenerationMode",
"src/node-host/invoke.ts: testing",
"src/plugin-state/plugin-state-store.sqlite.ts: probePluginStateStore",

View File

@@ -25,7 +25,6 @@ export const KNIP_OPTIONAL_UNUSED_FILE_ALLOWLIST = [
"src/gateway/gateway-cli-backend.live-helpers.ts",
"src/gateway/gateway-cli-backend.live-probe-helpers.ts",
"src/gateway/gateway-codex-harness.live-helpers.ts",
"src/mcp/openclaw-tools-serve.ts",
"src/mcp/plugin-tools-handlers.ts",
"src/mcp/plugin-tools-serve.ts",
"src/mcp/tools-stdio-server.ts",

View File

@@ -663,8 +663,7 @@ export class OpenClawChannelBridge {
}
}
/** Decide whether startup should wait for a retryable Gateway connect failure to recover. */
export function shouldRetryInitialMcpGatewayConnect(error: Error): boolean {
function shouldRetryInitialMcpGatewayConnect(error: Error): boolean {
if (
error.name === "GatewayClientRequestError" &&
"retryable" in error &&

View File

@@ -0,0 +1,68 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { VERSION } from "../version.js";
import { OpenClawChannelBridge } from "./channel-bridge.js";
import { ClaudePermissionRequestSchema, type ClaudeChannelMode } from "./channel-shared.js";
import { getChannelMcpCapabilities, registerChannelMcpTools } from "./channel-tools.js";
async function resolveMcpConfig(config: OpenClawConfig | undefined): Promise<OpenClawConfig> {
if (config) {
return config;
}
const { getRuntimeConfig } = await import("../config/config.js");
return getRuntimeConfig();
}
export async function createChannelMcpRuntime(
opts: {
gatewayUrl?: string;
gatewayToken?: string;
gatewayPassword?: string;
config?: OpenClawConfig;
claudeChannelMode?: ClaudeChannelMode;
verbose?: boolean;
} = {},
): Promise<{
server: McpServer;
bridge: OpenClawChannelBridge;
start: () => Promise<void>;
close: () => Promise<void>;
}> {
const cfg = await resolveMcpConfig(opts.config);
const claudeChannelMode = opts.claudeChannelMode ?? "auto";
const capabilities = getChannelMcpCapabilities(claudeChannelMode);
const server = new McpServer(
{ name: "openclaw", version: VERSION },
capabilities ? { capabilities } : undefined,
);
const bridge = new OpenClawChannelBridge(cfg, {
gatewayUrl: opts.gatewayUrl,
gatewayToken: opts.gatewayToken,
gatewayPassword: opts.gatewayPassword,
claudeChannelMode,
verbose: opts.verbose ?? false,
});
bridge.setServer(server);
server.server.setNotificationHandler(ClaudePermissionRequestSchema, async ({ params }) => {
await bridge.handleClaudePermissionRequest({
requestId: params.request_id,
toolName: params.tool_name,
description: params.description,
inputPreview: params.input_preview,
});
});
registerChannelMcpTools(server, bridge);
return {
server,
bridge,
start: async () => {
await bridge.start();
},
close: async () => {
await bridge.close();
await server.close();
},
};
}

View File

@@ -3,9 +3,8 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
import { describe, expect, test, vi } from "vitest";
import { z } from "zod";
import { shouldRetryInitialMcpGatewayConnect } from "./channel-bridge.js";
import { OpenClawChannelBridge } from "./channel-bridge.js";
import { createOpenClawChannelMcpServer } from "./channel-server.js";
import { createChannelMcpRuntime } from "./channel-server-runtime.js";
import { extractAttachmentsFromMessage } from "./channel-shared.js";
const ClaudeChannelNotificationSchema = z.object({
@@ -25,7 +24,7 @@ const ClaudePermissionNotificationSchema = z.object({
});
async function connectMcpWithoutGateway(params?: { claudeChannelMode?: "auto" | "on" | "off" }) {
const serverHarness = await createOpenClawChannelMcpServer({
const serverHarness = await createChannelMcpRuntime({
claudeChannelMode: params?.claudeChannelMode ?? "auto",
config: {} as never,
verbose: false,
@@ -84,22 +83,7 @@ function requireFirstMockCall(mock: { mock: { calls: unknown[][] } }, label: str
return call;
}
function gatewayRequestError(retryable: boolean): Error {
return Object.assign(new Error(retryable ? "gateway busy" : "auth failed"), {
name: "GatewayClientRequestError",
retryable,
});
}
describe("openclaw channel mcp server", () => {
test("keeps initial MCP gateway connection alive through transient connect errors", () => {
expect(
shouldRetryInitialMcpGatewayConnect(new Error("gateway request timeout for connect")),
).toBe(true);
expect(shouldRetryInitialMcpGatewayConnect(gatewayRequestError(true))).toBe(true);
expect(shouldRetryInitialMcpGatewayConnect(gatewayRequestError(false))).toBe(false);
});
describe("gateway-backed flows", () => {
describe("gateway integration", () => {
test("returns conversation and message payloads in primary MCP content", async () => {

View File

@@ -1,11 +1,5 @@
// Channel MCP server wires channel bridge tools into an MCP server instance.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { VERSION } from "../version.js";
import { OpenClawChannelBridge } from "./channel-bridge.js";
import { ClaudePermissionRequestSchema, type ClaudeChannelMode } from "./channel-shared.js";
import { getChannelMcpCapabilities, registerChannelMcpTools } from "./channel-tools.js";
import { createChannelMcpRuntime } from "./channel-server-runtime.js";
/**
* MCP stdio server assembly for OpenClaw channel conversations.
@@ -13,75 +7,11 @@ import { getChannelMcpCapabilities, registerChannelMcpTools } from "./channel-to
* This module wires config, the Gateway bridge, protocol notifications, and
* registered tools into a lifecycle that callers can either embed or serve.
*/
export { OpenClawChannelBridge } from "./channel-bridge.js";
/** Options accepted by the channel MCP server factory and stdio entry point. */
type OpenClawMcpServeOptions = {
gatewayUrl?: string;
gatewayToken?: string;
gatewayPassword?: string;
config?: OpenClawConfig;
claudeChannelMode?: ClaudeChannelMode;
verbose?: boolean;
};
async function resolveMcpConfig(config: OpenClawConfig | undefined): Promise<OpenClawConfig> {
if (config) {
return config;
}
const { getRuntimeConfig } = await import("../config/config.js");
return getRuntimeConfig();
}
/** Create an in-process channel MCP server plus explicit start and close hooks. */
export async function createOpenClawChannelMcpServer(opts: OpenClawMcpServeOptions = {}): Promise<{
server: McpServer;
bridge: OpenClawChannelBridge;
start: () => Promise<void>;
close: () => Promise<void>;
}> {
const cfg = await resolveMcpConfig(opts.config);
const claudeChannelMode = opts.claudeChannelMode ?? "auto";
const capabilities = getChannelMcpCapabilities(claudeChannelMode);
const server = new McpServer(
{ name: "openclaw", version: VERSION },
capabilities ? { capabilities } : undefined,
);
const bridge = new OpenClawChannelBridge(cfg, {
gatewayUrl: opts.gatewayUrl,
gatewayToken: opts.gatewayToken,
gatewayPassword: opts.gatewayPassword,
claudeChannelMode,
verbose: opts.verbose ?? false,
});
bridge.setServer(server);
server.server.setNotificationHandler(ClaudePermissionRequestSchema, async ({ params }) => {
await bridge.handleClaudePermissionRequest({
requestId: params.request_id,
toolName: params.tool_name,
description: params.description,
inputPreview: params.input_preview,
});
});
registerChannelMcpTools(server, bridge);
return {
server,
bridge,
start: async () => {
await bridge.start();
},
close: async () => {
await bridge.close();
await server.close();
},
};
}
type OpenClawMcpServeOptions = NonNullable<Parameters<typeof createChannelMcpRuntime>[0]>;
/** Serve the channel MCP server over stdio until transport or process shutdown. */
export async function serveOpenClawChannelMcp(opts: OpenClawMcpServeOptions = {}): Promise<void> {
const { server, start, close } = await createOpenClawChannelMcpServer(opts);
const { server, start, close } = await createChannelMcpRuntime(opts);
const transport = new StdioServerTransport();
let shuttingDown = false;

View File

@@ -28,6 +28,10 @@ describe("check-deadcode-exports", () => {
expect(knipConfig.workspaces["."].entry).toContain("src/agents/sessions/extension-sdk.ts!");
});
it("models the spawned system-agent MCP stdio entry", () => {
expect(knipConfig.workspaces["."].entry).toContain("src/mcp/openclaw-tools-serve.ts!");
});
it("parses all compact export sections and expands symbol lists", () => {
expect(
parseKnipCompactUnusedExports(`