From 1cae969151da7df8955c7f8b40f58a86b50f30c0 Mon Sep 17 00:00:00 2001 From: MSBrett Date: Thu, 20 Aug 2026 14:16:10 -0700 Subject: [PATCH 1/3] fix: correct Claude plugin schema Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .claude-plugin/marketplace.json | 3 ++- .../Tests/Unit/AgentPlugins.Tests.ps1 | 26 +++++++++++++++---- .../agent-plugin/.claude-plugin/plugin.json | 8 ++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4f8d4ba2a..ef99958b1 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,8 @@ { "name": "microsoft-finops-toolkit", "version": "15.0.0", - "source": "./plugins/microsoft-finops-toolkit", + "source": "./src/templates/agent-plugin", + "strict": true, "description": "Microsoft FinOps toolkit plugin for AI-powered cloud financial management.", "category": "finops", "homepage": "https://aka.ms/finops/toolkit" diff --git a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 index ccb2a66d4..39c438ec5 100644 --- a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 +++ b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 @@ -33,8 +33,8 @@ Describe 'Agent plugin manifest' { $root.skills[0].TrimStart('./') | Should -Be $claude.skills[0].TrimStart('./') $root.agents | Should -Be './agents/' $root.mcpServers | Should -Be '.mcp.json' - $claude.agents | Should -BeNullOrEmpty - $claude.mcpServers | Should -BeNullOrEmpty + $claude.agents.Count | Should -Be 5 + $claude.mcpServers | Should -Be './.mcp.json' $claude.outputStyles | Should -Be './output-styles/' } @@ -48,11 +48,20 @@ Describe 'Agent plugin manifest' { $claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json $root.mcpServers | Should -Be '.mcp.json' - $claude.mcpServers | Should -BeNullOrEmpty - $claude.agents | Should -BeNullOrEmpty + $claude.mcpServers | Should -Be './.mcp.json' Join-Path $script:Plugin '.mcp.json' | Should -Exist } + It 'Declares resolvable paths for every Claude component' { + $claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json + $paths = @($claude.commands) + @($claude.agents) + @($claude.skills) + @($claude.mcpServers) + @($claude.outputStyles) + + $paths.Count | Should -Be 9 + $paths | ForEach-Object { + Join-Path $script:Plugin $_ | Should -Exist + } + } + It 'Uses unpinned Azure MCP latest package in .mcp.json' { $mcp = Get-Content (Join-Path $script:Plugin '.mcp.json') -Raw | ConvertFrom-Json $args = $mcp.mcpServers.'azure-mcp-server'.args @@ -167,7 +176,7 @@ Describe 'Plugin discovery and marketplaces' { It 'Uses repository-root-relative marketplace sources' { $marketplaces = @{ '.github/plugin/marketplace.json' = './plugins/microsoft-finops-toolkit' - '.claude-plugin/marketplace.json' = './plugins/microsoft-finops-toolkit' + '.claude-plugin/marketplace.json' = './src/templates/agent-plugin' } foreach ($marketplace in $marketplaces.Keys) @@ -177,4 +186,11 @@ Describe 'Plugin discovery and marketplaces' { $entry.source | Should -Be $marketplaces[$marketplace] } } + + It 'Enables strict mode explicitly for the Claude plugin' { + $json = Get-Content (Join-Path $script:RepoRoot '.claude-plugin/marketplace.json') -Raw | ConvertFrom-Json + $entry = $json.plugins | Where-Object { $_.name -eq 'microsoft-finops-toolkit' } + + $entry.strict | Should -BeTrue + } } \ No newline at end of file diff --git a/src/templates/agent-plugin/.claude-plugin/plugin.json b/src/templates/agent-plugin/.claude-plugin/plugin.json index 109c206d7..9b8911ae3 100644 --- a/src/templates/agent-plugin/.claude-plugin/plugin.json +++ b/src/templates/agent-plugin/.claude-plugin/plugin.json @@ -11,8 +11,16 @@ "license": "MIT", "keywords": ["finops", "cost-management", "reservations", "savings-plans", "cloud-optimization", "commitments", "credits", "macc"], "commands": "./commands/", + "agents": [ + "./agents/azure-capacity-manager.agent.md", + "./agents/chief-financial-officer.agent.md", + "./agents/finops-practitioner.agent.md", + "./agents/ftk-database-query.agent.md", + "./agents/ftk-hubs-agent.agent.md" + ], "skills": [ "./skills/" ], + "mcpServers": "./.mcp.json", "outputStyles": "./output-styles/" } From 214dbcb438aaf93311cb69bc091fd90f4090ea53 Mon Sep 17 00:00:00 2001 From: MSBrett Date: Fri, 21 Aug 2026 06:09:36 -0700 Subject: [PATCH 2/3] fix: load Claude plugin agents Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Tests/Unit/AgentPlugins.Tests.ps1 | 18 +++++++++++------- .../agent-plugin/.claude-plugin/plugin.json | 7 ------- ...ager.agent.md => azure-capacity-manager.md} | 0 ...cer.agent.md => chief-financial-officer.md} | 0 ...itioner.agent.md => finops-practitioner.md} | 0 ...se-query.agent.md => ftk-database-query.md} | 0 ...k-hubs-agent.agent.md => ftk-hubs-agent.md} | 0 7 files changed, 11 insertions(+), 14 deletions(-) rename src/templates/agent-plugin/agents/{azure-capacity-manager.agent.md => azure-capacity-manager.md} (100%) rename src/templates/agent-plugin/agents/{chief-financial-officer.agent.md => chief-financial-officer.md} (100%) rename src/templates/agent-plugin/agents/{finops-practitioner.agent.md => finops-practitioner.md} (100%) rename src/templates/agent-plugin/agents/{ftk-database-query.agent.md => ftk-database-query.md} (100%) rename src/templates/agent-plugin/agents/{ftk-hubs-agent.agent.md => ftk-hubs-agent.md} (100%) diff --git a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 index 39c438ec5..f54e8cab2 100644 --- a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 +++ b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 @@ -33,7 +33,7 @@ Describe 'Agent plugin manifest' { $root.skills[0].TrimStart('./') | Should -Be $claude.skills[0].TrimStart('./') $root.agents | Should -Be './agents/' $root.mcpServers | Should -Be '.mcp.json' - $claude.agents.Count | Should -Be 5 + $claude.agents | Should -BeNullOrEmpty $claude.mcpServers | Should -Be './.mcp.json' $claude.outputStyles | Should -Be './output-styles/' } @@ -54,9 +54,9 @@ Describe 'Agent plugin manifest' { It 'Declares resolvable paths for every Claude component' { $claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json - $paths = @($claude.commands) + @($claude.agents) + @($claude.skills) + @($claude.mcpServers) + @($claude.outputStyles) + $paths = @($claude.commands) + @($claude.skills) + @($claude.mcpServers) + @($claude.outputStyles) - $paths.Count | Should -Be 9 + $paths.Count | Should -Be 4 $paths | ForEach-Object { Join-Path $script:Plugin $_ | Should -Exist } @@ -73,13 +73,17 @@ Describe 'Agent plugin manifest' { } Describe 'Agent plugin components' { - It 'Ships agent definitions as NAME.agent.md files' { - $agents = Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.agent.md' - $agents.Count | Should -BeGreaterThan 0 + It 'Ships agent definitions as Claude-compatible NAME.md files' { + $agents = Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.md' + + $agents.Count | Should -Be 5 + $agents.Name | ForEach-Object { + $_ | Should -Not -Match '\.agent\.md$' + } } It 'Gives every agent a name and description in front matter' { - Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.agent.md' | ForEach-Object { + Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.md' | ForEach-Object { $content = Get-Content $_.FullName -Raw $content | Should -Match '(?ms)^---\s.*^name:\s*\S.*^description:\s*\S.*^---' } diff --git a/src/templates/agent-plugin/.claude-plugin/plugin.json b/src/templates/agent-plugin/.claude-plugin/plugin.json index 9b8911ae3..21d3b74b8 100644 --- a/src/templates/agent-plugin/.claude-plugin/plugin.json +++ b/src/templates/agent-plugin/.claude-plugin/plugin.json @@ -11,13 +11,6 @@ "license": "MIT", "keywords": ["finops", "cost-management", "reservations", "savings-plans", "cloud-optimization", "commitments", "credits", "macc"], "commands": "./commands/", - "agents": [ - "./agents/azure-capacity-manager.agent.md", - "./agents/chief-financial-officer.agent.md", - "./agents/finops-practitioner.agent.md", - "./agents/ftk-database-query.agent.md", - "./agents/ftk-hubs-agent.agent.md" - ], "skills": [ "./skills/" ], diff --git a/src/templates/agent-plugin/agents/azure-capacity-manager.agent.md b/src/templates/agent-plugin/agents/azure-capacity-manager.md similarity index 100% rename from src/templates/agent-plugin/agents/azure-capacity-manager.agent.md rename to src/templates/agent-plugin/agents/azure-capacity-manager.md diff --git a/src/templates/agent-plugin/agents/chief-financial-officer.agent.md b/src/templates/agent-plugin/agents/chief-financial-officer.md similarity index 100% rename from src/templates/agent-plugin/agents/chief-financial-officer.agent.md rename to src/templates/agent-plugin/agents/chief-financial-officer.md diff --git a/src/templates/agent-plugin/agents/finops-practitioner.agent.md b/src/templates/agent-plugin/agents/finops-practitioner.md similarity index 100% rename from src/templates/agent-plugin/agents/finops-practitioner.agent.md rename to src/templates/agent-plugin/agents/finops-practitioner.md diff --git a/src/templates/agent-plugin/agents/ftk-database-query.agent.md b/src/templates/agent-plugin/agents/ftk-database-query.md similarity index 100% rename from src/templates/agent-plugin/agents/ftk-database-query.agent.md rename to src/templates/agent-plugin/agents/ftk-database-query.md diff --git a/src/templates/agent-plugin/agents/ftk-hubs-agent.agent.md b/src/templates/agent-plugin/agents/ftk-hubs-agent.md similarity index 100% rename from src/templates/agent-plugin/agents/ftk-hubs-agent.agent.md rename to src/templates/agent-plugin/agents/ftk-hubs-agent.md From cfcbeab8c392e57c641fed3cd93dbcdc7265d5ad Mon Sep 17 00:00:00 2001 From: MSBrett Date: Fri, 21 Aug 2026 21:14:05 -0700 Subject: [PATCH 3/3] test(agent-plugin): allow additional Claude component paths Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 index f54e8cab2..c702de2b2 100644 --- a/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 +++ b/src/powershell/Tests/Unit/AgentPlugins.Tests.ps1 @@ -56,8 +56,9 @@ Describe 'Agent plugin manifest' { $claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json $paths = @($claude.commands) + @($claude.skills) + @($claude.mcpServers) + @($claude.outputStyles) - $paths.Count | Should -Be 4 + $paths.Count | Should -BeGreaterOrEqual 4 $paths | ForEach-Object { + $_ | Should -Not -BeNullOrEmpty Join-Path $script:Plugin $_ | Should -Exist } }