Salesforce Developers Blog

Amazon Bedrock から MCP サーバー経由で Salesforce を触る

Avatar for odashoodasho
自分で作った AI エージェントからも、Salesforce Hosted MCP Server 経由で Salesforce のデータを読み書きできます。Amazon Bedrock と Strands Agents のエージェントから、ケースの優先度を判断して書き戻すまでを、コード付きで解説します。
Amazon Bedrock から MCP サーバー経由で Salesforce を触る
November 06, 2026

みなさん、こんにちは!外部の AI エージェントから、Salesforce のデータを読んだり更新したりしたいと思ったことはありませんか?

Salesforce Hosted MCP Server を使うと、ChatGPT や Claude などの AI アプリだけでなく、自分で作った AI エージェントからも、MCP (Model Context Protocol) で Salesforce のデータを扱えます。

この記事では、AWS のオープンソースの AI エージェント SDK、Strands Agents でエージェントを作り、Salesforce のケースを読んで、Amazon Bedrock のモデルが判断した優先度を書き戻すまでを解説します。

※この記事の内容を試すには、Salesforce 組織と AWS アカウントが必要です。Salesforce の環境は、無料で取得できる Developer Edition で試せます。Amazon Bedrock の利用には料金がかかります (この記事のエージェントは、1 回の実行で入力が約 1 万トークン、出力が約 3,500 トークンでした)。Hosted MCP Server も組織によっては請求の対象になるので、本番組織では、設定の「MCP サーバー」の画面に出る Flex Credits の案内を確認してください。

※2026 年 11 月時点の情報で作成しています。

この記事のポイント

  • Strands Agents の MCPClient にサーバー URL とアクセストークンを渡すと、Salesforce の標準ツールをそのまま使える
  • 読み取りと書き込みをサーバーの単位で分け、渡すツールも絞れる。動かせるのは、認可したユーザーの権限の範囲だけ
  • 書き込みの結果は、エージェント自身に読み直して確かめさせる

1. 今回作るもの

Python のエージェントを実行すると、Amazon Bedrock のモデルが Salesforce の未対応のケースを読み、件名と説明から優先度を判断して、Priority 項目を書き換えます。ケースの読み書きには Hosted MCP Server のツールを使うので、Salesforce の API を呼ぶコードは書きません。

処理の流れは次のとおりです。

権限の絞り方

エージェントに触らせる範囲は、外側から順に 4 段で絞れます。

  1. ユーザーの権限: 認可したユーザーに許された範囲 (オブジェクトの権限、項目レベルセキュリティ、共有ルール) しか動かせません
  2. サーバー: 書き込みには、削除のツールを持たない sobject-mutations を使います
  3. ツール: Strands の tool_filters で、渡すツールを soqlQuery と updateSobjectRecord に絞ります
  4. 人の確認: この記事では省いていますが、Strands の Interrupts で、書き込みの前に人が確認する仕組みも入れられます

2. 事前準備

次のものを用意します。所要時間は 1 時間ほどです。

  • Salesforce 組織 (この記事では Developer Edition) と、システム管理者のユーザー
  • Salesforce CLI (sf)。古い場合は sf update で更新します (詳しくは Update Salesforce CLI)
  • AWS アカウント (Amazon Bedrock を使える権限)
  • Python のパッケージ管理ツールの uv (Python 3.12 は uv が入れます)。古い場合は uv self update で更新します (詳しくは Upgrading uv)

※設定のクイック検索に「MCP」と入れて「MCP サーバー」が出ない組織では、Hosted MCP Server を使えません。新しく Developer Edition を取得してください。

この記事は、Python 3.12.14、strands-agents 1.64.0、mcp 2.3.0、Salesforce CLI 2.157.8 で動作を確認しています。

最初に、作業用のプロジェクトを作ります。このあと作るファイルは、すべてこのフォルダに置きます。

1uv init --python 3.12 bedrock-case-agent
2cd bedrock-case-agent
3uv add strands-agents python-dotenv

