Skip to main content
Glama
proxyServer.ts4.26 kB
import express from 'express'; import cors from 'cors'; import helmet from 'helmet'; import morgan from 'morgan'; import fetch from 'node-fetch'; import { config } from 'dotenv'; import { tools } from '../tools/index.js'; // 환경변수 로드 config(); const PROXY_PORT = process.env.PROXY_PORT || 3001; const MCP_SERVER_URL = process.env.MCP_SERVER_URL || 'http://localhost:3000'; const app = express(); // 미들웨어 설정 app.use(cors()); app.use(helmet()); app.use(express.json({ limit: '10mb' })); app.use(morgan('dev')); // 상태 확인 엔드포인트 app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', service: 'mcp-proxy', timestamp: new Date().toISOString(), }); }); // 사용 가능한 도구 목록 제공 엔드포인트 app.get('/tools', (req, res) => { const toolsList = Object.entries(tools).map(([name, tool]) => ({ name, description: tool.description, parameters: tool.parameters, })); res.json(toolsList); }); // MCP 엔드포인트 - 요청을 MCP 서버로 전달 app.post('/mcp', async (req, res) => { try { console.log('프록시 서버: MCP 요청 수신', req.body.name); // MCP 서버로 요청 전달 const response = await fetch(`${MCP_SERVER_URL}/mcp`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(req.body), }); if (!response.ok) { const errorText = await response.text(); console.error('MCP 서버 응답 오류:', response.status, errorText); return res.status(response.status).send(errorText); } const data = await response.json(); console.log('프록시 서버: MCP 응답 전달'); res.json(data); } catch (error) { console.error('프록시 서버 오류:', error); res.status(500).json({ error: `프록시 서버 오류: ${(error as Error).message}`, }); } }); // API 프록시 엔드포인트 app.all('/api/*', async (req, res) => { try { console.log(req.path, req.headers); const originalUrl = (req.headers['x-original-url'] as string).replace('cc', 'c'); if (!originalUrl) { return res.status(400).json({ error: 'X-Original-Url header is missing' }); } // API 경로 추출 (예: /api/rest/api/space → /rest/api/space) const apiPath = req.path.replace('/api', ''); // 오리지널 URL과 API 경로를 결합 const targetUrl = new URL(apiPath, originalUrl); // Object.entries 사용 Object.entries(req.query).forEach(([key, value]) => { value && targetUrl.searchParams.append(key, value?.toString()); }); const targetUrlString = targetUrl.toString(); console.log(`프록시 요청: ${req.method} ${targetUrlString}`); // 헤더 준비 (X-Original-Url은 제외) const headers: Record<string, string> = { ...(req.headers as Record<string, string>) }; delete headers['x-original-url']; delete headers['host']; // Confluence로 요청 전달 const response = await fetch(targetUrl, { method: req.method, headers, body: ['POST', 'PUT', 'PATCH'].includes(req.method) ? JSON.stringify(req.body) : undefined, }); // 응답 처리 const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { const data = await response.json(); return res.status(response.status).json(data); } else { const text = await response.text(); return res.status(response.status).send(text); } } catch (error) { console.error('API 프록시 오류:', error); res.status(500).json({ error: `API 프록시 오류: ${(error as Error).message}`, }); } }); // 서버 시작 const startProxyServer = () => { app.listen(PROXY_PORT, () => { console.log(`MCP 프록시 서버가 포트 ${PROXY_PORT}에서 실행 중입니다`); console.log(`MCP 엔드포인트: http://localhost:${PROXY_PORT}/mcp`); console.log(`API 프록시 엔드포인트: http://localhost:${PROXY_PORT}/api/*`); console.log(`도구 목록: http://localhost:${PROXY_PORT}/tools`); console.log(`MCP 서버 URL: ${MCP_SERVER_URL}`); }); }; // 서버 시작 함수 실행 startProxyServer();

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/minhoyooDEV/confluence-mcp-server'

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