import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
const BASE_URL = process.env.API_BASE_URL || "https://petstore.swagger.io/v2";
const server = new Server(
{ name: "mcp-api-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// --- Expose MCP Tools ---
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "findpetsbystatus",
description: "Finds Pets by status",
inputSchema: {
type: "object",
properties: {
"status": { type: "string", description: "Status values that need to be considered for filter" },
},
required: ["status"],
},
},
{
name: "getpetbyid",
description: "Find pet by ID",
inputSchema: {
type: "object",
properties: {
"petId": { type: "number", description: "ID of pet to return" },
},
required: ["petId"],
},
},
{
name: "deletepet",
description: "Deletes a pet",
inputSchema: {
type: "object",
properties: {
"petId": { type: "number", description: "Pet id to delete" },
},
required: ["petId"],
},
},
],
}));
// --- Tool Execution Handlers ---
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args = {} } = request.params;
const headers: Record<string, string> = {
"Content-Type": "application/json",
"User-Agent": "MCP-OpenAPI-Client/1.0",
};
switch (name) {
case "findpetsbystatus": {
let targetPath = `/pet/findByStatus`;
const queryParams = new URLSearchParams();
if (args.status !== undefined) queryParams.append("status", String(args.status));
if (queryParams.toString()) targetPath += "?" + queryParams.toString();
const response = await fetch(`${BASE_URL}${targetPath}`, { method: "GET", headers });
const responseText = await response.text();
return {
content: [
{ type: "text", text: `HTTP Status: ${response.status}\n${responseText}` }
],
isError: !response.ok,
};
}
case "getpetbyid": {
let targetPath = `/pet/${encodeURIComponent(String(args.petId ?? ""))}`;
const response = await fetch(`${BASE_URL}${targetPath}`, { method: "GET", headers });
const responseText = await response.text();
return {
content: [
{ type: "text", text: `HTTP Status: ${response.status}\n${responseText}` }
],
isError: !response.ok,
};
}
case "deletepet": {
let targetPath = `/pet/${encodeURIComponent(String(args.petId ?? ""))}`;
const response = await fetch(`${BASE_URL}${targetPath}`, { method: "DELETE", headers });
const responseText = await response.text();
return {
content: [
{ type: "text", text: `HTTP Status: ${response.status}\n${responseText}` }
],
isError: !response.ok,
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP OpenAPI Server listening over stdio...");
}
main().catch((err) => {
console.error("Server error:", err);
process.exit(1);
});