This commit is contained in:
bipproduction
2025-10-28 17:28:18 +08:00
parent 8a3eaa2193
commit b2f8dc3714
3 changed files with 17 additions and 12 deletions

View File

@@ -17,7 +17,7 @@ interface McpTool {
/** /**
* Convert OpenAPI 3.x JSON spec into MCP-compatible tool definitions (without run()). * Convert OpenAPI 3.x JSON spec into MCP-compatible tool definitions (without run()).
* Each tool corresponds to an endpoint, with metadata stored under `x-props`. * Hanya menyertakan endpoint yang memiliki tag berisi "mcp".
*/ */
export function convertOpenApiToMcpTools(openApiJson: any): McpTool[] { export function convertOpenApiToMcpTools(openApiJson: any): McpTool[] {
const tools: McpTool[] = []; const tools: McpTool[] = [];
@@ -28,10 +28,14 @@ export function convertOpenApiToMcpTools(openApiJson: any): McpTool[] {
if (path.startsWith("/mcp")) continue; if (path.startsWith("/mcp")) continue;
for (const [method, operation] of Object.entries<any>(methods as any)) { for (const [method, operation] of Object.entries<any>(methods as any)) {
const tags: string[] = Array.isArray(operation.tags) ? operation.tags : [];
// ✅ exclude semua yang tidak punya tag atau tag-nya tidak mengandung "mcp"
if (!tags.length || !tags.some(t => t.toLowerCase().includes("mcp"))) continue;
const rawName = _.snakeCase(operation.operationId || `${method}_${path}`) || "unnamed_tool"; const rawName = _.snakeCase(operation.operationId || `${method}_${path}`) || "unnamed_tool";
const name = cleanToolName(rawName); const name = cleanToolName(rawName);
const summary = operation.summary || `Execute ${method.toUpperCase()} ${path}`;
const description = const description =
operation.description || operation.description ||
operation.summary || operation.summary ||
@@ -51,9 +55,9 @@ export function convertOpenApiToMcpTools(openApiJson: any): McpTool[] {
method: method.toUpperCase(), method: method.toUpperCase(),
path, path,
operationId: operation.operationId, operationId: operation.operationId,
tag: Array.isArray(operation.tags) ? operation.tags[0] : undefined, tag: tags[0],
deprecated: operation.deprecated || false, deprecated: operation.deprecated || false,
summary: operation.summary, // ✅ tambahkan summary ke metadata summary: operation.summary,
}, },
inputSchema: { inputSchema: {
...schema, ...schema,
@@ -87,19 +91,18 @@ function cleanToolName(name: string): string {
.replace(/(^_|_$)/g, ""); .replace(/(^_|_$)/g, "");
} }
// === Contoh Pemakaian === /**
// import openApiJson from "./openapi.json"; * Ambil OpenAPI JSON dari endpoint dan konversi ke tools MCP
// const tools = convertOpenApiToMcpTools(openApiJson, "https://api.wibudev.com"); */
// console.log(JSON.stringify(tools, null, 2)); export async function getMcpTools() {
export async function getMcpTools(){
const data = await fetch(`${process.env.BUN_PUBLIC_BASE_URL}/docs/json`); const data = await fetch(`${process.env.BUN_PUBLIC_BASE_URL}/docs/json`);
const openApiJson = await data.json(); const openApiJson = await data.json();
const tools = convertOpenApiToMcpTools(openApiJson); const tools = convertOpenApiToMcpTools(openApiJson);
return tools; return tools;
} }
// === CLI Mode ===
if (import.meta.main) { if (import.meta.main) {
const tools = await getMcpTools(); const tools = await getMcpTools();
Bun.write("./tools.json", JSON.stringify(tools, null, 2)); await Bun.write("./tools.json", JSON.stringify(tools, null, 2));
} }

View File

@@ -96,6 +96,7 @@ const LayananRoute = new Elysia({
detail: { detail: {
summary: "Create Layanan KTP/KK", summary: "Create Layanan KTP/KK",
description: "Create a new service request for KTP or KK.", description: "Create a new service request for KTP or KK.",
tags: ["mcp"],
}, },
} }
) )
@@ -131,6 +132,7 @@ const LayananRoute = new Elysia({
detail: { detail: {
summary: "Cek Status KTP", summary: "Cek Status KTP",
description: "Retrieve the current status of a KTP/KK request by unique ID.", description: "Retrieve the current status of a KTP/KK request by unique ID.",
tags: ["mcp"],
}, },
} }
); );

View File

@@ -151,7 +151,7 @@ async function handleMCPRequestAsync(
// Elysia MCP Server // Elysia MCP Server
// ===================== // =====================
export const MCPRoute = new Elysia({ export const MCPRoute = new Elysia({
tags: ["MCP"] tags: ["MCP Server"]
}) })
.post("/mcp", async ({ request, set }) => { .post("/mcp", async ({ request, set }) => {
if (!tools.length) { if (!tools.length) {