MCP高级特性:内容类型与多媒体数据处理

6 阅读5分钟

在构建现代AI应用时,处理多种内容类型至关重要。本文将深入探讨MCP框架的内容类型系统,展示如何在工具中返回和处理各种数据格式,包括纯文本、HTML、图像、SVG图表和JSON数据。通过这些示例,你将了解如何为AI应用提供丰富的多媒体内容支持,使其能够生成和处理各种形式的数据,从而构建更加强大和灵活的AI工具。

内容类型系统简介

MCP的内容类型系统提供了一种统一的方式来处理不同格式的数据。通过指定适当的MIME类型,工具可以返回各种形式的内容,而客户端则可以根据MIME类型正确地解释和显示这些内容。这使得AI应用能够处理从简单文本到复杂多媒体的各种数据。

内容类型与实现

1. 简单数据类型

最基本的内容类型是简单的数据类型,如字符串、数字、布尔值等:

@mcp.tool()
def simple_text_types() -> Dict[str, Any]:
    """展示简单类型如何转换为文本"""
    return {
        "string_value": "这是一个字符串",
        "integer_value": 42,
        "float_value": 3.14159,
        "boolean_value": True,
        "none_value": None,
        "datetime_value": datetime.now(),
        "list_of_numbers": [1, 2, 3, 4, 5],
        "nested_dict": {
            "name": "张三",
            "age": 30,
            "is_active": True
        }
    }

MCP会自动将这些简单类型转换为文本表示,使其可以被客户端正确处理。

2. 图像数据

对于图像数据,MCP提供了专门的Image类来封装图像内容:

@mcp.tool()
def generate_image() -> Image:
    """生成并返回一个图像"""
    # 创建一个基本的1x1像素红色PNG图像
    png_data = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==")
    
    # 使用Image类包装图像数据
    return Image(data=png_data, format="png")

Image类自动处理图像数据的编码和MIME类型,使客户端能够正确显示图像。

3. 混合内容

有时,我们需要在同一个响应中包含多种类型的内容:

@mcp.tool()
def mixed_content() -> Dict[str, str]:
    """返回混合内容类型"""
    return {
        "title": "混合内容示例",
        "description": "这个示例展示了如何在同一个响应中包含不同类型的内容",
        "text_item": "这是一个普通文本项",
        "number_item": "42", # 转换为字符串
        "image_reference": "使用generate_image工具可获取图像",
        "html_reference": "使用custom_content_types工具的text_html键可获取HTML内容",
        "nested_data": json.dumps({
            "name": "嵌套对象",
            "data": [1, 2, 3]
        }),
        "timestamp": datetime.now().isoformat()
    }

对于复杂对象,我们可以将其序列化为字符串(如JSON),以确保它们能够被正确传输和处理。

4. 自定义MIME类型

MCP允许我们指定自定义的MIME类型,以便客户端能够正确解释内容:

@mcp.tool()
def custom_content_types() -> Dict[str, Dict[str, str]]:
    """展示如何直接使用MCP内容类型类"""
    return {
        "contents": {
            "text_plain": {
                "content": "这是普通文本内容。",
                "mime_type": "text/plain"
            },
            "text_html": {
                "content": "<h1>HTML标题</h1><p>这是<em>HTML</em>格式的段落。</p>",
                "mime_type": "text/html"
            },
            "text_markdown": {
                "content": "# Markdown标题\n\n这是**Markdown**格式的内容。\n\n- 项目1\n- 项目2\n- 项目3",
                "mime_type": "text/markdown"
            },
            "application_json": {
                "content": '{"name": "JSON示例", "values": [1, 2, 3], "enabled": true}',
                "mime_type": "application/json"
            },
            "text_css": {
                "content": "body { font-family: Arial, sans-serif; color: #333; }\n.header { background-color: #f5f5f5; }",
                "mime_type": "text/css"
            },
            "text_javascript": {
                "content": "function greet() {\n  return 'Hello, world!';\n}\nconsole.log(greet());",
                "mime_type": "text/javascript"
            }
        },
        "timestamp": datetime.now().isoformat()
    }

通过指定不同的MIME类型,我们可以为同一工具提供多种格式的内容,客户端可以根据需要选择合适的格式。

5. 数据可视化

一个特别有用的应用是数据可视化,我们可以根据需要返回不同格式的可视化内容:

@mcp.tool()
def data_visualization_tool(data_type: str = "table") -> Dict[str, str]:
    """数据可视化工具"""
    # 示例数据
    sample_data = {
        "categories": ["一月", "二月", "三月", "四月", "五月"],
        "values": [10, 25, 15, 30, 20]
    }
    
    result = {
        "type": data_type,
        "timestamp": datetime.now().isoformat()
    }
    
    if data_type == "table":
        # 创建HTML表格
        table_html = "<table border='1'><tr><th>月份</th><th>销售额</th></tr>"
        for i, category in enumerate(sample_data["categories"]):
            table_html += f"<tr><td>{category}</td><td>{sample_data['values'][i]}</td></tr>"
        table_html += "</table>"
        
        result["content"] = table_html
        result["mime_type"] = "text/html"
    
    elif data_type == "chart":
        # 创建图表的SVG表示
        # ... SVG生成代码 ...
        result["content"] = svg
        result["mime_type"] = "image/svg+xml"
    
    elif data_type == "raw":
        # 返回原始JSON数据
        result["content"] = json.dumps(sample_data)
        result["mime_type"] = "application/json"
    
    return result

这个工具可以根据请求返回同一数据的不同表示形式:HTML表格、SVG图表或原始JSON数据。

客户端处理内容类型

在客户端,我们需要正确解析和处理不同类型的内容:

# 解析MCP返回值的辅助函数
def parse_mcp_result(result):
    if hasattr(result, 'content') and hasattr(result, 'isError'):
        if result.isError:
            return {"error": "工具调用失败"}
        
        if hasattr(result.content[0], 'text'):
            try:
                # 尝试解析JSON内容
                return json.loads(result.content[0].text)
            except:
                # 如果不是JSON,返回原始文本
                return result.content[0].text
    return result

对于不同类型的内容,客户端可能需要不同的处理方式:

  1. 文本内容:直接显示或进一步解析
  2. HTML内容:渲染为网页元素
  3. 图像内容:显示为图像
  4. JSON数据:解析为结构化数据进行处理

内容类型最佳实践

  1. 明确指定MIME类型:始终为内容指定正确的MIME类型,以便客户端能够正确处理
  2. 使用专门的类:对于特殊内容类型(如图像),使用MCP提供的专门类
  3. 序列化复杂对象:将复杂对象序列化为字符串(如JSON),以确保它们能够被正确传输
  4. 提供多种格式选项:为同一数据提供多种格式选项,以满足不同的需求
  5. 考虑客户端兼容性:确保返回的内容格式能够被目标客户端正确处理