关于 generate-codeful-mcp-tool
此技能为 codeful MCP 工具生成配套的 JavaScript 实现和 JSON 元数据文件,并指导需求收集、必要时的 Dataverse 架构核验,以及工具契约和输出验证。
主要功能
- 01生成配套的 JavaScript 与 JSON 文件
- 02定义 MCP 工具架构和注解
- 03按需核验 Dataverse 架构
- 04验证输入与结果契约
- 05支持转交可选 MCP App 小组件
适用场景
- 01创建基于 Dataverse 的 MCP 工具
- 02定义工具的输入和输出架构
- 03为生成 MCP App UI 准备工具文件
MCP 相关
生成 MCP 工具的 JavaScript 实现和 JSON 注册元数据,包含架构与注解;也支持将需求转交给可选的 MCP App 小组件生成流程。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill generate-codeful-mcp-tool安装后在 Claude Code 中输入/generate-codeful-mcp-tool确认已加载。
详细介绍
触发词: codeful MCP 工具、MCP 服务工具、生成 runTool、MCP 工具 JavaScript、 Dataverse MCP 工具、MCP App 的服务端逻辑
关键词: mcp apps、codeful tool、runTool、dataApi、Dataverse、服务端运行时
别名: /generate-codeful-mcp-tool、/codeful-tool
参考资料:
- Host API 类型:codeful-tool-host-data-api.d.ts
- 已验证可用的工具:account-summary.tool.js
- 已验证可用的元数据:account-summary.tool.json
- Widget 生成:generate-mcp-app-ui
为一个 MCP 工具生成一对匹配的文件:
<tool-name>.tool.js:完整的 JavaScript 服务端实现。<tool-name>.tool.json:声明式注册元数据,包含工具名称、 描述、输入架构、输出架构和 MCP 工具注释。
主机导入 JavaScript 模块并调用:
await runTool({ toolInput, dataApi });
必要信息
生成之前,确定:
- 工具的用途和 kebab-case 格式的工具名称。根据用途编写简洁、 可供模型执行操作的工具描述;仅在预期行为不明确时提问。
- 输入字段、类型、必填字段和约束。接受 JSON Schema、具有代表性的输入对象 或精确的字段说明。绝不猜测输入结构。
- 预期结果,最好提供具有代表性的输出对象。
- 是否读取或写入 Dataverse、以业务术语描述所需的表,以及 任何写入操作是创建、追加、更新、覆盖还是删除状态。
- 用户是否也需要 MCP App widget。
仅询问缺失的信息。用户提供了同样精确的约定时,输入/输出示例并非必需, 但优先提供。
阶段 1:读取运行时和元数据约定
读取:
${PLUGIN_ROOT}/references/codeful-tool-host-data-api.d.ts
${PLUGIN_ROOT}/samples/account-summary.tool.js
${PLUGIN_ROOT}/samples/account-summary.tool.json
生成的运行时代码是纯 ESM JavaScript,旁置文件是纯 JSON。类型文件 仅供生成时参考,绝不能由输出文件导入。
阶段 2:按需验证 Dataverse 架构
如果工具不使用 Dataverse,则跳过此阶段。
对于基于 Dataverse 的工具:
-
确认 PAC CLI 已通过身份验证并连接到目标环境。
-
查找候选表:
pac model list-tables --search "table terms"--search使用子字符串匹配。对其输出进行后置筛选,且仅当表的逻辑名称 与选定结果完全一致时才接受该表。如果仍有多个可能的表,请让用户选择。 -
在最终输出路径之外创建唯一的临时目录并生成类型:
pac model genpage generate-types --data-sources "logical1,logical2" --output-file "<temp>/RuntimeTypes.ts" -
读取
RuntimeTypes.ts。提取已注册的表、确切的可读/可写逻辑 列、查找字段结构、选项名称和选项的原始数值。 -
仅使用该文件中验证过的名称和值。自定义列无法预测;不要 根据显示名称推导其名称。
如果发现表或生成类型失败,则停止并报告错误。不要退而使用
臆造的表或列。验证后删除临时类型和目录,确保最终输出仅包含请求的 .tool.js、
.tool.json 和可选的 widget 文件。
阶段 3:生成配套工具文件
在用户的工作目录中写入 <tool-name>.tool.js 和 <tool-name>.tool.json,
除非用户指定了其他输出目录。两个文件必须使用相同的基本名称,
且该名称必须等于已确认的 kebab-case 工具名称。
JavaScript 文件必须:
-
仅导出一个名为
runTool的 MCP 入口点,优先使用:export async function runTool({ toolInput, dataApi }) { // complete implementation } -
使用自包含的 JavaScript,不得包含运行时导入、软件包、网络调用、文件系统访问、环境变量访问或生成的类型依赖。
-
使用外部提供的
toolInput前,先对其进行验证。限制计数范围,并对插入 OData 筛选条件的值进行转义。 -
使用单数形式的 Dataverse 实体逻辑名称。在
select、filter、orderBy和行对象中使用准确的逻辑列名称。 -
从
"<column>@OData.Community.Display.V1.FormattedValue"读取选项和查找标签。 -
通过
page.rows访问查询行。仅当page.hasMoreRows为 true 且存在page.loadMoreRows()函数时,才调用它继续加载。 -
使用
RuntimeTypes.ts中已验证的_<field>_value形式设置查找字段;绝不输出原始 Web API@odata.bind键。 -
让
dataApi错误直接抛出。仅在需要补充有用上下文时捕获错误,并将原始错误作为原因重新抛出。读取或写入失败后,绝不返回看似成功的备用结果。 -
不得包含占位符、TODO、省略号、测试凭据或真实环境 ID。
-
仅返回可序列化为 JSON 的值。绝不返回
loadMoreRows、函数、类实例或循环对象。 -
仅在用户明确要求时发送遥测数据,且遥测属性中绝不包含工具输入、行内容、标识符或其他用户数据。
JSON sidecar 必须是有效 JSON,且顶层字段必须恰好如下:
{
"name": "account-summary",
"description": "Search accounts and return revenue and status summaries.",
"annotations": {
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
},
"inputSchema": {
"type": "object",
"properties": {}
},
"outputSchema": {
"type": "object",
"properties": {}
}
}
name:必须与已确认的工具名称及共享文件的基本名称完全一致。description:提供简洁、便于模型采取行动的指导,说明工具的功能及适用场景。不要照抄用户提示,也不要包含实现细节。annotations:使用 MCPToolAnnotations描述工具的行为。始终输出以下四个布尔提示:readOnlyHint:仅当工具无法修改 Dataverse 或任何其他状态时设为true。destructiveHint:当工具可能删除、覆盖或以其他方式进行破坏性更新时设为true。只读工具以及非破坏性创建或追加写入操作应设为false。idempotentHint:当使用相同的有效输入重复调用不会产生额外影响时设为true。读取、确定性计算以及设置相同值的更新操作具有幂等性;创建和追加式操作则不具有幂等性。openWorldHint:始终设为false,因为代码运行时无法访问任意外部系统。 根据生成的实现和请求的行为推断这些值。如果写入语义确实不明确,生成前先提问,不要猜测。注解仅为参考元数据,不能替代运行时验证或授权。
inputSchema:描述toolInput的完整 JSON Schema。根节点使用对象类型,在properties下列出所有接受的字段,并通过required标明必填字段;编码运行时约束,例如范围、格式、枚举和数组项形状;除非用户明确要求可扩展输入,否则设置additionalProperties: false。outputSchema:描述模型可见的structuredContent业务载荷的 JSON Schema。对于普通对象返回值,描述完整的返回对象,因为宿主会将其提升为structuredContent。对于信封式返回值,仅描述其structuredContent属性。绝不要在outputSchema中包含content、自定义meta或运行时_meta。
仅使用标准 JSON Schema 关键字。sidecar 中不得包含凭据、环境标识符、Dataverse 发现产物、宿主配置、JavaScript 表达式、注释或占位符。
结果通道约定
选择最小且正确的结果形状。
简单结构化结果
当所有有用输出都属于模型可见的结构化数据时,返回一个普通对象:
return { records, totalCount: records.length };
宿主会将该对象提升为 MCP structuredContent。
分区 MCP 结果
当不同通道面向不同受众时,返回一个封装对象:
return {
content: `Found ${records.length} records.`,
structuredContent: { records },
meta: { preferredView: "table" },
};
content:模型可见的对话文本,可以是字符串或文本内容块。structuredContent:模型可见的机器可读对象。meta:仅供小组件使用的对象。宿主会将其映射到 MCP_meta;小组件读取result._meta。
content、structuredContent 和 meta 是保留的封装键。如果业务负载中自然包含其中任何键,请显式封装整个负载:
return { structuredContent: businessPayload };
不要将封装键与无关的顶层业务字段混用。
第 4 阶段:验证
报告完成前:
- 确认此技能恰好创建了一个最终
.tool.js和一个匹配的.tool.json。 - 使用 Node.js 将文件作为 ESM 数据 URL 导入,并断言
runTool是一个函数。导入时绝不能执行数据访问或其他顶层副作用。 - 使用
JSON.parse解析 sidecar。确认其中恰好包含name、description、annotations、inputSchema和outputSchema;名称与两个文件名均匹配;四个注解提示均为布尔值;openWorldHint为false;其他提示与实现的实际行为相符;两个 schema 的根节点均为对象;并且运行时强制执行的每项输入约束都已在inputSchema中体现。 - 使用 grep 检查输出中的导入、
require、占位符、猜测的列名和不受支持的宿主访问。 - 如果提供了有代表性的输入/输出,请使用内联 Node 脚本和内存中的模拟
dataApi调用runTool。不要创建持久化测试文件。 - 确认返回值符合所请求的结果约定,不包含函数或不可序列化的值,且其结构化负载符合
outputSchema。确认有代表性的输入符合inputSchema。 - 删除所有临时 schema 文件。
可选的 MCP App 交接
当用户要求提供小组件时:
- 先完成并验证配对的
.tool.js和.tool.json。 - 构建一个有代表性的结果样例:
- 普通工具返回值 → 视为
structuredContent。 - 封装返回值 → 传入
content、structuredContent和_meta(由编写的meta字段重命名而来)。
- 普通工具返回值 → 视为
- 调用
generate-mcp-app-ui,并提供视觉要求、工具名称、输入样例和完整的代表性结果。按用户要求明确传递 CDN 政策。如果用户未提供,请让 UI 技能提出其必需的 CDN 政策问题;不要假定允许使用公共 URL。 - 分别保留各项输出:一个
.tool.js、一个.tool.json,以及一个遵循所选 CDN 政策的单文件.html。
优化
编辑现有的代码型工具时,请先阅读配对的两个文件,并且只更改所请求的行为。保持运行时验证与元数据 schema 同步。如果编辑引入了尚未针对该文件验证过的表、列、查找项或选项值,请重新运行 schema 验证。
完成回复
说明生成的两个工具文件路径,并概述描述、工具注解、输入约定和结构化结果约定。如果用户要求了小组件,还需说明 HTML 路径以及它使用哪些结果通道。