mcp-server
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Другие команды:
Команда | Что делает |
| Запуск в режиме watch с чтением |
| Компиляция TypeScript в |
| Проверка типов без сборки |
| Запуск скомпилированного кода (использует переменные окружения; то, что работает в поде) |
| Запуск скомпилированного кода с чтением |
Быстрая проверка, что сервер работает:
curl http://localhost:3000/healthz
# {"status":"ok","server":"mcp-server","version":"0.1.0"}3. Конфигурация (.env)
Все переменные читаются из process.env. Если обязательная переменная отсутствует или имеет недопустимое значение, процесс не запускается и объясняет, что именно нужно исправить.
Переменная | Обязательная | По умолчанию | Описание |
| ✅ | — | Базовый URL eng-api, без косой черты в конце. Должен быть |
| ✅ | — | Допустимые API-ключи разработчиков для этого MCP-сервера (см. §4) |
| — |
| Тайм-аут на один вызов eng-api (1000–120000) |
| — |
| Дополнительные повторные попытки при 5xx/429/тайм-ауте (0–5) |
| — |
| HTTP-порт MCP-сервера |
| — |
|
|
Пример неудачного запуска (намеренно):
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-дайджестов.
Ситуация | Ответ |
Без ключа |
|
Неверный/отозванный ключ |
|
| Без аутентификации (для проб Kubernetes) |
Отозвать доступ у пользователя = удалить его ключ из MCP_DEV_API_KEYS и перезапустить Deployment. Поскольку у каждого разработчика свой ключ, это не влияет на остальных. В production храните значение в Secret Kubernetes, никогда в 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 в вашем 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:
Transport Type:
Streamable HTTPURL:
http://localhost:3000/mcpВ Authentication укажите 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.0Многоступенчатый образ на основе node:22-alpine: финальный содержит только dist/ + зависимости production, запускается от пользователя node (без root) и включает HEALTHCHECK, который обращается к /healthz через сам Node (без 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.
Правила стиля для новых инструментов:
Имя
сервис_действие_объект, в нижнем регистре.Каждое поле схемы с
.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 |
Тайм-аут / ошибка сети | Повторяет с экспоненциальной задержкой + джиттер ( |
| Повторяет (учитывает |
| Не повторяет: параметры недействительны |
| Уточняет, что это не ваш API-ключ MCP, а учётные данные/разрешения eng-api |
| Предлагает проверить точные идентификаторы и пути в |
| Конфликт состояния (например, синхронизация ArgoCD уже выполняется): проверьте состояние и повторите позже |
Ответ не-JSON | Обычно это прокси, возвращающий HTML: вероятно, путь не существует |
Огромная полезная нагрузка | Обрезается до 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Проектные решения:
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.
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