mcp-server
mcp-server
팀의 엔지니어링 도구(Bitbucket, Jira, Confluence, ArgoCD)를 MCP를 지원하는 편집기(VS Code + Copilot, Claude Code 등)에 노출하는 TypeScript 기반 MCP 서버입니다.
**얇은 래퍼(thin wrapper)**입니다. Bitbucket/Jira/Confluence/ArgoCD와 직접 통신하지 않으며, 해당 서비스의 자격 증명을 저장하지 않습니다. 모든 것을 내부 백엔드 eng-api에 대한 HTTP 호출로 변환하며, eng-api는 이미 연결 및 자격 증명 문제를 해결했습니다.
VS Code (dev A) ─┐
VS Code (dev B) ─┼─► MCP Server ───► eng-api ───► Bitbucket / Jira / Confluence / ArgoCD
VS Code (dev C) ─┘ (este repo) (credenciales viven aquí)
Streamable HTTP HTTP
+ API key por dev장점: 개발자가 Bitbucket/Jira/Confluence/ArgoCD에 대한 개인 토큰이 필요 없습니다. 이 MCP 서버의 API 키 하나만 있으면 되며, 개별적으로 폐기 가능합니다.
1. 요구 사항
Node.js ≥ 22
ENG_API_BASE_URL(eng-api의 URL)에 대한 네트워크 액세스
Related MCP server: Work Integrations MCP
2. 로컬에서 실행하기
npm ci
cp .env.example .env # y rellena los valores (ver sección 3)
npm run dev # hot-reload, lee .env automáticamente기타 명령어:
명령어 | 설명 |
|
|
| TypeScript를 |
| 내보내기 없이 타입 검사 |
| 컴파일된 파일 시작 (환경 변수 사용, 파드에서 실행되는 것) |
|
|
서버가 실행 중인지 빠르게 확인:
curl http://localhost:3000/healthz
# {"status":"ok","server":"mcp-server","version":"0.1.0"}3. 설정 (.env)
모든 변수는 process.env에서 읽어옵니다. 필수 변수가 없거나 유효하지 않은 값이 있으면 프로세스가 시작되지 않으며 정확히 무엇을 수정해야 하는지 설명합니다.
변수 | 필수 | 기본값 | 설명 |
| ✅ | — | eng-api의 기본 URL, 마지막 슬래시 없음. |
| ✅ | — | 이 MCP 서버에 대한 개발자의 유효한 API 키 (§4 참조) |
| — |
| eng-api 호출당 타임아웃 (1000–120000) |
| — |
| 5xx/429/타임아웃 발생 시 추가 재시도 횟수 (0–5) |
| — |
| MCP 서버의 HTTP 포트 |
| — |
|
|
실패한 시작 예시 (의도적):
Configuración inválida: el MCP Server no puede arrancar.
- Falta la variable obligatoria ENG_API_BASE_URL. Debe apuntar a la URL base de eng-api, ej. https://eng-api.internal.example/api/v1
Revisa tu archivo .env (usa .env.example como plantilla) o el ConfigMap/Secret del Deployment.4. 인증: 개발자당 하나의 API 키
이 인증 계층은 MCP 서버 자체의 것이며 eng-api가 최종 서비스에 대해 사용하는 인증과는 독립적입니다.
키 생성
openssl rand -hex 32 # una por cada persona del equipo키 설정
MCP_DEV_API_KEYS는 네 가지 형식을 허용합니다 (키당 최소 24자, 중복 없음):
MCP_DEV_API_KEYS=<key1>,<key2> # CSV simple
MCP_DEV_API_KEYS=alice:<key1>,bob:<key2> # CSV etiquetado ← recomendado
MCP_DEV_API_KEYS=["<key1>","<key2>"] # JSON array
MCP_DEV_API_KEYS={"alice":"<key1>","bob":"<key2>"} # JSON objeto태그가 있는 형식을 사용하세요. 태그는 MCP 서버 로그에 표시되며 X-Mcp-Dev 헤더를 통해 eng-api로 전파되므로, 키를 노출하지 않고 누가 각 작업(예: argocd_sync_app)을 시작했는지 감사할 수 있습니다.
키 사용
MCP 클라이언트는 각 요청에 다음을 보내야 합니다:
Authorization: Bearer <API_KEY>(또는 대안으로 x-api-key: <API_KEY>). 비교는 SHA-256 다이제스트에 대해 타이밍 세이프(timing-safe) 합니다.
상황 | 응답 |
키 없음 |
|
유효하지 않음/폐기된 키 |
|
| 인증 없음 (Kubernetes 프로브용) |
누군가 폐기 = MCP_DEV_API_KEYS에서 해당 키를 제거하고 Deployment를 다시 시작합니다. 각 개발자가 자신의 키를 가지고 있으므로 나머지에는 영향을 미치지 않습니다. 프로덕션에서는 값을 Kubernetes Secret에 저장하고, 절대 ConfigMap에 저장하지 마십시오.
5. 도구 카탈로그
이름은 서비스 접두사를 가지며 동작 지향적입니다. 해당되는 경우 모든 것은 페이지네이션(page, pageSize 1~100, 기본값 25)을 지원합니다.
Bitbucket (읽기 전용)
도구 | 인수 | eng-api 엔드포인트 |
|
|
|
|
|
|
|
|
|
Jira
도구 | 인수 | eng-api 엔드포인트 |
|
|
|
|
|
|
|
|
|
Confluence (읽기 전용)
도구 | 인수 | eng-api 엔드포인트 |
|
|
|
|
|
|
ArgoCD
도구 | 인수 | eng-api 엔드포인트 |
|
|
|
|
|
|
|
|
|
주석 (MCP 클라이언트용 힌트)
도구 |
|
|
|
|
모든 읽기 도구 | ✅ | ❌ | ✅ | ✅ |
| ❌ | ❌ | ❌ | ✅ |
| ❌ | ✅ | ❌ | ✅ |
argocd_sync_app은 앱의 정확한 이름(와일드카드 또는 기본값 없음)을 요구하며, prune/dryRun은 명시적으로 요청하지 않는 한 false입니다.
eng-api 경로는 모두 src/client/routes.ts에 있습니다. eng-api가 경로를 변경하면 해당 파일만 수정하면 됩니다.
6. VS Code 설정 (각 개발자, 자신의 키 사용)
워크스페이스에 .vscode/mcp.json을 생성하거나 (또는 모든 프로젝트에서 사용하려면 사용자 mcp.json):
{
"inputs": [
{
"type": "promptString",
"id": "eng-mcp-api-key",
"description": "Tu API key personal del MCP Server de ingeniería",
"password": true
}
],
"servers": {
"eng": {
"type": "http",
"url": "https://<host-del-mcp-server>/mcp",
"headers": {
"Authorization": "Bearer ${input:eng-mcp-api-key}"
}
}
}
}VS Code는 처음에 키를 요청하고 암호화하여 저장합니다. 절대 커밋되지 않습니다. 그런 다음 Agent 모드에서 채팅을 열면 eng 서버 아래에 11개의 도구가 표시됩니다.
Claude Code (CLI)의 경우, 동등한 설정은 다음과 같습니다:
claude mcp add --transport http eng https://<host-del-mcp-server>/mcp \
--header "Authorization: Bearer <TU_API_KEY>"로컬에서는 URL을 http://localhost:3000/mcp로 바꾸십시오.
7. MCP Inspector로 테스트
npm run build && npm run start:local # en una terminal
npx @modelcontextprotocol/inspector # en otraInspector UI에서:
Transport Type:
Streamable HTTPURL:
http://localhost:3000/mcpAuthentication에서 Header Name
Authorization을 설정하고 Bearer Token에 API 키를 입력하세요.Connect → Tools 탭 → List Tools → 원하는 도구 테스트
curl로 직접 테스트할 수도 있습니다 (CI 또는 파드에서 유용):
KEY=<tu-api-key>
curl -s -X POST http://localhost:3000/mcp \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'도구 호출:
curl -s -X POST http://localhost:3000/mcp \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $KEY" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"bitbucket_list_prs",
"arguments":{"workspace":"acme","repoSlug":"web-frontend","state":"OPEN","pageSize":10}}}'8. Docker
docker build -t mcp-server:0.1.0 .
docker run --rm -p 3000:3000 \
-e ENG_API_BASE_URL="https://<eng-api>/api/v1" \
-e MCP_DEV_API_KEYS="alice:<key1>,bob:<key2>" \
mcp-server:0.1.0node:22-alpine 기반의 멀티-스테이지 이미지: 최종 이미지에는 dist/ + 프로덕션 종속성만 포함되며, node 사용자 (루트 아님)로 실행되고 자체 Node로 /healthz를 확인하는 HEALTHCHECK를 포함합니다 (curl/wget 없음).
Kubernetes용 (매니페스트는 이 저장소에 없음):
서버는 **무상태(stateless)**입니다. 메모리에 세션을 저장하지 않으므로 고정 세션 없이 N개의 복제본으로 확장됩니다.
프로브:
livenessProbe→GET /healthz,readinessProbe→GET /readyz(둘 다 인증 없음).MCP_DEV_API_KEYS는Secret에 있습니다.ENG_API_BASE_URL과 타임아웃은ConfigMap에 있을 수 있습니다.SIGTERM을 처리하여 HTTP 서버를 정상적으로 종료합니다 (최대 10초 드레인).
9. 새 서비스 또는 도구 추가 방법
패턴은 새 서비스를 추가해도 기존 항목을 건드리지 않도록 설계되었습니다. 가상의 Grafana 예시:
1. 경로 추가 src/client/routes.ts:
grafana: {
listDashboards: (): string => "/grafana/dashboards",
getDashboard: (uid: string): string => `/grafana/dashboards/${seg(uid)}`,
},2. src/tools/grafana.ts 생성 다른 것과 동일한 템플릿을 따름:
export function registerGrafanaTools(server: McpServer, deps: ToolDeps): void {
registerEngTool(server, deps, {
name: "grafana_list_dashboards", // prefijo de servicio + acción
title: "Grafana: listar dashboards",
description: "Qué hace y cuándo usarlo.",
inputSchema: { query: z.string().optional().describe('Texto a buscar. Ejemplo: "latencia checkout".'),
...paginationShape },
annotations: readOnlyAnnotations("Grafana: listar dashboards"),
describeOperation: (args) => `listar dashboards de Grafana`, // encaja tras "al …"
execute: (args, { client, context }) =>
client.get(engApiRoutes.grafana.listDashboards(), {
query: { query: args.query, ...paginationQuery(args) },
context,
}),
});
}3. 등록 TOOL_REGISTRARS의 src/server.ts:
const TOOL_REGISTRARS = [ …, registerGrafanaTools ];끝입니다. registerEngTool은 이미 무료로 제공합니다: Zod 검증, 응답 형식 지정, 대용량 페이로드 잘라내기, 오류 캡처 및 실행 가능한 메시지로의 변환, requestId가 있는 로깅.
새 도구에 대한 스타일 규칙:
이름
service_action_object, 소문자.스키마의 각 필드는
.describe()와 구체적인 예시 포함 — 모델이 도구를 호출하는 방법을 결정하기 위해 읽는 유일한 정보입니다.정직한 주석: 쓰기 작업이면
readOnlyHint: false, 무언가를 삭제할 수 있으면destructiveHint: true.파괴적인 작업에는 위험한 기본값 없음: 정확한 식별자를 요구하세요.
목록을 반환하는 모든 것에 페이지네이션 (
...paginationShape+paginationQuery(args))을 포함하세요.tools/에서 URL을 수동으로 생성하지 마세요. 항상engApiRoutes를 통해 사용하세요.
10. 오류 처리
어떤 도구도 맨몸의 "Error 500"을 반환하지 않습니다. 각 오류에는 무엇이 실패했는지, 무엇을 확인해야 하는지 및 eng-api 로그와 교차 참조하기 위한 requestId가 포함됩니다. 실제 예시:
No existe el recurso al obtener el estado de la aplicación boom (404). Verifica los identificadores
exactos (workspace/repo, key de issue, id de página, nombre de app) — distinguen mayúsculas. Si los
identificadores son correctos, la ruta de eng-api puede haber cambiado (src/client/routes.ts).
[requestId=8a4bf9e6-…, intentos=1, upstream=GET /argocd/applications/boom]
Respuesta de eng-api: {"error":"application not found"}상황 | MCP 서버의 동작 |
시간 초과 / 네트워크 오류 | 지수 백오프 + 지터( |
| 재시도( |
| 재시도하지 않음: 파라미터가 유효하지 않음 |
eng-api의 | MCP의 API 키가 아닌, eng-api의 자격 증명/권한 문제임을 명시 |
| 정확한 식별자와 |
| 상태 충돌(예: 이미 진행 중인 ArgoCD 동기화): 상태를 확인한 후 재시도 |
JSON이 아닌 응답 | 일반적으로 프록시가 HTML을 반환하는 경우: 경로가 존재하지 않을 가능성이 있음 |
대용량 페이로드 |
|
11. 프로젝트 구조
src/
├── index.ts # entrypoint: Express + Streamable HTTP (stateless), /healthz, /readyz
├── config.ts # lectura y validación de env vars, fail-fast
├── auth.ts # middleware de API key (timing-safe)
├── logger.ts # logs JSON de una línea, aptos para Cloud Logging
├── server.ts # createMcpServer(): registra todas las familias de tools
├── client/
│ ├── routes.ts # ÚNICO sitio con las rutas de eng-api
│ ├── errors.ts # EngApiError → mensajes accionables
│ └── engApiClient.ts # fetch + timeout + retry con backoff
└── tools/
├── shared.ts # registerEngTool(), paginación, formateo, errores
├── bitbucket.ts ├── jira.ts ├── confluence.ts └── argocd.ts설계 결정:
Stateless 모드의 Streamable HTTP(
sessionIdGenerator: undefined,enableJsonResponse: true): 요청별로McpServer+ 전송을 생성합니다. 개발자 간 상태 공유 불가, 고정 세션 불필요, 수평 확장 가능하며 응답은 일반 JSON입니다(SSE보다 인그레스/프록시에 더 친화적).POST /mcp만 허용:GET/DELETE는405로 응답합니다. Stateless 모드에서는 서버→클라이언트 스트림이나 종료할 세션이 없기 때문입니다.추적 가능성: 각 요청은
X-Request-Id(클라이언트가 보낸 경우 해당 값 사용)와 개발자 태그가 포함된X-Mcp-Dev를 가지며, 둘 다 eng-api로 전파됩니다.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceA TypeScript-based MCP server that provides backend API handling and facilitates communication between microservices. Features an organized structure with controllers, routes, and models for easy extensibility and maintenance.2831MIT
- Alicense-qualityDmaintenanceAn MCP server that enables interaction with Jira to fetch issues by key and perform JQL searches. It provides a foundation for integrating multiple work systems, with planned support for Slack and GitHub.376MIT
- AlicenseBqualityDmaintenanceProduction-ready TypeScript MCP server exposing utility, GitHub, and Microsoft Teams tools over stdio.141MIT
- AlicenseBqualityCmaintenanceLightweight MCP server for Jira, Confluence, and Bitbucket — read, create, and update from your AI IDE.20MIT
Related MCP Connectors
A MCP server built for developers enabling Git based project management with project and personal…
MCP server for interacting with the Supabase platform
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/ElJijuna/mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server