ACG SmartHR MCP

Model Context Protocol Server for SmartHR

v0.1.0

概要

ACG SmartHR MCP は、あおぞらケアグループ(ACG)が社内利用のために構築した Model Context Protocol (MCP) サーバーです。

AI アシスタント(Claude)から SmartHR API を利用して人事データを安全に参照・更新できるようにします。 8 つのツールを提供し、従業員情報の閲覧・検索・更新・登録、部署・役職の参照、給与明細の参照が可能です。

8
利用可能ツール
4
認証レイヤー
2
接続モード

アーキテクチャ

Core + Shell パターン

トランスポート非依存の Core(ビジネスロジック)と、 差し替え可能な Shell(接続方式)で構成されています。

graph TB subgraph Clients["クライアント"] CC["Claude Code"] CD["Claude Desktop"] CW["Cowork / claude.ai"] APP["自社アプリ"] end subgraph Shell["Shell(トランスポート層)"] STDIO["stdio Shell"] HTTP["HTTP Shell
Hono + Streamable HTTP"] end subgraph Core["Core(ビジネスロジック)"] AUTH["4層認証"] TOOLS["ツール定義
8ツール"] PII["PII フィルタ"] AUDIT["監査ログ"] RL["レート制限"] end SMARTHR["SmartHR API"] CC --> STDIO CD --> STDIO CW --> HTTP APP --> HTTP STDIO --> AUTH HTTP --> AUTH AUTH --> TOOLS TOOLS --> PII TOOLS --> AUDIT TOOLS --> RL RL --> SMARTHR style Core fill:#e0f2fe,stroke:#0284c7 style Shell fill:#f0fdf4,stroke:#16a34a style Clients fill:#fef3c7,stroke:#d97706

接続モード

モード トランスポート 対象クライアント 認証
stdio 標準入出力 Claude Code, Claude Desktop 環境変数(ローカル実行)
HTTP Streamable HTTP Cowork, claude.ai, 自社アプリ OAuth 2.1(Google OIDC 委譲 + JWT)

認証フロー

4 層認証モデル

SmartHR API トークンにスコープ制限がないため、アプリケーション側で 4 層の認証・認可を実装しています。

flowchart TD REQ["リクエスト受信"] --> L1 L1{"Layer 1: トランスポート認証"} L1 -->|stdio| L1A["ローカル実行 = 信頼済み"] L1 -->|HTTP| L1B["OAuth 2.1 JWT 検証"] L1B -->|検証失敗| DENY1["401 Unauthorized"] L1A --> L2 L1B -->|検証成功| L2 L2{"Layer 2: ドメイン検証"} L2 -->|"hd == aozora-cg.com"| L3 L2 -->|"それ以外"| DENY2["403 Forbidden"] L3{"Layer 3: ユーザー許可リスト"} L3 -->|"登録済み"| L4 L3 -->|"未登録"| DENY3["403 Forbidden"] L4{"Layer 4: ツール権限"} L4 -->|"read+write+pay"| ALL["全ツール利用可"] L4 -->|"read+write"| WRITE["閲覧+更新"] L4 -->|"read"| LIMITED["閲覧のみ"] style L1 fill:#fef3c7,stroke:#d97706 style L2 fill:#e0f2fe,stroke:#0284c7 style L3 fill:#f0fdf4,stroke:#16a34a style L4 fill:#fce7f3,stroke:#db2777 style DENY1 fill:#fee2e2,stroke:#dc2626 style DENY2 fill:#fee2e2,stroke:#dc2626 style DENY3 fill:#fee2e2,stroke:#dc2626

ロールとアクセス制御

Firestore 許可リストに登録されたアカウントのみ接続可能です。未登録のアカウントはドメイン内でもアクセスできません。

admin 全操作(削除を除く)
  • ✅ 従業員の閲覧・検索
  • ✅ 従業員の更新・新規登録
  • ✅ 給与明細の閲覧
  • ✅ 部署・役職の閲覧
  • ✅ 生年月日・性別・連絡先を含む詳細情報
  • ❌ 削除操作(未実装・スコープ外)
readonly 読み取りのみ
  • ✅ 従業員の閲覧・検索
  • ❌ 従業員の更新・新規登録
  • ❌ 給与明細の閲覧
  • ✅ 部署・役職の閲覧
  • ❌ 生年月日・性別・連絡先(自動除外)
  • ❌ 削除操作(未実装・スコープ外)

ツール別アクセス権限

ツール 操作内容 必要権限 admin readonly
list_employees 従業員一覧 read
get_employee 従業員詳細 read
search_employees 従業員検索 read
list_departments 部署一覧 read
list_positions 役職一覧 read
update_employee 従業員情報の更新 write
create_employee 従業員の新規登録 write
get_pay_statements 給与明細の取得 pay_statements

※ 削除操作(DELETE)は全ロールで利用不可(未実装・安全性のためスコープ外)

⚠️ コネクタ設定画面の表示について

claude.ai のコネクタ設定画面にはサーバーが提供する全ツールが一覧表示されますが、表示 ≠ 実行可能です。 各ツールの実行時にサーバー側でユーザーの権限を検証し、権限不足の場合はリクエストを拒否します(fail-closed)。

ツール一覧

list_employees readonly

従業員一覧を取得します。ページネーション対応。

パラメータ

pageページ番号(1始まり、任意)
per_page1ページあたりの件数(最大100、任意)

使用例(Claude への指示)

"従業員一覧を10件取得して"
get_employee readonly

従業員IDを指定して詳細情報を取得します。

パラメータ

id *SmartHR 従業員ID(必須)

使用例

"従業員ID abc123 の詳細を見せて"
search_employees readonly

名前・社員番号などで従業員を検索します。

パラメータ

query *検索キーワード(必須)
pageページ番号(任意)
per_page1ページあたりの件数(任意)

使用例

"田中さんの情報を検索して"
get_pay_statements pay_statements

給与明細を取得します。従業員ID・年・月で絞り込み可能。pay_statements 権限必須。

パラメータ

crew_id従業員ID(任意)
year年(例: 2026、任意)
month月(1-12、任意)
pageページ番号(任意)
per_page1ページあたりの件数(任意)

使用例

"2026年3月の給与明細を見せて"
list_departments readonly

部署一覧を取得します。

パラメータ

pageページ番号(任意)
per_page1ページあたりの件数(任意)

使用例

"部署の一覧を表示して"
list_positions readonly

役職一覧を取得します。

パラメータ

pageページ番号(任意)
per_page1ページあたりの件数(任意)

使用例

"役職の一覧を整理して"
update_employee write

従業員情報を部分更新します(PATCH)。変更するフィールドのみ指定します。

パラメータ

id *SmartHR 従業員ID(必須)
last_name姓(任意)
first_name名(任意)
emp_code社員番号(任意)
entered_at入社日(任意)
resigned_at退職日(任意)
department部署ID(任意)
position役職ID(任意)

使用例

"田中さんの部署を人事部に変更して"
create_employee write

新しい従業員を SmartHR に登録します。

パラメータ

last_name *姓(必須)
first_name *名(必須)
emp_code社員番号(任意)
entered_at入社日(任意)
department部署ID(任意)
position役職ID(任意)

使用例

"新入社員の山田花子さん(社員番号: 2001、入社日: 2026-04-01)を登録して"

セットアップガイド

推奨 Cowork / claude.ai

Team プラン: 組織オーナーが 1 回コネクタを登録すれば、メンバーは個別にカスタムコネクタを追加する必要はありません。メンバーは「連携させる」をクリックして Google 認証するだけで利用開始できます。

管理者(組織オーナー)の操作(初回のみ):

  1. 設定 > コネクタ を開く
  2. カスタムコネクタを追加 をクリック
  3. 名前: SmartHR
  4. URL: MCP サーバーの /mcp エンドポイント URL を入力
  5. 追加 をクリック

メンバーの操作:

  1. 設定 > コネクタ で「SmartHR」の 連携/連携させる をクリック
  2. Google アカウント(@aozora-cg.com)で認証
  3. 会話の + ボタン > コネクタ で SmartHR を ON にして使用

Claude Code(stdio)

.claude.json に以下を追加:

{
  "mcpServers": {
    "smarthr": {
      "command": "npx",
      "args": ["tsx", "packages/mcp-smarthr/src/index.ts"],
      "env": {
        "SMARTHR_API_KEY": "your-api-key",
        "SMARTHR_TENANT_ID": "your-tenant-id",
        "MCP_USER_EMAIL": "you@aozora-cg.com",
        "MCP_USER_ROLE": "readonly"
      }
    }
  }
}

Claude Desktop(stdio)

claude_desktop_config.json に以下を追加:

{
  "mcpServers": {
    "smarthr": {
      "command": "node",
      "args": ["/path/to/packages/mcp-smarthr/dist/index.js"],
      "env": {
        "SMARTHR_API_KEY": "your-api-key",
        "SMARTHR_TENANT_ID": "your-tenant-id",
        "MCP_USER_EMAIL": "you@aozora-cg.com",
        "MCP_USER_ROLE": "readonly"
      }
    }
  }
}

セキュリティ

flowchart LR subgraph Protection["多層防御"] direction TB IP["IP 制限
Cloud Armor 移行予定"] OAUTH["OAuth 2.1
Google OIDC + JWT"] DOMAIN["ドメイン制限
@aozora-cg.com"] RBAC["パーミッション制御
read / write / pay"] PIIF["PII フィルタ
個人情報保護"] AUDITL["監査ログ
全操作記録"] end IP --> OAUTH --> DOMAIN --> RBAC --> PIIF --> AUDITL style Protection fill:#f0fdf4,stroke:#16a34a

IP アドレス制限(Cloud Armor 移行予定)

Cloud Armor による IP 制限を導入予定。Anthropic のサーバー IP 範囲のみ許可し、 直接アクセスを遮断します。現在は OAuth 2.1 認証で保護されています。

PII フィルタリング

readonly ロールでは生年月日・性別・メールアドレス・電話番号が自動的に除外されます。 マイナンバーは全ロールで除外されます。

監査ログ

全ツール呼び出しが構造化ログとして記録されます。 ツール名・ユーザーメール・パラメータ(PII マスク済み)・実行時間を含みます。

レート制限

SmartHR API のレート制限(10 req/sec)に合わせたトークンバケット方式のスロットリングを実装。 429 レスポンス時は自動リトライします。

デプロイ構成

graph LR subgraph GCP["Google Cloud Platform"] CR["Cloud Run
mcp-smarthr"] SM["Secret Manager
API Key / Tenant ID"] FS["Firestore
監査ログ / 許可リスト"] CL["Cloud Logging
構造化ログ"] end CR --> SM CR --> FS CR --> CL CR --> SMARTHR["SmartHR API"] ANTHROPIC["Anthropic
(Cowork/claude.ai)"] --> CR style GCP fill:#e0f2fe,stroke:#0284c7
コンポーネント 技術スタック 役割
HTTP サーバー Hono + @modelcontextprotocol/hono MCP Streamable HTTP トランスポート
ランタイム Node.js 22 (node:22-slim) コンテナ実行環境
OAuth 2.1 / JWT jose + google-auth-library JWT 検証 + Google OIDC 委譲
セッション管理 ステートレス Cloud Run スケーリング対応

FAQ

データの書き込み・更新はできますか?

はい。write 権限を持つユーザーは、従業員情報の更新(update_employee)と 新規登録(create_employee)が可能です。AI は実行前に必ず変更内容を確認し、 ユーザーの承認を得てから SmartHR API を呼び出します。 更新可能なフィールドは氏名・社員番号・入退社日・部署・役職に限定されています。

誰がアクセスできますか?

@aozora-cg.com ドメインのユーザーのみです。Team プランでは管理者がコネクタを登録した後、 チームメンバー全員が利用可能になります。個人プランでは各自がコネクタを登録します。

給与情報は誰でも見られますか?

いいえ。pay_statements 権限を持つユーザーのみが get_pay_statements ツールを利用できます。 権限のないユーザーが呼び出すと「権限不足」エラーが返ります。

操作ログは残りますか?

はい。全てのツール呼び出しが監査ログに記録されます(ツール名、ユーザー、パラメータ、実行時間)。 パラメータ内の個人情報は自動的にマスキングされます。ログは 7 年間保持されます。

Claude が計算ミスをする心配はありませんか?

MCP サーバーは SmartHR のデータをそのまま返します。AI が計算や加工をすることはありません。 給与計算などの金銭計算は、別途確定的なプログラムコードで処理されます(ADR-007)。

参考リンク