Skip to main content
Glama

akij-hr-data-mcp

本番利用可能な、読み取り専用のリモートModel Context Protocol (MCP)サーバーで、単一のGoogle Driveフォルダ(AKIJ HR DATAリポジトリ)を、最新のStreamable HTTPトランスポートを通じてMCP互換クライアントに公開します。

これは汎用Drive MCPです。XLSX、XLS、CSV、PDF、DOCX、TXT、画像、およびネイティブのGoogle Docs/Sheets/Slidesファイルを扱います。Excel専用ツールではありません。


1. このプロジェクトの機能

  • Google Driveへの接続にはサービスアカウントを使用します(ユーザーOAuthフローやブラウザログインは不要)。

  • すべての操作を設定済みの1つのフォルダ(GOOGLE_DRIVE_FOLDER_ID)とそのサブフォルダに制限します。ツリー外のファイルは、サービスアカウントから技術的に見えたとしても決して返されません。

  • ファイルの発見と読み取りのための11個のMCPツールを公開します(一覧、検索、メタデータ、コンテンツ、Excel/CSV/PDF/DOCX向けのフォーマット別抽出)。

  • 標準のNode/Express HTTPサーバーとして、単一のPOST /mcpエンドポイント(Streamable HTTPトランスポート)とGET /healthエンドポイントを備えて実行されます。Render(または任意のNodeホスト)にデプロイできるため、PCの電源がオフでも稼働し続けます。

  • すべてのMCPリクエストでAPIキー認証を強制します。

  • 厳密に読み取り専用です。Driveファイルのアップロード、編集、削除、名前変更、移動、共有、権限変更を行うコードパスは一切ありません。

Related MCP server: Google Drive MCP Server

2. アーキテクチャ

Google Drive (AKIJ HR DATA folder)
        ↓ Drive API v3 (read-only scope)
Google Service Account (GCP_KEY_BASE64)
        ↓
GoogleDriveClient (src/google-drive.ts) — enforces folder-tree scope
        ↓
MCP Server (src/mcp-server.ts) — 11 tools, Zod-validated inputs
        ↓
Express app (src/index.ts) — API-key auth, Streamable HTTP transport
        ↓ POST /mcp  (stateless, one transport per request)
        ↓
Render (always-on host)
        ↓ HTTPS
Remote MCP Clients (Claude, other MCP-compatible clients)

サーバーはステートレスです。各POST /mcpリクエストは独自のMcpServer + StreamableHTTPServerTransportインスタンス(sessionIdGenerator: undefined)を取得するため、セッションアフィニティは不要で、Render上でスティッキーセッションなしに水平スケーリングできます。

プロジェクト構造

src/
  index.ts            Express app: /health, /mcp, startup
  config.ts           Environment variable loading/validation
  auth.ts             API-key authentication middleware
  google-auth.ts      Decodes GCP_KEY_BASE64 → JWT auth client
  google-drive.ts      Drive API client with folder-scope enforcement
  mcp-server.ts        McpServer wiring: registers all 11 tools

  tools/
    files.ts           list_files, get_file_metadata, get_file_content, list_supported_files
    search.ts           search_files, search_repository
    excel.ts            inspect_excel, read_excel_sheet
    csv.ts               read_csv
    pdf.ts               extract_pdf_text
    docx.ts              extract_docx_text

  utils/
    errors.ts            Typed AppError hierarchy + safe error serialization
    limits.ts            Size/row/timeout/pagination limits
    mime-types.ts         MIME → file-category classification

tests/                  Jest test suite (46 tests, 10 suites)
.env.example
.gitignore
render.yaml             Render Blueprint (optional one-click deploy)
README.md
package.json
tsconfig.json
jest.config.cjs

3. 前提条件

  • Node.js 20+ と npm

  • Google Drive APIが有効なGoogle Cloudプロジェクト

  • AKIJ HR DATA Driveフォルダで閲覧者アクセスが共有されているGoogleサービスアカウント

  • GitHubアカウント(リポジトリからRenderへデプロイするため)

  • Renderアカウント

4. インストール

npm install

