I tried operating a lakehouse with natural language from Amazon QuickSight against an aws-dataprocessing-mcp-server hosted on Amazon Bedrock AgentCore Runtime

I tried operating a lakehouse with natural language from Amazon QuickSight against an aws-dataprocessing-mcp-server hosted on Amazon Bedrock AgentCore Runtime

I tried hosting AWS Labs' aws-dataprocessing-mcp-server on Amazon Bedrock AgentCore Runtime to enable referencing and modifying a lakehouse in natural language from Amazon QuickSight. I will introduce the implementation challenges encountered along the way, including switching to streamable-http and handling DNS rebinding protection, along with their solutions.
2026.05.23

This page has been translated by machine translation. View original

This is Ishikawa from the Cloud Business Division. I tried hosting the aws-dataprocessing-mcp-server published by AWS Labs on Amazon Bedrock AgentCore Runtime, and enabling natural language operations on data lakes and lakehouses from Amazon Quick.

https://aws.amazon.com/jp/blogs/machine-learning/integrating-aws-api-mcp-server-with-amazon-quick-suite-using-amazon-bedrock-agentcore-runtime/

The AWS Labs MCP server collection includes servers specialized for specific use cases. This time, I'll focus on the aws-dataprocessing-mcp-server tailored for data analysis operations, and run it with an integration pattern of Quick + AgentCore Runtime + Cognito JWT authentication.

https://github.com/awslabs/mcp/tree/main/src/aws-dataprocessing-mcp-server

aws-dataprocessing-mcp-server is distributed via PyPI / uvx and is stdio-only. To run it on AgentCore Runtime, you need to build a custom container that listens on streamable-http, and work around several "pitfalls." This article covers the implementation as well.

What is aws-dataprocessing-mcp-server

aws-dataprocessing-mcp-server is a server for operating AWS data processing services such as AWS Glue and Amazon Athena via the Model Context Protocol (MCP). Operations commonly used in data engineering work—such as querying the Glue Data Catalog, executing Athena queries, and managing tables and databases—are provided as 36 tools.

The main tool categories are as follows.

  • Glue Data Catalog: manage_aws_glue_databases, manage_aws_glue_tables, manage_aws_glue_connections, manage_aws_glue_partitions
  • Glue ETL: manage_aws_glue_jobs, manage_aws_glue_workflows, manage_aws_glue_triggers, manage_aws_glue_crawlers
  • Glue Interactive Sessions: manage_aws_glue_sessions, manage_aws_glue_statements
  • EMR: manage_aws_emr_clusters, manage_aws_emr_ec2_steps, manage_aws_emr_serverless_applications
  • Athena: manage_aws_athena_query_executions, manage_aws_athena_workgroups, manage_aws_athena_data_catalogs
  • Common: create_data_processing_role, list_s3_buckets, add_inline_policy

By default it starts in read-only mode, and adding the --allow-write flag also enables write operations. In this article, I verified with read-only mode to prioritize safety.

https://awslabs.github.io/mcp/servers/aws-dataprocessing-mcp-server/

What is Amazon Bedrock AgentCore Runtime

Amazon Bedrock AgentCore Runtime is a serverless execution environment for hosting AI agents and MCP servers. It supports communication via the Model Context Protocol (MCP) and Agent to Agent (A2A) protocols, and isolates sessions per microVM. It handles JWT authentication, sending observability data to CloudWatch / X-Ray, and launching from ECR container images all in one place.

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-mcp.html

Overall Architecture

The request flow is as follows.

20260522-amazon-bedrock-agentcore-with-amazon-quick-17

What I Did

Prerequisites

  • AWS account (this verification was performed in a sandbox in ap-northeast-1)
  • Amazon Quick Enterprise edition
  • A container runtime capable of building linux/arm64 images (this verification used Mac + Podman)
  • MCP version at verification time: awslabs.aws-dataprocessing-mcp-server: 0.1.31

Step1: Designing a Custom Container for AgentCore Runtime

The server.py of aws-dataprocessing-mcp-server starts FastMCP() with default settings, so it listens on stdio transport. Since AgentCore Runtime requires streamable-http, port 8000, and the /mcp path, I wrote a thin wrapper to do the following.

  1. Override FastMCP.__init__ and pass TransportSecuritySettings(enable_dns_rebinding_protection=False)
  2. Override FastMCP.run, set mcp.settings.host = "0.0.0.0", port = 8000, stateless_http = True, and launch with streamable-http
  3. Make the same handler respond not only to /mcp but also to /mcp/, and suppress 307 redirects with redirect_slashes=False

The core of the wrapper server_http.py is as follows.

import uvicorn
from mcp.server.fastmcp import FastMCP
from mcp.server.transport_security import TransportSecuritySettings
from starlette.routing import Route

