Enterprises building AI-powered experiences need a way to expose their backend services as interactive, conversational tools — without rewriting APIs or coupling to a single AI host. This project demonstrates how to do that using MCP Apps — an extension to the Model Context Protocol that lets MCP servers deliver interactive HTML user interfaces rendered directly inside AI hosts like ChatGPT, Claude, and VS Code Copilot — deployed on Amazon Bedrock AgentCore Runtime.
The sample implements Unicorn Rentals — a conversational rental service with rich interactive widgets rendered inline. Because MCP Apps are host-agnostic, the same server works across any supporting client. Customers can:
- List unicorns — Browse the full fleet with details like name, speed, color, availability and hourly rate
- Book a unicorn — Reserve a unicorn at its hourly rate and receive a booking confirmation
- View active rental — Monitor the current booking status and elapsed time
- Return a unicorn — End the rental and receive an automatic duration-based invoice
Disclaimer: This sample is provided for demonstration purposes and is not intended for production use without further security hardening, testing, and review appropriate to your environment.
This sample shows how to deploy an MCP (Model Context Protocol) server with MCP Apps on Amazon Bedrock AgentCore Runtime and connect it to AI hosts (ChatGPT, Claude, etc.) with rich interactive widget UI.
- MCP Server: Node.js 22 / TypeScript
- Business Logic: Python Lambda (DynamoDB access)
- Proxy Lambda: Node.js 22 / TypeScript
- Infrastructure: AWS CDK (TypeScript)
- Runtime: Amazon Bedrock AgentCore Runtime (NODEJS_22)
| Action | Screenshot |
|---|---|
| List Unicorns: | ![]() |
| Book Unicorns: | ![]() |
| Show bookings: | ![]() |
| Return unicorn: | ![]() |
You will be able to interact with the app with requests like:
- List all unicorns
- I would like to book Stardust unicorn
- Show me my unicorn bookings
- I would like to return my unicorn
How it works:
| Component | Purpose |
|---|---|
| MCP Server (Node.js/TS) | Thin MCP protocol layer — receives JSON-RPC, resolves identity, invokes service Lambda, serves widget HTML as MCP resources |
| Unicorn Rental Service (Python) | Lambda function that implements business logic (list, book, view, return unicorns) with DynamoDB access |
| AgentCore Runtime | Managed runtime hosting the MCP server (Node.js 22) |
| API Gateway | Public HTTPS endpoint for MCP hosts to call |
| API Gateway Proxy Lambda (Node.js/TS) | Translates HTTPS from API Gateway into InvokeAgentRuntime calls |
| S3 + CloudFront | Serves unicorn images referenced by widgets |
| DynamoDB | Stores unicorn inventory and booking records |
- The MCP host sends an MCP JSON-RPC request (e.g.,
tools/callwithlist_unicorns) to the API Gateway endpoint. - API Gateway receives the HTTPS request, applies WAF rules (IP allowlisting, rate limiting, common attack protection), and routes it to the Proxy Lambda.
- API Gateway Proxy Lambda forwards the request to AgentCore Runtime.
- AgentCore Runtime (MCP Server) receives the MCP request, resolves customer identity from the host context, and invokes the Unicorn Service Lambda.
- Unicorn Service Lambda executes the business logic against DynamoDB and returns the results.
- AgentCore Runtime (MCP Server) wraps the response in MCP structured output with widget resource references and returns it to the host.
- The MCP host receives a
tools/callresponse containing a widget resource URI (e.g.,ui://widget/unicorn-list) in the tool's_meta.ui.resourceUrifield. - The MCP host sends an MCP
resources/readrequest for that URI to the API Gateway endpoint. - API Gateway routes the request through WAF and forwards it to the Proxy Lambda.
- API Gateway Proxy Lambda forwards the request to AgentCore Runtime.
- AgentCore Runtime (MCP Server) resolves the resource URI, loads the corresponding widget HTML (served as an MCP resource using
registerAppResource) and returns it. - The MCP host renders the HTML widget in a sandboxed iframe, injecting the structured data from the original
tools/callresponse via the MCP Apps lifecycle. - Images referenced by widgets are fetched directly from CloudFront (backed by S3).
This project demonstrates a clean separation between the MCP protocol layer and the business logic layer:
- MCP Server (AgentCore Runtime) — Handles MCP protocol, tool definitions, structured output, widget resources (MCP Apps pattern), and customer identity resolution from host context. It delegates all business operations to the Unicorn Service Lambda.
- Unicorn Rental Service Lambda — Pure business logic that accepts JSON requests and returns JSON responses.
- AWS account with Amazon Bedrock AgentCore enabled
- AWS CLI configured (
aws configure) - Node.js 22+ (for MCP server, proxy Lambda, and AWS CDK)
- AWS CDK CLI installed globally:
npm install -g aws-cdk
A single build script handles both the API Gateway Proxy Lambda and MCP Server packaging:
chmod +x build.sh
./build.sh --cleanThis script:
- Builds the API Gateway Proxy Lambda (
src/lambda/api-gateway-proxy/dist/index.mjs) - Installs MCP server dependencies (clean install via
--cleanflag for reproducible builds) - Bundles widget HTML files with Vite using
vite-plugin-singlefile(inlines the MCP Apps SDK so widgets work on any host without external CDN dependencies) - Bundles the Node.js server with esbuild into a single
main.js - Packages everything into
build/mcp-server-deployment.zip
The --clean flag removes node_modules and package-lock.json before installing, ensuring a reproducible build. Omit it for faster local iteration when dependencies haven't changed.
The build output is pure JavaScript — no native modules — so it runs on ARM64 AgentCore Runtime regardless of the build host architecture.
cd infrastructure/cdk
npm installIf this is the first time deploying CDK in your AWS account/region, you need to bootstrap:
npx cdk bootstrapVerify the stack synthesizes without errors:
npx cdk synthYou can optionally pass a custom project name via context:
npx cdk synth -c projectName=unicorn-rentalsThe default project name is unicorn-mcp.
npx cdk deployCDK will:
- Create the S3 deployment bucket and upload the MCP server zip
- Create DynamoDB tables and seed them with unicorn data
- Deploy the Unicorn Service Lambda with DynamoDB permissions
- Create the IAM role for AgentCore with S3 read and Lambda invoke permissions
- Create the AgentCore Runtime (MCP Server) pointing to the service Lambda
- Deploy the API Gateway Proxy Lambda
- Deploy API Gateway with WAF
Note the outputs printed after deployment — you'll need the McpEndpointUrl to connect an MCP host.
After deployment, connect the MCP endpoint to your preferred host:
- ChatGPT — ChatGPT Setup Guide
- Claude — Claude Setup Guide
Both guides cover configuration steps, demo prompts, and troubleshooting. You'll need the McpEndpointUrl from the CDK output.
This project implements multiple layers of security to protect the API endpoint and backend services:
AWS WAF is attached to the API Gateway with a default-deny policy. Only requests originating from allowlisted IP ranges are permitted through. The deployed stack includes outbound IP ranges for both ChatGPT (OpenAI outbound IPs) and Claude (Anthropic outbound IPs). To connect additional MCP hosts or for testing the MCP server directly using tools like MCP Inspector, add their outbound IP ranges to the WAF IP set.
- AWS Managed Rules Common Rule Set — Blocks requests matching common attack patterns
- AWS Managed Rules Known Bad Inputs — Blocks requests with payloads known to be associated with exploitation
- Rate Limiting — Blocks IPs exceeding 1,000 requests per 5-minute window
A resource-based access policy is attached directly to the AgentCore Runtime. It explicitly allows only the API Gateway Proxy Lambda's execution role to invoke the runtime, and denies all other principals.
To destroy all deployed resources:
cd infrastructure/cdk
npx cdk destroy



