【自作 MCP】Amazon Bedrock Guardrails の ApplyGuardrail API を MCP 経由で実行し EDR っぽく使ってみた

【自作 MCP】Amazon Bedrock Guardrails の ApplyGuardrail API を MCP 経由で実行し EDR っぽく使ってみた

Clock Icon2025.04.17

こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。

MCP サーバー、非常に便利ですよね。

MCP を使いこなせられれば、さまざまな用途に応用できる可能性があります。

そこで今回は Amazon Bedrock Guardrailsの機能を活用して、MCP Server を実装してみました。

ApplyGuardrail API

Amazon Bedrock Guardrails の ApplyGuardrail API は、LLM とのやり取りで期待される入出力データを Amazon Bedrock Guardrails に渡してチェックする API です。

やり取りで期待される入出力データを受け渡しすることで、Amazon Bedrock でホストされていない LLM の入出力をチェックできます。

image.png

より詳しい内容は以下をご覧ください。

https://dev.classmethod.jp/articles/filtering-non-generative-ai-apps-with-amazon-bedrock-guardrails-apply-guardrail-api/

Amazon Bedrock Guardrails MCP Server

個人的な感想ですが、執筆時点では MCP の用途として、LLM のコンテキスト強化に関するものが多い印象です。

たとえば、検索 API として利用可能な Brave Search MCP であったり、AWS だと AWS Documentation MCP Server などが挙げられます。生成する系で言うと Amazon Nova Canvas MCP Server などがありますね。

MCP はあくまでプロトコルの話なので、 EDR (Endpoint Detection and Response) 的なことができないのか試してみました。

やってみた

Amazon Bedrock Guardrails の作成

ガードレールの作成を行います。プロンプトフィルターのすべての項目の強さを High に設定してみました。

2025-04-17 at 21.20.39-Amazon Bedrock  ap-northeast-1.png

作成されたガードレールの ID を控えておきます。バージョンは DRAFT を利用します。

2025-04-17 at 21.21.42-Amazon Bedrock  ap-northeast-1.png

コード

以下のコードを作成しました。Tools を使い contents_filter なるものを作成してみました。

はじめて自作 MCP をやってみたのですが、難しい概念がない(知らないだけかもですが)ので良きですね。

main.py
"""
Bedrock Guardrails MCP Server implementation.
"""

import logging
import os
import sys
import boto3
from typing import Optional
from pydantic import BaseModel, Field
from mcp.server.fastmcp import Context, FastMCP

# Logging
logging.basicConfig(
    level=os.getenv("FASTMCP_LOG_LEVEL", "INFO"),
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
    stream=sys.stderr,
)
logger = logging.getLogger(__name__)

# Bedrock Runtime Client
aws_region = os.environ.get("AWS_REGION", "us-east-1")
try:
    if aws_profile := os.environ.get("AWS_PROFILE"):
        bedrock_client = boto3.Session(
            profile_name=aws_profile, region_name=aws_region
        ).client("bedrock-runtime")
    else:
        bedrock_client = boto3.Session(region_name=aws_region).client("bedrock-runtime")
except Exception as e:
    logger.error(f"Error creating bedrock runtime client: {str(e)}")
    raise

# MCP Response Model
class McpGuardrailFilterResponse(BaseModel):
    filtered_text: str = Field(description="Guardrail適用後のテキスト")
    guardrail_intervened: bool = Field(description="ガードレールが介入したかどうか")
    trace: Optional[dict] = Field(default=None, description="ガードレールのトレース情報")

# FastMCPサーバー初期化
mcp = FastMCP(
    "bedrock-guardrails-mcp-server",
    instructions="""
# Bedrock Guardrails MCP Server

このMCPサーバーは、Amazon Bedrock Guardrailsを使ってテキストのフィルタリングを行うツールを提供します。
""",
    dependencies=[
        "pydantic",
        "boto3",
    ],
)

