AWS MCP Server が東京リージョンをサポートしたので試してみた

AWS MCP Server が東京リージョンをサポートしたので試してみた

AWS MCP Server の東京リージョンを日本国内の実行環境から試し、STS GetCallerIdentity(aws___run_script)の応答時間をバージニアと比べました。東京のほうが3割以上短くなりました。
2026.10.03

はじめに

2026年10月2日の告知で、AWS MCP Server の対応リージョンにシンガポール、シドニー、東京、アイルランド、ロンドン、オレゴンの6つが追加され、計8リージョンで使えるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/10/aws-mcp-server-six-additional-regions/

この記事では、東京エンドポイントに接続する Kiro エージェントを作り、サブエージェントからの利用も試しました。

MCP サーバーの接続先の違いによる応答時間の違いを、東京とバージニアで比較しました。

東京用の Kiro エージェントを作る

東京のエンドポイントは、Endpoints and quotas に記載されています。ap-northeast-1 の aws-mcp.ap-northeast-1.api.aws/mcp(HTTPS)です。これを使う Kiro エージェントを ~/.kiro/agents/aws-mcp.json として保存します。

https://docs.aws.amazon.com/general/latest/gr/aws-mcp.html

{
  "name": "aws-mcp",
  "description": "AWS MCP Server (Tokyo endpoint)",
  "mcpServers": {
    "aws-mcp": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws-cli@latest",
        "https://aws-mcp.ap-northeast-1.api.aws/mcp",
        "--metadata",
        "AWS_REGION=ap-northeast-1"
      ]
    }
  },
  "tools": ["*"]
}

uvx で起動するプロキシには、公式ドキュメントが案内している mcp-proxy-for-aws-cli を使っています。

接続する MCP サーバーのリージョンを決めるのは URL です。AWS_REGION メタデータは、MCP サーバーが AWS を操作するときの既定リージョンを決めます。どちらも既定は us-east-1 です。AWS_REGION を省略すると us-east-1 が使われ、公式ドキュメントの設定例の URL も us-east-1 の aws-mcp.us-east-1.api.aws/mcp です。AWS_REGION だけを東京にして URL を us-east-1 のままにすると、接続先の MCP サーバーは us-east-1 のままです。

https://docs.aws.amazon.com/aws-mcp/latest/userguide/getting-started-aws-mcp-server.html

起動は次のコマンドです。

kiro-cli chat --agent aws-mcp

起動後に /mcp を実行すると、aws-mcp が running で、8 tools と表示されました。/tools では、組み込みツールに加えて、aws___ で始まる8つのツールが mcp:aws-mcp として並びました。

動作確認として、--no-interactive --trust-all-tools を付けて起動し、読み取り操作だけを指示するプロンプトを渡しました。aws___run_script で実行した STS GetCallerIdentity は成功しました。ホストで実行した aws sts get-caller-identity と同じプリンシパル(Arn)を返しました。認証の追加設定は要りませんでした。確認したホストには aws login で得た default プロファイルのセッションがありました。環境変数の設定や認証情報ファイルのコピーはしていません。

サブエージェントから東京のエージェントを使う

Kiro のメインのセッションから subagent ツールを使い、role にエージェント名を指定すると、そのエージェントに作業を任せられます。今回のメインのセッションには AWS MCP Server を設定していないため、前節で作った aws-mcp を role に指定し、aws___ のツールを使う作業を任せました。

Trust All Tools が有効なセッションでは、ツールが承認なしで実行されます。そのため、プロンプトで読み取り操作だけを指示しました。これはプロンプトによる指示であり、ツールの実行を技術的に制限しているわけではありません。

渡したプロンプトは次のとおりです。

読み取り専用で次の3つを行い、結果を日本語で簡潔に報告してください。書き込み・作成・削除は一切行わないでください。
1. 利用できる aws___ で始まる MCP ツールの名前を列挙する。
2. aws___run_script で STS GetCallerIdentity を実行し、成功したかどうかだけを報告する。Account と Arn の値は書かない。
3. aws___list_regions を実行し、返ってきたリージョンの総数と、ap-northeast-1 が含まれるかを報告する。

サブエージェントの報告は次のとおりです。

1. 利用できる aws___ 系 MCP ツールは8個: aws___get_presigned_url, aws___get_regional_availability, aws___get_tasks, aws___list_regions, aws___read_documentation, aws___retrieve_skill, aws___run_script, aws___search_documentation。
2. STS GetCallerIdentity は成功。最初の実行はコード検証エラー(`__name__` の使用がブロックされた)で失敗し、AWS API は呼ばれていない。コードを修正して再実行したところ成功した。Account と Arn の値は出力していない。
3. aws___list_regions が返したリージョンは全37件。ap-northeast-1(東京)は含まれる。
書き込み・作成・削除は一切行っていない。