作り終えたときのファイル構成は次のとおりです (uv が作るファイルは省いています)。

1bedrock-case-agent/
2├── .env              # 4 で作成。接続情報なので、リポジトリに含めない
3├── agent.py          # 6 で作成
4├── sf_auth.py        # 5 で作成
5├── reset_cases.apex  # 7 で作成 (試し直すとき用)
6└── data/
7    └── cases.json    # 3 で作成

3. Salesforce 側の設定

ステップ 1:MCP サーバーを有効化する

Hosted MCP Server は、初期状態ではすべて無効になっています。

  1. 設定のクイック検索で「MCP サーバー」と入力し、API カタログの「MCP サーバー」を開く
  2. 一覧から「sobject-reads」を開き、「有効化」をクリックする
  3. 同じように「sobject-mutations」も有効化する

サーバーの状態が「稼働中」になれば完了です。有効化してから使えるようになるまで、最大 2 分ほどかかります。

続けて、sobject-reads と sobject-mutations の詳細画面を開き、「サーバー URL」をそれぞれコピーしておきます。4 のステップ 2 で .env に書きます。

Developer Edition では、次の形の URL が表示されます。

1https://api.salesforce.com/platform/mcp/v1/d/<My Domain 名>/develop/platform/sobject-reads
2https://api.salesforce.com/platform/mcp/v1/d/<My Domain 名>/develop/platform/sobject-mutations

※URL には組織の My Domain 名が入ります。本番組織や Sandbox では形が少し変わるので、画面の URL をそのまま使ってください (形式の一覧は Find Your Server URL)。

ステップ 2:外部クライアントアプリケーションを作成する

エージェントが OAuth で接続するための外部クライアントアプリケーションを作成します。画面の流れは「Salesforce Hosted MCP Server 使い始め」で詳しく解説されているので、ここでは設定する値をまとめます。

  1. 設定のクイック検索で「外部クライアントアプリケーションマネージャー」を開き、「新規外部クライアントアプリケーション」をクリックする
  2. 下の表の値を設定して、「作成」をクリックする
  3. 作成したら「設定」タブの「OAuth 設定」で「コンシューマー鍵と秘密」をクリックし、メールの確認コードを入力して、コンシューマー鍵をコピーする
項目 値
外部クライアントアプリケーション名 任意 (例: Hosted MCP Clients)
取引先責任者メール 自分のメールアドレス
OAuth を有効化 オン
コールバック URL http://localhost:8765/callback
OAuth 範囲 「Salesforce でホストされている MCP サーバーにアクセス (mcp_api)」と「いつでも要求を実行 (refresh_token, offline_access)」の 2 つ
フローの有効化 すべてオフ
セキュリティ 「指名ユーザーの JSON Web トークン (JWT) ベースのアクセストークンを発行」をオン、「Web サーバーフローの秘密が必要」と「更新トークンフローの秘密が必要」をオフ

※外部クライアントアプリケーションは、作成してから使えるようになるまで、最大 30 分かかることがあります。

※コールバック URL は複数登録できるので、ほかの MCP クライアント (Claude や Postman など) のものも足せば、同じアプリを使い回せます。本番の組織では、クライアントごとにアプリを分けると管理しやすくなります。

ステップ 3:試すためのケースを投入する

エージェントが触るケースを絞るため、ケースの「会社名」 (SuppliedCompany) に目印の BEDROCK-DEMO を入れて投入し、エージェントの SOQL でもこの値で絞ります。

緊急度にばらつきのある 6 件を、優先度はすべて Medium で用意します。data/cases.json を次の内容で作ります。

