Is there a way to access the JSON schema object from the context?
I want to make an MCP server for the OpenAPI documentation using elysia-mcp.
I'm currently stuck with a separate app:
import { mcp } from "elysia-mcp";
import { env } from "./core/env";
import { OpenAPIToolGenerator } from "mcp-from-openapi";
import { z } from "zod";
export const opeapiMCP = mcp({
basePath: "/openapi",
enableJsonResponse: true,
serverInfo: {
name: "Project API Documentation MCP",
version: "unknown",
},
async setupServer(server) {
const spec = (await fetch(`${env.BASE_API_URL}/openapi.json`).then((res) =>
res.json()
)) as object;
const generator = await OpenAPIToolGenerator.fromJSON(spec);
const tools = await generator.generateTools();
for (const tool of tools) {
server.registerTool(
tool.name,
{
description: tool.description,
inputSchema: z.fromJSONSchema(tool.inputSchema),
},
async (args) => {
let path = tool.metadata.path;
const headers: Record<string, string> = { "Content-Type": "application/json" };
const query: Record<string, string> = {};
const body: Record<string, unknown> = {};
for (const { inputKey, key, type } of tool.mapper) {
const value = (args as Record<string, unknown>)[inputKey];
if (value === undefined) continue;
if (type === "path") path = path.replace(`{${key}}`, String(value));
else if (type === "query") query[key] = String(value);
else if (type === "header") headers[key] = String(value);
else if (type === "body") body[key] = value;
}
const qs = new URLSearchParams(query).toString();
const url = `${env.BASE_API_URL}${path}${qs ? `?${qs}` : ""}`;
const res = await fetch(url, {
method: tool.metadata.method.toUpperCase(),
headers,
...(Object.keys(body).length && { body: JSON.stringify(body) }),
});
const text = await res.text();
return {
content: [{ type: "text" as const, text }],
isError: !res.ok,
};
}
);
}
},
});
If I can access the object, I would do something like this:
import OpenAPI from "@elysiajs/openapi";
import z from "zod";
import packageJson from "../../package.json";
export const openapi = OpenAPI({
path: "/docs",
specPath: "/openapi.json",
mapJsonSchema: {
zod: z.toJSONSchema,
},
documentation: {
info: {
title: packageJson.name,
version: packageJson.version,
description: packageJson.description,
},
},
// @ts-expect-error - elysia didnt type this yet
scalar: {
defaultHttpClient: {
targetKey: "js",
clientKey: "fetch",
},
},
}).use((c) => {
const { spec } = c;
return mcp({
basePath: "/openapi",
enableJsonResponse: true,
serverInfo: {
name: "finals-project API Documentation MCP",
version: "unknown",
},
async setupServer(server) {
const generator = await OpenAPIToolGenerator.fromJSON(spec);
const tools = await generator.generateTools();
for (const tool of tools) {
server.registerTool(
tool.name,
{
description: tool.description,
inputSchema: z.fromJSONSchema(tool.inputSchema),
},
async (args) => {
let path = tool.metadata.path;
const headers: Record<string, string> = { "Content-Type": "application/json" };
const query: Record<string, string> = {};
const body: Record<string, unknown> = {};
for (const { inputKey, key, type } of tool.mapper) {
const value = (args as Record<string, unknown>)[inputKey];
if (value === undefined) continue;
if (type === "path") path = path.replace(`{${key}}`, String(value));
else if (type === "query") query[key] = String(value);
else if (type === "header") headers[key] = String(value);
else if (type === "body") body[key] = value;
}
const qs = new URLSearchParams(query).toString();
const url = `${env.BASE_API_URL}${path}${qs ? `?${qs}` : ""}`;
const res = await fetch(url, {
method: tool.metadata.method.toUpperCase(),
headers,
...(Object.keys(body).length && { body: JSON.stringify(body) }),
});
const text = await res.text();
return {
content: [{ type: "text" as const, text }],
isError: !res.ok,
};
}
);
}
},
});
});
Is there a way to access the JSON schema object from the context?
I want to make an MCP server for the OpenAPI documentation using elysia-mcp.
I'm currently stuck with a separate app:
If I can access the object, I would do something like this: