Skip to content
This repository was archived by the owner on Sep 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
295823e
Add custom words for function app to cspell configuration
colbytimm Jul 31, 2025
a60d467
Scaffold and setup Function app with list command
colbytimm Aug 4, 2025
d7c2329
Add test setup bicep
colbytimm Aug 4, 2025
5175ce1
Add unit tests for list command
colbytimm Aug 4, 2025
d79871d
Add live tests
colbytimm Aug 4, 2025
f190073
Add Azure Function App operations and test prompts
colbytimm Aug 4, 2025
1bb7753
Add "azurewebsites" to cspell dictionary and update README with Funct…
colbytimm Aug 5, 2025
46ef11f
Fix formatting
colbytimm Aug 5, 2025
e11e809
Remove unnecessary comments
colbytimm Aug 5, 2025
66c07bb
Update FunctionAppListCommandTests to include ResourceGroupName in ex…
colbytimm Aug 5, 2025
3fd3c12
Update codeowners
colbytimm Aug 5, 2025
5ddf883
Add additional test prompt for azmcp-aks-functionapp-list in e2eTestP…
colbytimm Aug 5, 2025
62d780d
Fix typo for function app e2e tests
colbytimm Aug 5, 2025
0a2a2a1
Add additional words to cspell configuration for content connection s…
colbytimm Aug 5, 2025
ff21840
Merge branch 'main' into feat/function-app-list
colbytimm Aug 5, 2025
a21429b
Update FunctionAppListCommand to inherit BaseFunctionAppCommand. Over…
colbytimm Aug 5, 2025
dc9c17f
Update subscription parameter name. Update cacheKey to remove unneces…
colbytimm Aug 7, 2025
8e67d70
Merge branch 'main' into feat/function-app-list
colbytimm Aug 7, 2025
8f00c34
Update changelog to include function app list command
colbytimm Aug 7, 2025
fc2ad62
Merge branch 'main' into feat/function-app-list
colbytimm Aug 8, 2025
214a26e
Rename areas directory to `functionapp`
colbytimm Aug 8, 2025
bf5d253
Remove duplicate
colbytimm Aug 8, 2025
7048bdd
Fix casing in function app directory paths in solution file
colbytimm Aug 8, 2025
1f1228d
Update .github/CODEOWNERS
jongio Aug 8, 2025
f9e51c5
Update .github/CODEOWNERS
jongio Aug 8, 2025
2ac753b
Update .github/CODEOWNERS
jongio Aug 8, 2025
0d5c94d
Update .github/CODEOWNERS
jongio Aug 8, 2025
bcc1032
Remove base function app options since they are not necessary and ext…
colbytimm Aug 12, 2025
17c4eb7
Remove option definition as it's not necessary for the list command.
colbytimm Aug 12, 2025
3efb30a
Update command group description to align with other areas.
colbytimm Aug 12, 2025
facc849
Refactor BaseFunctionAppCommand to use SubscriptionOptions and update…
colbytimm Aug 12, 2025
fd1493d
Update FunctionApp to be record and update references and unit tests.
colbytimm Aug 12, 2025
09d6a8a
Remove SubscriptionId from FunctionAppInfo and update related tests
colbytimm Aug 12, 2025
6295ae7
Refactor FunctionAppInfo to include JsonPropertyName attributes for s…
colbytimm Aug 12, 2025
3efe5f1
Update Azure.ResourceManager.AppService package version to 1.4.1
colbytimm Aug 12, 2025
1565b61
Merge branch 'main' into feat/function-app-list
colbytimm Aug 13, 2025
c0f9d76
Remove telemetry tag based on consolidation change in #935
colbytimm Aug 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
# ServiceLabel: %area-Foundry
# ServiceOwners: @jayzzh @xiangyan99

# PRLabel: %area-FunctionApp
/src/Areas/FunctionApp/ @colbytimm @Azure/azure-mcp

# ServiceLabel: %area-FunctionApp
# ServiceOwners: @colbytimm

# PRLabel: %area-Grafana
/src/Areas/Grafana/ @weng5e @xiangyan99 @Azure/azure-mcp

