Claude Code × MCP で APIキー・シークレットを統合管理する — 1Password / GitHub Secrets / Vault の3パターン実装

Claude Code × MCP で APIキー・シークレットを統合管理する — 1Password / GitHub Secrets / Vault の3パターン実装

Claude Code環境でシークレットをMCPで統合管理する3パターンを実装レベルで解説。1Password op://URI連携、GitHub Codespaces・Actions連携、HashiCorp Vault dynamic secrets。mcp.json設定例とセキュリティリスク評価付き。

エンジニアのゆとです。

1Passwordの設定方法もシークレット管理の設計論も個別に書いてきた。

1Password MCPをClaude Codeに導入する完全ガイド — シークレット管理をVaultに一元化する
1Password MCPをClaude Codeに導入する完全ガイド — シークレット管理をVaultに一元化する1Password MCPサーバーをClaude Codeに接続する手順を完全解説。インストール・Vault設定・環境変数の自動注入・claude_desktop_config.jsonの設定方法から、実運用でのシークレット管理パターンまでカバー。読む →
AI Agent 時代のシークレット管理設計 — Vault・SSO・MCP の3層アーキテクチャ
AI Agent 時代のシークレット管理設計 — Vault・SSO・MCP の3層アーキテクチャAIエージェントが増えると秘密鍵の管理が破綻する。開発者個人・Agent・CI環境の3層に分けて設計する方法と、1Password/Vault/Doppler/AWS Secrets Managerのツール選定マトリクス、MCP×Vaultパターン、SSO+Token Lifecycle設計、監査ログ、鍵流出パターン3つを網羅した設計論。読む →

今回は「MCPプロトコルとしてシークレットを扱うとどうなるか」という角度で書く。ツールの使い方ではなく、「MCPがなぜシークレット管理に向くか」というアーキテクチャの話から始める。

なぜシークレット管理にMCPが向くのか

MCPの正式名称はModel Context Protocol。Anthropicが設計した、AIモデルと外部ツールをつなぐ標準プロトコルだ。

普通「MCPでシークレット管理」と言うと、「MCPサーバーがシークレット管理ツールへのインターフェースを提供する」という意味になる。1Password MCPを例にすると、Claudeが「この変数の値が必要」と判断したとき、1PasswordのVaultから実行時に値を取得してクライアントに渡す。

これがなぜ良いかを整理すると:

設定ファイルへの平文書き込みを排除できる

claude_desktop_config.json にAPIキーを書くと、Dotfilesでバックアップしたとき・バックアップソフトがクラウド同期したとき・Claudeのログに出力されたとき、に漏洩リスクがある。MCPを経由すると、設定ファイルには op://Vault/Item/Field という参照パスだけが残る。

アクセスログが残せる

Claudeがシークレットにアクセスするたびに、MCPサーバー側でログを取れる。「誰がいつどのシークレットを読んだか」の監査証跡が作れる。これは .env では不可能だ。

ローテーションが一元化できる

シークレットの実体をMCPサーバー側(VaultやGitHub Secrets)に置いておけば、ローテーション時に参照パスを変える必要がない。op://Personal/Stripe/api_key というパスは変わらず、Vault側の値だけ更新すれば全プロジェクトに即時反映される。

最小権限の実装が楽になる

MCPサーバーごとに「どのVault・どのシークレットへのアクセスを許可するか」を設定できる。プロジェクトAのMCP設定ではプロジェクトAのシークレットだけ、プロジェクトBでは別のセット、という分離ができる。

前提: MCP設定ファイルの場所と基本構造

Claude Codeのグローバル設定は ~/.claude/claude_desktop_config.json、プロジェクト固有の設定は .mcp.json(プロジェクトルート)に書く。

// ~/.claude/claude_desktop_config.json (全プロジェクト共通のMCP設定)
{
  "mcpServers": {
    "1password": {
      "command": "op-mcp",
      "env": {
        "OP_SERVICE_ACCOUNT_TOKEN": "ops_xxxxx"
      }
    }
  }
}
// .mcp.json (プロジェクト固有)
{
  "mcpServers": {
    "project-secrets": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-custom"],
      "env": {}
    }
  }
}

env ブロックに書いた値はMCPサーバーの起動時に環境変数として渡る。ここに平文でシークレットを書くのが「従来の問題」だ。以下の3パターンはこの env ブロックからシークレットを追い出すアプローチになる。