5. 環境変数

変数

必須

説明

PORT

任意(デフォルト 10000)

HTTPサーバーがリッスンするポート。Renderが自動的に設定します。

GOOGLE_DRIVE_FOLDER_ID

必須

このMCPが制限されるDriveフォルダID。

GCP_KEY_BASE64

必須

Base64エンコードされたサービスアカウントのJSONキー。

API_KEYS

必須

POST /mcpで有効なAPIキーのカンマ区切りリスト。

テンプレートは.env.exampleを参照してください(実際のシークレットはコミットされません)。

6. Google Cloudの設定

  1. console.cloud.google.comにアクセスし、プロジェクトを選択/作成します。

  2. APIとサービス → ライブラリ → Google Drive APIを有効にします。

  3. APIとサービス → 認証情報 → 認証情報を作成 → サービスアカウント。

  4. 名前を付けます(例: akij-hr-data-mcp)。プロジェクトレベルのIAMロールは不要です。

  5. 新しいサービスアカウントを開き、キー → 新しいキーを追加 → 新しいキーを作成 → JSONを選択します。gcp-key.jsonファイルがダウンロードされますが、このファイルをコミットしないでください。

  6. サービスアカウントのメールアドレスを控えます(akij-hr-data-mcp@your-project.iam.gserviceaccount.comのような形式)。

7. Google Driveの権限

  1. Google DriveでAKIJ HR DATAフォルダを開きます(フォルダID: 1oxYLPcC9MPVuxsbeP0kGgYhLmkxt0w2o)。

  2. 共有をクリックし、サービスアカウントのメールアドレスを貼り付けて、閲覧者アクセスを許可します。

  3. 編集者/オーナーは許可しないでください。このサーバーはDriveに書き込むことはないため、閲覧者で十分であり、より安全です。

8. ローカルセットアップ

npm install
cp .env.example .env
# fill in GOOGLE_DRIVE_FOLDER_ID, GCP_KEY_BASE64, API_KEYS in .env
npm run dev

npm run devは、tsx watchを使用してTypeScriptサーバーを直接実行します(ローカルでの反復にビルドステップは不要です)。

9. GCP_KEY_BASE64の生成

生のサービスアカウントJSONをチャットやソースコード、.env.exampleに貼り付けることは絶対にしないでください。ダウンロードしたgcp-key.jsonからbase64値をローカルで生成し、ローカルの.env(gitignore対象)またはRenderの環境変数設定にのみ配置してください。

PowerShell:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("$HOME\Downloads\gcp-key.json")) | Set-Clipboard

これによりキーファイルが読み取られ、base64文字列が直接クリップボードにコピーされます。.env(ローカル)またはRenderダッシュボード(デプロイ用)のGCP_KEY_BASE64の値として貼り付けてください。gcp-key.jsonがダウンロードフォルダにない場合はパスを調整してください。

クリップボードではなく端末に出力したい場合は:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("$HOME\Downloads\gcp-key.json"))

10. ローカルテスト

サーバーを起動:

npm run dev

ヘルスチェック:

curl http://localhost:10000/health

curlを使用してMCPツール(例: list_files)を呼び出すには、initialize → tools/callのシーケンスを使うか、Streamable HTTP対応のMCPクライアントをhttp://localhost:10000/mcpに向け、ヘッダーX-Api-Key: <one of your API_KEYS>を指定します。

11. ビルド

npm run build

src/(TypeScript、NodeNext ESM)をdist/にコンパイルします。ファイルを出力せずに型チェックを行うにはnpm run typecheckを実行します。

テストスイートを実行:

npm test

これはJestをインバンドで実行します(10スイート、46テスト: config、auth、Google auth、Driveフォルダスコープの強制、全11ツール、/health・/mcp HTTPエンドポイント)。

12. GitHubのセットアップ

git init
git add .
git commit -m "Initial commit: akij-hr-data-mcp"
git branch -M main
git remote add origin https://github.com/<your-username>/akij-hr-data-mcp.git
git push -u origin main

.env、gcp-key.json、*.pem、*.keyはすでにgitignoreされています。コミット前にgit statusで機密情報がステージングされていないことを確認してください。

