待翻譯:How we built an MCP bridge to give our AgentCore-hosted AI agent access to local MCP tools
AI 服務暫時不可用,以下為來源摘要,待恢復後補全翻譯:AI agents on Amazon Bedrock AgentCore run in the cloud, but users' tools and files live on their laptops. Learn how to build a secure MCP bridge that lets a cloud-hosted agent call local MCP servers by tunneling signed messages over the existing WebSocket connection through a browser extension and Chrome native messaging, with no open ports or VPN required.
AI 服務暫時不可用,以下為來源正文,待恢復後補全翻譯。
Our agent runs in the cloud, but our users’ spreadsheets live on their laptops. How do you bridge that gap? The Model Context Protocol (MCP) is an open source standard introduced by Anthropic in November 2024 to standardize how AI models connect to external data and tools. MCP follows a client-server architecture where an MCP host, an AI application like Amazon Quick or Claude Code, establishes connections to one or more MCP servers. The MCP protocol supports two transport mechanisms: stdio (standard I/O for communication between local processes on the same machine) and streamable HTTP transport (HTTP-based communication between remote servers and clients). A missing piece is when the MCP server exists locally and the MCP client is remote. This pattern matters for financial managers and analysts who primarily work with Excel and local files. They can use centrally deployed AI agents to act on those files while also drawing context from their browser. This is the same pattern that powers products like Claude Cowork, a cloud agent calling local tools through MCP, but fully self-hosted on AWS with your own model and custom tool servers. Internally, we built a production-grade AI assistant for finance that has seen over 41,000 conversations within a year since launch. In this post, we recreate what we built internally in a simplified form. Our agent, deployed on Amazon Bedrock AgentCore, uses MCP servers that run on a user’s local machine. We bridge the gap between the remote MCP client and the local MCP server by tunneling MCP messages over WebSocket and native messaging. We discuss additional production hardening measures in the What’s Next section. The complete source code is available on GitHub. The MCP Bridge Demo extension summarizing a local Excel workbook. The cloud-hosted agent reads the file directly from the user’s machine through the MCP bridge and streams a structured summary back to the side panel Architecture overview The AgentCore runtime, a capability of Amazon Bedrock AgentCore, anchors an architecture with four components: AgentCore runtime: Hosts the Strands agent in the cloud. The agent acts as the MCP client, issuing tool discovery and tool invocation requests. Browser extension: Provides the chat interface and acts as a bidirectional relay, forwarding MCP messages between the AgentCore runtime (over WebSocket) and the MCP Bridge (over native messaging). MCP Bridge: A FastMCP proxy running on the user’s local machine, spawned by the browser through the native messaging host registration. It translates between the native messaging envelope format and raw MCP JSON-RPC. MCP Server: A standard MCP server running locally. Because the bridge is co-located, communication uses the stdio transport. The following diagram shows the end-to-end message flow. The user sends a message through the extension, which connects to the AgentCore runtime over a presigned WebSocket. When the Strands agent needs to call a tool, it sends an MCP JSON-RPC request wrapped in a JSON envelope back through the WebSocket to the extension. The extension relays the message as-is to the bridge through native messaging. The bridge unwraps the envelope, extracts the JSON-RPC content, and forwards it to the MCP server over stdio. The response travels the reverse path. The bridge wraps the unmodified MCP server response back into an envelope and relays it through the extension to the AgentCore runtime, where the agent consumes the tool result and continues generation. High-level architecture diagram showing all components. The browser extension and MCP Bridge act as relays that wrap and unwrap JSON messages from the AgentCore runtime and JSON-RPC messages from the MCP server The following table shows a single tool call as it travels from the agent to the MCP server, with each hop stripping one layer of wrapping: Hop Sender → Receiver Message 1 Agent -> Extension (WebSocket) {“type”: “mcpbridge”, “content”: {“type”: “mcp”, “payload”: “”}, “session_id”: “session_123”} 2 Extension -> Bridge (Native Messaging) {“type”: “mcp”, “payload”: “”} 3 Bridge → MCP Server (stdio) {“jsonrpc”: “2.0”, “id”: 1, “method”: “tools/call”, “params”: {“name”: “read_sheet”, “arguments”: {“file_path”: “budget.xlsx”}}} How does the Strands agent work in AgentCore runtime WebSocket connection: The browser extension connects to the AgentCore runtime over a presigned WebSocket URL. On startup, the side panel sends a presign request through the background script to the native bridge, which uses the user’s local AWS credentials and the bedrock-agentcore software development kit (SDK) to generate a SigV4-signed wss:// URL scoped to the deployed runtime ARN (valid for 5 minutes). The side panel opens a WebSocket to that URL. No credentials ever leave the user’s machine or enter the browser. If the connection drops because of URL expiry or network interruption, the side panel automatically requests a fresh presigned URL after 2 seconds and reconnects, making the expiry window invisible to the user during normal use. MCP initialization: Before discovering tools, the agent performs the standard MCP initialization handshake. It sends an initialize request with the protocol version, waits for the server’s capabilities response, and then sends a notifications/initialized notification. Only after this handshake completes does the server accept tools/list and tools/call requests. Tool discovery: On each user message, the agent calls tools/list and receives an array of tool schemas. It wraps each schema into a Strands AgentTool whose stream() method sends a tools/call request through the bridge. Tools added to the MCP server are automatically available on the next request with no agent code changes. Request-response correlation: Each outbound JSON-RPC request from the agent is assigned a unique ID and registered against an asyncio.Future keyed by (session_id, jsonrpc_id). When the response arrives back over the WebSocket, it is matched to the waiting Future and resolved. This allows multiple tool calls to be in flight concurrently without ambiguity. How does native messaging work We need the extension to talk to a long-running local process without network permissions or per-message user prompts. Native messaging provides exactly this. Both Chrome and Firefox support native messaging for their extensions. The browser looks for a manifest file at a well-known location on the user’s machine that specifies which binary to launch. The native messaging manifest file for Chrome on macOS is as follows: # Stored at ~/Library/Application\ Support/Google/Chrome/NativeMessagingHosts/com.example.mcp_bridge.json { "name": "com.example.mcp_bridge", "description": "MCP Bridge - Routes MCP messages to local servers", "path": "/path/to/mcp-bridge-demo/bridge/run_bridge.sh", "type": "stdio", "allowed_origins": [ "chrome-extension:///" ] } On extension startup, the background script calls chrome.runtime.connectNative("com.example.mcp_bridge") to launch the native app locally. The run_bridge.sh script referenced in the manifest activates the Python environment and starts the bridge: #!/bin/bash cd "/path/to/mcp-bridge-demo/bridge" source .venv/bin/activate exec python3 bridge.py The native messaging host process stays alive for the lifetime of the connection. Each message is serialized as JSON, UTF-8 encoded, and preceded with a 32-bit message length in little-endian byte order. The maximum size of a single message from the native messaging host is 1 MB (to protect the browser from misbehaving native applications). The maximum size of a message sent to the native messaging host is 64 MiB. How does the MCP Bridge work The MCP Bridge acts as a protocol translator between two worlds: Chrome’s native messaging protocol on one side and the MCP standard (JSON-RPC 2.0 over stdio) on the other. On the inbound path, it strips the 4-byte length header from stdin, parses the JSON body, and unwraps the envelope to extract the raw JSON-RPC message. On the outbound path, it does the reverse: wraps the JSON-RPC response in an envelope and writes it back with the length header. The JSON-RPC content itself passes through untouched. Internally, the bridge runs two concurrent loops connected through a FastMCP proxy. The main loop reads messages from the browser, unwraps them, and places the JSON-RPC content onto an input queue. The FastMCP proxy, started once and kept alive for the bridge’s lifetime, picks messages off this queue, forwards them to the MCP server subprocess over its stdin, and places responses from the server’s stdout onto an output queue. A second background loop reads from the output queue, wraps each response back into an envelope, and writes it to stdout for the browser to receive. This two-loop design decouples the browser’s request timing from the MCP server’s processing speed so the bridge does not block waiting for a slow tool to finish before accepting the next request. The MCP server itself is a child process spawned by the bridge on startup, configured through a mcp.json file. It stays running for the bridge’s lifetime with no per-request process overhead. Adding a new MCP server is a one-line config change. The bridge handles the plumbing. # mcp.json { "mcpServers": { "excel": { "command": "python3", "args": ["excel_server.py"] } } } Internal architecture of the MCP Bridge. The MCP Bridge translates messages from the browser extension into the MCP protocol for the MCP server. I/O queues work with a FastMCP proxy server to forward messages to the locally running MCP server and relay messages back to the browser extension Prerequisites The following prerequisites are needed to deploy and test the MCP bridge solution. These cover the browser extension, the agent deployed on AgentCore, the MCP Bridge, and a sample Excel MCP server. AWS account and permissions AWS account with Bedrock model access enabled (the code uses Claude Opus 4.7). Model availability varies by Region. See the Amazon Bedrock model availability documentation for the current list. AWS Identity and Access Management (IAM) permissions for Bedrock AgentCore (bedrock-agentcore:*), AWS CloudFormation, IAM role creation, and S3. AWS Command Line Interface (AWS CLI) configured with credentials (aws sts get-caller-identity to verify). AWS Cloud Development Kit (AWS CDK) bootstrapped in your target Region (cdk bootstrap). Tools and software Python 3.10+. Node.js 20+ (for the AgentCore command line interface (CLI)). Google Chrome (Manifest V3 side panel support). Git. Install AgentCore CLI: npm install -g @aws/agentcore. AWS CDK: npm install -g aws-cdk. Estimated time and cost Setup: ~15 minutes (deploy, install extension, and register bridge). AgentCore runtime: pay-per-invocation (no idle cost). Bedrock model usage: standard per-token pricing for Claude. Other components run locally at no additional cost. Deploying the solution Clone the repository. git clone https://github.com/aws-samples/sample-mcp-bridge-agentcore.git cd mcp-bridge-demo Install Python dependencies. chmod +x scripts/setup.sh manifests/install.sh ./scripts/setup.sh Create and deploy the agent to AgentCore. npm install -g @aws/agentcore cd agent agentcore create --name McpBridgeAgent --defaults cd McpBridgeAgent cp ../agent.py app/McpBridgeAgent/main.py cp ../mcp_bridge_transport.py app/McpBridgeAgent/ agentcore deploy Note the runtime Amazon Resource Name (ARN) from the output (or run agentcore status). Configure the bridge.Edit bridge/bridge_config.json with your runtime ARN: { "runtime_arn": "arn:aws:bedrock-agentcore:::runtime/", "region": "us-east-1", "presign_expires": 300 } The bridge uses your local AWS credentials to generate presigned WebSocket URLs automatically, with no manual token management needed. Load the Chrome extension. Navigate to chrome://extensions. Turn on Developer mode. Choose Load unpacked, and [truncated for AI cost control]