MCP Adapter 开发文档

为 MCP 创建能力

Estimated reading: 22 minutes 1 views 贡献人员

为 MCP 创建能力

本指南涵盖如何为 MCP(模型上下文协议)集成创建 WordPress 能力,包括工具、资源和提示词。

系统概述

WordPress 能力可以注册为不同的 MCP 组件:

  • 工具:执行操作并返回结果
  • 资源:提供对数据或内容的访问
  • 提示词:为语言模型生成结构化消息

完整注解支持:所有组件类型通过能力的 meta.annotations 字段支持 MCP 注解,为 MCP 客户端提供行为提示。

MCP 暴露

WordPress 能力默认情况下不可通过默认 MCP 服务器访问。要使能力通过默认 MCP 服务器可用,您必须在能力的元数据中明确添加 mcp.public: true

'meta' => [
    'mcp' => [
        'public' => true,  // MCP 访问需要此属性
        'type'   => 'tool' // 可选:'tool'(默认)、'resource' 或 'prompt'
    ],
    'annotations' => [...] // 可选的 MCP 注解
]

MCP 类型

type 参数指定能力应如何在 MCP 服务器中暴露:

  • tool(默认):通过默认服务器的发现机制暴露为可调用工具
  • resource:暴露为资源(需要 meta 中的 'uri')
  • prompt:暴露为提示词(需要 meta 中的 'arguments')

如果未指定,能力默认使用 type: 'tool'

基本能力结构

wp_register_ability('my-plugin/my-ability', [
    'label' => '我的能力',
    'description' => '此能力的功能',
    'input_schema' => [...],      // 工具使用(支持对象和扁平模式)
    'output_schema' => [...],     // 工具可选
    'execute_callback' => 'my_callback',
    'permission_callback' => 'my_permission_check',
    'meta' => [
        'annotations' => [...],   // MCP 注解
        'uri' => '...',          // 资源使用
        'arguments' => [...],    // 提示词使用
        'mcp' => [
            'public' => true,    // 通过 MCP 暴露(MCP 访问需要)
            'type'   => 'tool',  // 'tool'、'resource' 或 'prompt'
        ]
    ]
]);

输入和输出模式

MCP Adapter 支持两种 inputschemaoutputschema 格式:

对象模式(推荐)

标准格式使用带属性的 JSON Schema 对象:

'input_schema' => [
    'type' => 'object',
    'properties' => [
        'name' => [
            'type' => 'string',
            'description' => '用户名'
        ],
        'age' => [
            'type' => 'number',
            'minimum' => 0
        ]
    ],
    'required' => ['name']
]

扁平模式(简化版)

对于简单的单值输入,您可以使用扁平模式。这些会自动转换为 MCP 兼容的对象格式:

// 简单字符串输入
'input_schema' => [
    'type' => 'string',
    'description' => '要查询的文章类型',
    'enum' => ['post', 'page', 'attachment']
]

// 自动转换为:
[
    'type' => 'object',
    'properties' => [
        'input' => [
            'type' => 'string',
            'description' => '要查询的文章类型',
            'enum' => ['post', 'page', 'attachment']
        ]
    ],
    'required' => ['input']
]

支持的扁平类型

支持所有 JSON Schema 原始类型:

  • string – 文本值
  • number – 数值(包括小数)
  • integer – 整数
  • boolean – 布尔值
  • array – 值列表

扁平模式示例

// 带约束的数字
'input_schema' => [
    'type' => 'number',
    'description' => '最大文章数量',
    'minimum' => 1,
    'maximum' => 100,
    'default' => 10
]

// 布尔标志
'input_schema' => [
    'type' => 'boolean',
    'description' => '包含草稿文章'
]

// 字符串数组
'input_schema' => [
    'type' => 'array',
    'description' => '文章 ID 列表',
    'items' => ['type' => 'integer'],
    'minItems' => 1
]

输出模式

输出模式遵循与输入模式相同的模式,支持对象和扁平格式:

对象输出模式

'output_schema' => [
    'type' => 'object',
    'properties' => [
        'post_id' => [
            'type' => 'integer',
            'description' => '创建的文章 ID'
        ],
        'url' => [
            'type' => 'string',
            'description' => '文章永久链接'
        ],
        'status' => [
            'type' => 'string',
            'description' => '文章状态'
        ]
    ]
]

扁平输出模式

对于简单的单值输出,您可以使用扁平模式。这些会自动转换为 MCP 兼容的对象格式,使用 "result" 作为包装属性:

// 简单字符串输出
'output_schema' => [
    'type' => 'string',
    'description' => '生成的文章别名'
]

