# MCP Server チャットUI連携 Model Context Protocol サーバ ## 概要 本プロジェクトは、チャットUIとバックエンドサービス(Discovery Finder、Discovery Service、ドローン航路システム)を連携するMCPサーバです。OpenAPI仕様またはSAMMアスペクトモデル(TTL形式)で定義されたサービスを、MCPツールとして公開します。 ## 技術スタック - **Node.js**: 18.x以上 - **TypeScript**: 5.x - **Fastify**: 5.x - **MCP SDK**: @modelcontextprotocol/sdk (StreamableHTTP) - **Zod**: スキーマ検証 - **OpenAPI Parser**: @apidevtools/swagger-parser - **RDF/Turtle**: N3.js ## 主要機能 ### スキーマ変換機能 #### OpenAPI対応 OpenAPIスキーマからZodスキーマへの変換をサポートします。 - **oneOf**: `z.union()`に変換 - **anyOf**: 全組み合わせのユニオンに変換 - **allOf**: オブジェクトのマージに変換 - **パスパラメータ**: URL内の`{param}`を自動置換 #### TTL/SAMMアスペクトモデル対応 SAMMアスペクトモデルとAPI定義(TTL形式)からMCPツールを生成します。 - **SAMM Aspect Model**: プロパティ、エンティティ、特性、オペレーション抽出 - **API Definition**: ODS/Hydra API仕様からHTTPメソッド、パス、パラメータ抽出 - **デバッグログ**: 各処理フェーズで詳細なログ出力 ### デバッグ機能 - Fastify統合ロガーによる詳細ログ出力 - API呼び出し時のリクエスト/レスポンス情報をログ出力 ## セットアップ ### 1. 依存関係のインストール ```bash npm install ``` ### 2. 環境変数の設定 `.env-default`を`.env`にコピーして環境変数を設定します。 ```bash cp .env-default .env ``` ### 3. ビルド ```bash npm run build ``` ### 4. 起動 ```bash npm start ``` 開発モード(ホットリロード): ```bash npm run dev ``` ## 設定 ### サービス設定ファイル `src/config/service-config.yaml`でサービスを設定します。 #### OpenAPI形式の例 ```yaml server: host: 0.0.0.0 port: 8000 logLevel: info services: - name: discoveryFinder displayName: Discovery Finder specType: openapi specPath: ./specs/discovery-finder.yaml timeout: 30000 auth: type: apiKey headerName: X-API-Key secretEnv: DISCOVERY_FINDER_API_KEY defaultBaseUrl: ${DISCOVERY_FINDER_URL:-} mock: enabled: false responseFile: ./mocks/discovery-finder-responses.json ``` #### TTL/SAMMアスペクトモデル形式の例 ```yaml services: - name: discoveryFinder displayName: Discovery Finder specType: ttl aspectModelPath: ./specs/DiscoveryFinder_AspectModel.ttl apiDefinitionPath: ./specs/DiscoveryFinder_API.ttl instancePath: ./specs/DiscoveryFinder_Instance.ttl timeout: 30000 auth: type: apiKey headerName: X-API-Key secretEnv: DISCOVERY_FINDER_API_KEY defaultBaseUrl: ${DISCOVERY_FINDER_URL:-} mock: enabled: false responseFile: ./mocks/discovery-finder-responses.json ``` **specTypeの違い:** - `openapi`: OpenAPI/Swagger仕様ファイル(YAML/JSON)を使用 - `ttl`: SAMMアスペクトモデル(Turtle/RDF形式)を使用 ### ツール登録除外設定 `excludePatterns`を設定すると、ツール名にマッチするツールをMCPツールとして登録しないようにできます。正規表現で指定します。 ```yaml services: - name: discoveryFinder displayName: Discovery Finder specType: openapi specPath: ./specs/discovery-finder.yaml timeout: 30000 auth: type: apiKey headerName: X-API-Key secretEnv: DISCOVERY_FINDER_API_KEY defaultBaseUrl: ${DISCOVERY_FINDER_URL:-} # 除外するツール名パターンをリストで指定(正規表現) excludePatterns: - '^discoveryFinder_root' - '_delete$' ``` 除外設定が有効な場合、起動ログに登録ツール数・除外ツール数が出力されます。 ### 認証設定 `auth.type`で認証方式を選択します。 | type | 説明 | |------|------| | `none` | 認証なし | | `apiKey` | APIキーをヘッダに付与。`headerName`でヘッダ名、`secretEnv`で値を格納する環境変数を指定 | | `bearer` | BearerトークンをAuthorizationヘッダに付与。`secretEnv`でトークンを格納する環境変数を指定 | | `ods` | ODS認証(リソースオーナーパスワードクレデンシャルフロー)。`ods`配下に認証パラメータを指定 | #### ODS認証の設定例 ```yaml services: - name: exampleOdsService displayName: Example ODS Service specType: openapi specPath: ./specs/example-ods.yaml timeout: 30000 defaultBaseUrl: ${EXAMPLE_ODS_URL:-} auth: type: ods ods: # 認証APIエンドポイントURL tokenEndpoint: ${ODS_TOKEN_ENDPOINT:-} # クライアントID clientId: ${ODS_CLIENT_ID:-} # クライアントシークレット clientSecret: ${ODS_CLIENT_SECRET:-} # ログインユーザID(省略可) loginUserId: ${ODS_LOGIN_USER_ID:-} # パスワード(省略可) password: ${ODS_PASSWORD:-} # 認証APIに付与するAPIKEYヘッダ名 apiKeyHeaderName: ${ODS_APIKEY_HEADER_NAME:-X-API-Key} # 認証APIに付与するAPIKEYヘッダ値 apiKeyValue: ${ODS_APIKEY_VALUE:-} # サービス呼び出し時に付与するAPIキーヘッダ名(省略可) serviceApiKeyHeaderName: ${ODS_SERVICE_APIKEY_HEADER_NAME:-} # サービス呼び出し時に付与するAPIキーヘッダ値(省略可) serviceApiKeyValue: ${ODS_SERVICE_APIKEY_VALUE:-} mock: enabled: false responseFile: ./mocks/example-ods-responses.json ``` ODS認証では取得したアクセストークンをサービスごとにキャッシュし、有効期間内は再利用します。期限切れ直前(30秒前)に自動で再認証を行います。 ### モック機能 各サービスのモック機能を有効にすると、実際のAPI呼び出しを行わずに事前定義されたレスポンスを返します。 #### モックレスポンスファイル モックレスポンスファイルのキーはoperationIdに対応します。`|`区切りで複数のoperationIdを1つのエントリに集約できます。 モックレスポンスファイル例 (`mocks/discovery-finder-responses.json`): ```json { "root_get|rootGet": { "statusCode": 200, "body": {} }, "get_discovery_services|getDiscoveryServices": { "statusCode": 200, "body": { "available_services": [] } }, "default": { "statusCode": 200, "body": { "message": "Mock response" } } } ``` - キー名が`|`を含む場合、`|`で分割した各operationIdに対して同じレスポンスが返されます - `default`キーはoperationIdにマッチするエントリがない場合のフォールバックです #### 複数モックファイルのマージ `responseFile`に配列を指定すると、複数のファイルをマージして使用できます。同じキーが重複した場合は先に記述されたファイルの値が優先されます。 ```yaml mock: enabled: true responseFile: - ./mocks/service-responses.base.json - ./mocks/service-responses.override.json ``` ## API ### MCP StreamableHTTP エンドポイント 本サーバは**StreamableHTTP**トランスポートで動作します。 #### ステートフルエンドポイント - **URL**: `http://localhost:8000/mcp` - **Method**: POST - **Content-Type**: application/json - **説明**: セッション管理あり。複数回のやり取りで状態を保持。 #### ステートレスエンドポイント - **URL**: `http://localhost:8000/mcp/noses` - **Method**: POST - **Content-Type**: application/json - **説明**: セッション管理なし。単一のリクエスト-レスポンス。 #### initialize リクエスト (ステートフルモード) 接続を初期化します。 ```json { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "ChatUI", "version": "1.0.0" } } } ``` #### tools/list リクエスト 利用可能なツール一覧を取得します。 ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} } ``` #### tools/call リクエスト ツールを実行します。 ```json { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "discoveryService_findDomainApps", "arguments": { "baseUrl": "http://10.0.1.3:8000", "location": { "lat": 35.6895, "lng": 139.6917 } } } } ``` ### ヘルスチェック - **URL**: `http://localhost:8000/health` - **Method**: GET ## ディレクトリ構造 ``` mcp-server/ ├── src/ │ ├── index.ts # エントリーポイント │ ├── server.ts # Fastifyサーバ設定 │ ├── config/ # 設定管理 │ │ ├── config.ts # 設定読み込み │ │ ├── types.ts # 設定型定義 │ │ └── service-config.yaml # サービス設定ファイル │ ├── mcp/ # MCPコアロジック │ │ ├── mcp-server.ts # MCP Service (StreamableHTTP) │ │ ├── tool-registry.ts # ツール登録・管理 │ │ └── tool-executor.ts # ツール実行・検証 (Zod) │ ├── schema/ # スキーマ生成 │ │ ├── schema-generator.ts # Zod変換基底クラス │ │ ├── openapi-schema-generator.ts # OpenAPI → MCPツールスキーマ生成 │ │ ├── ttl-parser.ts # TTLファイルパーサ (N3.js) │ │ ├── ttl-schema-extractor.ts # SAMM要素抽出 │ │ └── ttl-schema-generator.ts # TTL/SAMM → MCPツールスキーマ生成 │ ├── api/ # API Client │ │ ├── api-client.ts # バックエンドAPI呼び出し │ │ └── ods-token-manager.ts # ODS認証トークン取得・キャッシュ管理 │ ├── cli/ # CLIツール │ │ └── test-ods-auth.ts # ODS認証動作確認スクリプト │ ├── error/ # エラー処理 │ │ ├── error-types.ts # エラー型定義 │ │ └── error-handler.ts # エラーハンドラ │ └── types/ # 型定義 │ └── n3.d.ts # N3.jsの型定義 ├── specs/ # OpenAPI/SAMM仕様 ├── mocks/ # モックレスポンス ├── .env-default # 環境変数テンプレート ├── package.json ├── tsconfig.json └── README.md ``` ## ライセンス - 本リポジトリはMITライセンスで提供されています。 - ソースコードおよび関連ドキュメントの著作権はIntent Exchange株式会社に帰属します。 ## 免責事項 - 本リポジトリの内容は予告なく変更・削除する可能性があります。 - 本リポジトリの利用により生じた損失及び損害等について、いかなる責任も負わないものとします。