Expand Down
6 changes: 6 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
"azureterraformbestpractices",
"azuresdk",
"azuretools",
"azurewebsites",
"codegen",
"codeium",
"cslschema",
Expand All @@ -197,6 +198,8 @@
"codesign",
"CODEOWNERS",
"containerapps",
"CONTENTAZUREFILECONNECTIONSTRING",
"CONTENTSHARE",
"cvzf",
"dataplane",
"datalake",
Expand All @@ -213,6 +216,8 @@
"exfiltration",
"filefilters",
"fnames",
"functionapp",
"functionapps",
"gethealth",
"grpcio",
"healthmodels",
Expand Down Expand Up @@ -277,6 +282,7 @@
"resourcegroups",
"Runtimes",
"searchdocs",
"serverfarms",
"servicebus",
"setparam",
"skillset",
Expand Down
54 changes: 54 additions & 0 deletions AzureMcp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureMcp.Core.UnitTests", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureMcp.Tests", "core\tests\AzureMcp.Tests\AzureMcp.Tests.csproj", "{527FE0F6-40AE-4E71-A483-0F0A2368F2A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureMcp.FunctionApp", "areas\functionApp\src\AzureMcp.FunctionApp\AzureMcp.FunctionApp.csproj", "{E6E10688-A3CD-4C33-8E13-E0E905329272}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "functionapp", "functionapp", "{3310D97C-93BE-4434-BED7-81EB639B3141}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4A85B59D-2802-46D2-B9D1-CDFE11A37945}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C1C50B06-1175-49A1-81C6-59842EEFC51B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureMcp.FunctionApp.LiveTests", "areas\functionApp\tests\AzureMcp.FunctionApp.LiveTests\AzureMcp.FunctionApp.LiveTests.csproj", "{59A3843F-39AD-45C9-90A6-EBD40D644451}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureMcp.FunctionApp.UnitTests", "areas\functionApp\tests\AzureMcp.FunctionApp.UnitTests\AzureMcp.FunctionApp.UnitTests.csproj", "{5918EA72-9701-4223-B7BB-C64EB81B6351}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1097,6 +1109,42 @@ Global
{527FE0F6-40AE-4E71-A483-0F0A2368F2A7}.Release|x64.Build.0 = Release|Any CPU
{527FE0F6-40AE-4E71-A483-0F0A2368F2A7}.Release|x86.ActiveCfg = Release|Any CPU
{527FE0F6-40AE-4E71-A483-0F0A2368F2A7}.Release|x86.Build.0 = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|x64.ActiveCfg = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|x64.Build.0 = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|x86.ActiveCfg = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Debug|x86.Build.0 = Debug|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|Any CPU.Build.0 = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|x64.ActiveCfg = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|x64.Build.0 = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|x86.ActiveCfg = Release|Any CPU
{E6E10688-A3CD-4C33-8E13-E0E905329272}.Release|x86.Build.0 = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|x64.ActiveCfg = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|x64.Build.0 = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|x86.ActiveCfg = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Debug|x86.Build.0 = Debug|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|Any CPU.Build.0 = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|x64.ActiveCfg = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|x64.Build.0 = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|x86.ActiveCfg = Release|Any CPU
{59A3843F-39AD-45C9-90A6-EBD40D644451}.Release|x86.Build.0 = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|x64.ActiveCfg = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|x64.Build.0 = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|x86.ActiveCfg = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Debug|x86.Build.0 = Debug|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|Any CPU.Build.0 = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|x64.ActiveCfg = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|x64.Build.0 = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|x86.ActiveCfg = Release|Any CPU
{5918EA72-9701-4223-B7BB-C64EB81B6351}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1240,5 +1288,11 @@ Global
{2A3CD1B4-38A3-46A1-AEDC-2C2AC47CB8F1} = {8783C0BC-EE27-8E0C-7452-5882FB8E96CA}
{1AE3FC50-8E8C-4637-AAB1-A871D5FB4535} = {8783C0BC-EE27-8E0C-7452-5882FB8E96CA}
{527FE0F6-40AE-4E71-A483-0F0A2368F2A7} = {8783C0BC-EE27-8E0C-7452-5882FB8E96CA}
{3310D97C-93BE-4434-BED7-81EB639B3141} = {87783708-79E3-AD60-C783-1D52BE7DE4BB}
{4A85B59D-2802-46D2-B9D1-CDFE11A37945} = {3310D97C-93BE-4434-BED7-81EB639B3141}
{C1C50B06-1175-49A1-81C6-59842EEFC51B} = {3310D97C-93BE-4434-BED7-81EB639B3141}
{E6E10688-A3CD-4C33-8E13-E0E905329272} = {4A85B59D-2802-46D2-B9D1-CDFE11A37945}
{59A3843F-39AD-45C9-90A6-EBD40D644451} = {C1C50B06-1175-49A1-81C6-59842EEFC51B}
{5918EA72-9701-4223-B7BB-C64EB81B6351} = {C1C50B06-1175-49A1-81C6-59842EEFC51B}
EndGlobalSection
EndGlobal
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<PackageVersion Include="Azure.ResourceManager" Version="1.13.1" />
<PackageVersion Include="Azure.ResourceManager.ApplicationInsights" Version="1.0.1" />
<PackageVersion Include="Azure.ResourceManager.AppConfiguration" Version="1.4.0" />
<PackageVersion Include="Azure.ResourceManager.AppService" Version="1.4.0" />
<PackageVersion Include="Azure.ResourceManager.Authorization" Version="1.1.4" />
<PackageVersion Include="Azure.ResourceManager.ContainerService" Version="1.2.3" />
<PackageVersion Include="Azure.ResourceManager.Kusto" Version="1.6.0" />
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Here's a short (16 seconds) video to help you get the Azure MCP Server installed
| Cosmos DB | Manage NoSQL databases and containers. | [![Install](https://img.shields.io/badge/VS_Code-Install_cosmos-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Cosmos&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22cosmos%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_cosmos-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Cosmos%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22cosmos%22%2C%22--read-only%22%5D%7D) |
| Data Explorer | Query and manage clusters and databases. | [![Install](https://img.shields.io/badge/VS_Code-Install_kusto-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Kusto&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22kusto%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_kusto-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Kusto%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22kusto%22%2C%22--read-only%22%5D%7D) |
| Foundry | Manage AI model deployments and foundations. | [![Install](https://img.shields.io/badge/VS_Code-Install_foundry-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Foundry&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22foundry%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_foundry-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Foundry%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22foundry%22%2C%22--read-only%22%5D%7D) |
| Function App | Manage function apps. | [![Install](https://img.shields.io/badge/VS_Code-Install_functionapp-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Function%20App&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22functionapp%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_functionapp-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Function%20App%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22functionapp%22%2C%22--read-only%22%5D%7D) |
| Grafana | Monitor dashboards and analytics visualization. | [![Install](https://img.shields.io/badge/VS_Code-Install_grafana-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Grafana&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22grafana%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_grafana-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Grafana%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22grafana%22%2C%22--read-only%22%5D%7D) |
| Key Vault | Manage secrets, keys, and certificates. | [![Install](https://img.shields.io/badge/VS_Code-Install_keyvault-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Key%20Vault&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22keyvault%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_keyvault-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=Azure%20Key%20Vault%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22keyvault%22%2C%22--read-only%22%5D%7D) |
| Kubernetes Service | List and manage clusters. | [![Install](https://img.shields.io/badge/VS_Code-Install_aks-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=Azure%20AKS&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22aks%22%5D%7D) | [![Install](https://img.shields.io/badge/VS_Code-Install_aks-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=Azure%20AKS%20Read%20Only&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@azure%2Fmcp%40latest%22%2C%22server%22%2C%22start%22%2C%22--mode%22%2C%22all%22%2C%22--namespace%22%2C%22aks%22%2C%22--read-only%22%5D%7D) |
Expand Down
7 changes: 7 additions & 0 deletions areas/functionApp/src/AzureMcp.FunctionApp/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("AzureMcp.FunctionApp.UnitTests")]
[assembly: InternalsVisibleTo("AzureMcp.FunctionApp.LiveTests")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="**\Resources\*.txt" />
<EmbeddedResource Include="**\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\core\src\AzureMcp.Core\AzureMcp.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.ResourceManager" />
<PackageReference Include="Azure.ResourceManager.AppService" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="ModelContextProtocol" />
<PackageReference Include="System.CommandLine" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Diagnostics.CodeAnalysis;
using AzureMcp.Core.Commands;
using AzureMcp.Core.Commands.Subscription;
using AzureMcp.FunctionApp.Options;
using Microsoft.Extensions.Logging;

namespace AzureMcp.FunctionApp.Commands;

public abstract class BaseFunctionAppCommand<
[DynamicallyAccessedMembers(TrimAnnotations.CommandAnnotations)] TOptions>(ILogger logger)
: SubscriptionCommand<TOptions>() where TOptions : BaseFunctionAppOptions, new()
{
private readonly ILogger _logger = logger;
private readonly Option<string> _functionAppName = FunctionAppOptionDefinitions.FunctionApp;

protected override void RegisterOptions(Command command)
{
base.RegisterOptions(command);
command.AddOption(_functionAppName);
}

protected override TOptions BindOptions(ParseResult parseResult)
{
var options = base.BindOptions(parseResult);
options.FunctionAppName = parseResult.GetValueForOption(_functionAppName);
return options;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure;
using AzureMcp.Core.Commands.Subscription;
using AzureMcp.Core.Services.Telemetry;
using AzureMcp.FunctionApp.Models;
using AzureMcp.FunctionApp.Options;
using AzureMcp.FunctionApp.Services;
using Microsoft.Extensions.Logging;

namespace AzureMcp.FunctionApp.Commands.FunctionApp;

public sealed class FunctionAppListCommand(ILogger<FunctionAppListCommand> logger)
: SubscriptionCommand<FunctionAppListOptions>()
{
private const string CommandTitle = "List Azure Function Apps";
private readonly ILogger<FunctionAppListCommand> _logger = logger;

public override string Name => "list";

public override string Description =>
"""
Lists all Azure Function Apps in a subscription.
Returns a list of function app details including name, location, status, and app service plan name.
""";

public override string Title => CommandTitle;

[McpServerTool(Destructive = false, ReadOnly = true, Title = CommandTitle)]
public override async Task<CommandResponse> ExecuteAsync(CommandContext context, ParseResult parseResult)
{
var options = BindOptions(parseResult);

try
{
if (!Validate(parseResult.CommandResult, context.Response).IsValid)
return context.Response;

context.Activity?.WithSubscriptionTag(options);

var functionAppService = context.GetService<IFunctionAppService>();
var functionApps = await functionAppService.ListFunctionApps(
options.Subscription!,
options.Tenant,
options.RetryPolicy);

context.Response.Results = functionApps?.Count > 0
? ResponseResult.Create(
new FunctionAppListCommandResult(functionApps),
FunctionAppJsonContext.Default.FunctionAppListCommandResult)
: null;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error listing function apps. Subscription: {Subscription}, Options: {@Options}",
options.Subscription, options);
HandleException(context, ex);
}

return context.Response;
}

protected override string GetErrorMessage(Exception ex) => ex switch
{
RequestFailedException reqEx when reqEx.Status == 404 =>
"Subscription not found. Verify the subscription ID and you have access.",
RequestFailedException reqEx when reqEx.Status == 403 =>
$"Authorization failed accessing the function app resources. Details: {reqEx.Message}",
RequestFailedException reqEx => reqEx.Message,
_ => base.GetErrorMessage(ex)
};

protected override int GetStatusCode(Exception ex) => ex switch
{
RequestFailedException reqEx => reqEx.Status,
_ => base.GetStatusCode(ex)
};

internal record FunctionAppListCommandResult(List<FunctionAppModel> Results);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Text.Json.Serialization;
using AzureMcp.FunctionApp.Commands.FunctionApp;
using AzureMcp.FunctionApp.Models;

namespace AzureMcp.FunctionApp.Commands;

[JsonSerializable(typeof(FunctionAppListCommand.FunctionAppListCommandResult))]
[JsonSerializable(typeof(FunctionAppModel))]
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
internal partial class FunctionAppJsonContext : JsonSerializerContext;
Loading