Vibe Coder 实战指南
7.1 MCP 消费最佳实践
Do’s(最佳实践)
| 实践 | 描述 | 原因 |
|---|---|---|
| ✅ 审核公共 Server | 连接前审查开源 MCP Server 代码 | 防止恶意代码访问文件系统/凭证 |
| ✅ 使用 RAG for tools | 动态加载工具,任务完成后移除上下文 | 防止注意力稀释 |
| ✅ 依赖内部 API Gateway | 优先使用内部 Registry | 确保数据 schema 审核和治理 |
| ✅ 使用 MCP Inspector | Agent 幻觉时查原始传输数据,而非盲改提示 | 快速定位问题 |
| ✅ 包含 HITL | 调用工具前向用户展示输入 | 防止恶意/意外数据泄露 |
| ✅ 审计日志 | 记录工具使用日志 | 合规和追溯 |
Don’ts(常见陷阱)
| 陷阱 | 描述 | 替代方案 |
|---|---|---|
| ❌ 可消费却自建 | 能找到现有 MCP Server 却手写 REST wrapper | 先搜索 Registry,遵循”universal outlet”哲学 |
| ❌ 生产用公共 MCP | 将核心业务逻辑绑定未审核公共 endpoint | 仅用于原型,生产用官方托管服务 |
| ❌ 硬编码凭证 | 将 API keys 直接写入提示或脚本 | 使用环境变量传递给 MCP Server |
| ❌ 直连生产环境 | MCP Server 连接生产数据和系统 | 使用开发项目,确保非生产/混淆数据 |
| ❌ 写模式用于更新 | 必须连接真实数据时 | 设置 Server 为 read-only 模式 |
| ❌ 宽 Project 访问 | MCP Server 可访问所有 Projects | 限制到特定 Project,最小权限原则 |
7.2 A2UI 生成最佳实践
使用 a2ui-agent-sdk
# pip install a2ui-agent-sdk google-adk
import asyncio, json
import jsonschema
from a2ui.schema.manager import A2uiSchemaManager
from a2ui.basic_catalog.provider import BasicCatalog
from a2ui.schema.constants import VERSION_0_9
from a2ui.parser.parser import parse_response
from google.adk.agents import LlmAgent
from google.adk.models import Gemini
from google.adk.runners import InMemoryRunner
from google.genai import types
# 1. SDK 加载 catalog,构建 validator,渲染系统提示(含 schema 和示例)
schema_manager = A2uiSchemaManager(
version=VERSION_0_9,
catalogs=[BasicCatalog.get_config(version=VERSION_0_9)]
)
catalog = schema_manager.get_selected_catalog()
agent = LlmAgent(
model=Gemini(model="gemini-flash-latest"),
name="ui_agent",
instruction=schema_manager.generate_system_prompt(
role_description="You generate interactive UIs as A2UI v0.9 messages.",
ui_description="Use Cards, Lists, ChoicePickers, and Buttons to present data.",
include_schema=True,
include_examples=True
)
)
# 2. 运行 Agent,解析 <a2ui-json> blocks,验证 schema
async def create_ui(intent: str, data: dict, max_retries: int = 3) -> list:
runner = InMemoryRunner(agent=agent, app_name="ui_demo")
session = await runner.session_service.create_session(
app_name="ui_demo", user_id="u",
state={"expression": "{expression}"} # escapes SDK's templating placeholder
)
query = f"{intent}\n\nData: {json.dumps(data)}"
last_error = None
for _ in range(max_retries + 1):
chunks = []
msg = types.Content(role="user", parts=[types.Part(text=query)])
async for ev in runner.run_async(user_id="u", session_id=session.id, new_message=msg):
if ev.content and ev.content.parts:
chunks.extend(p.text for p in ev.content.parts if p.text)
blocks = [rp.a2ui_json for rp in parse_response("".join(chunks)) if rp.a2ui_json]
try:
for b in blocks:
for m in (b if isinstance(b, list) else [b]):
catalog.validator.validate(m)
return blocks
except jsonschema.ValidationError as e:
last_error = e
path = "/".join(str(p) for p in e.absolute_path)
query = (
f"Your previous response failed schema validation at {path}: "
f"{e.message[:200]}\nFix this and retry: {intent}\nData: {json.dumps(data)}"
)
raise ValueError(f"Schema validation failed after {max_retries} retries: {last_error}")关键: - A2uiSchemaManager 自动生成系统提示(含 schema + 示例) - 自动 schema 验证 - 失败时重试
Hybrid Output(混合输出)
提供数据和 UI,让消费者选择:
{
"data": {"sales": [...]},
"ui": {"version": "v0.9", "updateComponents": {"surfaceId": "main", "components": [...]}},
"ui_available": true
}API 客户端:忽略 ui,只用 data
人类用户客户端:渲染 A2UI 消息