1{
2  "records": [
3    {
4      "attributes": { "type": "Case", "referenceId": "Case01" },
5      "Subject": "本番環境で全ユーザーがログインできない",
6      "Description": "本日 9:30 頃から全ユーザーが管理ポータルにログインできず、受注処理が止まっています。至急対応をお願いします。",
7      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
8    },
9    {
10      "attributes": { "type": "Case", "referenceId": "Case02" },
11      "Subject": "夜間バッチ後に取引先の住所データが消えている",
12      "Description": "昨夜の連携バッチの後、取引先の約 300 件で住所が空になりました。請求書の発送に影響します。",
13      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
14    },
15    {
16      "attributes": { "type": "Case", "referenceId": "Case03" },
17      "Subject": "心当たりのない海外 IP からのログイン成功通知が届いた",
18      "Description": "今朝、海外の IP アドレスからのログイン成功通知が届きました。チームの誰も海外にはいません。",
19      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
20    },
21    {
22      "attributes": { "type": "Case", "referenceId": "Case04" },
23      "Subject": "営業ダッシュボードの表示が遅い",
24      "Description": "ダッシュボードの表示に 30 秒以上かかるようになりました。使えてはいますが、朝会で待たされています。",
25      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
26    },
27    {
28      "attributes": { "type": "Case", "referenceId": "Case05" },
29      "Subject": "二要素認証の設定手順書はありますか",
30      "Description": "新入社員向けに、二要素認証の設定手順の資料があれば共有してください。急ぎではありません。",
31      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
32    },
33    {
34      "attributes": { "type": "Case", "referenceId": "Case06" },
35      "Subject": "見積書テンプレートに会社ロゴを入れたい",
36      "Description": "見積書のテンプレートに、自社ロゴを入れられるようにしてほしいという要望です。",
37      "Status": "New", "Priority": "Medium", "SuppliedCompany": "BEDROCK-DEMO"
38    }
39  ]
40}

Salesforce CLI で組織にログインし、ケースを投入します。1 行目でブラウザが開くので、使う組織でログインします。–alias my-de で付けた別名は、このあとのコマンドの –target-org で使います。

※既定のブラウザでは、使う組織にだけログインしておきます。ほかの組織にもログインしていると、別の組織を認可してしまうことがあります (5 の sf_auth.py も同じです)。

1sf org login web --alias my-de
2sf data import tree --files data/cases.json --target-org my-de

次のコマンドで、6 件の優先度がすべて Medium になっていれば準備完了です。

1sf data query --query "SELECT CaseNumber, Subject, Priority FROM Case WHERE SuppliedCompany = 'BEDROCK-DEMO' ORDER BY CaseNumber" --target-org my-de

画面では、ケースの「私のケース」のリストビューで確かめられます。


4. AWS 側の設定

ステップ 1:Bedrock API キーを発行する

今回は、Amazon Bedrock の API キーで認証します。

  1. AWS マネジメントコンソールのリージョンを「アジアパシフィック (東京)」にする
  2. Amazon Bedrock のコンソールで、左のメニューの「API キー」を開く
  3. 「短期 API キー」タブの「短期 API キーを生成」をクリックし、表示されたキーをコピーする (キーは一度しか表示されません)

※短期 API キーは、発行したリージョンでしか使えません。Amazon Nova のモデルは、利用開始の手続きなしで使えます。

モデルは Amazon Nova 2 Lite を、推論プロファイル jp.amazon.nova-2-lite-v1:0 (東京と大阪のリージョンで処理する ID) で呼び出します。

ステップ 2:.env に接続情報を書く

プロジェクトの直下に .env を作り、次の値を入れます。.env はリポジトリに含めないでください。

1# Salesforce
2SF_CONSUMER_KEY=<コンシューマー鍵>
3SF_LOGIN_URL=https://login.salesforce.com
4SF_MCP_READS_URL=<sobject-reads のサーバー URL>
5SF_MCP_MUTATIONS_URL=<sobject-mutations のサーバー URL>
6
7# Amazon Bedrock
8AWS_BEARER_TOKEN_BEDROCK=<Bedrock API キー>
9AWS_REGION=ap-northeast-1
10BEDROCK_MODEL_ID=jp.amazon.nova-2-lite-v1:0

SF_MCP_READS_URL と SF_MCP_MUTATIONS_URL には、3 のステップ 1 でコピーしたサーバー URL を書きます。

