Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ jobs:
with:
node-version: "20"

- uses: astral-sh/setup-uv@v5

- run: npm ci

- name: Install Playwright browsers
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ Or edit your `package.json` manually:
| [**Scenario Modeler**](examples/scenario-modeler-server) | [**Budget Allocator**](examples/budget-allocator-server) | [**Customer Segmentation**](examples/customer-segmentation-server) |
| [![System Monitor](examples/system-monitor-server/grid-cell.png "Real-time OS metrics")](examples/system-monitor-server) | [![Transcript](examples/transcript-server/grid-cell.png "Live speech transcription")](examples/transcript-server) | [![Video Resource](examples/video-resource-server/grid-cell.png "Binary video via MCP resources")](examples/video-resource-server) |
| [**System Monitor**](examples/system-monitor-server) | [**Transcript**](examples/transcript-server) | [**Video Resource**](examples/video-resource-server) |
| [![PDF Server](examples/pdf-server/grid-cell.png "Interactive PDF viewer with chunked loading")](examples/pdf-server) | | |
| [**PDF Server**](examples/pdf-server) | | |
| [![PDF Server](examples/pdf-server/grid-cell.png "Interactive PDF viewer with chunked loading")](examples/pdf-server) | [![QR Code](examples/qr-server/grid-cell.png "QR code generator")](examples/qr-server) | |
| [**PDF Server**](examples/pdf-server) | [**QR Code (Python)**](examples/qr-server) | |

### Starter Templates

Expand Down
38 changes: 20 additions & 18 deletions examples/qr-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,28 @@ A minimal Python MCP server that generates customizable QR codes with an interac
- Interactive widget that displays in MCP-UI enabled clients
- Supports both HTTP (for web clients) and stdio (for Claude Desktop)

## Quick Start
## Prerequisites

This server uses [uv](https://docs.astral.sh/uv/) for dependency management. Install it first:

```bash
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate
curl -LsSf https://astral.sh/uv/install.sh | sh
```

# Install dependencies
pip install -r requirements.txt
## Quick Start

# Run server (HTTP mode)
python server.py
# → QR Server listening on http://localhost:3108/mcp
```bash
# Run server (HTTP mode) - uv handles dependencies automatically
uv run server.py
# → QR Code Server listening on http://localhost:3108/mcp
```

## Usage

### HTTP Mode (for basic-host / web clients)

```bash
python server.py
uv run server.py
```

Connect from basic-host:
Expand All @@ -43,7 +44,7 @@ SERVERS='["http://localhost:3108/mcp"]' bun serve.ts
### Stdio Mode (for Claude Desktop)

```bash
python server.py --stdio
uv run server.py --stdio
```

Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
Expand All @@ -52,8 +53,8 @@ Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_deskt
{
"mcpServers": {
"qr": {
"command": "/path/to/qr-server/.venv/bin/python",
"args": ["/path/to/qr-server/server.py", "--stdio"]
"command": "uv",
"args": ["run", "/path/to/qr-server/server.py", "--stdio"]
}
}
}
Expand Down Expand Up @@ -135,9 +136,8 @@ Generate a QR code with optional customization.

```
qr-server/
├── server.py # MCP server (FastMCP + uvicorn)
├── server.py # MCP server (FastMCP + uvicorn, deps inline via PEP 723)
├── widget.html # Interactive UI widget
├── requirements.txt
└── README.md
```

Expand All @@ -153,10 +153,12 @@ The widget uses MCP Apps SDK protocol:

## Dependencies

- `mcp[cli]` - MCP Python SDK with FastMCP
Dependencies are declared inline in `server.py` using [PEP 723](https://peps.python.org/pep-0723/) and managed by [uv](https://docs.astral.sh/uv/):

- `mcp` - MCP Python SDK with FastMCP
- `qrcode[pil]` - QR code generation with Pillow
- `uvicorn` - ASGI server (included with mcp)
- `starlette` - CORS middleware (included with mcp)
- `uvicorn` - ASGI server
- `starlette` - CORS middleware

## License

Expand Down
Binary file added examples/qr-server/grid-cell.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions examples/qr-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@modelcontextprotocol/server-qr",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "uv run server.py",
"dev": "uv run server.py",
"build": "echo 'No build step needed for Python server'"
}
}
2 changes: 0 additions & 2 deletions examples/qr-server/requirements.txt

This file was deleted.

16 changes: 13 additions & 3 deletions examples/qr-server/server.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
#!/usr/bin/env uv run
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "mcp>=1.9.0",
# "qrcode[pil]>=8.0",
# "uvicorn>=0.34.0",
# "starlette>=0.46.0",
# ]
# ///
"""
QR Code MCP Server - Generates QR codes from text
"""
Expand All @@ -17,12 +27,12 @@
HOST = os.environ.get("HOST", "0.0.0.0") # 0.0.0.0 for Docker compatibility
PORT = int(os.environ.get("PORT", "3108"))

