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
23 changes: 23 additions & 0 deletions samples/agent/adk/mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# A2UI over MCP Demo

A demo of A2UI running over MCP, exposing a tool that returns a recipe UI.

## Usage

1. Start the server using either stdio (default) or SSE transport:

```bash
# Using SSE transport (default) on port 8000
uv run .
```

The server exposes a tool named "get_recipe_ui" that accepts no arguments.

2. Inspect the server using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)

```bash
npx @modelcontextprotocol/inspector
```

Connect to http://localhost:8000/sse using Transport Type SSE and run the tool. You should see something like the screenshot below:
![MCP Inspector Screenshot](mcp_inspector_screenshot.png)
13 changes: 13 additions & 0 deletions samples/agent/adk/mcp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
19 changes: 19 additions & 0 deletions samples/agent/adk/mcp/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys

from server import main

sys.exit(main()) # type: ignore[call-arg]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type: ignore[call-arg] comment suggests a type incompatibility that is being suppressed. It's best practice to either fix the underlying type issue to ensure type safety or provide a more detailed comment explaining why the ignore is necessary and what the expected behavior is, to aid future maintainers.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions samples/agent/adk/mcp/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[project]
name = "a2ui-mcp-demo"
version = "0.1.0"
description = "A demo of A2UI running over MCP"
readme = "README.md"
requires-python = ">=3.10"
keywords = ["mcp", "llm", "automation", "a2ui", "agent"]
license = { text = "MIT" }
dependencies = ["anyio>=4.5", "click>=8.2.0", "httpx>=0.27", "mcp", "a2ui-agent"]

[project.scripts]
a2ui-mcp-demo = "server:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["."]

[[tool.uv.index]]
url = "https://pypi.org/simple"
default = true


[tool.pyright]
include = ["."]
venvPath = "."
venv = ".venv"

[tool.ruff.lint]
select = ["E", "F", "I"]
ignore = []

[tool.ruff]
line-length = 120
target-version = "py310"

[dependency-groups]
dev = ["pyright>=1.1.378", "pytest>=8.3.3", "ruff>=0.6.9"]

[tool.uv.sources]
a2ui-agent = { path = "../../../../a2a_agents/python/a2ui_agent", editable = true }

244 changes: 244 additions & 0 deletions samples/agent/adk/mcp/recipe_a2ui.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
[
{
"beginRendering": {
"surfaceId": "recipe-card",
"root": "root-column",
"styles": {
"primaryColor": "#00BFFF",
"font": "Arial"
}
}
},
{
"surfaceUpdate": {
"surfaceId": "recipe-card",
"components": [
{
"id": "root",
"component": {
"Card": {
"child": "main-column"
}
}
},
{
"id": "main-column",
"component": {
"Column": {
"children": {
"explicitList": [
"recipe-image",
"content"
]
},
"gap": "small"
}
}
},
{
"id": "recipe-image",
"component": {
"Image": {
"url": {
"path": "/image"
},
"altText": {
"path": "/title"
},
"fit": "cover"
}
}
},
{
"id": "content",
"component": {
"Column": {
"children": {
"explicitList": [
"title",
"rating-row",
"times-row",
"servings"
]
},
"gap": "small"
}
}
},
{
"id": "title",
"component": {
"Text": {
"text": {
"path": "/title"
},
"usageHint": "h3"
}
}
},
{
"id": "rating-row",
"component": {
"Row": {
"children": {
"explicitList": [
"star-icon",
"rating",
"review-count"
]
},
"gap": "small",
"alignment": "center"
}
}
},
{
"id": "star-icon",
"component": {
"Icon": {
"name": {
"literalString": "star"
}
}
}
},
{
"id": "rating",
"component": {
"Text": {
"text": {
"path": "/rating"
},
"usageHint": "body"
}
}
},
{
"id": "review-count",
"component": {
"Text": {
"text": {
"path": "/reviewCount"
},
"usageHint": "caption"
}
}
},
{
"id": "times-row",
"component": {
"Row": {
"children": {
"explicitList": [
"prep-time",
"cook-time"
]
},
"gap": "medium"
}
}
},
{
"id": "prep-time",
"component": {
"Row": {
"children": {
"explicitList": [
"prep-icon",
"prep-text"
]
},
"gap": "small",
"alignment": "center"
}
}
},
{
"id": "prep-icon",
"component": {
"Icon": {
"name": {
"literalString": "timer"
}
}
}
},
{
"id": "prep-text",
"component": {
"Text": {
"text": {
"path": "/prepTime"
},
"usageHint": "caption"
}
}
},
{
"id": "cook-time",
"component": {
"Row": {
"children": {
"explicitList": [
"cook-icon",
"cook-text"
]
},
"gap": "small",
"alignment": "center"
}
}
},
{
"id": "cook-icon",
"component": {
"Icon": {
"name": {
"literalString": "shoppingCart"
}
}
}
},
{
"id": "cook-text",
"component": {
"Text": {
"text": {
"path": "/cookTime"
},
"usageHint": "caption"
}
}
},
{
"id": "servings",
"component": {
"Text": {
"text": {
"path": "/servings"
},
"usageHint": "caption"
}
}
}
]
}
},
{
"dataModelUpdate": {
"surfaceId": "recipe-card",
"path": "/",
"contents": [
{ "key": "image", "valueString": "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=300&h=180&fit=crop" },
{ "key": "title", "valueString": "Mediterranean Quinoa Bowl" },
{ "key": "rating", "valueNumber": 4.9 },
{ "key": "reviewCount", "valueString": "(1,247 reviews)" },
{ "key": "prepTime", "valueString": "15 min prep" },
{ "key": "cookTime", "valueString": "20 min cook" },
{ "key": "servings", "valueString": "Serves 4" }
]
}
}
]


Loading
Loading