Skip to main content
Glama

mcp-server

MCP Server 用 TypeScript 编写,将团队的工程工具——Bitbucket、Jira、Confluence 和 ArgoCD——暴露给支持 MCP 的编辑器(VS Code + Copilot、Claude Code 等)。

它是一个薄层封装:不与 Bitbucket/Jira/Confluence/ArgoCD 直接通信,也不保存这些服务的凭据。所有操作都转换为对内部后端 eng-api 的 HTTP 调用,该后端已处理连接和凭据。

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 Server 的 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

npm run build

将 TypeScript 编译到 dist/

npm run typecheck

仅类型检查,不输出

npm start

启动编译后的代码(使用环境变量;这是 Pod 中运行的命令)

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 Server 的有效开发者 API 密钥(参见 §4)

ENG_API_TIMEOUT_MS

10000

每次调用 eng-api 的超时时间(1000–120000)

ENG_API_MAX_RETRIES

2

遇到 5xx/429/超时时的额外重试次数(0–5)

PORT

3000

MCP Server 的 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 Server 自身 的,与 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 Server 的日志中,并传播到 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。由于每个开发者都有自己的密钥,不会影响其他人。在生产环境中,将值保存在 Kubernetes 的 Secret 中,切勿放在 ConfigMap 中。

5. 工具目录

工具名称以服务为前缀,并面向操作。所有支持分页的地方(pagepageSize 范围 1 到 100,默认为 25)都支持分页。

Bitbucket(只读)

工具

参数

eng-api 端点

bitbucket_list_prs

workspacerepoSlugstate? (OPEN|MERGED|DECLINED|ALL)、author?page?pageSize?

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

bitbucket_get_pr

workspacerepoSlugpullRequestId

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

bitbucket_get_commits

workspacerepoSlugbranchsinceCommit?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 ✍️

projectKeyissueTypesummarydescription?assignee?labels?priority?parentKey?extraFields?

POST /jira/issues

Confluence(只读)

工具

参数

eng-api 端点

confluence_search_pages

queryspaceKey?page?pageSize?

GET /confluence/pages/search

confluence_get_page

pageIdformat? (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 TypeStreamable HTTP

  2. URLhttp://localhost:3000/mcp

  3. Authentication 中,设置 Header NameAuthorizationBearer Token 为你的 API 密钥

  4. Connect → 选项卡 ToolsList Tools → 测试任意一个

也可以直接用 curl 测试(在 CI 或 Pod 中很有用):

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 用户身份运行(非 root),并包含一个 HEALTHCHECK,使用 Node 自身(无需 curl/wget)访问 /healthz

对于 Kubernetes(清单不在本仓库中):

  • 服务器是无状态的:不在内存中保存会话,因此可以扩展到 N 个副本无需粘性会话

  • 探针:livenessProbeGET /healthzreadinessProbeGET /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. 在 src/server.tsTOOL_REGISTRARS 中注册它:

const TOOL_REGISTRARS = [ …, registerGrafanaTools ];

仅此而已。registerEngTool 已经免费为你提供了:Zod 验证、响应格式化、大负载截断、错误捕获并转换为可操作消息、以及带有 requestId 的日志记录。

新工具的样式规则:

  • 名称格式:服务_动作_对象,小写。

  • Schema 中的每个字段必须使用 .describe() 并提供具体示例——这是模型决定如何调用它的唯一依据。

  • 诚实的注释:如果是写入操作,readOnlyHint: false;如果可能删除内容,destructiveHint: true

  • 破坏性操作中不要使用危险的默认值:要求精确的标识符。

  • 所有返回列表的工具都要支持分页(...paginationShape + paginationQuery(args))。

  • 切勿在 tools/ 中手动构建 URL:始终通过 engApiRoutes

10. 错误处理

任何工具都不会返回赤裸裸的“Error 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 服务器的行为

Timeout / 网络错误

使用指数退避 + 抖动重试(ENG_API_MAX_RETRIES),否则解释请检查 ENG_API_BASE_URL / 延迟

429, 5xx

重试(如果存在则遵循 Retry-After),若持续失败,则指向 eng-api 日志

400 / 422

重试:参数无效

401 / 403 来自 eng-api

澄清这不是你的 MCP API 密钥,而是 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 无状态模式sessionIdGenerator: undefined, enableJsonResponse: true):每个请求创建一个 McpServer + transport。开发者之间无共享状态,无粘性会话,水平扩展,响应为纯 JSON(比 SSE 对 ingress/proxy 更友好)。

  • POST /mcpGET/DELETE 返回 405,因为在无状态下没有服务器→客户端流或需要关闭的会话。

  • 可追溯性:每个请求都带有 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