import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { PROJECT_NAME } from "./config/constants.js";
import { loadRuntimeConfig } from "./config/runtime.js";
import { registerTools, type RegisteredTool } from "./mcp/tools/registerTools.js";
import { PACKAGE_VERSION } from "./shared/version.js";
import { fromEnv, toSessionConfig } from "./shared/config/schema.js";
import { createToolGate } from "./shared/config/toolGate.js";
const runtime = loadRuntimeConfig();
export const server = new McpServer({ name: PROJECT_NAME, version: PACKAGE_VERSION });
let registeredTools: RegisteredTool[] | undefined;
async function ensureTools(): Promise<RegisteredTool[]> {
if (registeredTools) {
return registeredTools;
}
const envConfig = fromEnv();
const session = toSessionConfig(envConfig);
const tools = await registerTools(server.server, runtime, session);
const gate = createToolGate();
const filtered = gate.filter(tools, (tool, detail) => {
const reason = detail.reason === "deny_list" ? "deny" : "allow";
console.warn("tool_gate_skipped", { name: tool.name, reason });
});
for (const tool of filtered) {
server.registerTool(
tool.name,
{
title: tool.name,
description: tool.description,
inputSchema: tool.inputSchema,
annotations: tool.annotations
},
async (args) => {
const result = await tool.execute(args);
return {
content: [],
structuredContent: result,
isError: result.isError
};
}
);
}
registeredTools = filtered;
return filtered;
}
export async function start(): Promise<void> {
await ensureTools();
if (server.isConnected()) {
return;
}
const transport = new StdioServerTransport();
await server.connect(transport);
server.sendToolListChanged();
console.log("ready");
}
function isMainModule(): boolean {
if (!process.argv[1]) {
return false;
}
const entryPath = fileURLToPath(import.meta.url);
return entryPath === resolve(process.argv[1]);
}
if (isMainModule()) {
start().catch(error => {
const reason = error instanceof Error ? error.message : String(error);
console.error(reason);
process.exitCode = 1;
});
}