mcp = FastMCP("QR Server", port=PORT, stateless_http=True)
mcp = FastMCP("QR Code Server", port=PORT, stateless_http=True)


@mcp.tool(meta={"ui/resourceUri": WIDGET_URI})
def generate_qr(
text: str,
text: str = "https://modelcontextprotocol.io",
box_size: int = 10,
border: int = 4,
error_correction: str = "M",
Expand Down Expand Up @@ -122,5 +132,5 @@ async def _read_resource_with_meta(req: types.ReadResourceRequest):
allow_methods=["*"],
allow_headers=["*"],
)
print(f"QR Server listening on http://{HOST}:{PORT}/mcp")
print(f"QR Code Server listening on http://{HOST}:{PORT}/mcp")
uvicorn.run(app, host=HOST, port=PORT)
2 changes: 1 addition & 1 deletion examples/qr-server/widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<body>
<div id="qr"></div>
<script type="module">
import { App } from "https://unpkg.com/@modelcontextprotocol/ext-apps@0.3.1/app-with-deps";
import { App } from "https://unpkg.com/@modelcontextprotocol/ext-apps@0.4.0/app-with-deps";

const app = new App({ name: "QR Widget", version: "1.0.0" });

Expand Down
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
"test:e2e": "playwright test",
"test:e2e:update": "playwright test --update-snapshots",
"test:e2e:ui": "playwright test --ui",
"test:e2e:docker": "docker run --rm -v $(pwd):/work -w /work -it mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'npm i -g bun && npm ci && npx playwright test'",
"test:e2e:docker:update": "npm run build:all && docker run --rm -v $(pwd):/work -w /work -it mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'npm i -g bun && npm ci && npx playwright test --update-snapshots'",
"test:e2e:docker": "docker run --rm -v $(pwd):/work -w /work -it mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'apt-get update -qq && apt-get install -qq -y python3-venv curl > /dev/null && curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH=\"$HOME/.local/bin:$PATH\" && npm i -g bun && npm ci && npx playwright test'",
"test:e2e:docker:update": "npm run build:all && docker run --rm -v $(pwd):/work -w /work -it mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'apt-get update -qq && apt-get install -qq -y python3-venv curl > /dev/null && curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH=\"$HOME/.local/bin:$PATH\" && npm i -g bun && npm ci && npx playwright test --update-snapshots'",
"preexamples:build": "npm run build",
"examples:build": "bun examples/run-all.ts build",
"examples:start": "NODE_ENV=development npm run build && bun examples/run-all.ts start",
Expand All @@ -64,7 +64,7 @@
"prepare": "node scripts/setup-bun.mjs && npm run build && husky",
"docs": "typedoc",
"docs:watch": "typedoc --watch",
"generate:screenshots": "npm run build:all && docker run --rm -v $(pwd):/work -w /work mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'npm i -g bun && npm ci && npx playwright test tests/e2e/generate-grid-screenshots.spec.ts'",
"generate:screenshots": "npm run build:all && docker run --rm -v $(pwd):/work -w /work mcr.microsoft.com/playwright:v1.57.0-noble sh -c 'apt-get update -qq && apt-get install -qq -y python3-venv curl > /dev/null && curl -LsSf https://astral.sh/uv/install.sh | sh && export PATH=\"$HOME/.local/bin:$PATH\" && npm i -g bun && npm ci && npx playwright test tests/e2e/generate-grid-screenshots.spec.ts'",
"prettier": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --check",
"prettier:fix": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --write",
"check:versions": "node scripts/check-versions.mjs"
Expand Down
3 changes: 2 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export default defineConfig({
url: "http://localhost:8080",
// Always start fresh servers to avoid stale state issues
reuseExistingServer: false,
timeout: 120000,
// 3 minutes to allow uv to download Python dependencies on first run
timeout: 180000,
},
// Snapshot configuration
expect: {
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/servers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const SERVERS = [
{ key: "customer-segmentation", name: "Customer Segmentation Server" },
{ key: "map-server", name: "CesiumJS Map Server" },
{ key: "pdf-server", name: "PDF Server" },
{ key: "qr-server", name: "QR Code Server" },
{ key: "scenario-modeler", name: "SaaS Scenario Modeler" },
{ key: "shadertoy", name: "ShaderToy Server" },
{ key: "sheet-music", name: "Sheet Music Server" },
Expand Down
Binary file added tests/e2e/servers.spec.ts-snapshots/qr-server.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading