Spaces:
Sleeping
Sleeping
File size: 4,885 Bytes
cec8267 b7c3fee cec8267 b7c3fee 1f9050d b7c3fee 1f9050d cec8267 1f9050d b7c3fee 1f9050d b7c3fee 1f9050d b7c3fee 1f9050d cec8267 b7c3fee cec8267 b7c3fee cec8267 b7c3fee cec8267 b7c3fee 1f9050d b7c3fee 1f9050d b7c3fee cec8267 b7c3fee cec8267 1f9050d cec8267 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #!/usr/bin/env bun
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { z } from "zod";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
import { createServer, IncomingMessage, ServerResponse } from "node:http";
import { URL } from "node:url";
import { searchDatasets, fetchDatasetAggregate, textContent } from "./utils.ts";
const SearchSchema = z.object({
query: z
.string()
.describe(
"Search query for datasets (e.g., 'nlp sentiment analysis', 'computer vision', 'question answering')",
),
});
const FetchSchema = z.object({
id: z
.string()
.describe(
"Unique dataset identifier (e.g., 'squad', 'imdb', 'cfahlgren1/hub-stats')",
),
});
const TOOL_DEFS: Tool[] = [
{
name: "search",
description: "Search for datasets on Hugging Face Hub",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description:
"Search query for datasets (e.g., 'nlp sentiment analysis', 'computer vision', 'question answering')",
},
},
required: ["query"],
},
},
{
name: "fetch",
description:
"Retrieve full information and sample data for a specific dataset",
inputSchema: {
type: "object",
properties: {
id: {
type: "string",
description:
"Unique dataset identifier (e.g., 'squad', 'imdb', 'cfahlgren1/hub-stats')",
},
},
required: ["id"],
},
},
];
const server = new Server(
{ name: "dataset-viewer-mcp", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOL_DEFS }));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case "search": {
const validatedArgs = SearchSchema.parse(args);
const { query } = validatedArgs;
const results = await searchDatasets(query);
return textContent({ results });
}
case "fetch": {
const validatedArgs = FetchSchema.parse(args);
const { id: datasetId } = validatedArgs;
const fetchResult = await fetchDatasetAggregate(datasetId);
return textContent(fetchResult);
}
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true,
};
}
});
async function main() {
const port = Number(process.env.PORT) || 3000;
const transports = new Map<string, SSEServerTransport>();
const httpServer = createServer(async (req: IncomingMessage, res: ServerResponse) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
const url = new URL(req.url || "", `http://localhost:${port}`);
if (req.method === "OPTIONS") {
res.writeHead(204);
res.end();
return;
}
if (url.pathname === "/sse") {
if (req.method === "GET") {
const transport = new SSEServerTransport("/sse", res);
transport.onclose = () => transports.delete(transport.sessionId);
await server.connect(transport);
transports.set(transport.sessionId, transport);
return;
}
if (req.method === "POST") {
const sessionId = url.searchParams.get("sessionId");
if (!sessionId) {
res.writeHead(400).end("Missing sessionId");
return;
}
const transport = transports.get(sessionId);
if (!transport) {
res.writeHead(404).end("Session not found");
return;
}
try {
await transport.handlePostMessage(req, res);
} catch (error) {
console.error("Error handling POST message:", error);
if (!res.headersSent) {
res.writeHead(500).end("Internal Server Error");
}
}
return;
}
}
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({
name: "Dataset Viewer MCP Server",
version: "1.0.0",
transport: "SSE",
endpoint: "/sse",
usage: "GET /sse for SSE connection, POST /sse?sessionId=<id> for messages"
}));
});
httpServer.listen(port, () => {
console.log(`Dataset Viewer MCP server running on http://localhost:${port}/sse`);
});
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});
|