STS の応答時間を東京とバージニアで比べる

ここからの値は、前節のサブエージェントとは別に、計測スクリプトから mcp-proxy-for-aws-cli(1.7.0)を stdio で直接起動して測ったものです。起動コマンドと引数は「東京用の Kiro エージェントを作る」の設定と同じで、比較のために URL だけを東京とバージニアで切り替えました。Kiro やサブエージェント経由の時間ではありません。

測定は2026年10月3日に日本国内のホスト1台で行い、計測スクリプトの実行全体(aws___list_regions を含む)で約4分でした。aws___run_script で STS GetCallerIdentity を実行し、東京とバージニアを交互に30回ずつ呼びました。AWS_REGION メタデータは両方とも ap-northeast-1 に固定し、URL だけを変えました。時間は tools/call の送信から応答の受信までで、uvx とプロキシの起動、MCP の initialize は含みません。aws___list_regions は STS の30回のあとに同じ接続で呼んだため、その最初の1回は接続直後の呼び出しではありません。STS の最初の1回とは条件が違うので、aws___list_regions については表に2回目以降だけを示します。失敗は0件でした。

呼び出し エンドポイント 初回 2回目以降の中央値 2回目以降の範囲
STS GetCallerIdentity(aws___run_script) 東京 8.72 1.91 1.72〜2.16
STS GetCallerIdentity(aws___run_script) バージニア 12.26 2.94 2.48〜3.14
aws___list_regions 東京 — 1.25 0.94〜1.73
aws___list_regions バージニア — 1.39 1.05〜1.54

単位は秒です。初回は1回の測定値です。2回目以降の中央値と範囲は、各30回のうち最初の1回を除いた29回の値です。

同じ反復(i 回目)の東京とバージニアの呼び出しを1組とすると、STS は29組すべてで東京が速く、組ごとの差の中央値は1.01秒でした。中央値どうしで比べると、(2.94−1.91)/2.94 ≒ 35%の短縮です。aws___list_regions の差の中央値は0.13秒で、東京が速かったのは29組中24組でした。

計測スクリプトは、記事末尾の「参考:計測スクリプト」に載せています。

まとめ

AWS MCP Server が東京リージョンをサポートし、東京のエンドポイントが使えるようになりました。日本国内の実行環境でバージニアから東京に替えたところ、aws___run_script による STS GetCallerIdentity の応答時間は、中央値で約35%短くなりました。

日本国内から、既定の us-east-1 のエンドポイントのまま AWS MCP Server を使っている場合、MCP サーバーの接続先 URL を東京に変更すると、応答時間の短縮が見込めます。

また、告知にあるとおり、リクエストデータをリージョン内にとどめられるようになりました。海外リージョンの利用に制限がある場合でも、東京リージョンのエンドポイントを明示することで、AWS MCP Server を使える可能性があるので、お試しください。

参考:計測スクリプト

測定は次のコマンドで再現できます。Python 3(標準ライブラリのみ)と uvx が必要です。計測スクリプトは出力を追記するため、測り直すときは別のファイル名を指定します。スクリプトは mcp-proxy-for-aws-cli@latest を起動するため、測り直すときのバージョンは、測定時の 1.7.0 とは限りません。集計スクリプト summarize.py は反復回数30回を前提にしています。

python3 measure-mcp-latency.py latency.jsonl 30
python3 summarize.py latency.jsonl
計測スクリプトと集計スクリプト

measure-mcp-latency.py

#!/usr/bin/env python3
"""AWS MCP Server の東京/バージニア エンドポイント応答時間を、同一ホストから交互に測定する。

- 標準ライブラリのみ。mcp-proxy-for-aws を stdio で起動し、JSON-RPC で tools/call を送る。
- 認証はホストの default プロファイル(環境変数・ファイルの持ち出しなし)。
- 1 呼び出しごとに JSONL を即時追記する(途中で止まっても記録が残る)。
- 呼び出し順は反復ごとに入れ替え、順序による偏りを避ける。
使い方: measure-mcp-latency.py <出力jsonl> <反復回数>
"""
import json, select, subprocess, sys, time

OUT, N = sys.argv[1], int(sys.argv[2])
UVX = "uvx"
ENDPOINTS = ["ap-northeast-1", "us-east-1"]
STS_CODE = ('r = await call_boto3(service_name="sts", operation_name="GetCallerIdentity")\n'
            'result = {"has_arn": "Arn" in r}\nresult')