_original_init = FastMCP.__init__

def _patched_init(self, *args, **kwargs):
    kwargs.setdefault(
        "transport_security",
        TransportSecuritySettings(enable_dns_rebinding_protection=False),
    )
    _original_init(self, *args, **kwargs)

FastMCP.__init__ = _patched_init

_original_run = FastMCP.run

def _patched_run(self, transport=None, **kwargs):
    self.settings.host = "0.0.0.0"
    self.settings.port = 8000
    self.settings.stateless_http = True

    if transport == "streamable-http" or transport is None:
        app = self.streamable_http_app()
        app.router.redirect_slashes = False
        existing = next(
            r for r in app.router.routes if isinstance(r, Route) and r.path == "/mcp"
        )
        app.router.routes.append(
            Route("/mcp/", endpoint=existing.endpoint, methods=existing.methods)
        )
        uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info")
        return
    return _original_run(self, transport=transport)

FastMCP.run = _patched_run

from awslabs.aws_dataprocessing_mcp_server.server import main  # noqa: E402

if __name__ == "__main__":
    main()

The important point here is the first override of transport_security. Since MCP Python SDK 1.21, FastMCP has DNS rebinding protection enabled by default. Since AgentCore Runtime's proxy sets the upstream AWS domain in the Host header and forwards it to the internal microVM, without disabling this you will get 421 Misdirected Request. Since JWT authentication is handled on the AgentCore Runtime side, disabling this here still maintains defense in depth.

https://github.com/modelcontextprotocol/python-sdk/issues/1798

Step2: Building the Docker Image

The Dockerfile is structured as follows.

FROM --platform=linux/arm64 python:3.12-slim

ENV PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /app

COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r /app/requirements.txt

COPY server_http.py /app/server_http.py

RUN groupadd -r app && useradd -r -g app -d /home/app -m app
USER app

EXPOSE 8000

ENTRYPOINT ["python", "/app/server_http.py"]

Pin versions in requirements.txt.

awslabs.aws-dataprocessing-mcp-server==0.1.31
mcp[cli]==1.23.0
uvicorn==0.32.0

Build specifying linux/arm64. On Apple Silicon Mac, this becomes a native build.

podman build --platform linux/arm64 -t dataprocessing-mcp-agentcore:v0.4 .

Do a quick operation check locally using curl.

$ curl -s -X POST "http://localhost:8000/mcp" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0.1"}}}' | head -3

event: message
data: {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{...},"serverInfo":{"name":"awslabs.aws-dataprocessing-mcp-server","version":"1.23.0"}, ...}}

I created a private repository in ap-northeast-1 and pushed the built image.

Step3: Creating an Amazon Cognito User Pool

Create a User Pool and App Client for Machine-to-Machine authentication.

aws cognito-idp create-user-pool \
  --pool-name dp-mcp-agentcore-pool \
  --policies '{"PasswordPolicy":{"MinimumLength":12,"RequireUppercase":true,"RequireLowercase":true,"RequireNumbers":true,"RequireSymbols":true}}' \
  --region ap-northeast-1

The Pool ID ap-northeast-1_ogeMbwGMK is obtained. Next, create a Resource Server and scopes.

aws cognito-idp create-resource-server \
  --user-pool-id ap-northeast-1_ogeMbwGMK \
  --identifier dp-mcp \
  --name "Dataprocessing MCP Resource Server" \
  --scopes \
    ScopeName=read,ScopeDescription="Read data processing resources" \
    ScopeName=write,ScopeDescription="Write data processing resources" \
  --region ap-northeast-1

Create a domain prefix and App Client (for client_credentials).

aws cognito-idp create-user-pool-domain \
  --user-pool-id ap-northeast-1_ogeMbwGMK \
  --domain dp-mcp-1f6b687c \
  --region ap-northeast-1

aws cognito-idp create-user-pool-client \
  --user-pool-id ap-northeast-1_ogeMbwGMK \
  --client-name dp-mcp-m2m-client \
  --generate-secret \
  --allowed-o-auth-flows client_credentials \
  --allowed-o-auth-scopes "dp-mcp/read" "dp-mcp/write" \
  --allowed-o-auth-flows-user-pool-client \
  --supported-identity-providers COGNITO \
  --region ap-northeast-1

This gives you the Token URL https://dp-mcp-1f6b687c.auth.ap-northeast-1.amazoncognito.com/oauth2/token and Client ID / Client Secret.

20260522-amazon-bedrock-agentcore-with-amazon-quick-1

Step4: Creating an IAM Execution Role