パターン1: 1Password CLI 連携(op:// URI)

最も完成度が高い方法。1Password CLI(op コマンド)が op:// URI を環境変数に展開する機能を使う。

仕組み

op run -- コマンドを使うと、起動するコマンドに渡る環境変数の中の op:// URI を、実行時にVaultから取得した値で置換してから起動する。

# 直接起動した場合(値が展開される)
op run -- node server.js

# op:// URIを環境変数に設定しておけば、値をインライン展開してくれる
OPENAI_API_KEY="op://Personal/OpenAI/api_key" op run -- node server.js

Claude Codeとの連携では、MCPサーバーの起動コマンドを op run -- でラップする:

// ~/.claude/claude_desktop_config.json
{
  "mcpServers": {
    "github": {
      "command": "op",
      "args": [
        "run",
        "--no-masking",
        "--",
        "npx",
        "-y",
        "@modelcontextprotocol/server-github"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "op://Personal/GitHub-PAT-MCP/token"
      }
    },
    "stripe": {
      "command": "op",
      "args": [
        "run",
        "--no-masking",
        "--",
        "npx",
        "-y",
        "@modelcontextprotocol/server-stripe"
      ],
      "env": {
        "STRIPE_SECRET_KEY": "op://Personal/Stripe-Dev/api_key"
      }
    }
  }
}
op:// URI の構造
op://[Vault名]/[Item名]/[Field名]

例:
op://Personal/OpenAI/api_key
op://Work/AWS-Dev/access_key_id
op://Work/AWS-Dev/secret_access_key

Vault名・Item名・Field名はいずれも1Passwordに登録してあるものと一致させる必要がある。スペースがある場合はダッシュか、URLエンコード(%20)で書く。

Service Account Tokenを使う場合

上記は「ローカルにデスクトップアプリがある前提」の方法だ。CI/CDや、デスクトップアプリのない環境では Service Account Token を使う。

1Password の管理コンソールで Service Account を作成し、アクセスするVaultを制限した上でトークンを発行する。

# Service Account Token を使う場合
export OP_SERVICE_ACCOUNT_TOKEN="ops_xxxxxxxxxx"

# op run の動作は同じ
op run -- node server.js

Claude Codeの設定でも同様:

{
  "mcpServers": {
    "github": {
      "command": "op",
      "args": ["run", "--", "npx", "-y", "@modelcontextprotocol/server-github"],
      "env": {
        "OP_SERVICE_ACCOUNT_TOKEN": "ops_xxxxxxxxxx",
        "GITHUB_PERSONAL_ACCESS_TOKEN": "op://CI/GitHub-MCP/token"
      }
    }
  }
}

ここで「Service Account Tokenを env に平文で書いたら意味ないのでは?」と思った人は正しい。完全に解決するには、このトークン自体も環境変数(~/.zshenv~/.zprofile)で管理して、設定ファイルには $OP_SERVICE_ACCOUNT_TOKEN のように参照だけ書く。

{
  "mcpServers": {
    "github": {
      "command": "op",
      "args": ["run", "--", "npx", "-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "op://Personal/GitHub-PAT/token"
      }
    }
  }
}

~/.zprofileexport OP_SERVICE_ACCOUNT_TOKEN="ops_xxxxx" を書いておけば、Claude Code起動時にシェルが環境変数を読み込んで op run が認証される。設定ファイルには何も書かなくて済む。

1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン
1Password CLI × Claude Code で .env を Vault化する完全ガイド — op run・シェル統合・MCP の3パターン.envファイルの平文管理から脱却するための実践ガイド。1Password CLIを使ったop runによる実行時注入・fish/zshシェル統合・MCPサーバー経由の3パターンを解説。Claude Code SubAgentsとの組み合わせ、Doppler/Infisicalとの比較まで網羅。読む →

パターン2: GitHub Secrets 連携

GitHub の Secrets 機能を Claude Code や MCP の文脈で使う方法。「Codespaces での開発」と「Actions でのCI連携」の2サブパターンがある。

2-A: GitHub Codespaces でのシークレット利用

Codespaces 上で Claude Code を使う場合、GitHub の「Codespaces secrets」機能でシークレットを設定すると、コンテナ起動時に環境変数として注入される。

# GitHub CLI でCodespacesシークレットを設定
gh secret set OPENAI_API_KEY --app codespaces

# organizationレベルで全リポジトリに適用
gh secret set OPENAI_API_KEY --app codespaces --org myorg

Codespaces 側でのClaudeの設定:

// ~/.claude/claude_desktop_config.json(Codespaces上)
{
  "mcpServers": {
    "openai-tools": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-openai"],
      "env": {
        "OPENAI_API_KEY": "${OPENAI_API_KEY}"
      }
    }
  }
}

