Skip to main content
Glama

mcp-server

MCP-сервер на TypeScript, который предоставляет инженерные инструменты команды — Bitbucket, Jira, Confluence и ArgoCD — редакторам с поддержкой MCP (VS Code + Copilot, Claude Code и т.д.).

Это тонкая обёртка: он не общается напрямую с Bitbucket/Jira/Confluence/ArgoCD и не хранит учётные данные этих сервисов. Всё транслируется в 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. Только API-ключ этого MCP-сервера, отзываемый индивидуально.


1. Требования

  • Node.js ≥ 22

  • Сетевой доступ к ENG_API_BASE_URL (URL eng-api)

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

Запуск в режиме watch с чтением .env

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

Базовый URL eng-api, без косой черты в конце. Должен быть http(s)://…

MCP_DEV_API_KEYS

Допустимые API-ключи разработчиков для этого MCP-сервера (см. §4)

ENG_API_TIMEOUT_MS

10000

Тайм-аут на один вызов eng-api (1000–120000)

ENG_API_MAX_RETRIES

2

Дополнительные повторные попытки при 5xx/429/тайм-ауте (0–5)

PORT

3000

HTTP-порт MCP-сервера

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-сервера и передаётся в eng-api в заголовке X-Mcp-Dev, что позволяет отследить, кто инициировал каждую операцию (например, argocd_sync_app), не раскрывая ключ.

Использование ключей

Клиент MCP должен отправлять в каждом запросе:

Authorization: Bearer <API_KEY>

(или, как альтернатива, x-api-key: <API_KEY>). Сравнение выполняется с защитой от временных атак на основе SHA-256-дайджестов.

Ситуация

Ответ

Без ключа

401 + сообщение, указывающее, какой заголовок отсутствует

Неверный/отозванный ключ

403 + сообщение, указывающее, что проверить

/healthz, /readyz

Без аутентификации (для проб Kubernetes)

Отозвать доступ у пользователя = удалить его ключ из MCP_DEV_API_KEYS и перезапустить Deployment. Поскольку у каждого разработчика свой ключ, это не влияет на остальных. В production храните значение в Secret Kubernetes, никогда в 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 в вашем workspace (или пользовательский 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, и вы увидите 11 инструментов под сервером eng.

Для 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

В UI Inspector:

  1. Transport Type: Streamable HTTP

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

  3. В Authentication укажите Header Name Authorization и Bearer Token с вашим API-ключом

  4. Connect → вкладка ToolsList 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/ + зависимости production, запускается от пользователя node (без root) и включает HEALTHCHECK, который обращается к /healthz через сам Node (без curl/wget).

Для Kubernetes (манифесты не в этом репозитории):

  • Сервер stateless: не хранит сессии в памяти, поэтому масштабируется до N реплик без привязанных сессий.

  • Пробы: livenessProbeGET /healthz, readinessProbeGET /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.

Правила стиля для новых инструментов:

  • Имя сервис_действие_объект, в нижнем регистре.

  • Каждое поле схемы с .describe() и конкретным примером — это единственное, что модель читает, чтобы решить, как его вызвать.

  • Честные аннотации: если пишет, readOnlyHint: false; если может что-то удалить, destructiveHint: true.

  • Никаких опасных значений по умолчанию в деструктивных операциях: требуйте точные идентификаторы.

  • Пагинация (...paginationShape + paginationQuery(args)) во всём, что возвращает списки.

  • Никогда не конструируйте URL вручную в tools/: всегда через engApiRoutes.

10. Обработка ошибок

Ни один инструмент не возвращает голую ошибку "500". Каждая ошибка включает что не удалось, что проверить и requestId для сопоставления с логами eng-api. Пример:

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 Server

Тайм-аут / ошибка сети

Повторяет с экспоненциальной задержкой + джиттер (ENG_API_MAX_RETRIES), затем объясняет, что нужно проверить ENG_API_BASE_URL / задержку

429, 5xx

Повторяет (учитывает Retry-After, если есть) и, если не проходит, указывает на логи eng-api

400 / 422

Не повторяет: параметры недействительны

401 / 403 от eng-api

Уточняет, что это не ваш API-ключ MCP, а учётные данные/разрешения eng-api

404

Предлагает проверить точные идентификаторы и пути в routes.ts

409

Конфликт состояния (например, синхронизация ArgoCD уже выполняется): проверьте состояние и повторите позже

Ответ не-JSON

Обычно это прокси, возвращающий HTML: вероятно, путь не существует

Огромная полезная нагрузка

Обрезается до 120 000 символов с предупреждением уменьшить pageSize или сузить фильтры

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

Проектные решения:

  • Streamable HTTP в stateless-режиме (sessionIdGenerator: undefined, enableJsonResponse: true): создаётся McpServer + transport на каждый запрос. Нет общего состояния между разработчиками, нет sticky sessions, горизонтальное масштабирование, ответы — простой JSON (более дружелюбны к ingress/прокси, чем SSE).

  • Только POST /mcp: GET/DELETE отвечают 405, потому что в 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