AWS_BEARER_TOKEN_BEDROCK は、AWS の SDK が Bedrock の API キーとして読み取る環境変数なので、コードでキーを扱う必要はありません。


5. Salesforce の認可を通す

Hosted MCP Server には、OAuth 2.0 の認可コードフロー (PKCE 付き) で取得したアクセストークンで接続します。ブラウザで認可してトークンを保存する、小さなスクリプト sf_auth.py を用意します。

1"""Salesforce Hosted MCP Server 用のアクセストークンを、認可コードフロー + PKCE で取得する。
2
3  uv run sf_auth.py login   ブラウザで認可し、トークンを保存する
4  uv run sf_auth.py token   アクセストークンを出力する (MCP Inspector での疎通確認用)
5"""
6import base64
7import hashlib
8import http.server
9import json
10import os
11import secrets
12import sys
13import time
14import urllib.error
15import urllib.parse
16import urllib.request
17import webbrowser
18from pathlib import Path
19
20from dotenv import load_dotenv
21
22load_dotenv()
23
24LOGIN_URL = os.environ.get("SF_LOGIN_URL", "https://login.salesforce.com").rstrip("/")
25CLIENT_ID = os.environ.get("SF_CONSUMER_KEY", "")
26REDIRECT_URI = "http://localhost:8765/callback"  # 外部クライアントアプリケーションのコールバック URL と同じにする
27SCOPES = "mcp_api refresh_token"
28TOKEN_FILE = Path("~/.config/bedrock-case-agent/sf_token.json").expanduser()
29
30
31def _b64url(data: bytes) -> str:
32    return base64.urlsafe_b64encode(data).rstrip(b"=").decode()
33
34
35def _post_token(form: dict) -> dict:
36    req = urllib.request.Request(
37        f"{LOGIN_URL}/services/oauth2/token",
38        data=urllib.parse.urlencode(form).encode(),
39        headers={"Content-Type": "application/x-www-form-urlencoded"},
40    )
41    try:
42        with urllib.request.urlopen(req, timeout=30) as res:
43            return json.loads(res.read())
44    except urllib.error.HTTPError as e:
45        sys.exit(f"トークンの取得に失敗しました (HTTP {e.code}): {e.read().decode()}")
46
47
48def _save(tokens: dict) -> None:
49    tokens["saved_at"] = int(time.time())
50    TOKEN_FILE.parent.mkdir(parents=True, exist_ok=True)
51    TOKEN_FILE.write_text(json.dumps(tokens))
52    TOKEN_FILE.chmod(0o600)  # 自分だけが読めるようにする
53
54
55def login() -> None:
56    if not CLIENT_ID:
57        sys.exit(".env に SF_CONSUMER_KEY (コンシューマー鍵) を設定してください。")
58
59    # PKCE: code_verifier から code_challenge を作り、認可画面に渡す
60    verifier = _b64url(secrets.token_bytes(64))
61    challenge = _b64url(hashlib.sha256(verifier.encode()).digest())
62    state = secrets.token_urlsafe(16)
63    params = {
64        "response_type": "code",
65        "client_id": CLIENT_ID,
66        "redirect_uri": REDIRECT_URI,
67        "scope": SCOPES,
68        "code_challenge": challenge,
69        "code_challenge_method": "S256",
70        "state": state,
71    }
72
73    result: dict = {}
74
75    class CallbackHandler(http.server.BaseHTTPRequestHandler):
76        def do_GET(self):
77            url = urllib.parse.urlparse(self.path)
78            if url.path == "/callback":
79                result.update(urllib.parse.parse_qsl(url.query))
80            self.send_response(200)
81            self.send_header("Content-Type", "text/plain; charset=utf-8")
82            self.end_headers()
83            self.wfile.write("認可が完了しました。ターミナルに戻ってください。".encode())
84
85        def log_message(self, *args):
86            pass
87
88    server = http.server.HTTPServer(("localhost", 8765), CallbackHandler)
89    webbrowser.open(f"{LOGIN_URL}/services/oauth2/authorize?" + urllib.parse.urlencode(params))
90    while "code" not in result and "error" not in result:
91        server.handle_request()  # コールバックが届くまで待つ
92    server.server_close()
93
94    if "error" in result or result.get("state") != state:
95        sys.exit(f"認可に失敗しました: {result.get('error_description', result)}")
96
97    # PKCE: トークンを取るときに code_verifier を送る
98    tokens = _post_token({
99        "grant_type": "authorization_code",
100        "code": result["code"],
101        "client_id": CLIENT_ID,
102        "redirect_uri": REDIRECT_URI,
103        "code_verifier": verifier,
104    })
105    _save(tokens)
106    print(f"トークンを保存しました: {TOKEN_FILE}")
107
108
109def get_access_token(max_age_sec: int = 3600) -> str:
110    if not TOKEN_FILE.exists():
111        sys.exit("トークンがありません。先に `uv run sf_auth.py login` を実行してください。")
112    tokens = json.loads(TOKEN_FILE.read_text())
113    if time.time() - tokens["saved_at"] > max_age_sec:  # 保存から時間が経っていたら取り直す
114        new = _post_token({
115            "grant_type": "refresh_token",
116            "refresh_token": tokens["refresh_token"],
117            "client_id": CLIENT_ID,
118        })
119        tokens = {**tokens, **new}
120        _save(tokens)
121    return tokens["access_token"]
122
123
124if __name__ == "__main__":
125    command = sys.argv[1] if len(sys.argv) > 1 else ""
126    if command == "login":
127        login()
128    elif command == "token":
129        print(get_access_token())
130    else:
131        sys.exit("使い方: uv run sf_auth.py login | token")

