import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
ListPromptsRequestSchema,
GetPromptRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import os from "node:os";
import express from "express";
import { sysinfoTools, handleSysinfoTool } from "./tools/sysinfo.js";
import { fileManagerTools, handleFileManagerTool } from "./tools/fileManager.js";
/**
* Functions to create a new server instance for each connection (needed for SSE)
*/
function createServer() {
const s = new Server(
{
name: "mcp-server-sysinfo",
version: "1.2.0",
},
{
capabilities: {
tools: {},
resources: {},
prompts: {},
},
}
);
s.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [...sysinfoTools, ...fileManagerTools],
}));
s.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
const res = await handleSysinfoTool(name, args) || await handleFileManagerTool(name, args);
if (res) return res;
throw new Error(`Unknown tool: ${name}`);
});
s.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [{ uri: "system://os_info", name: "Static OS Information", mimeType: "application/json" }],
}));
s.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === "system://os_info") {
return {
contents: [{
uri: "system://os_info",
mimeType: "application/json",
text: JSON.stringify({ platform: os.platform(), release: os.release(), arch: os.arch(), hostname: os.hostname(), type: os.type() }, null, 2),
}],
};
}
throw new Error(`Unknown resource: ${request.params.uri}`);
});
s.setRequestHandler(ListPromptsRequestSchema, async () => ({
prompts: [{ name: "system_health_check", description: "System Health Check" }],
}));
s.setRequestHandler(GetPromptRequestSchema, async (request) => {
if (request.params.name === "system_health_check") {
return {
messages: [{ role: "user", content: { type: "text", text: "Analyze system health..." } }],
};
}
throw new Error(`Unknown prompt: ${request.params.name}`);
});
return s;
}
/**
* Start the server. Support both Stdio and SSE transports.
*/
async function main() {
const isSSE = process.argv.includes("--sse");
if (isSSE) {
const app = express();
app.get("/sse", async (req, res) => {
console.error("New SSE connection established");
const transport = new SSEServerTransport("/messages", res);
const connectionServer = createServer();
await connectionServer.connect(transport);
req.on("close", () => {
console.error("SSE connection closed");
connectionServer.close();
});
});
app.post("/messages", async (req, res) => {
// Note: In a real multi-user SSE, we'd need to route messages to the correct transport instance.
// For now, this is simpler for local dev.
res.status(400).send("Message routing not implemented for multi-session SSE. Use Stdio for Claude Desktop.");
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.error(`MCP Server running on SSE at http://localhost:${PORT}/sse`);
});
} else {
const transport = new StdioServerTransport();
const stdioServer = createServer();
await stdioServer.connect(transport);
console.error("MCP Server running on stdio");
}
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});