MCP server by Masa1984a
MCP Streamable HTTP Server with Terraform
Model Context Protocol (MCP) の Streamable HTTP transport を使用したサーバー実装です。TypeScript/Node.jsで構築され、Terraformを使用してAzure Container Instances (ACI) へ自動デプロイします。
🎯 プロジェクト概要
本プロジェクトは、MCPサーバーをHTTP経由でアクセス可能にし、Infrastructure as Code (Terraform) で管理する実装例です:
- ステートレス設計: Azure Container Instancesなどのサーバーレス環境に最適
- Streamable HTTP Transport: HTTPストリーミングによる効率的な通信
- 完全自動化: PowerShellスクリプトによるワンコマンドデプロイ
- 段階的デプロイ: インフラ → イメージプッシュ → アプリケーションの順序で安全にデプロイ
- サンプルツール実装:
add
(加算)とgreet
(挨拶)の2つのツール
🏗️ アーキテクチャ
┌─────────────────────────────────────────────────────────────────┐
│ Azure Cloud │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
│ │ Resource Group │ │ Azure Container Registry (ACR) │ │
│ │ (Terraformで管理) │ │ (Terraformで作成) │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
│ ↓ ↓ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Azure Container Instances (ACI) │ │
│ │ (Terraformでデプロイ) │ │
│ │ ┌─────────────────────────────────────────────────────────┐│ │
│ │ │ MCP Streamable HTTP Server ││ │
│ │ │ - Node.js 20 ││ │
│ │ │ - Express.js ││ │
│ │ │ - Port 8080 ││ │
│ │ │ - Stateless Mode ││ │
│ │ └─────────────────────────────────────────────────────────┘│ │
│ │ Public FQDN: mymcp-server.japaneast.azurecontainer.io │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▲
│ HTTP/HTTPS
│
┌─────────────────────────────────────────────────────────────────┐
│ Client Side │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
│ │ MCP Inspector │ │ Future: ChatGPT Integration │ │
│ │ (Testing Tool) │ │ (MCP Custom Connector) │ │
│ └─────────────────────┘ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
📁 プロジェクト構成
Minimum_MCP/
├── app/ # アプリケーション本体
│ ├── src/ # TypeScriptソースコード
│ │ └── server.ts # MCPサーバー実装
│ ├── dist/ # コンパイル済みJavaScript
│ ├── package.json # Node.js依存関係
│ ├── tsconfig.json # TypeScript設定
│ ├── Dockerfile # コンテナイメージ定義
│ └── .dockerignore # Docker除外設定
├── terraform/ # インフラ定義(Infrastructure as Code)
│ ├── main.tf # Azureリソース定義
│ ├── variables.tf # 変数定義
│ ├── outputs.tf # 出力値定義
│ ├── terraform.tfvars # 【要設定】環境固有の値
│ └── versions.tf # Terraformバージョン管理
├── scripts/ # 自動化スクリプト
│ ├── deploy.ps1 # 完全自動デプロイスクリプト
│ └── build-and-push.ps1 # Dockerイメージビルド&プッシュ
└── .gitignore # Git除外設定
🚀 クイックスタート
前提条件
開発環境(Windows 11):
- PowerShell 5.1+
- Node.js 20.x+
- npm 10.x+
- Terraform 1.5.0+
- Podman 5.x(またはDocker)
- Azure CLI 2.70+
Azureアカウント:
- 有効なAzureサブスクリプション
- Contributor以上の権限
🔑 Azure Subscription IDの取得方法
方法1: Azure ポータルから取得
- Azure Portal にログイン
- 左側メニューまたは検索バーで「サブスクリプション」を検索
- 使用するサブスクリプションをクリック
- 「概要」ページに表示される「サブスクリプション ID」をコピー
方法2: Azure CLIから取得(推奨)
# 1. Azure CLIのインストール確認
az --version
# インストールされていない場合は以下から入手:
# https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli-windows
# 2. Azureにログイン
az login
# → ブラウザが開きます。Azureアカウントでログイン
# 3. アカウント一覧を表示
az account list --output table
# 出力例:
# Name CloudName SubscriptionId State IsDefault
# -------------------- ----------- ------------------------------------ ------- -----------
# My Subscription AzureCloud xxx Enabled True
# 4. 現在のサブスクリプションIDのみ取得
az account show --query "id" --output tsv
# → xxx
# 5. 複数のサブスクリプションがある場合、使用するものを選択
az account set --subscription "サブスクリプション名またはID"
方法3: PowerShellから取得
# Azure PowerShellモジュールを使用
Connect-AzAccount
Get-AzSubscription | Select-Object Name, Id
初期設定(必須)
- terraform.tfvarsの作成
# テンプレートから設定ファイルを作成
cd terraform
copy terraform.tfvars.template terraform.tfvars
# 設定ファイルを編集
notepad terraform.tfvars
以下の値を実際の環境に合わせて変更:
# プロジェクト固有の値を設定
prefix = "yourname123" # ← 一意のプレフィックスに変更
location = "japaneast"
# Azure Subscription ID(各自の環境に合わせて変更)
subscription_id = "xxx" # ← 実際のIDに変更
重要な注意事項:
prefix
はグローバルに一意である必要があります(ACR名に使用されるため)- 例:
johndoe123
,testmcp2024
, など - 3-20文字の英数字のみ使用可能
完全自動デプロイ(推奨)
# プロジェクトルートで実行
.\scripts\deploy.ps1
# 以下が自動実行されます:
# 1. TypeScriptのビルド
# 2. Terraformの初期化
# 3. インフラの作成(Resource Group + ACR)
# 4. Dockerイメージのビルド
# 5. ACRへのイメージプッシュ
# 6. Container Instancesのデプロイ
実行時間:約3-5分
動作確認
デプロイ完了後、以下のURLが表示されます:
# ヘルスチェック
Invoke-WebRequest -Uri "http://mymcp-server.japaneast.azurecontainer.io:8080/health" -Method GET
# MCP Inspectorで接続
# Transport Type: Streamable HTTP
# URL: http://mymcp-server.japaneast.azurecontainer.io:8080/mcp
🔧 詳細な使用方法
ローカル開発
cd app
# 依存関係のインストール
npm install
# 開発サーバーの起動(ファイル変更監視)
npm run dev
# TypeScriptビルド
npm run build
# 本番サーバーの起動
npm start
手動での段階的デプロイ
自動デプロイではなく、段階的に確認しながらデプロイしたい場合:
cd terraform
# 1. Terraform初期化
terraform init
# 2. インフラのみ作成(Resource Group + ACR)
terraform apply "-target=azurerm_resource_group.main" "-target=azurerm_container_registry.acr"
# 3. ACR情報の確認
terraform output acr_login_server
$password = terraform output -raw acr_admin_password
# 4. Dockerイメージのビルド&プッシュ
cd ../app
podman build -t mcp-server:latest .
echo $password | podman login $(terraform output -raw acr_login_server) --username $(terraform output -raw acr_admin_username) --password-stdin
podman tag mcp-server:latest $(terraform output -raw acr_login_server)/mcp-server:latest
podman push $(terraform output -raw acr_login_server)/mcp-server:latest
# 5. Container Instancesのデプロイ
cd ../terraform
terraform apply "-target=azurerm_container_group.aci"
リソースの削除
cd terraform
# 全リソースの削除
terraform destroy
# → yes を入力して確認
# 状態ファイルも削除する場合
Remove-Item -Force terraform.tfstate*
Remove-Item -Recurse -Force .terraform
📋 トラブルシューティング
よくあるエラーと対処法
1. Terraform実行時のエラー
Error: `subscription_id` is a required provider property
解決法: terraform/terraform.tfvars
にSubscription IDを設定してください。
2. ACR名の重複エラー
Error: The registry DNS name mymcpacr is already in use
解決法: terraform/terraform.tfvars
のprefix
を一意の値に変更してください。
3. Container Groupのイメージアクセスエラー
Error: InaccessibleImage: The image 'mymcpacr.azurecr.io/mcp-server:latest' in container group
解決法: Dockerイメージがプッシュされていません。build-and-push.ps1
を実行してください。
4. PowerShell実行ポリシーエラー
cannot be loaded because running scripts is disabled on this system
解決法:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
ログの確認方法
# Container Instancesのログ確認
az container logs --resource-group rg-mymcp --name mymcp-container
# リアルタイムログ監視
az container logs --resource-group rg-mymcp --name mymcp-container --follow
# コンテナの状態確認
az container show --resource-group rg-mymcp --name mymcp-container --query "containers[0].instanceView.currentState"
📚 IT学習者向け詳細解説
プロジェクト構造の理解
Minimum_MCP/
├── app/ # アプリケーション本体
│ ├── src/ # TypeScriptソースコード
│ │ └── server.ts # メインのサーバーファイル
│ ├── dist/ # コンパイル済みJavaScript(自動生成)
│ │ ├── server.js # 実行可能なJSファイル
│ │ ├── server.d.ts # 型定義ファイル
│ │ └── *.map # デバッグ用マップファイル
│ ├── node_modules/ # 依存パッケージの実体
│ ├── package.json # プロジェクト設定と依存関係
│ ├── package-lock.json # 依存関係のバージョン固定
│ ├── tsconfig.json # TypeScriptコンパイラ設定
│ ├── Dockerfile # Dockerイメージ構築設定
│ └── .dockerignore # Docker除外ファイル設定
├── terraform/ # インフラ定義
│ ├── main.tf # メインのリソース定義
│ ├── variables.tf # 変数定義
│ ├── outputs.tf # 出力値定義
│ ├── terraform.tfvars # 変数の実際の値
│ └── versions.tf # バージョン制約
└── scripts/ # 自動化スクリプト
Node.js/TypeScriptの基礎知識
TypeScriptとJavaScriptの関係
TypeScriptは、JavaScriptに型システムを追加した言語です:
// TypeScript(src/server.ts)- 開発時に型チェック
const greet = (name: string): string => {
return `Hello, ${name}!`;
}
// コンパイルエラー: 型が合わない
greet(123); // Error: Argument of type 'number' is not assignable to parameter of type 'string'
↓ tsc
コンパイラで変換
// JavaScript(dist/server.js)- 実行時は型情報なし
const greet = (name) => {
return `Hello, ${name}!`;
}
Node.jsの役割
Node.jsはJavaScriptの実行環境です:
TypeScript(人間が書く)
↓ tscコンパイラ
JavaScript(マシンが理解)
↓
Node.js(V8エンジンで実行)
各ファイルの詳細解説
1. package.json - プロジェクトの心臓部
{
"name": "mcp-streamable-http-server",
"version": "1.0.0",
"type": "module", // ES Modules使用宣言
"scripts": {
"build": "tsc", // npm run build → TypeScriptコンパイル
"start": "node dist/server.js", // npm start → 本番実行
"dev": "tsx watch src/server.ts" // npm run dev → 開発モード
},
"dependencies": {
"express": "^5.1.0", // 本番で必要(実行時に使用)
"@modelcontextprotocol/sdk": "^1.12.1"
},
"devDependencies": {
"typescript": "^5.8.3", // 開発時のみ(コンパイラ)
"@types/express": "^5.0.2", // 開発時のみ(型定義)
"tsx": "^4.19.4" // 開発時のみ(TS直接実行)
}
}
ポイント:
dependencies
: 本番環境で必要なパッケージdevDependencies
: 開発時のみ必要なパッケージscripts
: よく使うコマンドのショートカット
2. package-lock.json - 依存関係の完全な固定
{
"packages": {
"express": {
"version": "5.1.0", // 厳密なバージョン指定
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-..." // ファイルの整合性チェック
}
}
}
なぜ必要?
- チーム全員が同じバージョンを使用
- 「私の環境では動くのに...」を防ぐ
npm ci
コマンドで高速・確実にインストール
3. tsconfig.json - TypeScriptの設定
{
"compilerOptions": {
"target": "ES2022", // 出力するJSのバージョン
"module": "NodeNext", // モジュールシステム
"outDir": "./dist", // 出力先ディレクトリ
"rootDir": "./src", // ソースコードの場所
"strict": true, // 厳密な型チェック
"sourceMap": true // デバッグ用マップ生成
},
"include": ["src/**/*"], // コンパイル対象
"exclude": ["node_modules"] // 除外するフォルダ
}
4. server.ts - メインのソースコード
// 1. 必要なモジュールのインポート
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
// 2. Expressアプリケーションの初期化
const app = express();
app.use(express.json()); // JSONボディのパース
// 3. MCPサーバーの初期化
const server = new McpServer({
name: 'mcp-streamable-http-server',
version: '1.0.0'
});
// 4. ツールの定義(関数のようなもの)
server.tool(
'add', // ツール名
{ a: z.number(), b: z.number() }, // パラメータの型定義
async ({ a, b }) => ({ // 実装
content: [{
type: 'text',
text: String(a + b)
}]
})
);
// 5. HTTPエンドポイントの設定
app.post('/mcp', async (req, res) => {
// MCPプロトコルの処理
});
// 6. サーバーの起動
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
5. Dockerfile - コンテナ化の設定
# ベースイメージ(軽量版Node.js)
FROM node:20-slim
# 作業ディレクトリ設定
WORKDIR /app
# 依存関係定義ファイルをコピー(キャッシュ効率化)
COPY package*.json ./
# 本番用パッケージのみインストール
RUN npm ci --only=production
# ビルド済みコードをコピー
COPY dist ./dist
# ポート公開(ドキュメント的)
EXPOSE 8080
# 環境変数設定
ENV NODE_ENV=production
# 起動コマンド
CMD ["node", "dist/server.js"]
最適化のポイント:
- 軽量イメージ使用(node:20-slim)
- レイヤーキャッシュ活用(package*.jsonを先にコピー)
- 開発用パッケージを除外(--only=production)
6. .dockerignore - Dockerビルド時の除外設定
node_modules # コンテナ内で再インストールするから不要
src # TypeScriptソースは不要(distがあれば十分)
*.ts # TypeScriptファイルは全て不要
tsconfig.json # コンパイル設定も不要
開発フローの理解
graph LR
A[TypeScript開発] --> B[npm run dev]
B --> C[自動コンパイル・再起動]
C --> D[動作確認]
D --> A
A --> E[npm run build]
E --> F[dist/生成]
F --> G[Dockerビルド]
G --> H[ACRプッシュ]
H --> I[ACIデプロイ]
npmコマンドチートシート
| コマンド | 説明 | 実行内容 |
|---------|------|---------|
| npm install
| 依存関係インストール | package.jsonを読んでnode_modules作成 |
| npm ci
| クリーンインストール | package-lock.jsonから厳密にインストール |
| npm run build
| ビルド | tscを実行してTypeScript→JavaScript |
| npm run dev
| 開発モード | ファイル監視&自動再起動 |
| npm start
| 本番起動 | node dist/server.js |
よくある質問(FAQ)
Q: なぜTypeScriptを使うの?
A: 型安全性により、開発時にエラーを発見できます:
// TypeScript - コンパイル時にエラー発見
function divide(a: number, b: number): number {
return a / b;
}
divide("10", "2"); // Error: 文字列は渡せない
// JavaScript - 実行時まで分からない
function divide(a, b) {
return a / b;
}
divide("10", "2"); // "10" / "2" = 5(暗黙の型変換)
Q: node_modulesはなぜ巨大?
A: 各プロジェクトが独立して全ての依存関係を持つため:
- express本体
- expressが依存するパッケージ
- それらが依存するパッケージ...
- 全てがnode_modulesに物理的に保存される
Q: distフォルダを編集してもいい?
A: いいえ。distは自動生成されるため:
- 手動編集しても次回ビルドで上書きされる
- 必ずsrc/のTypeScriptを編集する
- distは.gitignoreに追加(バージョン管理しない)
Q: 開発環境と本番環境の違いは?
A: 主な違い: | 項目 | 開発環境 | 本番環境 | |------|---------|---------| | 実行方法 | tsx(TypeScript直接) | node(JavaScript) | | ファイル監視 | あり(自動再起動) | なし | | エラー表示 | 詳細 | 最小限 | | パッケージ | 全て | dependenciesのみ |
Q: DockerfileのCMDとRUNの違いは?
A: タイミングが違います:
RUN
: イメージ構築時に実行(npm installなど)CMD
: コンテナ起動時に実行(node server.jsなど)
🔍 Terraform詳細解説
Terraformとは?
Terraformは HashiCorp社が開発した Infrastructure as Code (IaC) ツールです。インフラストラクチャをコードで定義し、バージョン管理できます。
各Terraformファイルの詳細
1. versions.tf - プロバイダーとバージョン管理
terraform {
required_version = ">= 1.5.0" # Terraform本体のバージョン制約
required_providers {
azurerm = {
source = "hashicorp/azurerm" # プロバイダーのソース
version = "~> 4.0" # 4.x系の最新を使用
}
}
}
provider "azurerm" {
features {} # 必須の空ブロック
subscription_id = var.subscription_id # どのAzureアカウントを使うか
}
解説:
required_version
: Terraformの最小バージョンを指定required_providers
: 使用するプロバイダー(Azureとの連携部分)provider
: プロバイダーの設定
2. variables.tf - 変数定義
variable "prefix" {
description = "リソース名のプレフィックス"
type = string
# defaultがないので必須入力
}
variable "location" {
description = "Azureリージョン"
type = string
default = "japaneast" # デフォルト値あり
}
variable "container_cpu" {
description = "コンテナのCPU割り当て"
type = string # 数値だが文字列で定義(Azureの仕様)
default = "0.5" # 0.5コア
}
変数の型:
string
: 文字列number
: 数値bool
: 真偽値list
: リストmap
: マップ(辞書)
3. terraform.tfvars - 変数の実際の値
# これが実際に使われる値
prefix = "mymcp"
location = "japaneast"
subscription_id = "xxx"
重要: このファイルには秘密情報が含まれるため、.gitignore
に追加推奨
4. main.tf - リソース定義(メイン)
# リソースブロックの構文:
# resource "リソースタイプ" "リソース名" {
# 設定項目 = 値
# }
# 1. リソースグループ(全てのリソースを格納する箱)
resource "azurerm_resource_group" "main" {
name = "rg-${var.prefix}" # 変数の参照
location = var.location
tags = {
Environment = "Production"
Project = "MCP-Server"
}
}
# 2. Container Registry(Dockerイメージの保管庫)
resource "azurerm_container_registry" "acr" {
name = "${var.prefix}acr" # グローバルに一意
resource_group_name = azurerm_resource_group.main.name # 他リソース参照
location = azurerm_resource_group.main.location
sku = "Basic" # Basic/Standard/Premium
admin_enabled = true # 管理者アクセス有効化
tags = {
Environment = "Production"
Project = "MCP-Server"
}
}
# 3. Container Group(実際にアプリが動く場所)
resource "azurerm_container_group" "aci" {
name = "${var.prefix}-container"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
os_type = "Linux"
# コンテナの定義
container {
name = "mcp-server"
image = "${azurerm_container_registry.acr.login_server}/mcp-server:${var.image_tag}"
cpu = var.container_cpu
memory = var.container_memory
ports {
port = 8080
protocol = "TCP"
}
environment_variables = {
NODE_ENV = "production"
PORT = "8080"
}
}
# ACR認証情報
image_registry_credential {
server = azurerm_container_registry.acr.login_server
username = azurerm_container_registry.acr.admin_username
password = azurerm_container_registry.acr.admin_password
}
dns_name_label = "${var.prefix}-server" # FQDN生成用
tags = {
Environment = "Production"
Project = "MCP-Server"
}
}
リソース間の依存関係:
Resource Group
↓ 依存
Container Registry
↓ 依存
Container Group
5. outputs.tf - 出力値定義
output "resource_group_name" {
value = azurerm_resource_group.main.name
}
output "acr_login_server" {
value = azurerm_container_registry.acr.login_server
# 例: mymcpacr.azurecr.io
}
output "acr_admin_password" {
value = azurerm_container_registry.acr.admin_password
sensitive = true # terraform output では表示されない
}
output "container_url" {
value = "http://${azurerm_container_group.aci.fqdn}:8080"
# 例: http://mymcp-server.japaneast.azurecontainer.io:8080
}
使い方:
# 値の取得
terraform output container_url
# "http://mymcp-server.japaneast.azurecontainer.io:8080"
# センシティブな値の取得
terraform output -raw acr_admin_password
# パスワードが表示される
Terraformの基本コマンド
| コマンド | 説明 | 用途 |
|---------|------|------|
| terraform init
| 初期化 | プロバイダーのダウンロード |
| terraform plan
| 実行計画 | 変更内容の事前確認 |
| terraform apply
| 適用 | リソースの作成・更新 |
| terraform destroy
| 破棄 | 全リソースの削除 |
| terraform output
| 出力 | 作成済みリソースの情報取得 |
| terraform state list
| 状態一覧 | 管理中のリソース確認 |
Terraformの状態管理
Terraformはterraform.tfstate
ファイルで現在の状態を管理:
{
"version": 4,
"terraform_version": "1.5.0",
"resources": [
{
"type": "azurerm_resource_group",
"name": "main",
"instances": [
{
"attributes": {
"id": "/subscriptions/.../resourceGroups/rg-mymcp",
"location": "japaneast",
"name": "rg-mymcp"
}
}
]
}
]
}
重要:
- このファイルを失うと、Terraformは既存リソースを認識できなくなる
- チーム開発では、Azure Blob StorageやTerraform Cloudで共有
段階的デプロイの仕組み
# -targetオプションで特定のリソースのみ操作
terraform apply "-target=azurerm_resource_group.main" "-target=azurerm_container_registry.acr"
これにより:
- まずインフラ(RG + ACR)を作成
- Dockerイメージをプッシュ
- 最後にコンテナをデプロイ
という順序制御が可能になります。
Terraformのベストプラクティス
-
変数の活用
# ハードコーディングを避ける # 悪い例 location = "japaneast" # 良い例 location = var.location
-
タグの統一
# 全リソースに同じタグを付ける tags = { Environment = var.environment Project = var.project_name ManagedBy = "Terraform" }
-
命名規則
# リソースタイプを含める name = "rg-${var.prefix}" # リソースグループ name = "${var.prefix}acr" # ACR name = "${var.prefix}-vm" # 仮想マシン
-
出力の活用
# 他のスクリプトで使う値は必ず出力 output "important_value" { value = azurerm_resource.example.important_attribute }
トラブルシューティングガイド
TypeScript関連
# エラー: Cannot find module 'express'
npm install
npm install -D @types/express
# エラー: tsc: command not found
npm install -D typescript
Docker関連
# エラー: port is already allocated
lsof -i :8080 # Mac/Linux
netstat -ano | findstr :8080 # Windows
# ビルドが遅い
# .dockerignoreにnode_modulesが含まれているか確認
Azure関連
# ACR認証エラー
az acr update --name $ACR_NAME --admin-enabled true
# コンテナログ確認
az container logs --resource-group $RESOURCE_GROUP --name $CONTAINER_NAME
Terraform関連
# 状態の不整合
terraform refresh # 実際のリソースと同期
# 特定リソースの再作成
terraform taint azurerm_container_group.aci # 次回applyで再作成
terraform apply
# 状態から削除(リソースは残る)
terraform state rm azurerm_container_group.aci
さらなる学習リソース
-
TypeScript
-
Node.js/Express
-
Docker
-
Azure
-
Terraform
-
MCP
🛠️ カスタマイズ
環境変数の追加
terraform/main.tf
のContainer Group定義内で環境変数を追加:
environment_variables = {
NODE_ENV = "production"
PORT = "8080"
MY_CUSTOM_VAR = "value" # 追加
}
リソースサイズの変更
terraform/variables.tf
で定義されている値を変更:
variable "container_cpu" {
description = "コンテナのCPU割り当て"
type = string
default = "1" # 0.5 → 1 に変更
}
variable "container_memory" {
description = "コンテナのメモリ割り当て(GB)"
type = string
default = "2" # 1 → 2 に変更
}
新しいMCPツールの追加
app/src/server.ts
でツールを追加:
// 新しいツールの追加例
server.tool(
'multiply',
{
a: z.number().describe('First number'),
b: z.number().describe('Second number')
},
async ({ a, b }) => ({
content: [{
type: 'text',
text: `${a} × ${b} = ${a * b}`
}]
})
);
📚 技術スタック詳細
Terraform
Infrastructure as Code (IaC) の実装:
- 宣言的なリソース管理
- 状態管理による差分デプロイ
- モジュール化された構成
PowerShell自動化
deploy.ps1の処理フロー:
1. TypeScriptビルド
↓
2. Terraform初期化
↓
3. インフラ作成(段階的)
- Resource Group
- Container Registry
↓
4. Dockerイメージビルド&プッシュ
↓
5. アプリケーションデプロイ
- Container Instances
Docker最適化
マルチステージビルドではなく、事前ビルド方式を採用:
- 開発環境でTypeScriptをビルド
- Dockerイメージには実行に必要な最小限のファイルのみ含める
- イメージサイズ: 約220MB(node:20-slim使用)
🔐 セキュリティ考慮事項
-
Subscription ID:
terraform.tfvars
はGitHubに公開しない- 必要に応じて
.gitignore
に追加
-
ACR認証:
- 管理者権限は開発・テスト用
- 本番環境ではService Principalやマネージドアイデンティティを使用
-
ネットワーク:
- デフォルトでパブリックアクセス
- 必要に応じてVNet統合を検討
📄 ライセンス
このプロジェクトはMITライセンスの下で公開されています。
🤝 貢献
プルリクエストやイシュー報告を歓迎します。貢献する前に:
- 既存のコードスタイルに従ってください
- Terraformのフォーマットを実行してください:
terraform fmt
- TypeScriptのリントを実行してください:
npm run lint
(設定されている場合)