13. Renderへのデプロイ

  1. render.comにアクセス → New → Web Service。

  2. GitHubリポジトリ(akij-hr-data-mcp)を接続します。

  3. Renderはrender.yaml(Blueprint)を自動的に検出するか、手動で設定します:

    • ビルドコマンド: npm install && npm run build

    • 起動コマンド: npm start

    • ヘルスチェックパス: /health

  4. Renderダッシュボードで環境変数(セクション14)を追加します。絶対にコミットしないでください。

  5. デプロイします。Renderがビルドしてサービスを起動し、PCとは無関係に稼働し続けます。

14. Renderの環境変数

Render → サービス → Environmentでこれらを設定します:

PORT=10000
GOOGLE_DRIVE_FOLDER_ID=1oxYLPcC9MPVuxsbeP0kGgYhLmkxt0w2o
GCP_KEY_BASE64=<paste the base64 string from step 9>
API_KEYS=<comma-separated production keys, e.g. key-abc123,key-def456>

強力なランダムAPIキーを生成します。例:

[Convert]::ToBase64String([Guid]::NewGuid().ToByteArray()) -replace '[+/=]',''

15. ヘルスチェックエンドポイント

GET /health
{ "status": "ok", "timestamp": "2026-08-17T12:00:00.000Z" }

認証は不要です。シークレットや内部状態は公開されません。

16. MCPエンドポイント

POST /mcp
  • MCP Streamable HTTPトランスポート(@modelcontextprotocol/sdkのStreamableHTTPServerTransport)を実装し、ステートレス(sessionIdGenerator: undefined)です。SSEのみのフォールバックはありません。

  • 認証が必要です: Authorization: Bearer <API_KEY>またはX-Api-Key: <API_KEY>ヘッダー。

  • GET /mcpおよびDELETE /mcpは405を返します。このサーバーはセッションを維持せず、オプションのSSEストリームもサポートしません。

17. リモートMCPをクライアントに接続する

デプロイ後、MCPエンドポイントは次のとおりです:

https://<your-render-service>.onrender.com/mcp

リモート/HTTPサーバーをサポートするMCPクライアントの場合は、次の内容でサーバーエントリを追加します:

  • URL: https://<your-render-service>.onrender.com/mcp

  • トランスポート: Streamable HTTP

  • ヘッダー: X-Api-Key: <one of your API_KEYS>(または Authorization: Bearer <API_KEY>)

汎用クライアント設定の例:

{
  "mcpServers": {
    "akij-hr-data": {
      "url": "https://<your-render-service>.onrender.com/mcp",
      "headers": {
        "X-Api-Key": "<API_KEY>"
      }
    }
  }
}

18. セキュリティ

  • 読み取り専用: このコードベースには、アップロード/削除/編集/名前変更/移動/共有/権限変更ツールは存在しません。

  • フォルダスコープ: GoogleDriveClient.assertFileInScopeは、メタデータやコンテンツが返される前に各ファイルのparentsチェーンを設定されたルートまでたどります。ツリー外のファイルはForbiddenErrorを発生させます。

  • APIキー認証: すべてのPOST /mcpリクエストは、タイミングセーフな比較(crypto.timingSafeEqual)でAPI_KEYSに対してチェックされます。キーがない、または無効な場合は401を返します。

  • 認証情報はログやレスポンスに決して出力されません: デコードされたサービスアカウントJSONはgoogle-auth.ts内に留まります。いかなるツール、ログ行、エラーメッセージもそれを表面化できません。エラーレスポンスはtoSafeErrorMessageを通過し、スタックトレースと生の上流エラーボディが除去されます。

  • サイズ/出力制限: ダウンロードは上限付き(LIMITS.MAX_DOWNLOAD_BYTES / MAX_PARSE_BYTES)、テキスト抽出は切り詰め(MAX_TEXT_OUTPUT_CHARS)、行はページング(DEFAULT_ROW_LIMIT/MAX_ROW_LIMIT)、すべてのGoogle API送信呼び出しにはタイムアウト(GOOGLE_API_TIMEOUT_MS)があります。

  • 拡張可能な認証: req.identityは小規模で安定した形状({ keyId })であり、将来のユーザー別キー、OAuth、ロールベースの認可レイヤーがすべての呼び出し箇所を変更せずにリッチなクレームを追加できるように設計されています。

  • 既知の依存関係アドバイザリ: レガシーな.xls解析に使用されるxlsx(SheetJS)パッケージには、公開済みの高深刻度アドバイザリ(プロトタイプ汚染 / ReDoS)があります。これは自分のDriveフォルダから取得した内部のアクセス制御済みファイルにのみ使用され(任意のインターネットアップロードには使用されません)、解析前にファイルサイズが制限されます。定期的にnpm auditを実行し、パッチ済みリリースが利用可能になったら置き換えを検討してください。

