mcp-harbor
Version:
A Node.js application for connecting to Harbor and providing operations capabilities.
121 lines • 3.92 kB
JavaScript
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, } 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 = async () => {
// Initialize the MCP server
const server = new Server({
name: "mcp-harbor",
version: "1.0.0",
}, {
capabilities: {
tools: TOOL_DEFINITIONS,
},
});
server.onerror = (error) => {
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 () => ({
tools: Object.entries(TOOL_DEFINITIONS).map(([name, def]) => ({
name,
description: def.description,
inputSchema: def.inputSchema,
})),
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const args = request.params.arguments || {};
return await harborService.handleToolRequest(request.params.name, args);
}
catch (error) {
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 = 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());
}
//# sourceMappingURL=app.js.map