// Planu — MCP Server Detector
// SPEC-016b: Detects if a project is an MCP server by checking dependencies,
// transport patterns, and tool registration calls.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
// === Package detection ===
async function loadPackageJson(projectPath) {
    try {
        const content = await readFile(join(projectPath, 'package.json'), 'utf-8');
        return JSON.parse(content);
    }
    catch {
        return {};
    }
}
function allDeps(pkg) {
    return [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
}
async function readSourceFiles(projectPath) {
    const candidates = ['index.ts', 'index.js', 'server.ts', 'server.js', 'src/index.ts'];
    const parts = [];
    for (const file of candidates) {
        try {
            const content = await readFile(join(projectPath, file), 'utf-8');
            parts.push(content);
        }
        catch {
            // ignore missing files
        }
    }
    return parts.join('\n');
}
// === MCP detection ===
/**
 * Returns true if the project is an MCP server.
 * Criteria: has @modelcontextprotocol/sdk dependency OR uses MCP transport classes.
 */
export async function detectIsMcpServer(projectPath) {
    const pkg = await loadPackageJson(projectPath);
    const deps = allDeps(pkg);
    if (deps.some((d) => d.includes('@modelcontextprotocol'))) {
        return true;
    }
    const source = await readSourceFiles(projectPath);
    return (source.includes('StdioServerTransport') ||
        source.includes('SSEServerTransport') ||
        source.includes('StreamableHTTPServerTransport') ||
        source.includes('McpServer') ||
        source.includes('server.tool(') ||
        source.includes('setRequestHandler'));
}
/**
 * Detect which transport the MCP server uses.
 */
export async function detectMcpTransport(projectPath) {
    const source = await readSourceFiles(projectPath);
    if (source.includes('StreamableHTTPServerTransport') || source.includes('http-streamable')) {
        return 'http-streamable';
    }
    if (source.includes('SSEServerTransport') || source.includes('SseServerTransport')) {
        return 'sse';
    }
    return 'stdio';
}
/**
 * Detect tool names registered in the MCP server source code.
 */
export async function detectMcpToolNames(projectPath) {
    const source = await readSourceFiles(projectPath);
    const toolNames = [];
    // Match patterns like: server.tool("tool_name", ...) or .tool('tool_name', ...)
    const toolCallPattern = /\.tool\(["']([^"']+)["']/g;
    let match = toolCallPattern.exec(source);
    while (match !== null) {
        const name = match[1];
        if (name && !toolNames.includes(name)) {
            toolNames.push(name);
        }
        match = toolCallPattern.exec(source);
    }
    return toolNames;
}
/**
 * Convenience check using project knowledge (no file I/O).
 * Used from tool handlers that already have knowledge loaded.
 */
export function isMcpServerProject(knowledge) {
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    const stackLower = (knowledge.stack ?? []).map((s) => s.toLowerCase());
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    const toolingStr = JSON.stringify(knowledge.tooling ?? {}).toLowerCase();
    return (stackLower.some((s) => s.includes('mcp') || s.includes('@modelcontextprotocol')) ||
        toolingStr.includes('modelcontextprotocol') ||
        toolingStr.includes('@modelcontextprotocol') ||
        // also check framework
        (knowledge.framework?.toLowerCase().includes('mcp') ?? false));
}
//# sourceMappingURL=mcp-server-detector.js.map