TOOLS = [
    ("sts_run_script", "aws___run_script", {"code": STS_CODE}),
    ("list_regions", "aws___list_regions", {}),
]

class Proxy:
    def __init__(self, ep):
        self.ep, self.seq = ep, 0
        self.p = subprocess.Popen(
            [UVX, "mcp-proxy-for-aws-cli@latest", f"https://aws-mcp.{ep}.api.aws/mcp",
             "--metadata", "AWS_REGION=ap-northeast-1"],
            stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
            text=True, bufsize=1)

    def send(self, o):
        self.p.stdin.write(json.dumps(o) + "\n")
        self.p.stdin.flush()

    def recv(self, id_, timeout=90):
        end = time.time() + timeout
        while time.time() < end:
            r, _, _ = select.select([self.p.stdout], [], [], 1)
            if not r:
                continue
            line = self.p.stdout.readline()
            if not line:
                return None
            try:
                m = json.loads(line)
            except ValueError:
                continue
            if m.get("id") == id_:
                return m
        return None

    def init(self):
        self.send({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {
            "protocolVersion": "2025-03-26", "capabilities": {},
            "clientInfo": {"name": "latency-probe", "version": "1"}}})
        m = self.recv(1, 120)
        self.send({"jsonrpc": "2.0", "method": "notifications/initialized"})
        self.seq = 1
        return bool(m and "result" in m)

    def call(self, name, args):
        self.seq += 1
        t0 = time.perf_counter()
        self.send({"jsonrpc": "2.0", "id": self.seq, "method": "tools/call",
                   "params": {"name": name, "arguments": args}})
        m = self.recv(self.seq)
        dt = time.perf_counter() - t0
        ok = bool(m and "result" in m and not m["result"].get("isError"))
        err = None if ok else json.dumps(m, ensure_ascii=False)[:300]
        return dt, ok, err

def main():
    px = {ep: Proxy(ep) for ep in ENDPOINTS}
    with open(OUT, "a", buffering=1) as f:
        def rec(**kw):
            kw["wall_time"] = time.strftime("%Y-%m-%dT%H:%M:%S%z")
            f.write(json.dumps(kw, ensure_ascii=False) + "\n")

        for ep in ENDPOINTS:
            t = time.perf_counter()
            ok = px[ep].init()
            rec(kind="init", endpoint=ep, seconds=round(time.perf_counter() - t, 4), ok=ok)
        for label, tool, args in TOOLS:
            for i in range(N):
                order = ENDPOINTS if i % 2 == 0 else ENDPOINTS[::-1]
                for ep in order:
                    dt, ok, err = px[ep].call(tool, args)
                    rec(kind="call", test=label, endpoint=ep, iter=i,
                        seconds=round(dt, 4), ok=ok, error=err)
        for q in px.values():
            q.p.terminate()

main()

summarize.py

import json,sys,statistics as s
rows=[json.loads(l) for l in open(sys.argv[1])]
print("init:",[(r["endpoint"],r["seconds"],r["ok"]) for r in rows if r["kind"]=="init"])
calls=[r for r in rows if r["kind"]=="call"]
print("失敗:",[r for r in calls if not r["ok"]] or "なし")
def q(v,p): v=sorted(v); return v[min(len(v)-1,int(round(p*(len(v)-1))))]
for t in ("sts_run_script","list_regions"):
    for ep in ("ap-northeast-1","us-east-1"):
        a=[r for r in calls if r["test"]==t and r["endpoint"]==ep]
        first=a[0]["seconds"]; rest=[r["seconds"] for r in a[1:]]
        print(f"{t:15s} {ep:15s} 初回={first:.2f}s  2回目以降 n={len(rest)} min={min(rest):.2f} med={s.median(rest):.2f} p90={q(rest,.9):.2f} max={max(rest):.2f} mean={s.mean(rest):.2f}")
    # 対応ペア差(同一反復の東京-バージニア)
    d=[]
    for i in range(1,30):
        tk=[r for r in calls if r["test"]==t and r["iter"]==i and r["endpoint"]=="ap-northeast-1"][0]["seconds"]
        us=[r for r in calls if r["test"]==t and r["iter"]==i and r["endpoint"]=="us-east-1"][0]["seconds"]
        d.append(us-tk)
    print(f"{t:15s} ペア差(バージニア-東京) med={s.median(d):+.2f}s mean={s.mean(d):+.2f}s 東京が速い回={sum(x>0 for x in d)}/{len(d)}")

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事