${OPENAI_API_KEY} は起動シェルの環境変数を参照する(Claude Codeの設定ファイルがこの展開に対応しているかはバージョンによって異なる。対応していない場合はシェルスクリプトでラップする方が確実だ)。

より確実な方法:

# start-mcp.sh
#!/bin/bash
# Codespacesシークレットが環境変数に入っているので、それを使ってMCPを起動
exec npx -y @modelcontextprotocol/server-openai
{
  "mcpServers": {
    "openai-tools": {
      "command": "bash",
      "args": ["/workspaces/myproject/.devcontainer/start-mcp.sh"]
    }
  }
}
2-B: GitHub Actions でのMCP利用

Actions でClaude Code Agentを動かす場合(CI/CD や自動化タスク)、Actionsのシークレットを環境変数に渡す:

# .github/workflows/claude-agent.yml
name: Claude Code Agent Task

on:
  workflow_dispatch:
    inputs:
      task:
        description: 'Task to execute'
        required: true

jobs:
  run-claude:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Configure MCP
        run: |
          mkdir -p ~/.claude
          cat > ~/.claude/claude_desktop_config.json << 'EOF'
          {
            "mcpServers": {
              "github": {
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-github"],
                "env": {}
              }
            }
          }
          EOF
        env:
          GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.MCP_GITHUB_TOKEN }}

      - name: Run Claude Code Task
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.MCP_GITHUB_TOKEN }}
        run: |
          claude --print "${{ github.event.inputs.task }}"

ここで注意点がある。ActionsのシークレットはJobステップの env: で受け取るが、そのシークレットが claude_desktop_config.json に書き出されると一時ファイルに平文で残る。Actions環境はジョブ終了後に破棄されるので大きなリスクではないが、ジョブのアーティファクトとして保存しないように注意する。

Organization Secrets の管理

複数リポジトリでClaude CodeのActionsを使う場合、シークレットをorg単位で管理すると楽になる:

# GitHub CLI でorg secrets を設定
gh secret set ANTHROPIC_API_KEY \
  --org myorg \
  --repos "repo1,repo2,repo3"

# 全リポジトリに適用
gh secret set ANTHROPIC_API_KEY \
  --org myorg \
  --visibility all

--repos でアクセス可能なリポジトリを制限できる。全リポジトリに visibility all で共有するのは最小権限の観点からは避けた方がいい。

パターン3: HashiCorp Vault 連携(Dynamic Secrets)

チーム開発・本番環境での運用に最も適したパターン。Vault の「Dynamic Secrets」機能を使うと、MCPサーバーを起動するたびに有効期限付きの一時トークンを発行できる。

なぜDynamic Secretsが強いのか

従来の「Static Secrets」(固定値のAPIキー)は、漏洩した場合にローテーションするまでリスクが続く。Dynamic Secretsは「リクエストするたびに新しいトークンを生成し、使い終わったら失効させる」という設計だ。

たとえばAWS IAM Role へのアクセスをVaultで管理すると:

Claudeが「AWSのシークレットが必要」とVaultに要求
→ Vault がAWS IAMに対して一時的なAccess Key/Secret Key を発行
→ 有効期限は1時間
→ 1時間後に自動失効
→ 漏洩しても次のリクエストまでに失効している
Vault MCPサーバーの設定

Vault 用の MCP サーバーは公式のものがまだ少ないため、カスタムで作るか、Vault の CLI をラップする形になる。

Vault CLI をラップするシンプルなMCPサーバー(概念実装):

# vault_mcp_server.py
import subprocess
import json
import sys