// 自动转换为:
[
    'type' => 'object',
    'properties' => [
        'result' => [
            'type' => 'string',
            'description' => '生成的文章别名'
        ]
    ],
    'required' => ['result']
]

输出模式示例

// 数字输出
'output_schema' => [
    'type' => 'integer',
    'description' => '找到的文章总数'
]

// 布尔输出
'output_schema' => [
    'type' => 'boolean',
    'description' => '操作是否成功'
]

// 数组输出
'output_schema' => [
    'type' => 'array',
    'description' => '文章标题列表',
    'items' => ['type' => 'string']
]

重要提示:使用扁平输出模式时,您的回调应直接返回未包装的值。适配器会自动将其包装在 {result: <value>} 中供 MCP 客户端使用:

// 使用扁平输出模式:['type' => 'string']
'execute_callback' => function($input) {
    return 'my-post-slug';  // 返回未包装的值
}

// MCP 客户端收到:{result: 'my-post-slug'}

何时使用每种格式

使用对象模式的情况

  • 您的能力接受/返回多个参数或字段
  • 需要复杂验证或嵌套结构
  • 想要描述性参数名称
  • 您的输出包含多个相关值(例如 {post_id, url, status}

使用扁平模式的情况

  • 您的能力接受/返回单个简单值
  • 输入/输出简单直接(例如字符串、数字、布尔值或数组)
  • 您希望简化基本操作的 API
  • 您的输出是单个原始值(例如计数、别名、布尔标志)

注意:所有模式元数据(描述、约束、枚举等)在从扁平格式自动转换为对象格式时都会保留。输入模式使用 "input" 作为包装属性,而输出模式使用 "result"

MCP 注解

注解为 MCP 客户端提供关于如何处理您的能力的行为提示。注解是类型特定的 – 工具使用的注解与资源和提示词不同。

注解格式:WordPress Abilities API 与 MCP

最佳实践:使用 WordPress Abilities API 格式

MCP Adapter 会自动将 WordPress Abilities API 注解名称转换为 MCP 格式。建议使用 WordPress Abilities API 格式(如果可用),以保持 WordPress 生态系统的一致性。

对于工具:WordPress 格式首选

// ✅ 推荐:WordPress Abilities API 格式
'meta' => [
    'annotations' => [
        'readonly' => true,        // 自动转换为 readOnlyHint
        'destructive' => false,    // 自动转换为 destructiveHint
        'idempotent' => true,      // 自动转换为 idempotentHint
        'openWorldHint' => false,  // 无 WordPress 等效项,使用 MCP 格式
        'title' => 'My Tool'       // 无 WordPress 等效项,使用 MCP 格式
    ]
]

// ✅ 也是有效的:直接 MCP 格式
'meta' => [
    'annotations' => [
        'readOnlyHint' => true,
        'destructiveHint' => false,
        'idempotentHint' => true,
        'openWorldHint' => false,
        'title' => 'My Tool'
    ]
]

工具注解映射表

| WordPress 格式 | MCP 格式 | 描述 |

|—————-|———-|——|

| readonly | readOnlyHint | 工具不修改数据 |

| destructive | destructiveHint | 工具可能删除/销毁数据 |

| idempotent | idempotentHint | 相同输入 → 相同输出 |

| (无等效项) | openWorldHint | 可以处理任意数据 |

| (无等效项) | title | 自定义显示标题 |

为什么使用 WordPress 格式?

  • 一致性:符合 WordPress Abilities API 约定
  • 熟悉性:WordPress 开发人员已经了解这些术语
  • 未来兼容性:可能会添加其他 WordPress 格式
  • 互操作性:与其他 WordPress Abilities API 消费者配合使用

对于资源和提示词:仅 MCP 格式

资源和提示词直接使用 MCP 格式 – 没有 WordPress 等效项:

'meta' => [
    'annotations' => [
        'audience' => ['user', 'assistant'],      // MCP 格式(无 WordPress 等效项)
        'lastModified' => '2024-01-15T10:30:00Z', // MCP 格式(无 WordPress 等效项)
        'priority' => 0.8                         // MCP 格式(无 WordPress 等效项)
    ]
]

工具注解(ToolAnnotations)

工具支持这些 MCP 规范注解:

'meta' => [
    'annotations' => [
        'readOnlyHint' => true,       // 工具不修改数据
        'destructiveHint' => false,   // 工具不删除/销毁数据
        'idempotentHint' => true,     // 相同输入 → 相同输出
        'openWorldHint' => false,     // 仅处理预定义数据
        'title' => 'Custom Title'     // 自定义显示标题(可选)
    ]
]

支持的工具注解字段

  • readOnlyHint(布尔值):工具不修改数据
  • destructiveHint(布尔值):工具可能删除或销毁数据
  • idempotentHint(布尔值):相同输入始终产生相同输出
  • openWorldHint(布尔值):工具可以处理任意/未知数据
  • title(字符串):工具的自定义显示标题

WordPress → MCP 字段转换:为了向后兼容,工具支持会自动转换的 WordPress 格式字段名称:

  • readonlyreadOnlyHint
  • destructivedestructiveHint
  • idempotentidempotentHint

资源和提示词注解(Annotations)

资源和提示词共享相同的注解模式(符合 MCP 规范):

'meta' => [
    'annotations' => [
        'audience' => ['user', 'assistant'],      // 目标受众
        'lastModified' => '2024-01-15T10:30:00Z', // ISO 8601 时间戳
        'priority' => 0.8                         // 0.0(最低)到 1.0(最高)
    ]
]

支持的资源和提示词注解字段

  • audience(数组):目标角色 – ["user"]["assistant"] 或两者
  • lastModified(字符串):上次修改的 ISO 8601 时间戳
  • priority(浮点数):相对重要性(0.0 = 最低,1.0 = 最高)

按组件类型的注解使用

  • 工具:使用注解描述工具行为和执行特性
  • 资源:使用注解进行内容元数据和访问模式
  • 提示词:支持两种类型的注解(模板级和消息内容级)

完整注解示例

// 使用 WordPress Abilities API 格式的工具(推荐)
wp_register_ability('my-plugin/analyze-data', [
    'label' => '数据分析器',
    'description' => '使用各种算法分析数据',
    'input_schema' => [...],
    'execute_callback' => 'analyze_data_callback',
    'permission_callback' => function() { return current_user_can('read'); },
    'meta' => [
        'annotations' => [
            'readonly' => true,              // WordPress 格式 → readOnlyHint
            'destructive' => false,          // WordPress 格式 → destructiveHint
            'idempotent' => true,            // WordPress 格式 → idempotentHint
            'openWorldHint' => false,        // 无 WordPress 等效项
            'title' => '数据分析工具'  // 无 WordPress 等效项
        ],
        'mcp' => [
            'public' => true,
            'type' => 'tool'
        ]
    ]
]);

// 具有资源特定注解的资源
wp_register_ability('my-plugin/user-data', [
    'label' => '用户数据资源',
    'description' => '访问用户个人资料数据',
    'execute_callback' => 'get_user_data',
    'permission_callback' => function() { return current_user_can('read'); },
    'meta' => [
        'uri' => 'wordpress://users/profile',
        'annotations' => [
            'audience' => ['assistant'],     // 仅供 AI 使用
            'priority' => 0.9,              // 高重要性
            'lastModified' => date('c')      // ISO 8601 时间戳
        ],
        'mcp' => [
            'public' => true,
            'type' => 'resource'
        ]
    ]
]);

// 具有提示词特定注解的提示词
wp_register_ability('my-plugin/review-prompt', [
    'label' => '代码审查提示词',
    'description' => '生成结构化的代码审查提示词',
    'input_schema' => [
        'type' => 'object',
        'properties' => [
            'code' => ['type' => 'string', 'description' => '要审查的代码']
        ],
        'required' => ['code']
    ],
    'execute_callback' => 'generate_review_prompt',
    'permission_callback' => function() { return current_user_can('edit_posts'); },
    'meta' => [
        'annotations' => [
            'audience' => ['user', 'assistant'], // 供用户和 AI 使用
            'priority' => 0.8,                  // 高优先级
            'lastModified' => date('c')          // 当前时间戳
        ],
        'mcp' => [
            'public' => true,
            'type' => 'prompt'
        ]
    ]
]);

创建工具

工具执行操作并返回结果:

wp_register_ability('my-plugin/create-post', [
    'label' => '创建文章',
    'description' => '使用给定的标题和内容创建新的 WordPress 文章',
    'input_schema' => [
        'type' => 'object',
        'properties' => [
            'title' => [
                'type' => 'string',
                'description' => '文章标题'
            ],
            'content' => [
                'type' => 'string', 
                'description' => '文章内容'
            ],
            'status' => [
                'type' => 'string',
                'enum' => ['draft', 'publish'],
                'default' => 'draft'
            ]
        ],
        'required' => ['title', 'content']
    ],
    'output_schema' => [
        'type' => 'object',
        'properties' => [
            'post_id' => ['type' => 'integer'],
            'url' => ['type' => 'string'],
            'status' => ['type' => 'string']
        ]
    ],
    'execute_callback' => function($input) {
        $post_id = wp_insert_post([
            'post_title' => $input['title'],
            'post_content' => $input['content'],
            'post_status' => $input['status'] ?? 'draft'
        ]);
        
        return [
            'post_id' => $post_id,
            'url' => get_permalink($post_id),
            'status' => get_post_status($post_id)
        ];
    },
    'permission_callback' => function() {
        return current_user_can('publish_posts');
    },
    'meta' => [
        'annotations' => [
            'readonly' => false,       // 工具修改数据(WordPress 格式)
            'destructive' => false,    // 工具不删除数据(WordPress 格式)
            'idempotent' => false      // 多次调用会创建多个文章(WordPress 格式)
        ],
        'mcp' => [
            'public' => true  // 通过 MCP 暴露此能力
        ]
    ]
]);

使用扁平模式的工具

对于接受和返回单值的简单工具,您可以使用扁平模式:

wp_register_ability('my-plugin/count-posts', [
    'label' => '计数文章',
    'description' => '统计特定类型的文章数量',
    'input_schema' => [
        'type' => 'string',
        'description' => '要计数的文章类型',
        'enum' => ['post', 'page', 'attachment']
    ],
    'output_schema' => [
        'type' => 'integer',
        'description' => '找到的文章总数'
    ],
    'execute_callback' => function($input) {
        // $input 是未包装的字符串值(例如 'post')
        $count = wp_count_posts($input);
        // 返回未包装的整数值
        return $count->publish;
    },
    'permission_callback' => function() {
        return current_user_can('read');
    },
    'meta' => [
        'annotations' => [
            'readonly' => true,
            'idempotent' => false  // 计数可能随时间变化
        ],
        'mcp' => [
            'public' => true
        ]
    ]
]);

注意:使用扁平模式时:

  • 回调直接接收未包装的输入值(例如 'post' 而不是 ['input' => 'post']
  • 回调应返回未包装的输出值(例如 42 而不是 ['result' => 42]
  • 适配器会自动处理对 MCP 客户端的包装/解包

创建资源

资源提供对数据或内容的访问。它们需要在 meta 字段中有一个 uri,并应在 MCP 配置中设置 type: 'resource'

wp_register_ability('my-plugin/site-config', [
    'label' => '站点配置',
    'description' => 'WordPress 站点配置和设置',
    'execute_callback' => function() {
        return [
            'site_name' => get_bloginfo('name'),
            'site_url' => get_site_url(),
            'admin_email' => get_option('admin_email'),
            'timezone' => get_option('timezone_string'),
            'date_format' => get_option('date_format')
        ];
    },
    'permission_callback' => function() {
        return current_user_can('manage_options');
    },
    'meta' => [
        'uri' => 'wordpress://site/config',
        'annotations' => [
            'audience' => ['user', 'assistant'], // 供用户和 AI 使用
            'priority' => 0.8,                  // 高优先级资源
            'lastModified' => '2024-01-15T10:30:00Z' // 上次更新时间戳
        ],
        'mcp' => [
            'public' => true,      // 通过 MCP 暴露此能力
            'type'   => 'resource' // 标记为资源以便自动发现
        ]
    ]
]);

创建提示词

提示词为语言模型生成结构化消息。它们使用 input_schema 定义参数,这些参数会自动转换为 MCP 提示词参数格式。提示词应在 MCP 配置中设置 type: 'prompt'

提示词的输入模式

提示词使用标准 JSON Schema input_schema 定义其参数。MCP Adapter 会自动将其转换为 MCP 提示词 arguments 格式:

// 您的定义(JSON Schema):
'input_schema' => [
    'type' => 'object',
    'properties' => [
        'code' => ['type' => 'string', 'description' => '要审查的代码']
    ],
    'required' => ['code']
]

// 自动转换为 MCP 格式:
'arguments' => [
    ['name' => 'code', 'description' => '要审查的代码', 'required' => true]
]

完整提示词示例

wp_register_ability('my-plugin/code-review', [
    'label' => '代码审查提示词',
    'description' => '生成具有特定重点领域的代码审查提示词',
    'input_schema' => [
        'type' => 'object',
        'properties' => [
            'code' => [
                'type' => 'string',
                'description' => '要审查的代码'
            ],
            'focus' => [
                'type' => 'array',
                'description' => '审查期间要重点关注的领域',
                'items' => ['type' => 'string'],
                'default' => ['security', 'performance']
            ]
        ],
        'required' => ['code']
    ],
    'execute_callback' => function($input) {
        $code = $input['code'];
        $focus = $input['focus'] ?? ['security', 'performance'];

        return [
            'messages' => [
                [
                    'role' => 'user',
                    'content' => [
                        'type' => 'text',
                        'text' => "请审查此代码,重点关注: " . implode(', ', $focus) . "nn```n" . $code . "n```"
                    ]
                ]
            ]
        ];
    },
    'permission_callback' => function() {
        return current_user_can('edit_posts');
    },
    'meta' => [
        'annotations' => [
            'audience' => ['user'],         // 面向用户的提示词
            'priority' => 0.7               // 标准优先级
        ],
        'mcp' => [
            'public' => true,   // 通过 MCP 暴露此能力
            'type'   => 'prompt' // 标记为提示词以便自动发现
        ]
    ]
]);

消息内容注解(MCP 规范)

您还可以根据 MCP 规范 为生成的消息内容添加注解:

wp_register_ability('my-plugin/analysis-prompt', [
    'label' => '分析提示词',
    'description' => '生成带有内容注解的分析提示词',
    'input_schema' => [
        'type' => 'object',
        'properties' => [
            'data' => [
                'type' => 'string',
                'description' => '要分析的数据'
            ]
        ],
        'required' => ['data']
    ],
    'execute_callback' => function($input) {
        $data = $input['data'] ?? '';

        return [
            'messages' => [
                [
                    'role' => 'user',
                    'content' => [
                        'type' => 'text',
                        'text' => "分析此数据: " . $data,
                        'annotations' => [
                            'audience' => ['assistant'],           // 仅供 AI 使用
                            'priority' => 0.9,                   // 高优先级内容
                            'lastModified' => date('c')           // ISO 8601 时间戳
                        ]
                    ]
                ],
                [
                    'role' => 'assistant',
                    'content' => [
                        'type' => 'text',
                        'text' => "我会分析提供的数据...",
                        'annotations' => [
                            'audience' => ['user'],              // 供用户显示
                            'priority' => 0.7
                        ]
                    ]
                ]
            ]
        ];
    },
    'permission_callback' => function($input) {
        return current_user_can('read');
    },
    'meta' => [
        'annotations' => [
            'audience' => ['assistant'],        // 仅供 AI 分析
            'priority' => 0.9,                 // 高优先级分析
            'lastModified' => date('c')         // 当前时间戳
        ],
        'mcp' => [
            'public' => true,   // 通过 MCP 暴露此能力
            'type'   => 'prompt' // 标记为提示词以便自动发现
        ]
    ]
]);

提示词注解摘要

模板级注解(在 meta.annotations 中):

  • 应用于提示词模板本身
  • 描述提示词的行为特性
  • 支持提示词特定注解:audienceprioritylastModified

消息内容注解(在消息 content.annotations 中):

  • 应用于提示词中的各个消息
  • 为特定消息内容提供元数据
  • 支持:audienceprioritylastModified

提示词关键点

  1. 使用 input_schema 而不是 meta.arguments – 它提供验证,并自动转换为 MCP 格式
  2. 回调接收已验证的输入 – Abilities API 根据您的模式进行验证
  3. 返回 MCP 消息格式 – 提示词必须返回 { messages: [...] } 结构
  4. meta.mcp 中设置 type: 'prompt' 以进行正确的自动发现

权限和安全性

> 💡 两层安全:能力有自己的权限(细粒度),但 传输权限 作为整个服务器的看门狗。如果传输阻止了用户,无论个人能力权限如何,他们都无法访问任何能力。

权限回调示例

// 仅允许管理员
'permission_callback' => function() {
    return current_user_can('manage_options');
}

// 允许编辑及以上用户
'permission_callback' => function() {
    return current_user_can('edit_others_posts');
}

// 自定义权限检查
'permission_callback' => function($input) {
    return current_user_can('edit_posts') && wp_verify_nonce($input['nonce'], 'my_action');
}

最佳实践

模式设计

  • 使用清晰、描述性的字段名称
  • 为所有属性提供详细描述
  • 定义适当的数据类型和约束
  • 明确标记必填字段

错误处理

  • 返回有意义的错误消息
  • 使用适当的 HTTP 状态码
  • 包含调试的上下文信息

性能

  • 保持工具执行轻量级
  • 缓存昂贵的操作
  • 使用适当的数据库查询
  • 考虑对大型数据集进行分页

下一步

留下第一个评论