apply_agent_pack
Apply a saved agent pack to your SAPUI5 project with fingerprint verification and scaffolded materialization for consistent development.
Instructions
Apply a saved agent pack to the current project with fingerprint verification and scaffolded materialization.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- The main handler function for apply_agent_pack tool. It parses input arguments, reads the pack catalog, selects a pack by slug/name/version, verifies pack integrity via fingerprint, validates the blueprint, and then scaffolds the agents by calling scaffoldProjectAgentsTool.handler.
async handler(args, { context }) { const { packSlug, packName, packVersion, packCatalogPath, projectName, projectType, namespace, outputDir, includeVscodeMcp, dryRun, allowOverwrite, reason, maxDiffLines } = inputSchema.parse(args); const root = context.rootDir; const selectedCatalogPath = normalizePath(packCatalogPath ?? DEFAULT_PACK_CATALOG_PATH); enforceManagedSubtree(selectedCatalogPath, ".codex/mcp", "packCatalogPath"); const catalog = await readCatalog(selectedCatalogPath, root); const selectedPack = selectPack(catalog.packs, { packSlug, packName, packVersion }); if (!selectedPack) { throw new ToolError("Requested agent pack was not found in catalog.", { code: "AGENT_PACK_NOT_FOUND", details: { packSlug: packSlug ?? null, packName: packName ?? null, packVersion: packVersion ?? null } }); } const packManifestPath = joinPath(selectedPack.path, "pack.json"); const packBlueprintPath = joinPath(selectedPack.path, "blueprint.json"); const packGuidePath = joinPath(selectedPack.path, "AGENTS.generated.md"); const packPromptPath = joinPath(selectedPack.path, "task-bootstrap.txt"); const [manifestText, blueprintText, guideText, promptText] = await Promise.all([ readTextFile(packManifestPath, root), readTextFile(packBlueprintPath, root), readTextFile(packGuidePath, root), readTextFile(packPromptPath, root) ]); const packManifest = JSON.parse(manifestText); const fingerprintMatches = packManifest.fingerprint === hashArtifactSet(blueprintText, guideText, promptText); if (!fingerprintMatches) { throw new ToolError("Pack fingerprint mismatch detected. Pack integrity check failed.", { code: "AGENT_PACK_FINGERPRINT_MISMATCH", details: { slug: selectedPack.slug, version: selectedPack.version } }); } const blueprint = packBlueprintSchema.parse(JSON.parse(blueprintText)); const scaffoldResult = await scaffoldProjectAgentsTool.handler( { projectName, projectType: projectType ?? normalizeProjectType(blueprint.project?.type), namespace, outputDir, includeVscodeMcp, dryRun, allowOverwrite, reason: reason ?? `apply_agent_pack:${selectedPack.slug}@${selectedPack.version}`, maxDiffLines, agentDefinitions: blueprint.agents, qualityGates: blueprint.qualityGates, recommendationMeta: { source: `pack:${selectedPack.slug}@${selectedPack.version}`, selectedRecommendationIds: [`pack-${selectedPack.slug}`] } }, { context } ); return outputSchema.parse({ selectedPack: { name: selectedPack.name ?? packManifest.name ?? "Unnamed pack", slug: selectedPack.slug ?? packManifest.slug ?? "unknown-pack", version: selectedPack.version ?? packManifest.version ?? "1.0.0", fingerprint: selectedPack.fingerprint ?? packManifest.fingerprint ?? "", path: selectedPack.path }, integrity: { fingerprintMatches }, scaffoldResult }); } - Input and output Zod schemas for apply_agent_pack tool. Input schema validates packSlug/packName (at least one required), packVersion, project settings, and dryRun options. Output schema defines the structure for selectedPack, integrity check results, and scaffoldResult.
const inputSchema = z.object({ packSlug: z.string().min(1).optional(), packName: z.string().min(1).optional(), packVersion: z.string().min(1).optional(), packCatalogPath: z.string().min(1).optional(), projectName: z.string().min(1).optional(), projectType: z.enum(["sapui5", "node", "generic"]).optional(), namespace: z.string().min(1).optional(), outputDir: z.string().min(1).optional(), includeVscodeMcp: z.boolean().optional(), dryRun: z.boolean().optional(), allowOverwrite: z.boolean().optional(), reason: z.string().max(200).optional(), maxDiffLines: z.number().int().min(10).max(400).optional() }).strict().refine((value) => value.packSlug || value.packName, { message: "Provide packSlug or packName." }); const outputSchema = z.object({ selectedPack: z.object({ name: z.string(), slug: z.string(), version: z.string(), fingerprint: z.string(), path: z.string() }), integrity: z.object({ fingerprintMatches: z.boolean() }), scaffoldResult: scaffoldProjectAgentsOutputSchema }); - packBlueprintSchema validates the structure of agent pack blueprints, including schemaVersion, project metadata, qualityGates (requiredTools, requiredCommands, minimumReviewAgents), and agents array with id, title, goal, and allowedTools.
const packBlueprintSchema = z.object({ schemaVersion: z.string(), project: z.object({ name: z.string().nullable().optional(), type: z.string().nullable().optional(), namespace: z.string().nullable().optional() }).optional(), qualityGates: z.object({ requiredTools: z.array(z.string().min(1)), requiredCommands: z.array(z.string().min(1)), minimumReviewAgents: z.number().int().positive() }), agents: z.array( z.object({ id: z.string().min(1), title: z.string().min(1), goal: z.string().min(1), allowedTools: z.array(z.string().min(1)).min(1) }).strict() ).min(2) }); - src/tools/index.js:36-94 (registration)Registration of apply_agent_pack tool: imported from ./agents/applyAgentPack.js at line 36, and added to the allTools export array at line 94, making it available for MCP server registration.
import { applyAgentPackTool } from "./agents/applyAgentPack.js"; import { refreshProjectContextDocsTool } from "./agents/refreshProjectContextDocs.js"; import { recordAgentExecutionFeedbackTool } from "./agents/recordAgentExecutionFeedback.js"; import { rankAgentPacksTool } from "./agents/rankAgentPacks.js"; import { promoteAgentPackTool } from "./agents/promoteAgentPack.js"; import { auditProjectMcpStateTool } from "./agents/auditProjectMcpState.js"; import { upgradeProjectMcpTool } from "./agents/upgradeProjectMcp.js"; import { ensureProjectMcpCurrentTool } from "./agents/ensureProjectMcpCurrent.js"; import { collectLegacyProjectIntakeTool } from "./agents/collectLegacyProjectIntake.js"; import { analyzeLegacyProjectBaselineTool } from "./agents/analyzeLegacyProjectBaseline.js"; import { buildAiContextIndexTool } from "./agents/buildAiContextIndex.js"; import { prepareLegacyProjectForAiTool } from "./agents/prepareLegacyProjectForAi.js"; import { scaffoldProjectSkillsTool } from "./agents/scaffoldProjectSkills.js"; import { validateProjectSkillsTool } from "./agents/validateProjectSkills.js"; import { recordSkillExecutionFeedbackTool } from "./agents/recordSkillExecutionFeedback.js"; import { rankProjectSkillsTool } from "./agents/rankProjectSkills.js"; export const allTools = [ // Project intelligence analyzeUi5ProjectTool, // UI5 generation and validation generateUi5ControllerTool, generateUi5FragmentTool, generateUi5FormatterTool, generateUi5ViewLogicTool, generateUi5FeatureTool, manageUi5I18nTool, analyzeUi5PerformanceTool, readProjectFileTool, searchProjectFilesTool, analyzeCurrentFileTool, syncManifestJsonTool, writeProjectFilePreviewTool, applyProjectPatchTool, rollbackProjectPatchTool, runProjectQualityGateTool, mcpHealthReportTool, // External documentation lookup searchUi5SdkTool, searchMdnTool, // JavaScript assistant tools generateJavaScriptFunctionTool, refactorJavaScriptCodeTool, lintJavaScriptCodeTool, securityCheckJavaScriptTool, validateUi5CodeTool, validateUi5VersionCompatibilityTool, securityCheckUi5AppTool, analyzeODataMetadataTool, validateUi5ODataUsageTool, scaffoldUi5ODataFeatureTool, // Agent factory utilities scaffoldProjectAgentsTool, validateProjectAgentsTool, recommendProjectAgentsTool, materializeRecommendedAgentsTool, saveAgentPackTool, listAgentPacksTool, applyAgentPackTool, - Helper functions supporting the tool: readCatalog (loads pack catalog JSON), selectPack (filters and selects pack by version), hashArtifactSet (computes SHA256 fingerprint), normalizePath, joinPath, normalizeProjectType, and enforceManagedSubtree (security check for path traversal).
async function readCatalog(catalogPath, root) { if (!(await fileExists(catalogPath, root))) { throw new ToolError("Agent pack catalog does not exist.", { code: "AGENT_PACK_CATALOG_NOT_FOUND", details: { catalogPath } }); } const catalog = await readJsonFile(catalogPath, root); return { schemaVersion: catalog?.schemaVersion ?? "1.0.0", packs: Array.isArray(catalog?.packs) ? catalog.packs : [] }; } function selectPack(packs, input) { const { packSlug, packName, packVersion } = input; const matching = packs.filter((pack) => { if (packSlug && pack.slug !== packSlug) { return false; } if (packName && pack.name !== packName) { return false; } return true; }); if (matching.length === 0) { return null; } if (packVersion) { return matching.find((pack) => pack.version === packVersion) ?? null; } return matching .slice() .sort((a, b) => `${b.version}`.localeCompare(`${a.version}`))[0]; } function hashArtifactSet(blueprintContent, guideContent, promptContent) { return crypto .createHash("sha256") .update(blueprintContent) .update("\n---\n") .update(guideContent) .update("\n---\n") .update(promptContent) .digest("hex"); } function normalizePath(value) { return value.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/\/{2,}/g, "/"); } function joinPath(...segments) { return segments.filter(Boolean).join("/").replaceAll("\\", "/").replace(/\/{2,}/g, "/"); } function normalizeProjectType(value) { return value === "sapui5" || value === "node" || value === "generic" ? value : undefined; } function enforceManagedSubtree(pathValue, rootPrefix, label) { if (!pathValue.startsWith(`${rootPrefix}/`) && pathValue !== rootPrefix) { throw new ToolError(`${label} must stay inside ${rootPrefix}.`, { code: "INVALID_ARTIFACT_LAYOUT", details: { label, path: pathValue, expectedPrefix: rootPrefix } }); } }