UNPKG

@unifuncs/ufn-mcp-server

Version:

UniFuncs MCP Server

107 lines (106 loc) 3.55 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import express from "express"; import { z } from "zod"; import fetch from "node-fetch"; function getApiKey() { const apiKey = process.env.UNIFUNCS_API_KEY; if (!apiKey) { console.error("UNIFUNCS_API_KEY environment variable is not set"); process.exit(1); } return apiKey; } const UNIFUNCS_API_KEY = getApiKey(); const UNIFUNCS_API_BASE = "https://api.unifuncs.com"; async function request(method, url, data) { const response = await fetch(`${UNIFUNCS_API_BASE}/${url.replace(/^\//, "")}`, { method: method, body: JSON.stringify(data), headers: { "Content-Type": "application/json", Authorization: `Bearer ${UNIFUNCS_API_KEY}`, }, }); if (response.headers.get("Content-Type")?.includes("application/json")) { const result = (await response.json()); if (result.code !== 0) { throw new Error(result.message); } return result.data; } return response.text(); } async function handleWebSearch(params) { const data = await request("POST", "/api/web-search/search", params); return { content: [ { type: "text", text: JSON.stringify(data), }, ] }; } async function handleWebReader(params) { const content = await request("POST", "/api/web-reader/read", params); return { content: [ { type: "text", text: typeof content === "string" ? content : JSON.stringify(content), }, ], }; } // Server setup const server = new McpServer({ name: "mcp-server/unifuncs", version: "0.0.5", }); server.tool("web-search", { query: z.string(), freshness: z.enum(["Day", "Week", "Month", "Year"]).optional(), page: z.number().min(1).optional(), count: z.number().min(1).max(50).optional(), format: z.enum(["markdown", "text", "json"]).optional(), }, handleWebSearch); server.tool("web-reader", { url: z.string(), format: z.enum(["markdown"]).optional(), includeImages: z.boolean().optional(), linkSummary: z.boolean().optional(), }, handleWebReader); if (process.env.UNIFUNCS_SSE_SERVER || process.argv.includes("--sse")) { const app = express(); const transports = {}; app.get("/sse", async (_, res) => { const transport = new SSEServerTransport("/messages", res); transports[transport.sessionId] = transport; res.on("close", () => { delete transports[transport.sessionId]; }); await server.connect(transport); }); app.post("/messages", async (req, res) => { const sessionId = req.query.sessionId; const transport = transports[sessionId]; if (transport) { await transport.handlePostMessage(req, res); } else { res.status(400).send("No transport found for sessionId"); } }); const port = Number(process.env.UNIFUNCS_SSE_SERVER_PORT || 5656); app.listen(port, () => { console.log(`UniFuncs MCP Server running on http://localhost:${port}`); }); } else { const transport = new StdioServerTransport(); await server.connect(transport); console.log("UniFuncs MCP Server running on stdio"); }