mcp-server
mcp-server
チームのエンジニアリングツール(Bitbucket、Jira、Confluence、ArgoCD)をMCP対応エディタ(VS Code + Copilot、Claude Codeなど)に公開するTypeScript製MCPサーバー。
これは薄いラッパーです。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を |
| 出力なしで型チェック |
| コンパイル済みを起動(環境変数を使用。Podで実行されるもの) |
| コンパイル済みを |
動作確認のクイックチェック:
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. 認証: 開発者ごとに1つのAPIキー
この認証層はMCPサーバー独自のものであり、eng-apiが最終サービスに対して使用するものとは独立しています。
キーの生成
openssl rand -hex 32 # una por cada persona del equipo設定
MCP_DEV_API_KEYSは4つの形式を受け入れます(キーは最低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ダイジェストに対するタイミングセーフです。
状況 | 応答 |
キーなし |
|
無効/失効キー |
|
| 認証なし(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や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.0node:22-alpine上のマルチステージイメージ: 最終イメージにはdist/ + 本番依存関係のみが含まれ、nodeユーザー(rootなし)として実行され、Node自身で/healthzを叩くHEALTHCHECKを含みます(curl/wgetなし)。
Kubernetes用(マニフェストはこのリポジトリにはありません):
サーバーはステートレス: セッションをメモリに保存しないため、スティッキーセッションなしで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 in src/server.tsに:
const TOOL_REGISTRARS = [ …, registerGrafanaTools ];以上です。registerEngToolはすでに以下を無料で提供します: Zod検証、レスポンスのフォーマット、巨大なペイロードの切り詰め、エラーキャプチャとアクション可能なメッセージへの変換、requestId付きのロギング。
新しいツールのスタイルルール:
名前は
サービス_アクション_オブジェクト、小文字。スキーマの各フィールドには**
.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サーバーの動作 |
タイムアウト / ネットワークエラー | 指数バックオフ+ジッターで再試行し( |
| 再試行する( |
| 再試行しない: パラメータが無効 |
| MCPのAPIキーではなく、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 (
sessionIdGenerator: undefined,enableJsonResponse: true): リクエストごとにMcpServer+トランスポートが作成される。開発者間で状態を共有せず、スティッキーセッション不要で水平スケーリングが可能、レスポンスはプレーンJSON(SSEよりもイングレス/プロキシに優しい)。POST /mcpのみ:GET/DELETEは405を返す。ステートレスではサーバー→クライアントのストリームや閉じるべきセッションがないため。トレーサビリティ: 各リクエストは
X-Request-Id(クライアントから送信された場合はそれを尊重)と、開発者のタグが付いたX-Mcp-Devを持ち、両方ともeng-apiに伝搬される。
This server cannot be deployed
Maintenance
Related MCP Connectors
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
A MCP server built for developers enabling Git based project management with project and personal…
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
- SupabaseOAuthcom.supabase
MCP server for interacting with the Supabase platform
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA 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.398 npm1MIT
- AlicenseNot gradedqualityDmaintenanceAn 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.522 npmMIT
- 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