セキュリティチェックリスト

  • gcp-key.jsonがgitにコミットされていない

  • .envがgitにコミットされていない

  • API_KEYSがRenderで強力なランダム値に設定されている(ローカル開発値ではない)

  • サービスアカウントがDriveフォルダに対して閲覧者のみである

  • GOOGLE_DRIVE_FOLDER_IDが意図したリポジトリフォルダと一致している

  • Render環境変数がダッシュボードで直接設定されており、render.yamlのコミットされた値には設定されていない

19. トラブルシューティング

症状

原因

対処法

ConfigErrorですぐにサーバーが終了する

環境変数が欠落している、または無効

エラーメッセージに記載されている変数をセクション5と照合して確認する

GCP_KEY_BASE64 is not valid base64

誤ったファイルがエンコードされた、またはコピー&ペーストで文字列が切り詰められた

セクション9のPowerShellコマンドで再生成する

Drive APIからの403 Forbidden

サービスアカウントがフォルダに共有されていない、または誤ったメールアドレスと共有されている

セクション7を再確認し、キーのclient_emailが一致していることを確認する

File ... is outside the configured repository folder

GOOGLE_DRIVE_FOLDER_IDのツリー内にないfile_idを渡した

list_supported_filesまたはsearch_repositoryを使用して有効なIDを取得する

すべての/mcp呼び出しで401

APIキーが欠落している、または正しくない

API_KEYSのいずれかのエントリと一致するX-Api-KeyまたはAuthorization: Bearer <key>を送信する

FILE_TOO_LARGEエラー

ファイルが設定されたバイト制限を超えている

これは意図的です。大きなファイルはメモリに完全に読み込むのではなく拒否されます(src/utils/limits.tsを参照)

Renderサービスがスリープする / コールドスタートが遅い

無料/スターターのRenderプランはアイドル後に休止する

Renderプランをアップグレードするか、最初のリクエスト時のコールドスタート遅延を受け入れる

ローカルでテストが数分間ハングする

ts-jestが並列ワーカーで完全なgoogleapis型を型チェックしている

すでに緩和済み: npm testはJestを--runInBandで実行します。そのフラグを削除しないでください


残りの手動ステップ(あなたにしかできないこと)

  1. GCP_KEY_BASE64 を生成し、ダウンロードした gcp-key.json(セクション9)を使用して、テスト用にローカルの .env に設定してください。

  2. AKIJ HR DATA ドライブフォルダを共有し、サービスアカウントのメールアドレスを閲覧者として追加してください(セクション7)。

  3. ローカルで実行し(npm run dev)、実際の Drive フォルダに対して GET /health と実際の list_files 呼び出しが機能することを確認してください。

  4. GitHub にプッシュしてください(セクション12)。

  5. Render Web Service を作成し、リポジトリを接続して、Render ダッシュボードで4つの環境変数を設定してください(セクション13–14)— Render が自動的にビルドしてデプロイします。

  6. 本番用の API_KEYS を生成し(ローカル開発用のキーとは異なるもの)、MCP クライアント用に安全に保管してください。

  7. MCP クライアントを接続し、https://<your-render-service>.onrender.com/mcp を接続先に指定してください(セクション17)。

Related MCP Connectors

Related MCP Servers