ポイントは 2 つです。

  • PKCE: 認可画面を開くときに code_challenge を付け、トークンを取るときに code_verifier を送ります。認可コードの横取りを防ぐ仕組みで、コンシューマーの秘密は要りません
  • トークンの保存: プロジェクトの外 (~/.config/) に自分だけが読める権限で保存し、60 分を過ぎたらリフレッシュトークンで取り直します
1uv run sf_auth.py login

許可の画面が開いたら、要求しているアプリが自分で作った外部クライアントアプリケーションであることを確かめて、「許可」をクリックします。

ターミナルに「トークンを保存しました」と表示されれば完了です。

※MCP Inspector などで接続を確かめたいときは、uv run sf_auth.py token で出力したアクセストークンを使えます。


6. エージェントを書く

agent.py は次のとおりです。

1import os
2
3from dotenv import load_dotenv
4from strands import Agent
5from strands.models import BedrockModel
6from strands.tools.mcp import MCPClient
7
8from sf_auth import get_access_token
9
10load_dotenv()  # .env の値 (Bedrock の API キーを含む) を環境変数に読み込む
11
12headers = {"Authorization": f"Bearer {get_access_token()}"}
13
14# 読み取り用: sobject-reads の soqlQuery だけを渡す
15reads = MCPClient(
16    url=os.environ["SF_MCP_READS_URL"],  # sobject-reads のサーバー URL
17    headers=headers,
18    tool_filters={"allowed": ["soqlQuery"]},
19)
20
21# 書き込み用: sobject-mutations の updateSobjectRecord だけを渡す
22mutations = MCPClient(
23    url=os.environ["SF_MCP_MUTATIONS_URL"],  # sobject-mutations のサーバー URL
24    headers=headers,
25    tool_filters={"allowed": ["updateSobjectRecord"]},
26)
27
28model = BedrockModel(
29    model_id=os.environ["BEDROCK_MODEL_ID"],  # 例: jp.amazon.nova-2-lite-v1:0
30    region_name=os.environ["AWS_REGION"],  # 例: ap-northeast-1
31    temperature=0,
32    # Nova 2 の推論 (考えてから答える機能) をオンにする。オフのままだと、更新のツールを呼ばないことがあった
33    additional_request_fields={"reasoningConfig": {"type": "enabled", "maxReasoningEffort": "low"}},
34)
35
36SYSTEM_PROMPT = """あなたは Salesforce のサポートケース (Case) をトリアージする日本語の AI エージェントです。
37
38# 手順
391. 次の SOQL を soqlQuery で実行して、未対応のケースを取得する (そのまま使うこと)。
40   SELECT Id, CaseNumber, Subject, Description, Priority FROM Case
41   WHERE Status = 'New' AND SuppliedCompany = 'BEDROCK-DEMO'
42   ORDER BY CaseNumber LIMIT 10
432. 各ケースの件名と説明から、優先度を High、Medium、Low のどれかに判断する。
44   - High: 業務停止、データ消失、セキュリティ、法令、本番障害など緊急性が高いもの
45   - Medium: 不具合や設定の問題だが、業務は継続できるもの
46   - Low: 操作方法の質問、軽微な要望、情報提供の依頼など
473. 判断した優先度が、1 で取得した Priority と異なるケースは、すべて updateSobjectRecord で更新する。
48   High への変更も Low への変更も、同じように 1 件ずつ更新する。
49   sobject-name は "Case"、id は 1 の結果の Id をそのまま使い、body は {"Priority": "Low"} の形にする。
50   Priority 以外の項目は変更しない。
514. 更新が終わったら、1 と同じ SOQL をもう一度 soqlQuery で実行し、Priority が判断どおりになったかを確かめる。
52   判断どおりになっていないケースがあれば、もう一度 updateSobjectRecord で更新してから、もう一度確かめる。
535. 最後に、4 で確かめた結果を Markdown の表でまとめる (列: CaseNumber、件名、更新前の Priority、判定、理由、更新後の Priority)。
54"""
55
56agent = Agent(model=model, system_prompt=SYSTEM_PROMPT, tools=[reads, mutations])
57agent("未対応のケースの優先度を判断して、Priority を更新してください。")

