diff --git a/packages/gitea-mcp/src/index.ts b/packages/gitea-mcp/src/index.ts index d125f60..7ddc73d 100644 --- a/packages/gitea-mcp/src/index.ts +++ b/packages/gitea-mcp/src/index.ts @@ -15,10 +15,10 @@ import { z } from "zod"; import axios from "axios"; const GITEA_HOST = process.env.GITEA_HOST || "https://git.infra.mintel.me"; -const GITEA_ACCESS_TOKEN = process.env.GITEA_ACCESS_TOKEN; +const GITEA_ACCESS_TOKEN = process.env.GITEA_ACCESS_TOKEN || process.env.GITEA_TOKEN; if (!GITEA_ACCESS_TOKEN) { - console.error("Warning: GITEA_ACCESS_TOKEN environment variable is missing. Pipeline tools will return unauthorized errors."); + console.error("Warning: Neither GITEA_ACCESS_TOKEN nor GITEA_TOKEN environment variable is set. Pipeline tools will return unauthorized errors."); } const giteaClient = axios.create({ @@ -829,32 +829,42 @@ async function pollSubscriptions() { async function run() { - const app = express(); - let transport: SSEServerTransport | null = null; + const isStdio = process.argv.includes('--stdio'); - app.get('/sse', async (req, res) => { - console.error('New SSE connection established'); - transport = new SSEServerTransport('/message', res); + if (isStdio) { + const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); + const transport = new StdioServerTransport(); await server.connect(transport); - }); + console.error('Gitea MCP server is running on stdio'); + } else { + const app = express(); + let transport: SSEServerTransport | null = null; - app.post('/message', async (req, res) => { - if (!transport) { - res.status(400).send('No active SSE connection'); - return; - } - await transport.handlePostMessage(req, res); - }); + app.get('/sse', async (req, res) => { + console.error('New SSE connection established'); + transport = new SSEServerTransport('/message', res); + await server.connect(transport); + }); - const PORT = process.env.GITEA_MCP_PORT || 3001; - app.listen(PORT, () => { - console.error(`Gitea MCP Native Server running on http://localhost:${PORT}/sse`); - }); + app.post('/message', async (req, res) => { + if (!transport) { + res.status(400).send('No active SSE connection'); + return; + } + await transport.handlePostMessage(req, res); + }); - // Start the background poller - pollSubscriptions(); + const PORT = process.env.GITEA_MCP_PORT || 3001; + app.listen(PORT, () => { + console.error(`Gitea MCP server running on http://localhost:${PORT}/sse`); + }); + + // Start the background poller only in SSE mode or if specifically desired + pollSubscriptions(); + } } + run().catch((error) => { console.error("Fatal error:", error); process.exit(1); diff --git a/packages/glitchtip-mcp/src/index.ts b/packages/glitchtip-mcp/src/index.ts index fff499f..a3a40bb 100644 --- a/packages/glitchtip-mcp/src/index.ts +++ b/packages/glitchtip-mcp/src/index.ts @@ -132,25 +132,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }); async function run() { - const app = express(); - let transport: SSEServerTransport | null = null; + const isStdio = process.argv.includes('--stdio'); - app.get('/sse', async (req, res) => { - transport = new SSEServerTransport('/message', res); + if (isStdio) { + const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); + const transport = new StdioServerTransport(); await server.connect(transport); - }); + console.error('GlitchTip MCP server is running on stdio'); + } else { + const app = express(); + let transport: SSEServerTransport | null = null; - app.post('/message', async (req, res) => { - if (!transport) { res.status(400).send('No active SSE connection'); return; } - await transport.handlePostMessage(req, res); - }); + app.get('/sse', async (req, res) => { + console.error('New SSE connection established'); + transport = new SSEServerTransport('/message', res); + await server.connect(transport); + }); - const PORT = process.env.GLITCHTIP_MCP_PORT || 3005; - app.listen(PORT, () => { - console.error(`GlitchTip MCP server running on http://localhost:${PORT}/sse`); - }); + app.post('/message', async (req, res) => { + if (!transport) { + res.status(400).send('No active SSE connection'); + return; + } + await transport.handlePostMessage(req, res); + }); + + const PORT = process.env.GLITCHTIP_MCP_PORT || 3005; + app.listen(PORT, () => { + console.error(`GlitchTip MCP server running on http://localhost:${PORT}/sse`); + }); + } } + run().catch((err) => { console.error("Fatal error:", err); process.exit(1); diff --git a/packages/memory-mcp/src/index.ts b/packages/memory-mcp/src/index.ts index 182514a..da70118 100644 --- a/packages/memory-mcp/src/index.ts +++ b/packages/memory-mcp/src/index.ts @@ -12,14 +12,6 @@ async function main() { const qdrantService = new QdrantMemoryService(process.env.QDRANT_URL || 'http://localhost:6333'); - // Initialize embedding model and Qdrant connection - try { - await qdrantService.initialize(); - } catch (e) { - console.error('Failed to initialize local dependencies. Exiting.'); - process.exit(1); - } - server.tool( 'store_memory', 'Store a new piece of knowledge/memory into the vector database. Use this to remember architectural decisions, preferences, aliases, etc.', @@ -71,10 +63,18 @@ async function main() { const isStdio = process.argv.includes('--stdio'); if (isStdio) { + // Connect Stdio FIRST to avoid handshake timeouts while loading model const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); const transport = new StdioServerTransport(); await server.connect(transport); console.error('Memory MCP server is running on stdio'); + + // Initialize dependency after connection + try { + await qdrantService.initialize(); + } catch (e) { + console.error('Failed to initialize local dependencies:', e); + } } else { const app = express(); let transport: SSEServerTransport | null = null; @@ -94,13 +94,19 @@ async function main() { }); const PORT = process.env.MEMORY_MCP_PORT || 3002; - app.listen(PORT, () => { - console.error(`Memory MCP server is running on http://localhost:${PORT}/sse`); + app.listen(PORT, async () => { + console.error(`Memory MCP server running on http://localhost:${PORT}/sse`); + // Initialize dependencies in SSE mode on startup + try { + await qdrantService.initialize(); + } catch (e) { + console.error('Failed to initialize local dependencies:', e); + } }); } } main().catch((error) => { - console.error('Fatal error in main():', error); + console.error('Fatal error:', error); process.exit(1); }); diff --git a/packages/serpbear-mcp/src/index.ts b/packages/serpbear-mcp/src/index.ts index cbfcab1..050dcd7 100644 --- a/packages/serpbear-mcp/src/index.ts +++ b/packages/serpbear-mcp/src/index.ts @@ -7,6 +7,7 @@ import { Tool, } from "@modelcontextprotocol/sdk/types.js"; import axios from "axios"; +import https from "https"; const SERPBEAR_BASE_URL = process.env.SERPBEAR_BASE_URL || "https://serpbear.infra.mintel.me"; const SERPBEAR_API_KEY = process.env.SERPBEAR_API_KEY; @@ -18,8 +19,12 @@ if (!SERPBEAR_API_KEY) { const serpbearClient = axios.create({ baseURL: `${SERPBEAR_BASE_URL}/api`, headers: { apiKey: SERPBEAR_API_KEY }, + httpsAgent: new https.Agent({ + rejectUnauthorized: false, + }), }); + // --- Tool Definitions --- const LIST_DOMAINS_TOOL: Tool = { name: "serpbear_list_domains", @@ -199,26 +204,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { // --- Express / SSE Server --- async function run() { - const app = express(); - let transport: SSEServerTransport | null = null; + const isStdio = process.argv.includes('--stdio'); - app.get('/sse', async (req, res) => { - console.error('New SSE connection established'); - transport = new SSEServerTransport('/message', res); + if (isStdio) { + const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); + const transport = new StdioServerTransport(); await server.connect(transport); - }); + console.error('SerpBear MCP server is running on stdio'); + } else { + const app = express(); + let transport: SSEServerTransport | null = null; - app.post('/message', async (req, res) => { - if (!transport) { res.status(400).send('No active SSE connection'); return; } - await transport.handlePostMessage(req, res); - }); + app.get('/sse', async (req, res) => { + console.error('New SSE connection established'); + transport = new SSEServerTransport('/message', res); + await server.connect(transport); + }); - const PORT = process.env.SERPBEAR_MCP_PORT || 3004; - app.listen(PORT, () => { - console.error(`SerpBear MCP server running on http://localhost:${PORT}/sse`); - }); + app.post('/message', async (req, res) => { + if (!transport) { + res.status(400).send('No active SSE connection'); + return; + } + await transport.handlePostMessage(req, res); + }); + + const PORT = process.env.SERPBEAR_MCP_PORT || 3004; + app.listen(PORT, () => { + console.error(`SerpBear MCP server running on http://localhost:${PORT}/sse`); + }); + } } + run().catch((err) => { console.error("Fatal error:", err); process.exit(1); diff --git a/packages/umami-mcp/src/index.ts b/packages/umami-mcp/src/index.ts index a085931..ba159f7 100644 --- a/packages/umami-mcp/src/index.ts +++ b/packages/umami-mcp/src/index.ts @@ -7,12 +7,17 @@ import { Tool, } from "@modelcontextprotocol/sdk/types.js"; import axios from "axios"; +import https from "https"; const UMAMI_BASE_URL = process.env.UMAMI_BASE_URL || "https://umami.infra.mintel.me"; const UMAMI_USERNAME = process.env.UMAMI_USERNAME; const UMAMI_PASSWORD = process.env.UMAMI_PASSWORD; const UMAMI_API_KEY = process.env.UMAMI_API_KEY; // optional if using API key auth +const httpsAgent = new https.Agent({ + rejectUnauthorized: false, +}); + if (!UMAMI_USERNAME && !UMAMI_API_KEY) { console.error("Warning: Neither UMAMI_USERNAME/PASSWORD nor UMAMI_API_KEY is set."); } @@ -28,12 +33,13 @@ async function getAuthHeaders(): Promise> { const res = await axios.post(`${UMAMI_BASE_URL}/api/auth/login`, { username: UMAMI_USERNAME, password: UMAMI_PASSWORD, - }); + }, { httpsAgent }); cachedToken = res.data.token; } return { Authorization: `Bearer ${cachedToken}` }; } + // --- Tool Definitions --- const LIST_WEBSITES_TOOL: Tool = { name: "umami_list_websites", @@ -147,7 +153,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({ server.setRequestHandler(CallToolRequestSchema, async (request) => { const headers = await getAuthHeaders(); - const api = axios.create({ baseURL: `${UMAMI_BASE_URL}/api`, headers }); + const api = axios.create({ baseURL: `${UMAMI_BASE_URL}/api`, headers, httpsAgent }); const now = Date.now(); @@ -236,24 +242,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { // --- Express / SSE Server --- async function run() { - const app = express(); - let transport: SSEServerTransport | null = null; + const isStdio = process.argv.includes('--stdio'); - app.get('/sse', async (req, res) => { - console.error('New SSE connection established'); - transport = new SSEServerTransport('/message', res); + if (isStdio) { + const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); + const transport = new StdioServerTransport(); await server.connect(transport); - }); + console.error('Umami MCP server is running on stdio'); + } else { + const app = express(); + let transport: SSEServerTransport | null = null; - app.post('/message', async (req, res) => { - if (!transport) { res.status(400).send('No active SSE connection'); return; } - await transport.handlePostMessage(req, res); - }); + app.get('/sse', async (req, res) => { + console.error('New SSE connection established'); + transport = new SSEServerTransport('/message', res); + await server.connect(transport); + }); - const PORT = process.env.UMAMI_MCP_PORT || 3003; - app.listen(PORT, () => { - console.error(`Umami MCP server running on http://localhost:${PORT}/sse`); - }); + app.post('/message', async (req, res) => { + if (!transport) { + res.status(400).send('No active SSE connection'); + return; + } + await transport.handlePostMessage(req, res); + }); + + const PORT = process.env.UMAMI_MCP_PORT || 3003; + app.listen(PORT, () => { + console.error(`Umami MCP server running on http://localhost:${PORT}/sse`); + }); + } } run().catch((err) => {