def get_secret(path: str, field: str) -> str:
    """VaultからシークレットをJSON形式で取得"""
    result = subprocess.run(
        ["vault", "kv", "get", "-format=json", path],
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise ValueError(f"Vault lookup failed: {result.stderr}")
    
    data = json.loads(result.stdout)
    return data["data"]["data"][field]

def get_dynamic_aws_creds(role: str) -> dict:
    """AWS動的クレデンシャルを取得"""
    result = subprocess.run(
        ["vault", "read", "-format=json", f"aws/creds/{role}"],
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise ValueError(f"AWS creds lookup failed: {result.stderr}")
    
    data = json.loads(result.stdout)
    return {
        "access_key": data["data"]["access_key"],
        "secret_key": data["data"]["secret_key"],
        "lease_id": data["lease_id"],
        "lease_duration": data["lease_duration"]
    }

claude_desktop_config.json ではこのサーバーを指定:

{
  "mcpServers": {
    "vault": {
      "command": "python3",
      "args": ["/Users/yuto/.claude/vault_mcp_server.py"],
      "env": {
        "VAULT_ADDR": "https://vault.example.com",
        "VAULT_TOKEN": "${VAULT_TOKEN}"
      }
    }
  }
}

VAULT_TOKEN はシェルの環境変数から取るか、vault login コマンドで認証済みの状態を使う。

Vault の AppRole 認証(CI/CD向け)

CI/CDではVaultにロールを作って、Role IDとSecret IDで認証する AppRole が一般的:

# Vault設定(管理者が一度だけ実行)
vault auth enable approle

vault policy write claude-code-policy - <<EOF
path "secret/data/claude-code/*" {
  capabilities = ["read"]
}
path "aws/creds/claude-code-role" {
  capabilities = ["read"]
}
EOF

vault write auth/approle/role/claude-code \
  token_policies="claude-code-policy" \
  token_ttl="1h" \
  token_max_ttl="4h"

# Role ID と Secret ID を取得(CI/CDのシークレットに登録する)
vault read auth/approle/role/claude-code/role-id
vault write -f auth/approle/role/claude-code/secret-id

CI/CDパイプラインでの認証:

# GitHub Actions での Vault 認証
VAULT_TOKEN=$(vault write -field=token auth/approle/login \
  role_id="$VAULT_ROLE_ID" \
  secret_id="$VAULT_SECRET_ID")

export VAULT_TOKEN

これで取得した VAULT_TOKEN を MCP サーバーに渡せる。

3パターンのセキュリティリスク評価

実運用での選択基準として、リスクと運用コストを整理する。

1Password op:// URI

漏洩リスク: 低(設定ファイルに実値が残らない) アクセス制御: Vault単位・Item単位での制限が可能 監査ログ: 1Password Business以上で利用可能 ローテーション: Vault側で変更すれば自動反映 運用コスト: 低(デスクトップアプリが前提)

弱点: デスクトップアプリが起動していない環境では機能しない。Headless環境ではService Accountが必要。

GitHub Secrets

漏洩リスク: 中(Actionsのログにマスクされて出力されるが、設定ミスで露出する可能性) アクセス制御: リポジトリ・org単位での制限が可能 監査ログ: GitHub Enterprise では監査ログあり ローテーション: GitHub UI/CLI で更新(自動ローテーションなし) 運用コスト: 低(GitHub前提の環境なら追加コストなし)

弱点: Static Secretsなので漏洩時のリスクが残る。ローテーションを手動で実施する必要がある。

HashiCorp Vault Dynamic Secrets

漏洩リスク: 最低(有効期限付きの一時トークン) アクセス制御: ポリシーで詳細なアクセス制御が可能 監査ログ: 全アクセスを記録(Audit Device) ローテーション: 自動(TTLベース) 運用コスト: 高(Vaultのセルフホストまたは HCP Vault の費用)

弱点: 設定・運用の複雑さが高い。個人開発には過剰。

使い分けの指針
個人開発・フリーランス → 1Password op:// URI(操作シンプル、コスト最小)
小チーム・GitHubメイン → GitHub Secrets(運用コスト最小)
中〜大規模チーム・本番 → HashiCorp Vault(セキュリティ・監査が要件)

実際に使っている構成の話

僕の環境では1Password + op:// URI のパターンを使っている。理由はシンプルで、すでに1Passwordを使っていてVaultにAPIキーが入っているからだ。op run -- でラップするだけで既存の管理が活きる。

実際のgrep:

# 設定ファイルにAPIキーが含まれていないことの確認
grep -r "sk-" ~/.claude/ 2>/dev/null
grep -r "ghp_" ~/.claude/ 2>/dev/null
grep -r "AKIA" ~/.claude/ 2>/dev/null

全部空だ。op:// のURI参照だけが残っている。

移行前は claude_desktop_config.json に GitHub PAT と Anthropic API キーが平文で書いてあった。バックアップが Dropbox に同期されていたし、Dotfiles リポジトリに差し込みそうになったこともある。

「設定ファイルにシークレットを書かない」という一点だけでも、MCPを使った管理に移行した価値があった。

FAQ

Claude Code MCP のシークレット管理で1Password と GitHub Secrets どっちがおすすめ?

ローカル開発が中心なら 1Password + op:// URI、CI/CD ベースなら GitHub Secrets + Codespaces。両方併用も普通。1Password CLI は op run -- claude のラッパーが手軽で、設定ファイルに op://Vault/Item/field の参照だけ書けば実APIキーは漏れない。GitHub Codespaces 利用なら secrets.MY_KEY を Codespace 環境変数に自動注入。

op:// URI を mcp.json に書くだけで動く?

そのままでは動かない。Claude Code は claude_desktop_config.json / mcp.json の値を literal な文字列として読むため、op:// 解釈はされない。op run -- claude で 1Password CLI ラッパー越しに起動 → opop:// URI を実値に置換して環境変数として渡す、という流れが必要。claude_desktop_config.jsonenv: { "MY_KEY": "op://..." } と書いて op run -- claude で起動するパターンが定番。

HashiCorp Vault の Dynamic Secrets は個人開発でも使う価値ある?

正直、個人開発レベルなら オーバースペック。Dynamic Secrets の真価は「TTL付きで自動失効・自動ローテーション」なので、AWS / DB クレデンシャルが頻繁にローテーションされる本番運用で活きる。個人なら 1Password で十分。チーム規模3人以上、SOC2/ISO27001 対応必要、シークレットローテーション義務、のいずれかが当てはまるなら Vault 検討。

MCP サーバーが落ちたらシークレットも止まる?

そう。MCP サーバーが落ちると Claude Code はそのサーバー経由のシークレットを取得できなくなる。逆に言えば、シークレットが MCP に依存する場合、MCP サーバーの可用性が SLA の上限になる。1Password CLI は localファイル直接 に近いので落ちにくい、Vault は ネットワーク依存なので障害時に止まる。重要なシークレットは複数経路(local file + MCP)の冗長化を検討。

Claude Code の .env ファイル直接読みとMCPシークレット管理、どう使い分ける?

.env 直接読みは シンプルだが個人マシン限定(gitignoreされていればOK)。MCP シークレット管理は チーム共有・複数マシン・rotation 対応 が必要なときの定石。一人で固定マシンで開発するだけなら .env で十分。Codespaces や VPS との往復、複数人開発、定期 rotation のどれかが入った瞬間に MCP 化が割に合う。

1Password CLI を導入するコストは?

商用利用なら Teams プラン以上($7.99/user/月)が必要。個人利用は Family プランか個人プランで十分。CLI 自体は brew install 1password-cli で1分。op signin で認証、op run -- claude で起動 → 設定はこれだけ。Touch ID / Watch 経由の認証もサポート。

Claude Code MCP のシークレットを GitHub Actions に渡すには?

Actions の secretsmcp.json のenv に注入する形が一般的。.github/workflows/*.ymlenv: { "ANTHROPIC_API_KEY": "${{ secrets.ANTHROPIC_API_KEY }}" } と渡して、Action 内で claude を起動。secretsはログには *** でマスクされる。Actions の OIDC + Vault 連携も可能だが、setup overhead が大きいので、まず secrets 直接渡しから。

mcp.json と claude_desktop_config.json はどっち使う?

Claude Code 単体運用なら ~/.claude/mcp.json。Claude Desktop(GUI)と Code を両方使うなら、Claude Desktop は ~/Library/Application Support/Claude/claude_desktop_config.json を読むので、両方に同じ MCP 設定を書く or symlink で同期。Claude Code は .claude/mcp.json プロジェクト固有版も読むので、プロジェクト別にMCP切り替えしたいならこっち。

関連記事

Claude Code MCP設定ガイド — サーバーの追加から実用5選まで【2026年版】
Claude Code MCP設定ガイド — サーバーの追加から実用5選まで【2026年版】Claude Code MCPの設定方法をゼロから解説。MCPサーバーの追加・削除・スコープ管理、Filesystem・GitHub・Brave Search・Puppeteer・自作サーバーの実用5選、よくあるエラーと対処法まで網羅。読む →
1PasswordがAIエージェントの「鍵管理」に本気を出した — MCP対応・SDK連携を開発者目線で解説
1PasswordがAIエージェントの「鍵管理」に本気を出した — MCP対応・SDK連携を開発者目線で解説AIエージェントがAPIキーを扱う時代の鍵管理を1Passwordで解決する方法を解説。Agentic AI Security機能・MCPサーバー対応・Claude Codeやデプロイパイプラインへのシークレット注入の仕組みを開発者目線で整理。Bitwardenとの機能・料金比較も掲載。読む →
Claude Code × MCP で個人開発を自動化した実践構成と月額コストの話
Claude Code × MCP で個人開発を自動化した実践構成と月額コストの話Claude CodeとMCPを組み合わせた個人開発の自動化構成を公開。Filesystem・GitHub・Brave Search・自作MCPの実践的な設定、月額コストの実績、PromptCachingによる節約テクニック、MCPが合う場面・合わない場面の整理。読む →
← 記事一覧に戻る