The execution role passed to AgentCore Runtime must have at minimum the following permissions.

  • ECR pull (narrowed down to the target repository ARN)
  • CloudWatch Logs (only /aws/bedrock-agentcore/runtimes/*)
  • X-Ray PutTrace related
  • bedrock-agentcore:GetWorkloadAccessToken* (workload-identity-directory/default)
  • Read-only APIs for Glue / Athena / S3

The trust policy sets bedrock-agentcore.amazonaws.com as the Principal, restricted to your own account with aws:SourceAccount.

Step5: Creating the AgentCore Runtime

Create the AgentCore Runtime specifying the ECR image, IAM role, Cognito Discovery URL, and App Client ID.

$ aws bedrock-agentcore-control create-agent-runtime \
  --agent-runtime-name dp_mcp_agentcore \
  --agent-runtime-artifact 'containerConfiguration={containerUri=<AWS_ACCOUNT_ID>.dkr.ecr.ap-northeast-1.amazonaws.com/dataprocessing-mcp-agentcore:v0.4}' \
  --network-configuration 'networkMode=PUBLIC' \
  --protocol-configuration 'serverProtocol=MCP' \
  --role-arn arn:aws:iam::<AWS_ACCOUNT_ID>:role/AgentCoreRuntimeRole-DpMcp \
  --authorizer-configuration 'customJWTAuthorizer={discoveryUrl=https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_ogeMbwGMK/.well-known/openid-configuration,allowedClients=[38gvcra4aiq2kof9tim48ujoqb]}' \
  --environment-variables 'AWS_REGION=ap-northeast-1,FASTMCP_LOG_LEVEL=INFO' \
  --region ap-northeast-1

{
  "agentRuntimeArn": "arn:aws:bedrock-agentcore:ap-northeast-1:<AWS_ACCOUNT_ID>:runtime/dp_mcp_agentcore-O8HEgzH8Fj",
  "agentRuntimeId": "dp_mcp_agentcore-O8HEgzH8Fj",
  "agentRuntimeVersion": "1",
  "status": "CREATING"
}

It became READY within tens of seconds.

20260522-amazon-bedrock-agentcore-with-amazon-quick-2

Step6: Connecting from a Remote MCP Client

Obtain a JWT from Cognito via client_credentials grant, and connect to the AgentCore Runtime endpoint (/invocations?qualifier=DEFAULT) from a Python MCP client.

import asyncio, base64, json, urllib.parse, urllib.request
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

REGION = "ap-northeast-1"
ARN = "arn:aws:bedrock-agentcore:ap-northeast-1:<AWS_ACCOUNT_ID>:runtime/dp_mcp_agentcore-O8HEgzH8Fj"
DOMAIN = "dp-mcp-1f6b687c"
CLIENT_ID = "..."
CLIENT_SECRET = "..."

def get_jwt():
    body = urllib.parse.urlencode({"grant_type": "client_credentials",
                                   "scope": "dp-mcp/read dp-mcp/write"}).encode()
    creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
    req = urllib.request.Request(
        f"https://{DOMAIN}.auth.{REGION}.amazoncognito.com/oauth2/token",
        data=body,
        headers={"Authorization": f"Basic {creds}",
                 "Content-Type": "application/x-www-form-urlencoded"},
    )
    return json.loads(urllib.request.urlopen(req).read())["access_token"]

async def main():
    token = get_jwt()
    url = (f"https://bedrock-agentcore.{REGION}.amazonaws.com/runtimes/"
           f"{urllib.parse.quote(ARN, safe='')}/invocations?qualifier=DEFAULT")
    headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
    async with streamablehttp_client(url, headers, timeout=120) as (r, w, _):
        async with ClientSession(r, w) as session:
            await session.initialize()
            tools = await session.list_tools()
            print(f"tool count: {len(tools.tools)}")
            result = await session.call_tool(
                "manage_aws_glue_databases",
                {"operation": "list-databases", "region_name": REGION},
            )
            for c in result.content:
                if c.type == "text":
                    print(c.text[:600])

asyncio.run(main())

The execution result is as follows.

tool count: 36
Successfully listed 7 databases
{"databases":[{"name":"default", ...},{"name":"qsdemo_dev", ...},{"name":"qsdemo_iot", ...},{"name":"qsdemo_sandbox", ...},{"name":"quick_workshop", ...}], "count":7, ...}

36 tools were registered, and the list of Glue databases was also retrieved. Next, I call Athena workgroups and databases within the Athena catalog.

=== manage_aws_athena_databases_and_tables (list-databases) ===
{"database_list":[{"Name":"default"},{"Name":"ishikawa"},{"Name":"iwasa"},{"Name":"qsdemo_dev"},{"Name":"qsdemo_iot"},{"Name":"qsdemo_sandbox"},{"Name":"quick_workshop"}],"count":7}

I was able to verify "viewing the catalog"—the entry point for data analysis—through a natural language tool call.

Step7: Registering the MCP Connector in Amazon Quick

Select Connectors, then select Model Context Protocol from the Create for your team tab.

20260522-amazon-bedrock-agentcore-with-amazon-quick-4

Under "Connection," configure the following.

  • Name
  • Description
  • MCP server endpoint
  • Connection Type (leave the default Public Network)

20260522-amazon-bedrock-agentcore-with-amazon-quick-5

Under "Authentication," configure the following.

  • Authentication method: Select Service authentication
  • OAuth Configuration
  • Client ID
  • Client Secret
  • Token URL

20260522-amazon-bedrock-agentcore-with-amazon-quick-7

Under "Review," verify the content.

20260522-amazon-bedrock-agentcore-with-amazon-quick-8

Under "Publish," register the MCP. Since turning off Everyone in your organization does not allow individual configuration, you will register it as is.

20260522-amazon-bedrock-agentcore-with-amazon-quick-9

You can confirm the 36 registered actions.

20260522-amazon-bedrock-agentcore-with-amazon-quick-18

Step8: Verifying the Amazon Quick MCP Connector

Pressing the [Try it] button displays the chat screen.

20260522-amazon-bedrock-agentcore-with-amazon-quick-10

On the chat screen, this MCP is already selected as the Connector, and execution of the following prompt begins.

20260522-amazon-bedrock-agentcore-with-amazon-quick-11

Let's go ahead and enter a prompt. I type "Please display the list of tables in the ishikawa table." Before executing the MCP, "Allow" confirmation is always required. This is a consideration to prevent unexpected MCP calls.

20260522-amazon-bedrock-agentcore-with-amazon-quick-12

I typed "ishikawa table" where I meant "ishikawa database," but the list from the "ishikawa database" was displayed.

20260522-amazon-bedrock-agentcore-with-amazon-quick-13

Step9: Updating Amazon Quick Data with the MCP Connector

There is sometimes a need to update data on "QuickSight." Moreover, being able to instruct changes in natural language makes it very convenient. I enter the following prompt to perform the update.

In the ishikawa.orders table, for rows where profit is negative and discount is 0.4 or more, please put "要確認" (needs review) in the returned column as "high-discount deficit." Please also tell me how many rows were updated.

The results of the changes are also displayed in a human-readable format.

20260522-amazon-bedrock-agentcore-with-amazon-quick-14

:
:
:

20260522-amazon-bedrock-agentcore-with-amazon-quick-15

When I also checked from Amazon Athena, I was able to confirm the changes according to the specified conditions.

20260522-amazon-bedrock-agentcore-with-amazon-quick-16

Discussion

  • The verification in this article was conducted in read-only mode. When enabling write operations in production, you need to add the --allow-write flag and --allow-sensitive-data-access flag to the ENTRYPOINT, and also extend the IAM execution role permissions to include write operations.
  • It is recommended to manage the Cognito Client Secret using AWS Secrets Manager or similar, rather than embedding it in version control or on the client side.
  • The reason enable_dns_rebinding_protection=False is set for DNS rebinding protection is to conform to AgentCore Runtime's proxy behavior of rewriting the Host header. Unauthorized external access is blocked by AgentCore Runtime's JWT authentication, but please be careful if you reuse the container in a different environment as-is.
  • aws-dataprocessing-mcp-server is at version 0.1.31 (pre-1.0) at the time of writing this article. The tool structure and arguments may change in the future. In this article, the configuration pins the version within the container image.

Closing

By connecting Amazon Quick and aws-dataprocessing-mcp-server via Amazon Bedrock AgentCore Runtime, you can integrate Glue / Athena operations into a natural language interface. To run an OSS MCP server on AgentCore Runtime as-is, you will encounter the following "pitfalls":

  • A wrapper to switch to streamable-http
  • Building the container for linux/arm64 and pushing to ECR
  • Handling FastMCP's DNS rebinding protection
  • Redirect behavior for /mcp / /mcp/ paths

I hope the wrapper implementation and verification logs in this article serve as a reference for those who want to host other AWS Labs MCP servers (aws-iam-mcp-server, aws-s3-mcp-server, etc.) on AgentCore Runtime using the same pattern.


国内企業 AI活用実態調査2026 配布中

クラスメソッドが独自に行なったAI診断調査をもとに、企業のAI活用の現在地を調査レポートとしてまとめました。企業規模別の活用度傾向に加え、規模を超えてAI活用を進める企業に共通する取り組みまで、自社の現在地を捉えるためのヒントにぜひ。

国内企業 AI活用実態調査2026

無料でダウンロードする

Share this article

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