@mcp.tool(
    name="contents_filter",
    description="Bedrock Guardrailsを使って入力テキストにガードレールを適用し、フィルタ済みテキストを返します"
)
async def contents_filter(
    ctx: Context,
    input_text: str = Field(description="フィルタ対象のテキスト"),
    guardrail_id: Optional[str] = Field(default=None, description="ガードレールID(未指定時は環境変数から取得)"),
    guardrail_version: Optional[str] = Field(default=None, description="ガードレールバージョン(未指定時は環境変数から取得)"),
) -> McpGuardrailFilterResponse:
    """
    Bedrock Guardrailsを使って入力テキストにガードレールを適用し、フィルタ済みテキストを返します。
    """
    try:
        guardrail_id = guardrail_id or os.getenv("GUARDRAIL_ID")
        guardrail_version = guardrail_version or os.getenv("GUARDRAIL_VERSION")
        if not guardrail_id or not guardrail_version:
            raise ValueError("GUARDRAIL_IDとGUARDRAIL_VERSIONは必須です(引数または環境変数で指定)")
        # Guardrails適用用のmessages構築
        logger.info(f"Applying guardrail: id={guardrail_id}, version={guardrail_version}")
        logger.info(f"input_text type: {type(input_text)}, value: {input_text}")
        response = bedrock_client.apply_guardrail(
            content=[
                {
                    "text": {
                        "text": str(input_text)
                    }
                }
            ],
            guardrailIdentifier=guardrail_id,
            guardrailVersion=guardrail_version,
            source="INPUT"
        )

        outputs = response.get("outputs", [])
        filtered_text = outputs[0]["text"] if outputs and "text" in outputs[0] else input_text
        guardrail_intervened = response.get("action", "") == "GUARDRAIL_INTERVENED"
        return {
            "filtered_text": filtered_text,
            "guardrail_intervened": guardrail_intervened,
            "trace": None
        }
    except Exception as e:
        logger.error(f"Error in contents_filter: {str(e)}")
        await ctx.error(f"Guardrails適用時にエラーが発生しました: {str(e)}")
        raise

if __name__ == "__main__":
    mcp.run(transport="stdio")

パッケージマネージャーには Quick Start を真似て uv を利用してみました。

uv init

# Create virtual environment and activate it
uv venv
source .venv/bin/activate

# Install dependencies
uv add "mcp[cli]" boto3 pydantic

https://modelcontextprotocol.io/quickstart/server#set-up-your-environment

最後に MCP Client から MCP Server へ到達できるよう、設定ファイルを編集します。私の場合は Roo Code を利用しているため、mcp_settings.json を修正します。

mcp_settings.json
{
  "mcpServers": {
    "bedrock-guardrails-mcp-server": {
      "command": "uv",
      "args": [
        "--directory",
        "ファイル置き場の絶対パス/amazon-bedrock-guardrails-mcp",
        "run",
        "main.py"
      ],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR",
        "GUARDRAIL_ID": "rw2shyzgmcp6",
        "GUARDRAIL_VERSION": "DRAFT",
        "AWS_REGION": "ap-northeast-1",
        "AWS_ACCESS_KEY_ID": "ASIAAAAAAAAAAAAAAAAA",
        "AWS_SECRET_ACCESS_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
      },
      "disabled": false,
      "autoApprove": [],
      "alwaysAllow": []
    }
  }
}

以下のように MCP サーバーが緑になっていれば OK です。

2025-04-17 at 22.04.05-main.py — amazon-bedrock-guardrails-mcp@2x.png

まずは、「bedrock-guardrails-mcp-server と会話してみたいです。」と入力してみました。

強制力は強くありませんが、Roo Code のプロンプト内に「デフォルトで bedrock-guardrails-mcp-server を経由してください」などを入れておくのも良さそうです。

Guardrails の結果が返ってきましたが、エンコードされている様子でした。

2025-04-17 at 22.03.57-main.py — amazon-bedrock-guardrails-mcp@2x.png

調査していると FastMCP 側で ensure_ascii が True の状態で出力されていたため、 False に設定します。(LLM 的には日本語を認識しているため、無理に行わなくても良さそうですが)

/amazon-bedrock-guardrails-mcp/.venv/lib/python3.12/site-packages/mcp/server/fastmcp/server.py
     if not isinstance(result, str):
         try:
+             result = json.dumps(pydantic_core.to_jsonable_python(result), ensure_ascii=False)
-             result = json.dumps(pydantic_core.to_jsonable_python(result))

サーバーを再起動して再度実行すると、デコードされた状態で返ってきました!

2025-04-17 at 22.05.54-server.py — amazon-bedrock-guardrails-mcp@2x.png

最後に Guardrails で検出されるようなやりとりを想定します。想定通りブロックされていますね。

2025-04-17 at 22.06.17-server.py — amazon-bedrock-guardrails-mcp@2x.png

まとめ

以上、「Amazon Bedrock Guardrails の ApplyGuardrail API を MCP 経由で実行し EDR っぽく使ってみた」でした。

近い将来、このようなセキュリティ製品が出てきそうだなぁと思い、触りの部分だけ実装してみました。

このブログがどなたかの参考になれば幸いです。 クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.