Skip to content

Commit 810e3ad

Browse files
committed
feat(examples): upgrade mcp-shop-server to mcp 2.x, add TS/Python consumption snippets
The shop server now runs on MCPServer (mcp 2.x): it serves MCP protocol 2026-07-28 and still answers legacy clients through the handshake, so the Swift sample keeps working unchanged. host/port move from the constructor to run(), per the v2 API; decorators are unchanged. The README gains MCPToolProvider snippets for TypeScript and Python over streamable-http, closing the loop on the 2026-07-28 series: verified live with the provider on both mcp 2.0 (modern era) and mcp 1.29 (legacy handshake) against this server. Closes #635 Code written by Claude (Fable 5), architected and approved by @cornelcroi.
1 parent a861d34 commit 810e3ad

3 files changed

Lines changed: 44 additions & 11 deletions

File tree

examples/mcp-shop-server/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ A tiny [MCP](https://modelcontextprotocol.io) server for the [ChatGPTStyleChat](
44
Swift sample. It exposes an order-lookup tool that advertises a **UI widget**, over streamable HTTP,
55
so the native app can point at it instead of its built-in in-app tool.
66

7+
Built on `mcp` 2.x, so it serves MCP protocol **2026-07-28** and still answers older clients
8+
through the legacy handshake — the same server works for every consumer below, old or new.
9+
710
It shows the same contract ChatGPT Apps use: a tool returns `structuredContent` and advertises
811
`_meta.ui.resourceUri`. The app renders that widget as a native SwiftUI card, hydrated from the
912
tool's data — no HTML, no web view.
1013

1114
## Run it
1215

16+
Requires Python >= 3.10 (the `mcp` 2.x floor).
17+
1318
```bash
1419
# Optional: Set up a virtual environment
1520
python -m venv venv
@@ -19,6 +24,31 @@ python shop_server.py # serves on http://127.0.0.1:8000/mcp (l
1924
HOST=0.0.0.0 python shop_server.py # bind to the LAN, for a physical device
2025
```
2126

27+
## Consume it from agent-squad (TypeScript / Python)
28+
29+
`MCPToolProvider` connects over the `streamable-http` transport; the protocol era is negotiated
30+
per server, so nothing else is configured. With the v2 SDKs installed
31+
(`@modelcontextprotocol/client` / `mcp>=2`) the session runs on protocol 2026-07-28; with the v1
32+
SDKs it falls back to the legacy handshake — same code either way.
33+
34+
```typescript
35+
import { MCPToolProvider } from "agent-squad";
36+
37+
const provider = await MCPToolProvider.create([
38+
{ type: "streamable-http", url: "http://127.0.0.1:8000/mcp" },
39+
]);
40+
// get_order is offered to the model; refresh_order stays app-only.
41+
```
42+
43+
```python
44+
from agent_squad.tools import MCPToolProvider, MCPServerConfig
45+
46+
provider = await MCPToolProvider.create([
47+
MCPServerConfig(type="streamable-http", url="http://127.0.0.1:8000/mcp"),
48+
])
49+
# get_order is offered to the model; refresh_order stays app-only.
50+
```
51+
2252
## Point the app at it
2353

2454
In the Swift sample, set the toggle in `Config.swift`:
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
# Tested with mcp 1.28.1. `meta=` on @mcp.tool and structured_output need a recent build.
2-
# Capped to <2: mcp 2.0.0 is a breaking release (FastMCP renamed, snake_case types).
3-
mcp>=1.28.0,<2
1+
# mcp 2.x (MCPServer) serves MCP protocol 2026-07-28 and answers legacy clients too.
2+
mcp>=2.0.0

examples/mcp-shop-server/shop_server.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""A tiny MCP shop server for the ChatGPTStyleChat sample.
22
33
Exposes an order-lookup tool that advertises a UI widget, over streamable HTTP so a native app
4-
(the Swift ChatGPTStyleChat sample) can point at it with `MCPServer(url: "http://…/mcp")`.
4+
(the Swift ChatGPTStyleChat sample) can point at it with AgentSquadMCP's `MCPServer(url: "http://…/mcp")`.
55
66
pip install -r requirements.txt
77
python shop_server.py # serves on http://127.0.0.1:8000/mcp
@@ -20,19 +20,17 @@
2020

2121
import os
2222

23-
from mcp.server.fastmcp import FastMCP
23+
from mcp.server import MCPServer
2424
from pydantic import BaseModel
2525

2626
ORDER_CARD_URI = "ui://shop/order-card"
2727

28-
# Loopback by default (Simulator reaches it). For a physical device, bind to the LAN with
29-
# `HOST=0.0.0.0 python shop_server.py` and point the app at your Mac's LAN IP.
30-
mcp = FastMCP("shop", host=os.environ.get("HOST", "127.0.0.1"), port=int(os.environ.get("PORT", "8000")))
28+
mcp = MCPServer("shop")
3129

3230

3331
class Order(BaseModel):
34-
"""The order shape. A typed return makes FastMCP emit it as `structuredContent` — the render-only
35-
data the native card hydrates from."""
32+
"""The order shape. A typed return makes the server emit it as `structuredContent` — the
33+
render-only data the native card hydrates from."""
3634

3735
orderId: str
3836
status: str
@@ -81,4 +79,10 @@ def order_card_resource() -> str:
8179

8280

8381
if __name__ == "__main__":
84-
mcp.run(transport="streamable-http")
82+
# Loopback by default (Simulator reaches it). For a physical device, bind to the LAN with
83+
# `HOST=0.0.0.0 python shop_server.py` and point the app at your Mac's LAN IP.
84+
mcp.run(
85+
transport="streamable-http",
86+
host=os.environ.get("HOST", "127.0.0.1"),
87+
port=int(os.environ.get("PORT", "8000")),
88+
)

0 commit comments

Comments
 (0)