ポイントは 3 つです。

  • MCPClient を 2 つ作る: sobject-reads と sobject-mutations に分け、tool_filters で渡すツールを 1 つずつに絞ります。接続の開始と終了は Strands Agents が管理します
  • 推論をオンにする: additional_request_fields で Nova 2 の推論 (考えてから答える機能) をオンにしています。オフのままだと、更新のツールを呼ばないことがありました
  • 指示文: 使う SOQL と判断基準を固定し、更新のあとに読み直して確かめる手順まで書いています。結果の表の「更新後の Priority」は、読み直した値です

7. 動かしてみる

1uv run agent.py

エージェントが soqlQuery でケースを取得し、優先度が変わる 5 件について updateSobjectRecord を呼び出したあと、もう一度 soqlQuery で読み直します。

ログの [REDACTED]. は、推論の中身が表示されない部分です。

最後に、判断の結果が表にまとめて出力されます。

CaseNumber 件名 更新前の Priority 判定 理由 更新後の Priority
00001026 本番環境で全ユーザーがログインできない Medium High 業務停止、緊急性が高い High
00001027 夜間バッチ後に取引先の住所データが消えている Medium High データ消失、請求書に影響 High
00001028 心当たりのない海外 IP からのログイン成功通知が届いた Medium High セキュリティリスク High
00001029 営業ダッシュボードの表示が遅い Medium Medium 不具合だが業務は継続可能 Medium
00001030 二要素認証の設定手順書はありますか Medium Low 操作方法の質問 Low
00001031 見積書テンプレートに会社ロゴを入れたい Medium Low 軽微な要望 Low

3 の sf data query をもう一度実行するか、リストビューを更新すると、Priority が書き換わっていることを確認できます。

もう一度実行しても、優先度はすでに判断どおりなので、更新は行われません。最初から試し直すときは、次の reset_cases.apex を作って実行し、優先度を Medium に戻します。

