Skip to main content
Glama

MCP Harbor

by nomagicln
app.ts4.2 kB
#!/usr/bin/env node 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, McpError, ErrorCode, CallToolRequest, } from "@modelcontextprotocol/sdk/types.js"; import { HarborService } from "./services/harbor.service.js"; import { TOOL_DEFINITIONS } from "./definitions/tool.definitions.js"; import { config } from "dotenv"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import express from "express"; // Disable TLS/SSL certificate validation process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; // Load environment variables config(); // Parse command line arguments const argv = yargs(hideBin(process.argv)) .env("HARBOR") .options({ url: { type: "string", description: "Harbor API URL", demandOption: true, }, username: { type: "string", description: "Harbor username", demandOption: true, default: "admin", }, password: { type: "string", description: "Harbor password", demandOption: true, }, debug: { type: "boolean", description: "Enable debug mode", default: false, }, sse: { type: "boolean", description: "Enable SSE transport", default: false, }, port: { type: "number", description: "Port for SSE transport", default: 3000, }, }) .help() .parseSync(); // Use parseSync instead of argv // Initialize HarborService with command line arguments const harborService = new HarborService(argv.url, { username: argv.username, password: argv.password, }); const createServer: () => Promise<Server> = async (): Promise<Server> => { interface ToolDefinition { description: string; inputSchema: Record<string, unknown>; } interface Tool { name: string; description: string; inputSchema: Record<string, unknown>; } // Initialize the MCP server const server: Server = new Server( { name: "mcp-harbor", version: "1.0.0", }, { capabilities: { tools: TOOL_DEFINITIONS as Record<string, ToolDefinition>, }, } ); server.onerror = (error: Error): void => { console.error("[MCP Error]", error); console.error("[MCP Error Stack]", error.stack); if (error.cause) { console.error("[MCP Error Cause]", error.cause); } }; server.setRequestHandler( ListToolsRequestSchema, async (): Promise<{ tools: Tool[]; }> => ({ tools: Object.entries(TOOL_DEFINITIONS).map(([name, def]) => ({ name, description: def.description, inputSchema: def.inputSchema, })), }) ); server.setRequestHandler( CallToolRequestSchema, async (request: CallToolRequest) => { try { const args: Record<string, unknown> = request.params.arguments || {}; return await harborService.handleToolRequest(request.params.name, args); } catch (error: unknown) { if (error instanceof McpError) throw error; throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : "Unknown error occurred" ); } } ); return server; }; const server = await createServer(); // Check if SSE transport is enabled if (argv.sse) { console.info("[MCP Server] Using SSE transport"); const app = express(); let transport: SSEServerTransport | null = null; app.get("/sse", async (req, res) => { console.log("[MCP Server] SSE connection established"); transport = new SSEServerTransport("/messages", res); await server.connect(transport); }); app.post("/messages", (req, res) => { if (!transport) { res.status(400).send("No SSE connection established"); return; } transport.handlePostMessage(req, res); }); app.listen(argv.port, "0.0.0.0", () => { console.info(`[MCP Server] SSE server running on port ${argv.port}`); }); } else { await server.connect(new StdioServerTransport()); }

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/nomagicln/mcp-harbor'

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