Skip to main content
Glama
server.ts7.08 kB
/** * OssHub MCP Server * Universal Object Storage MCP Server */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import express from "express"; import path from "path"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; import { ProviderManager } from "./providers/manager.js"; import { ProviderRegistry } from "./providers/interface.js"; import { resolveTransport, resolvePort, resolveSourceConfigs, redactSourceConfig } from "./config/env.js"; import { registerTools } from "./tools/index.js"; // Create __dirname equivalent for ES modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Load package.json to get version let packageJson: { version: string }; try { const packageJsonPath = path.join(__dirname, "..", "package.json"); packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8")); } catch { packageJson = { version: "0.1.0" }; } // Server info export const SERVER_NAME = "OssHub MCP Server"; export const SERVER_VERSION = packageJson.version; /** * Generate ASCII art banner with version information */ export function generateBanner(version: string): string { return ` ___ _ _ _ / _ \\ | | | | | | | | | |___ ___ | |_| |_ _| |__ | | | / __/ __|| _ | | | | '_ \\ | |_| \\__ \\__ \\| | | | |_| | |_) | \\___/|___/___/|_| |_|\\__,_|_.__/ v${version} - Universal Object Storage MCP Server `; } /** * Initialize and start the OssHub server */ export async function main(): Promise<void> { try { // Resolve source configurations const sourceConfigsData = await resolveSourceConfigs(); if (!sourceConfigsData) { const samples = ProviderRegistry.getAllSampleEndpoints(); const sampleFormats = Object.entries(samples) .map(([id, endpoint]) => ` - ${id}: ${endpoint}`) .join("\n"); console.error(` ERROR: Storage source configuration is required. Please provide configuration in one of these ways (in order of priority): 1. TOML config file: --config=path/to/osshub.toml or ./osshub.toml 2. Environment variables: - OSSHUB_TYPE: Provider type (obs, oss, s3, cos, minio) - OSSHUB_ENDPOINT: Service endpoint URL - OSSHUB_ACCESS_KEY: Access Key ID - OSSHUB_SECRET_KEY: Secret Access Key - OSSHUB_REGION: Region (optional) Example endpoint formats: ${sampleFormats} Example TOML config (osshub.toml): [[sources]] id = "my_obs" type = "obs" endpoint = "https://obs.cn-east-2.myhuaweicloud.com" access_key = "your-access-key" secret_key = "your-secret-key" region = "cn-east-2" See documentation for more details on configuring storage sources. `); process.exit(1); } // Create provider manager and connect to storage service(s) const providerManager = new ProviderManager(); const sources = sourceConfigsData.sources; console.error(`Configuration source: ${sourceConfigsData.source}`); console.error(`Connecting to ${sources.length} storage source(s)...`); for (const source of sources) { console.error(` - ${redactSourceConfig(source)}`); } await providerManager.connectWithSources(sources); console.error("Connected to all storage sources"); // Create MCP server factory function const createServer = () => { const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION, }); // Register tools registerTools(server, sourceConfigsData.tools); return server; }; // Resolve transport type const transportData = resolveTransport(); const port = transportData.type === "http" ? resolvePort().port : null; // Print banner console.error(generateBanner(SERVER_VERSION)); // Print source summary console.error("Registered sources:"); for (const source of sources) { console.error(` - ${source.id} (${source.type})`); } console.error(""); // Set up transport-specific server if (transportData.type === "http") { // HTTP transport: Start Express server with MCP endpoint const app = express(); app.use(express.json()); // CORS and security headers app.use((req, res, next) => { const origin = req.headers.origin; if (origin && !origin.startsWith("http://localhost") && !origin.startsWith("https://localhost")) { return res.status(403).json({ error: "Forbidden origin" }); } res.header("Access-Control-Allow-Origin", origin || "http://localhost"); res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.header("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id"); res.header("Access-Control-Allow-Credentials", "true"); if (req.method === "OPTIONS") { return res.sendStatus(200); } next(); }); // Health check endpoint app.get("/healthz", (req, res) => { res.status(200).send("OK"); }); // Sources API endpoint app.get("/api/sources", (req, res) => { const sources = ProviderManager.getAllSourceConfigs().map((s) => ({ id: s.id, type: s.type, endpoint: s.endpoint, region: s.region, })); res.json({ sources }); }); // MCP endpoint (stateless mode) app.get("/mcp", (req, res) => { res.status(405).json({ error: "Method Not Allowed", message: "SSE streaming is not supported in stateless mode. Use POST requests.", }); }); app.post("/mcp", async (req, res) => { try { const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true, }); const server = createServer(); await server.connect(transport); await transport.handleRequest(req, res, req.body); } catch (error) { console.error("Error handling request:", error); if (!res.headersSent) { res.status(500).json({ error: "Internal server error" }); } } }); // Start HTTP server app.listen(port, "0.0.0.0", () => { console.error(`MCP server endpoint at http://0.0.0.0:${port}/mcp`); console.error(`Health check at http://0.0.0.0:${port}/healthz`); }); } else { // STDIO transport const server = createServer(); const transport = new StdioServerTransport(); await server.connect(transport); console.error("MCP server running on stdio"); process.on("SIGINT", async () => { console.error("Shutting down..."); await transport.close(); process.exit(0); }); } } catch (err) { console.error("Fatal error:", err); process.exit(1); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zq940222/OssHub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server