ailab_rip_mcp_app
A demo MCP server that exposes stock-quote tools to LLMs via FastMCP over streamable HTTP. It can be deployed to AWS ECS and integrated with ChatGPT as a custom connector.
README
ailab_rip_mcp_app
A foundational demo of a Model Context Protocol (MCP) app. A tiny FastMCP server exposes a stock-quote tool from a bundled JSON file, runs locally over streamable HTTP, deploys to AWS via ECS Express Mode, and plugs into ChatGPT as a Developer Mode custom connector.
The point is the walkthrough, not the depth. The code is short enough to read in one sitting.
What is MCP
The Model Context Protocol is an open standard for wiring LLMs to external tools and data. An MCP server exposes capabilities — most commonly tools (functions the model can call) — and an MCP client (ChatGPT, Claude, your own agent) discovers and invokes them over a transport such as stdio or streamable HTTP. This repo is an MCP server.
Prerequisites
- Python 3.10+
uvfor dependency management (brew install uvorcurl -LsSf https://astral.sh/uv/install.sh | sh)- Docker (for the AWS deploy)
- AWS CLI v2 with a configured profile that can create ECR repos and ECS services
- Node.js (only for
npx @modelcontextprotocol/inspectorduring local verification) - A ChatGPT account that can enable Developer Mode — see the ChatGPT integration section
Repo tour
.
├── src/
│ ├── server.py # FastMCP server, two tools + widget resource
│ └── data/quotes.json # 10 hand-curated tickers
├── web/ # React + Vite widget (Apps SDK compatible)
│ ├── src/ # StockCard.tsx, main.tsx, styles.css
│ ├── dist/stock-card.js # built bundle (committed — server needs no npm)
│ └── package.json
├── tests/ # pytest + in-memory FastMCP Client
├── scripts/push_to_ecr.sh # build + push helper
├── Dockerfile # uv-based image, exposes 8000
├── pyproject.toml # uv-managed deps
└── uv.lock # locked deps (committed)
Install and test
uv sync # create .venv from uv.lock
uv run pytest # 4 tests, in-memory, ~40 ms
Run locally and verify with MCP Inspector
uv run python src/server.py
# → FastMCP banner shows http://0.0.0.0:8000/mcp
In another shell:
npx @modelcontextprotocol/inspector
In the Inspector UI: Transport = Streamable HTTP, URL =
http://localhost:8000/mcp, then invoke:
list_supported_symbols→ 10 tickersget_stock_quotewithsymbol="AAPL"→ the seeded dict +day_change_pctget_stock_quotewithsymbol="ZZZZ"→ a tool error naming the supported symbols
Deploy to AWS with ECS Express Mode
ECS Express Mode is AWS's newest single-command path for containerized services. It auto-provisions the ECS cluster, Fargate task, ALB with HTTPS, target group, security groups, and auto-scaling from one API call — exactly what a ChatGPT connector needs.
1. Build and push the image to ECR
./scripts/push_to_ecr.sh
# → prints IMAGE_URI=<account>.dkr.ecr.<region>.amazonaws.com/mcp-stock-quote:latest
Overridable env vars: AWS_REGION, AWS_PROFILE, ECR_REPO_NAME,
IMAGE_TAG. The script builds for linux/amd64 explicitly — required for
Fargate x86 tasks when the dev machine is Apple silicon.
2. Deploy to ECS Express (via glab_iac)
Infrastructure lives in the sibling glab_iac Terraform
repo. Add a new ECS Express block that points to the ECR image you just
pushed, then apply:
- In
glab_iac, add a new ECS Express service block. Set:image→ theIMAGE_URIprinted bypush_to_ecr.sh.container_port→8000(what the FastMCP server binds to).health_check_path→/health.
terraform planand review — Express Mode auto-provisions the cluster, Fargate task, ALB with HTTPS, target group, security groups, IAM roles, and auto-scaling.terraform apply. Wait until the service reportsRUNNINGand its ALB target group reports healthy (a few minutes).- Grab the public HTTPS URL from the Terraform output (or the ECS
console). Your MCP endpoint is
https://<generated-domain>/mcp.
Verify with MCP Inspector or a quick curl before wiring ChatGPT:
curl -s https://<generated-domain>/health # → {"status":"ok"}
Then integrate it as a custom connector — see the next section.
Region caveat: ECS Express Mode is new (announced late 2025) and not yet available in every AWS region. Check the ECS console in your region.
Integrate with ChatGPT (Developer Mode)
All quotes below come from OpenAI's custom MCP docs.
Requirements
- ChatGPT subscription — Developer Mode is a gated feature. OpenAI's developer docs don't spell out the tier list; the authoritative source is help.openai.com article 11487775. Historically: Plus, Pro, Business, Enterprise, Edu. Free tier cannot follow this section.
- Developer Mode toggled on —
"In ChatGPT, open Settings → Security and login and turn on Developer mode."
- Server transport — public HTTPS URL, streamable-HTTP transport, path
/mcp. ECS Express Mode + FastMCP's defaults give you all three.
For this demo we use no authentication. OpenAI's docs neither mandate nor explicitly forbid it — a personal Developer Mode server only you connect to works fine unauthenticated, and it keeps the demo focused on MCP itself. This is dev-only. Production connectors should use OAuth.
Add the connector
- ChatGPT → Menu → Plugins → Add (+).
- Paste
https://<ecs-express-domain>/mcp. - Leave authentication empty: No Auth (dev-only).
- Save.
- Connect.
- Check at Plugins (browse until you find yours).
Try it
Prompt ChatGPT:
Using the stock quote connector, what is AAPL's current price? @stock_mcp_app what is AAPL's current price?
The trace panel should show a call to list_supported_symbols and/or
get_stock_quote. Both tools are read-only, so no confirmation prompt
appears.
The widget (sharing UI back to ChatGPT)
Chapter one served pure JSON and let ChatGPT paint a paragraph. Chapter two
attaches a small React "stock card" to every get_stock_quote result so
ChatGPT renders it inline. Two pieces make this work:
-
The tool declares its template and a typed return. In
src/server.py:@mcp.tool(meta={"openai/outputTemplate": "ui://stock-card/v1.html"}) def get_stock_quote(symbol: str) -> Quote: ...Two things matter here: the
_metafield points at the widget resource, and theQuoteTypedDict return makes FastMCP emit anoutputSchema. Without that schema, ChatGPT filterswindow.openai.toolOutputdown to a handful of fields — the widget wouldn't see the price. -
The resource ships the widget. Same file:
@mcp.resource("ui://stock-card/v1.html", mime_type="text/html;profile=mcp-app") def stock_card_widget() -> str: return _WIDGET_HTML # <div id="root"></div> + inlined React bundleThe mime type
text/html;profile=mcp-appis what tells ChatGPT to render this inside a sandboxed iframe next to the assistant reply. The React bundle inweb/dist/stock-card.jsreadswindow.openai.toolOutput(found by walking up the frame chain to the host frame) and paints a price card.
Editing the widget. Only needed if you want to change the UI itself — the server ships the built bundle:
cd web
npm install
npm run build # -> web/dist/stock-card.js
The bundle is committed on purpose so uv run python src/server.py works
without a JS toolchain. Rebuild the container after any widget change so the
new bundle ships to ECS. In ChatGPT, hit Refresh on the connector (or
remove + re-add) so it picks up any schema changes, then start a new chat.
Gotchas we hit. Two Apps SDK details worth knowing:
- Vite's
libmode doesn't replaceprocess.env.NODE_ENV. Withoutdefine: { "process.env.NODE_ENV": '"production"' }invite.config.ts, the widget throwsReferenceError: process is not definedin the sandbox. window.openaiis only injected on the outer host frame. Widgets rendered in a nested iframe must walk up (window.parent,window.top) to reach it — seeweb/src/main.tsx.
Limitations and next steps
- Static data — real prices need something like
yfinance; note its ToS. - No auth — add OAuth via FastMCP's built-in auth providers before making the server public.
- No infrastructure-as-code — Express Mode is one CLI call. For repeatable environments, port to CloudFormation (aws-samples/sample-mcp-server-on-ecs) or CDK.
- Single-stage Docker image — split builder/runtime stages to shrink the image.
Links
- FastMCP docs — https://gofastmcp.com
- OpenAI custom MCP connectors — https://developers.openai.com/api/docs/mcp
- ECS Express Mode launch post — https://aws.amazon.com/blogs/aws/build-production-ready-applications-without-infrastructure-complexity-using-amazon-ecs-express-mode/
- Deploying MCP on ECS (AWS blog) — https://aws.amazon.com/blogs/containers/deploying-model-context-protocol-mcp-servers-on-amazon-ecs/
- uv — https://astral.sh/uv
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。