feat(sdk): metadata statiques contributes.mcpServers[].tools — #296 (type IdeAPluginMcpToolMetadata {name exact non vide, description optionnelle non vide} exporté public; validation manifest: tools optionnel, noms uniques par serveur — metadata d'affichage pour l'UI d'attribution de capacités, ne remplace ni ne cache MCP tools/list et n'enregistre rien; scripts/check-manifest-tools.mjs + npm run test:manifest intégré à check: optionnel/valide/doublon rejeté; doc manifest.md: exemple unity_get_scene/run_tests + règles; QA verte reconfirmée par Git: npm run check)
This commit is contained in:
@ -5,6 +5,7 @@ export type {
|
||||
IdeAPluginEngineConstraints,
|
||||
IdeAPluginLayoutContribution,
|
||||
IdeAPluginMcpServerContribution,
|
||||
IdeAPluginMcpToolMetadata,
|
||||
IdeAPluginMenuItemContribution,
|
||||
IdeAPluginSkillContribution,
|
||||
IdeAPluginSkillKind,
|
||||
|
||||
@ -95,6 +95,15 @@ export interface IdeAPluginMcpServerContribution {
|
||||
transport: "stdio";
|
||||
autoStart?: boolean;
|
||||
allowAbsoluteCommand?: boolean;
|
||||
/** Optional static UI metadata; runtime MCP tools/list remains authoritative. */
|
||||
tools?: IdeAPluginMcpToolMetadata[];
|
||||
}
|
||||
|
||||
export interface IdeAPluginMcpToolMetadata {
|
||||
/** Exact tool name advertised by the MCP server. */
|
||||
name: string;
|
||||
/** Optional human-readable summary for capability-management UI. */
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export type PluginManifestValidationResult =
|
||||
@ -269,6 +278,22 @@ function validateContributes(value: unknown, errors: string[]): void {
|
||||
optionalString(server, "cwd", errors, `contributes.mcpServers[${index}].cwd`);
|
||||
optionalBoolean(server, "autoStart", errors, `contributes.mcpServers[${index}].autoStart`);
|
||||
optionalBoolean(server, "allowAbsoluteCommand", errors, `contributes.mcpServers[${index}].allowAbsoluteCommand`);
|
||||
validateArray(server, "tools", errors, (tool, toolIndex) => {
|
||||
requireString(tool, "name", errors, `contributes.mcpServers[${index}].tools[${toolIndex}].name`);
|
||||
if (tool.description !== undefined) {
|
||||
requireString(tool, "description", errors, `contributes.mcpServers[${index}].tools[${toolIndex}].description`);
|
||||
}
|
||||
});
|
||||
if (Array.isArray(server.tools)) {
|
||||
const names = new Set<string>();
|
||||
server.tools.forEach((tool, toolIndex) => {
|
||||
if (!isRecord(tool) || typeof tool.name !== "string" || tool.name.trim() === "") return;
|
||||
if (names.has(tool.name)) {
|
||||
errors.push(`contributes.mcpServers[${index}].tools[${toolIndex}].name must be unique within the server`);
|
||||
}
|
||||
names.add(tool.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user