1// BEDROCK-DEMO の目印が付いたケースを、優先度 Medium、状況 New に戻す
2List<Case> cases = [SELECT Id FROM Case WHERE SuppliedCompany = 'BEDROCK-DEMO'];
3for (Case c : cases) {
4    c.Priority = 'Medium';
5    c.Status = 'New';
6}
7update cases;
1sf apex run --file reset_cases.apex --target-org my-de

戻して実行するのを 3 回繰り返したところ、3 回とも同じ結果になりました。


8. 活用法

対象のオブジェクトと指示文を変えれば、同じ形で、期限を過ぎた商談のフェーズの一括更新や、フォローアップの ToDo の作成などにも使えます。読み取りだけで足りる使い方なら、sobject-reads のクライアントだけを渡します。ほかのサービスの MCP サーバーのツールと組み合わせることもできます。


9. よくあるエラーと対処法

invalid_client_id

原因: コンシューマー鍵が違うか、外部クライアントアプリケーションを作成した直後で、まだ使えない

対処: 鍵を確かめてください。作成した直後なら、最大 30 分待ってからやり直します (待ち続けている sf_auth.py は Ctrl + C で止めます)

redirect_uri_mismatch

原因: 外部クライアントアプリケーションのコールバック URL と、sf_auth.py の REDIRECT_URI が違う

対処: どちらも http://localhost:8765/callback にしてください

MCP サーバーに接続できない (404)

原因: MCP サーバーを有効化していない (Server ‘sobject-reads’ exists but is not active. と返ります)

対処: 3 のステップ 1 でサーバーを有効化し、最大 2 分ほど待ってください

ValidationException (モデル ID の指定)

原因: モデル ID に、推論プロファイルではない ID (amazon.nova-2-lite-v1:0 など) を指定している

対処: jp.amazon.nova-2-lite-v1:0 のように、推論プロファイルの ID を指定してください

Bedrock の認証が通らない

原因: 短期 API キーを発行したリージョンが AWS_REGION と違うか、キーの期限 (最長 12 時間) が切れている

対処: AWS_REGION と同じリージョンで、キーを発行し直してください

Your account is currently being verified

原因: AWS アカウントを作った直後で、確認が終わっていない

対処: 確認は通常 2 時間以内に終わるので、待ってから実行してください

更新していないのに「更新しました」と表示される

原因: モデルが、更新のツールを呼ばないまま結果の表を書くことがあります。この記事のエージェントでも、推論をオフにしていたときに起きました

対処: 推論をオンにし、更新のあとに読み直して確かめる手順を指示文に入れたところ、3 回続けて想定どおりに動きました。それでも表はモデルの報告なので、書き込みを伴うエージェントでは、sf data query などで実際の値も確かめてください


まとめ

Strands Agents と Salesforce Hosted MCP Server を組み合わせると、Amazon Bedrock の AI エージェントから、ユーザーの権限の範囲で Salesforce のデータを読み書きできます。ほかのフレームワークのエージェントでも、OAuth で取得したアクセストークンを付けて MCP サーバーに接続する考え方は同じです。書き込みを伴う場合は、読み直して確かめる手順を指示文に入れておくと安心です。

まずは無料で取得できる Developer Edition で試してみてください。


参考リソース

More Blog Posts

Building Interactive UI with Headless Experience Layer

Building Interactive UI with Headless Experience Layer

Learn how the Headless Experience Layer (HXL) lets you build one interactive widget that renders in Agentforce and MCP clients like Claude and ChatGPT.October 07, 2026

The Salesforce Developer’s Guide to Dreamforce 2026

The Salesforce Developer’s Guide to Dreamforce 2026

Build the Agentic Enterprise at Dreamforce 2026, September 15–17, in San Francisco or on Salesforce+.August 19, 2026

Explore the Headless Toolkit with the Pronto Sample App

Explore the Headless Toolkit with the Pronto Sample App

Discover how the Pronto sample app demonstrates the power of the Headless Toolkit with Agentforce, Hosted MCP servers, and rich experiences across surfaces.October 28, 2026