Skip to content

Commit 2b7b91d

Browse files
committed
refactor: use mcp-proxy-for-aws instead of custom SigV4 auth
Replace custom SigV4HTTPXAuth class with official mcp-proxy-for-aws: - Strands: factory pattern with aws_iam_streamablehttp_client - LangChain: direct session pattern with ClientSession + load_mcp_tools - OpenAI/ADK/AutoGen: removed custom auth (SDKs don't support custom transports, rely on runtime IAM credentials)
1 parent d9b90be commit 2b7b91d

4 files changed

Lines changed: 54 additions & 212 deletions

File tree

src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap

Lines changed: 27 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,59 +2001,42 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/la
20012001
exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/client.py should match snapshot 1`] = `
20022002
"import os
20032003
import logging
2004+
from mcp.client.streamable_http import streamablehttp_client
20042005
from langchain_mcp_adapters.client import MultiServerMCPClient
20052006
20062007
logger = logging.getLogger(__name__)
20072008
20082009
{{#if hasGateway}}
20092010
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
2010-
import boto3
2011-
import httpx
2012-
from botocore.auth import SigV4Auth
2013-
from botocore.awsrequest import AWSRequest
2014-
2015-
2016-
class SigV4HTTPXAuth(httpx.Auth):
2017-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
2018-
2019-
def __init__(self):
2020-
session = boto3.Session()
2021-
credentials = session.get_credentials().get_frozen_credentials()
2022-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
2023-
self.signer = SigV4Auth(credentials, "lambda", region)
2024-
2025-
def auth_flow(self, request):
2026-
headers = dict(request.headers)
2027-
headers.pop("connection", None)
2028-
aws_request = AWSRequest(
2029-
method=request.method,
2030-
url=str(request.url),
2031-
data=request.content,
2032-
headers=headers,
2033-
)
2034-
self.signer.add_auth(aws_request)
2035-
request.headers.update(dict(aws_request.headers))
2036-
yield request
2011+
from mcp.client.session import ClientSession
2012+
from langchain_mcp_adapters.tools import load_mcp_tools
2013+
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
20372014
{{/if}}
20382015
2039-
2040-
def get_all_gateway_mcp_client() -> MultiServerMCPClient | None:
2041-
"""Returns an MCP Client connected to all configured gateways."""
2042-
servers = {}
2043-
{{#each gatewayProviders}}
2016+
{{#each gatewayProviders}}
2017+
{{#if (eq authType "AWS_IAM")}}
2018+
async def get_{{snakeCase name}}_mcp_tools():
2019+
"""Returns MCP tools from the {{name}} gateway using SigV4 auth."""
20442020
url = os.environ.get("{{envVarName}}")
2045-
if url:
2046-
{{#if (eq authType "AWS_IAM")}}
2047-
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "http_client": httpx.AsyncClient(auth=SigV4HTTPXAuth())}
2048-
{{else}}
2049-
servers["{{name}}"] = {"transport": "streamable_http", "url": url}
2050-
{{/if}}
2051-
else:
2021+
if not url:
2022+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
2023+
return []
2024+
mcp_client = aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore")
2025+
async with mcp_client as (read, write, _):
2026+
async with ClientSession(read, write) as session:
2027+
await session.initialize()
2028+
return await load_mcp_tools(session)
2029+
{{else}}
2030+
def get_{{snakeCase name}}_mcp_client() -> MultiServerMCPClient | None:
2031+
"""Returns an MCP Client for the {{name}} gateway."""
2032+
url = os.environ.get("{{envVarName}}")
2033+
if not url:
20522034
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
2053-
{{/each}}
2054-
if not servers:
20552035
return None
2056-
return MultiServerMCPClient(servers)
2036+
return MultiServerMCPClient({"{{name}}": {"transport": "streamable_http", "url": url}})
2037+
{{/if}}
2038+
2039+
{{/each}}
20572040
{{else}}
20582041
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
20592042
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
@@ -2454,48 +2437,13 @@ from agents.mcp import MCPServerStreamableHttp
24542437
logger = logging.getLogger(__name__)
24552438
24562439
{{#if hasGateway}}
2457-
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
2458-
import boto3
2459-
import httpx
2460-
from botocore.auth import SigV4Auth
2461-
from botocore.awsrequest import AWSRequest
2462-
2463-
2464-
class SigV4HTTPXAuth(httpx.Auth):
2465-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
2466-
2467-
def __init__(self):
2468-
session = boto3.Session()
2469-
credentials = session.get_credentials().get_frozen_credentials()
2470-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
2471-
self.signer = SigV4Auth(credentials, "lambda", region)
2472-
2473-
def auth_flow(self, request):
2474-
headers = dict(request.headers)
2475-
headers.pop("connection", None)
2476-
aws_request = AWSRequest(
2477-
method=request.method,
2478-
url=str(request.url),
2479-
data=request.content,
2480-
headers=headers,
2481-
)
2482-
self.signer.add_auth(aws_request)
2483-
request.headers.update(dict(aws_request.headers))
2484-
yield request
2485-
{{/if}}
2486-
2487-
24882440
def get_all_gateway_mcp_servers() -> list[MCPServerStreamableHttp]:
24892441
"""Returns MCP servers for all configured gateways."""
24902442
servers = []
24912443
{{#each gatewayProviders}}
24922444
url = os.environ.get("{{envVarName}}")
24932445
if url:
2494-
{{#if (eq authType "AWS_IAM")}}
2495-
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url, "http_client": httpx.AsyncClient(auth=SigV4HTTPXAuth())}))
2496-
{{else}}
24972446
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url}))
2498-
{{/if}}
24992447
else:
25002448
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
25012449
{{/each}}
@@ -2786,33 +2734,7 @@ logger = logging.getLogger(__name__)
27862734
27872735
{{#if hasGateway}}
27882736
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
2789-
import boto3
2790-
import httpx
2791-
from botocore.auth import SigV4Auth
2792-
from botocore.awsrequest import AWSRequest
2793-
2794-
2795-
class SigV4HTTPXAuth(httpx.Auth):
2796-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
2797-
2798-
def __init__(self):
2799-
session = boto3.Session()
2800-
credentials = session.get_credentials().get_frozen_credentials()
2801-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
2802-
self.signer = SigV4Auth(credentials, "lambda", region)
2803-
2804-
def auth_flow(self, request):
2805-
headers = dict(request.headers)
2806-
headers.pop("connection", None)
2807-
aws_request = AWSRequest(
2808-
method=request.method,
2809-
url=str(request.url),
2810-
data=request.content,
2811-
headers=headers,
2812-
)
2813-
self.signer.add_auth(aws_request)
2814-
request.headers.update(dict(aws_request.headers))
2815-
yield request
2737+
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
28162738
{{/if}}
28172739
28182740
{{#each gatewayProviders}}
@@ -2823,8 +2745,7 @@ def get_{{snakeCase name}}_mcp_client() -> MCPClient | None:
28232745
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
28242746
return None
28252747
{{#if (eq authType "AWS_IAM")}}
2826-
http_client = httpx.AsyncClient(auth=SigV4HTTPXAuth())
2827-
return MCPClient(lambda: streamablehttp_client(url, http_client=http_client))
2748+
return MCPClient(lambda: aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore"))
28282749
{{else}}
28292750
return MCPClient(lambda: streamablehttp_client(url))
28302751
{{/if}}

src/assets/python/langchain_langgraph/base/mcp_client/client.py

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,41 @@
11
import os
22
import logging
3+
from mcp.client.streamable_http import streamablehttp_client
34
from langchain_mcp_adapters.client import MultiServerMCPClient
45

56
logger = logging.getLogger(__name__)
67

78
{{#if hasGateway}}
89
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
9-
import boto3
10-
import httpx
11-
from botocore.auth import SigV4Auth
12-
from botocore.awsrequest import AWSRequest
13-
14-
15-
class SigV4HTTPXAuth(httpx.Auth):
16-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
17-
18-
def __init__(self):
19-
session = boto3.Session()
20-
credentials = session.get_credentials().get_frozen_credentials()
21-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
22-
self.signer = SigV4Auth(credentials, "lambda", region)
23-
24-
def auth_flow(self, request):
25-
headers = dict(request.headers)
26-
headers.pop("connection", None)
27-
aws_request = AWSRequest(
28-
method=request.method,
29-
url=str(request.url),
30-
data=request.content,
31-
headers=headers,
32-
)
33-
self.signer.add_auth(aws_request)
34-
request.headers.update(dict(aws_request.headers))
35-
yield request
10+
from mcp.client.session import ClientSession
11+
from langchain_mcp_adapters.tools import load_mcp_tools
12+
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
3613
{{/if}}
3714

38-
39-
def get_all_gateway_mcp_client() -> MultiServerMCPClient | None:
40-
"""Returns an MCP Client connected to all configured gateways."""
41-
servers = {}
42-
{{#each gatewayProviders}}
15+
{{#each gatewayProviders}}
16+
{{#if (eq authType "AWS_IAM")}}
17+
async def get_{{snakeCase name}}_mcp_tools():
18+
"""Returns MCP tools from the {{name}} gateway using SigV4 auth."""
4319
url = os.environ.get("{{envVarName}}")
44-
if url:
45-
{{#if (eq authType "AWS_IAM")}}
46-
servers["{{name}}"] = {"transport": "streamable_http", "url": url, "http_client": httpx.AsyncClient(auth=SigV4HTTPXAuth())}
47-
{{else}}
48-
servers["{{name}}"] = {"transport": "streamable_http", "url": url}
49-
{{/if}}
50-
else:
20+
if not url:
21+
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
22+
return []
23+
mcp_client = aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore")
24+
async with mcp_client as (read, write, _):
25+
async with ClientSession(read, write) as session:
26+
await session.initialize()
27+
return await load_mcp_tools(session)
28+
{{else}}
29+
def get_{{snakeCase name}}_mcp_client() -> MultiServerMCPClient | None:
30+
"""Returns an MCP Client for the {{name}} gateway."""
31+
url = os.environ.get("{{envVarName}}")
32+
if not url:
5133
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
52-
{{/each}}
53-
if not servers:
5434
return None
55-
return MultiServerMCPClient(servers)
35+
return MultiServerMCPClient({"{{name}}": {"transport": "streamable_http", "url": url}})
36+
{{/if}}
37+
38+
{{/each}}
5639
{{else}}
5740
# ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
5841
EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"

src/assets/python/openaiagents/base/mcp_client/client.py

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,13 @@
55
logger = logging.getLogger(__name__)
66

77
{{#if hasGateway}}
8-
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
9-
import boto3
10-
import httpx
11-
from botocore.auth import SigV4Auth
12-
from botocore.awsrequest import AWSRequest
13-
14-
15-
class SigV4HTTPXAuth(httpx.Auth):
16-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
17-
18-
def __init__(self):
19-
session = boto3.Session()
20-
credentials = session.get_credentials().get_frozen_credentials()
21-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
22-
self.signer = SigV4Auth(credentials, "lambda", region)
23-
24-
def auth_flow(self, request):
25-
headers = dict(request.headers)
26-
headers.pop("connection", None)
27-
aws_request = AWSRequest(
28-
method=request.method,
29-
url=str(request.url),
30-
data=request.content,
31-
headers=headers,
32-
)
33-
self.signer.add_auth(aws_request)
34-
request.headers.update(dict(aws_request.headers))
35-
yield request
36-
{{/if}}
37-
38-
398
def get_all_gateway_mcp_servers() -> list[MCPServerStreamableHttp]:
409
"""Returns MCP servers for all configured gateways."""
4110
servers = []
4211
{{#each gatewayProviders}}
4312
url = os.environ.get("{{envVarName}}")
4413
if url:
45-
{{#if (eq authType "AWS_IAM")}}
46-
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url, "http_client": httpx.AsyncClient(auth=SigV4HTTPXAuth())}))
47-
{{else}}
4814
servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url}))
49-
{{/if}}
5015
else:
5116
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
5217
{{/each}}

src/assets/python/strands/base/mcp_client/client.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,7 @@
77

88
{{#if hasGateway}}
99
{{#if (includes gatewayAuthTypes "AWS_IAM")}}
10-
import boto3
11-
import httpx
12-
from botocore.auth import SigV4Auth
13-
from botocore.awsrequest import AWSRequest
14-
15-
16-
class SigV4HTTPXAuth(httpx.Auth):
17-
"""Signs HTTP requests with AWS SigV4 for Lambda function URL authentication."""
18-
19-
def __init__(self):
20-
session = boto3.Session()
21-
credentials = session.get_credentials().get_frozen_credentials()
22-
region = session.region_name or os.environ.get("AWS_REGION", "us-east-1")
23-
self.signer = SigV4Auth(credentials, "lambda", region)
24-
25-
def auth_flow(self, request):
26-
headers = dict(request.headers)
27-
headers.pop("connection", None)
28-
aws_request = AWSRequest(
29-
method=request.method,
30-
url=str(request.url),
31-
data=request.content,
32-
headers=headers,
33-
)
34-
self.signer.add_auth(aws_request)
35-
request.headers.update(dict(aws_request.headers))
36-
yield request
10+
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
3711
{{/if}}
3812

3913
{{#each gatewayProviders}}
@@ -44,8 +18,7 @@ def get_{{snakeCase name}}_mcp_client() -> MCPClient | None:
4418
logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
4519
return None
4620
{{#if (eq authType "AWS_IAM")}}
47-
http_client = httpx.AsyncClient(auth=SigV4HTTPXAuth())
48-
return MCPClient(lambda: streamablehttp_client(url, http_client=http_client))
21+
return MCPClient(lambda: aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore"))
4922
{{else}}
5023
return MCPClient(lambda: streamablehttp_client(url))
5124
{{/if}}

0 commit comments

Comments
 (0)