Skip to main content
Glama

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

기타 명령어:

명령어

설명

npm run dev

.env를 읽어 watch 모드로 시작

npm run build

TypeScript를 dist/로 컴파일

npm run typecheck

내보내기 없이 타입 검사

npm start

컴파일된 파일 시작 (환경 변수 사용, 파드에서 실행되는 것)

npm run start:local

.env를 읽어 컴파일된 파일 시작

서버가 실행 중인지 빠르게 확인:

curl http://localhost:3000/healthz
# {"status":"ok","server":"mcp-server","version":"0.1.0"}

3. 설정 (.env)

모든 변수는 process.env에서 읽어옵니다. 필수 변수가 없거나 유효하지 않은 값이 있으면 프로세스가 시작되지 않으며 정확히 무엇을 수정해야 하는지 설명합니다.

변수

필수

기본값

설명

ENG_API_BASE_URL

eng-api의 기본 URL, 마지막 슬래시 없음. http(s)://… 형식이어야 함

MCP_DEV_API_KEYS

MCP 서버에 대한 개발자의 유효한 API 키 (§4 참조)

ENG_API_TIMEOUT_MS

10000

eng-api 호출당 타임아웃 (1000–120000)

ENG_API_MAX_RETRIES

2

5xx/429/타임아웃 발생 시 추가 재시도 횟수 (0–5)

PORT

3000

MCP 서버의 HTTP 포트

LOG_LEVEL

info

debug | info | warn | error

실패한 시작 예시 (의도적):

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) 합니다.

상황

응답

키 없음

401 + 어떤 헤더가 누락되었는지 메시지

유효하지 않음/폐기된 키

403 + 무엇을 확인해야 하는지 메시지

/healthz, /readyz

인증 없음 (Kubernetes 프로브용)

누군가 폐기 = MCP_DEV_API_KEYS에서 해당 키를 제거하고 Deployment를 다시 시작합니다. 각 개발자가 자신의 키를 가지고 있으므로 나머지에는 영향을 미치지 않습니다. 프로덕션에서는 값을 Kubernetes Secret에 저장하고, 절대 ConfigMap에 저장하지 마십시오.

5. 도구 카탈로그

이름은 서비스 접두사를 가지며 동작 지향적입니다. 해당되는 경우 모든 것은 페이지네이션(page, pageSize 1~100, 기본값 25)을 지원합니다.

Bitbucket (읽기 전용)

도구

인수

eng-api 엔드포인트

bitbucket_list_prs

workspace, repoSlug, state? (OPEN|MERGED|DECLINED|ALL), author?, page?, pageSize?

GET /bitbucket/repositories/{ws}/{repo}/pull-requests

bitbucket_get_pr

workspace, repoSlug, pullRequestId

GET /bitbucket/repositories/{ws}/{repo}/pull-requests/{id}

bitbucket_get_commits

workspace, repoSlug, branch, sinceCommit?, sinceDate?, page?, pageSize?

GET /bitbucket/repositories/{ws}/{repo}/commits

Jira

도구

인수

eng-api 엔드포인트

jira_search_issues

jql? 또는 단순 필터 (projectKey?, status?, assignee?, labels?), fields?, page?, pageSize?

POST /jira/issues/search

jira_get_issue

issueKey (PLAT-4821 형식), fields?, includeComments?

GET /jira/issues/{key}

jira_create_issue ✍️

projectKey, issueType, summary, description?, assignee?, labels?, priority?, parentKey?, extraFields?

POST /jira/issues

Confluence (읽기 전용)

도구

인수

eng-api 엔드포인트

confluence_search_pages

query, spaceKey?, page?, pageSize?

GET /confluence/pages/search

confluence_get_page

pageId, format? (plain|storage|view)

GET /confluence/pages/{id}

ArgoCD

도구

인수

eng-api 엔드포인트

argocd_list_apps

project?, namespace?, syncStatus?, healthStatus?, page?, pageSize?

GET /argocd/applications

argocd_get_app_status

appName

GET /argocd/applications/{name}

argocd_sync_app ⚠️

appName (정확히, 기본값 없음), revision?, prune?, dryRun?, resources?

POST /argocd/applications/{name}/sync

주석 (MCP 클라이언트용 힌트)

도구

readOnlyHint

destructiveHint

idempotentHint

openWorldHint

모든 읽기 도구

jira_create_issue ✍️

argocd_sync_app ⚠️

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 otra

Inspector UI에서:

  1. Transport Type: Streamable HTTP

  2. URL: http://localhost:3000/mcp

  3. Authentication에서 Header Name Authorization을 설정하고 Bearer Token에 API 키를 입력하세요.

  4. ConnectTools 탭 → 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.0

node:22-alpine 기반의 멀티-스테이지 이미지: 최종 이미지에는 dist/ + 프로덕션 종속성만 포함되며, node 사용자 (루트 아님)로 실행되고 자체 Node로 /healthz를 확인하는 HEALTHCHECK를 포함합니다 (curl/wget 없음).

Kubernetes용 (매니페스트는 이 저장소에 없음):

  • 서버는 **무상태(stateless)**입니다. 메모리에 세션을 저장하지 않으므로 고정 세션 없이 N개의 복제본으로 확장됩니다.

  • 프로브: livenessProbeGET /healthz, readinessProbeGET /readyz (둘 다 인증 없음).

  • MCP_DEV_API_KEYSSecret에 있습니다. 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_REGISTRARSsrc/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_MAX_RETRIES)로 재시도 후, ENG_API_BASE_URL / 지연 시간을 확인하도록 안내

429, 5xx

재시도(Retry-After 헤더가 있으면 준수)하고, 지속되면 eng-api 로그를 참조하도록 안내

400 / 422

재시도하지 않음: 파라미터가 유효하지 않음

eng-api의 401 / 403

MCP의 API 키가 아닌, eng-api의 자격 증명/권한 문제임을 명시

404

정확한 식별자와 routes.ts의 경로를 확인하도록 제안

409

상태 충돌(예: 이미 진행 중인 ArgoCD 동기화): 상태를 확인한 후 재시도

JSON이 아닌 응답

일반적으로 프록시가 HTML을 반환하는 경우: 경로가 존재하지 않을 가능성이 있음

대용량 페이로드

pageSize를 줄이거나 필터를 좁히라는 안내와 함께 120,000자로 잘림

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/DELETE405로 응답합니다. Stateless 모드에서는 서버→클라이언트 스트림이나 종료할 세션이 없기 때문입니다.

  • 추적 가능성: 각 요청은 X-Request-Id(클라이언트가 보낸 경우 해당 값 사용)와 개발자 태그가 포함된 X-Mcp-Dev를 가지며, 둘 다 eng-api로 전파됩니다.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

View all related MCP servers

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

View all MCP Connectors

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

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