import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
/**
* OpenAPI & API Documentation Tools
*/
export const generateOpenApiSpecSchema = {
name: "generate_openapi_spec",
description:
"Generate an OpenAPI 3.0 specification from the Code-MCP tool registry",
inputSchema: z.object({
title: z.string().optional().default("Code-MCP API"),
version: z.string().optional().default("1.0.0"),
serverUrl: z.string().optional().default("http://localhost:3000"),
}),
};
// This will be called with the tool registry from the server
export function generateOpenApiSpecHandler(
toolRegistry: Map<string, { schema: any; handler: any }>,
) {
return async (args: {
title?: string;
version?: string;
serverUrl?: string;
}) => {
const paths: any = {};
// Convert each tool to an OpenAPI path
for (const [name, { schema }] of toolRegistry.entries()) {
const jsonSchema = zodToJsonSchema(schema.inputSchema, { name: "input" });
paths[`/tools/${name}`] = {
post: {
summary: schema.description || name,
operationId: name,
tags: [getToolCategory(name)],
requestBody: {
required: true,
content: {
"application/json": {
schema: jsonSchema.definitions?.input || jsonSchema,
},
},
},
responses: {
"200": {
description: "Successful response",
content: {
"application/json": {
schema: {
type: "object",
properties: {
content: {
type: "array",
items: {
type: "object",
properties: {
type: { type: "string" },
text: { type: "string" },
},
},
},
},
},
},
},
},
"401": { description: "Unauthorized - Missing or invalid API key" },
"403": { description: "Forbidden - Insufficient permissions" },
"429": { description: "Too Many Requests - Rate limited" },
},
security: [{ ApiKeyAuth: [] }],
},
};
}
const spec = {
openapi: "3.0.3",
info: {
title: args.title || "Code-MCP API",
version: args.version || "1.0.0",
description:
"Code-MCP provides tools for code generation, analysis, and project management.",
},
servers: [
{
url: args.serverUrl || "http://localhost:3000",
description: "Local",
},
],
paths,
components: {
securitySchemes: {
ApiKeyAuth: {
type: "apiKey",
in: "header",
name: "x-api-key",
},
},
},
};
return {
content: [
{
type: "text",
text: `# OpenAPI 3.0 Specification\n\n\`\`\`yaml\n${toYaml(spec)}\n\`\`\``,
},
],
};
};
}
// Helper to categorize tools for OpenAPI tags
function getToolCategory(toolName: string): string {
if (toolName.includes("memory")) return "Memory";
if (toolName.includes("generate")) return "Generation";
if (
toolName.includes("analyze") ||
toolName.includes("lint") ||
toolName.includes("security")
)
return "Analysis";
if (toolName.includes("api_key") || toolName.includes("admin"))
return "Admin";
if (toolName.includes("file") || toolName.includes("search"))
return "Filesystem";
if (toolName.includes("config")) return "Configuration";
if (toolName.includes("scaffold") || toolName.includes("project"))
return "Project";
if (
toolName.includes("think") ||
toolName.includes("plan") ||
toolName.includes("debug")
)
return "Cognitive";
return "Tools";
}
// Simple YAML serializer (avoids adding another dependency)
function toYaml(obj: any, indent = 0): string {
const pad = " ".repeat(indent);
let result = "";
for (const [key, value] of Object.entries(obj)) {
if (value === null || value === undefined) continue;
if (typeof value === "object" && !Array.isArray(value)) {
result += `${pad}${key}:\n${toYaml(value, indent + 1)}`;
} else if (Array.isArray(value)) {
result += `${pad}${key}:\n`;
for (const item of value) {
if (typeof item === "object") {
result += `${pad}- \n${toYaml(item, indent + 2).replace(/^ /, "")}`;
} else {
result += `${pad}- ${JSON.stringify(item)}\n`;
}
}
} else {
result += `${pad}${key}: ${typeof value === "string" && value.includes(":") ? `"${value}"` : value}\n`;
}
}
return result;
}
export const usageStatsSchema = {
name: "get_usage_stats",
description: "Get tool usage statistics (Admin only)",
inputSchema: z.object({
userId: z.number().optional().describe("Filter by specific user ID"),
}),
};