diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 49ddba521c..391b96db6e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -69,7 +69,7 @@
/tools/Azure.Mcp.Tools.AppService/ @KarishmaGhiya @microsoft/azure-mcp
# ServiceLabel: %tools-AppService
-# ServiceOwners: @ArthurMa1978 @weidongxu-microsoft
+# ServiceOwners: @ArthurMa1978 @weidongxu-microsoft
# PRLabel: %tools-BestPractices
@@ -137,7 +137,7 @@
/tools/Azure.Mcp.Tools.AzureIsv/ @pachaturvedi @agrimayadav @microsoft/azure-mcp
# ServiceLabel: %tools-ISV
-# ServiceOwners: @pachaturvedi @agrimayadav
+# ServiceOwners: @pachaturvedi @agrimayadav
# PRLabel: %tools-Kusto
/tools/Azure.Mcp.Tools.Kusto/ @prvavill @danield137 @microsoft/azure-mcp
@@ -213,6 +213,18 @@
# ServiceLabel: %tools-Storage
# ServiceOwners: @alzimmermsft @jongio
+# PRLabel: %tools-FileShares
+/tools/Azure.Mcp.Tools.FileShares/ @ankushbindlish2 @kszobi @microsoft/azure-mcp
+
+# ServiceLabel: %tools-FileShares
+# ServiceOwners: @ankushbindlish2 @kszobi
+
+# PRLabel: %tools-StorageSync
+/tools/Azure.Mcp.Tools.StorageSync/ @ankushbindlish2 @kszobi @microsoft/azure-mcp
+
+# ServiceLabel: %tools-StorageSync
+# ServiceOwners: @ankushbindlish2 @kszobi
+
# PRLabel: %tools-Authorization
/tools/Azure.Mcp.Tools.Authorization/ @vurhanau @jongio @xiangyan99 @microsoft/azure-mcp
diff --git a/AzureMcp.sln b/AzureMcp.sln
index 67aa29091c..4910d24c0d 100644
--- a/AzureMcp.sln
+++ b/AzureMcp.sln
@@ -273,6 +273,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0131AD4F-393
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.Storage", "tools\Azure.Mcp.Tools.Storage\src\Azure.Mcp.Tools.Storage.csproj", "{DE1B4312-1A4F-4774-B7EB-B1EC77F80D5E}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure.Mcp.Tools.FileShares", "Azure.Mcp.Tools.FileShares", "{1F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.FileShares", "tools\Azure.Mcp.Tools.FileShares\src\Azure.Mcp.Tools.FileShares.csproj", "{3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure.Mcp.Tools.VirtualDesktop", "Azure.Mcp.Tools.VirtualDesktop", "{B28A9B67-1C09-C756-C02A-7AC1895F9584}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E38B6DEF-57A1-6CCA-498B-5697FF0B466C}"
@@ -553,6 +559,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.Storage.Liv
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.Storage.UnitTests", "tools\Azure.Mcp.Tools.Storage\tests\Azure.Mcp.Tools.Storage.UnitTests\Azure.Mcp.Tools.Storage.UnitTests.csproj", "{F3F49C7E-9106-4FF7-A71D-442022D63F7B}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.FileShares.UnitTests", "tools\Azure.Mcp.Tools.FileShares\tests\Azure.Mcp.Tools.FileShares.UnitTests\Azure.Mcp.Tools.FileShares.UnitTests.csproj", "{5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.FileShares.LiveTests", "tools\Azure.Mcp.Tools.FileShares\tests\Azure.Mcp.Tools.FileShares.LiveTests\Azure.Mcp.Tools.FileShares.LiveTests.csproj", "{6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0F6CE16C-AE55-B930-C284-874202957B8E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Mcp.Tools.StorageSync.LiveTests", "tools\Azure.Mcp.Tools.StorageSync\tests\Azure.Mcp.Tools.StorageSync.LiveTests\Azure.Mcp.Tools.StorageSync.LiveTests.csproj", "{38FE6BAB-DAEF-2CF7-2752-379F9094C190}"
@@ -1129,6 +1141,18 @@ Global
{DE1B4312-1A4F-4774-B7EB-B1EC77F80D5E}.Release|x64.Build.0 = Release|Any CPU
{DE1B4312-1A4F-4774-B7EB-B1EC77F80D5E}.Release|x86.ActiveCfg = Release|Any CPU
{DE1B4312-1A4F-4774-B7EB-B1EC77F80D5E}.Release|x86.Build.0 = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.Build.0 = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.ActiveCfg = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.Build.0 = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.Build.0 = Release|Any CPU
{3156A400-78C7-410A-9B79-9CDFFD5B94E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3156A400-78C7-410A-9B79-9CDFFD5B94E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3156A400-78C7-410A-9B79-9CDFFD5B94E3}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -2089,6 +2113,30 @@ Global
{F3F49C7E-9106-4FF7-A71D-442022D63F7B}.Release|x64.Build.0 = Release|Any CPU
{F3F49C7E-9106-4FF7-A71D-442022D63F7B}.Release|x86.ActiveCfg = Release|Any CPU
{F3F49C7E-9106-4FF7-A71D-442022D63F7B}.Release|x86.Build.0 = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.Build.0 = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.ActiveCfg = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.Build.0 = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.Build.0 = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x64.Build.0 = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.ActiveCfg = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x64.Build.0 = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}.Release|x86.Build.0 = Release|Any CPU
{38FE6BAB-DAEF-2CF7-2752-379F9094C190}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38FE6BAB-DAEF-2CF7-2752-379F9094C190}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38FE6BAB-DAEF-2CF7-2752-379F9094C190}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -2322,6 +2370,9 @@ Global
{ED9D3D4A-502F-41A4-BBCC-970E65472F33} = {07C2787E-EAC7-C090-1BA3-A61EC2A24D84}
{0131AD4F-3934-F56E-5081-42129AD09143} = {ED9D3D4A-502F-41A4-BBCC-970E65472F33}
{DE1B4312-1A4F-4774-B7EB-B1EC77F80D5E} = {0131AD4F-3934-F56E-5081-42129AD09143}
+ {1F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {07C2787E-EAC7-C090-1BA3-A61EC2A24D84}
+ {2F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {1F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}
+ {3F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {2F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}
{B28A9B67-1C09-C756-C02A-7AC1895F9584} = {07C2787E-EAC7-C090-1BA3-A61EC2A24D84}
{E38B6DEF-57A1-6CCA-498B-5697FF0B466C} = {B28A9B67-1C09-C756-C02A-7AC1895F9584}
{3156A400-78C7-410A-9B79-9CDFFD5B94E3} = {E38B6DEF-57A1-6CCA-498B-5697FF0B466C}
@@ -2461,6 +2512,9 @@ Global
{E03D2171-C4AB-45A3-681D-A2A2EBBB122A} = {ED9D3D4A-502F-41A4-BBCC-970E65472F33}
{9A72A0E3-091A-4C64-AE66-ADAA5B46B1E8} = {E03D2171-C4AB-45A3-681D-A2A2EBBB122A}
{F3F49C7E-9106-4FF7-A71D-442022D63F7B} = {E03D2171-C4AB-45A3-681D-A2A2EBBB122A}
+ {4F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {1F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}
+ {5F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {4F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}
+ {6F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B} = {4F5E8A2B-3C4D-5E6F-7A8B-9C0D1E2F3A4B}
{0F6CE16C-AE55-B930-C284-874202957B8E} = {2D9320DA-227D-F433-BBCC-D1DDDE3FA403}
{38FE6BAB-DAEF-2CF7-2752-379F9094C190} = {0F6CE16C-AE55-B930-C284-874202957B8E}
{C5F9C8A1-2B3D-4E5F-6A7B-8C9D0E1F2A3B} = {0F6CE16C-AE55-B930-C284-874202957B8E}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 3efbe738b2..92a8d50921 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -58,6 +58,7 @@
+
diff --git a/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json b/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json
index 8630cd28f1..e81e1fe3e5 100644
--- a/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json
+++ b/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json
@@ -1828,6 +1828,178 @@
"eventgrid_events_publish"
]
},
+ {
+ "name": "get_azure_file_shares",
+ "description": "Get and list Azure File Shares. Retrieve details of specific file shares or list all file shares in a subscription or resource group.",
+ "toolMetadata": {
+ "destructive": {
+ "value": false,
+ "description": "This tool performs only additive updates without deleting or modifying existing resources."
+ },
+ "idempotent": {
+ "value": true,
+ "description": "Running this operation multiple times with the same arguments produces the same result without additional effects."
+ },
+ "openWorld": {
+ "value": false,
+ "description": "This tool's domain of interaction is closed and well-defined, limited to a specific set of entities."
+ },
+ "readOnly": {
+ "value": true,
+ "description": "This tool only performs read operations without modifying any state or data."
+ },
+ "secret": {
+ "value": false,
+ "description": "This tool does not handle sensitive or secret information."
+ },
+ "localRequired": {
+ "value": false,
+ "description": "This tool is available in both local and remote server modes."
+ }
+ },
+ "mappedToolList": [
+ "fileshares_fileshare_get",
+ "fileshares_fileshare_check-name-availability"
+ ]
+ },
+ {
+ "name": "manage_azure_file_shares",
+ "description": "Manage Azure File Shares including creating, updating, and deleting file shares.",
+ "toolMetadata": {
+ "destructive": {
+ "value": true,
+ "description": "This tool may delete or modify existing resources in its environment."
+ },
+ "idempotent": {
+ "value": false,
+ "description": "Running this operation multiple times with the same arguments may have additional effects or produce different results."
+ },
+ "openWorld": {
+ "value": false,
+ "description": "This tool's domain of interaction is closed and well-defined, limited to a specific set of entities."
+ },
+ "readOnly": {
+ "value": false,
+ "description": "This tool may modify its environment by creating, updating, or deleting data."
+ },
+ "secret": {
+ "value": false,
+ "description": "This tool does not handle sensitive or secret information."
+ },
+ "localRequired": {
+ "value": false,
+ "description": "This tool is available in both local and remote server modes."
+ }
+ },
+ "mappedToolList": [
+ "fileshares_fileshare_create",
+ "fileshares_fileshare_update",
+ "fileshares_fileshare_delete"
+ ]
+ },
+ {
+ "name": "get_azure_file_share_snapshots",
+ "description": "Get and list Azure File Share snapshots. Retrieve details of specific snapshots or list all snapshots for point-in-time recovery.",
+ "toolMetadata": {
+ "destructive": {
+ "value": false,
+ "description": "This tool performs only additive updates without deleting or modifying existing resources."
+ },
+ "idempotent": {
+ "value": true,
+ "description": "Running this operation multiple times with the same arguments produces the same result without additional effects."
+ },
+ "openWorld": {
+ "value": false,
+ "description": "This tool's domain of interaction is closed and well-defined, limited to a specific set of entities."
+ },
+ "readOnly": {
+ "value": true,
+ "description": "This tool only performs read operations without modifying any state or data."
+ },
+ "secret": {
+ "value": false,
+ "description": "This tool does not handle sensitive or secret information."
+ },
+ "localRequired": {
+ "value": false,
+ "description": "This tool is available in both local and remote server modes."
+ }
+ },
+ "mappedToolList": [
+ "fileshares_fileshare_snapshot_get"
+ ]
+ },
+ {
+ "name": "manage_azure_file_share_snapshots",
+ "description": "Manage Azure File Share snapshots including creating, updating, and deleting snapshots for point-in-time recovery.",
+ "toolMetadata": {
+ "destructive": {
+ "value": true,
+ "description": "This tool may delete or modify existing resources in its environment."
+ },
+ "idempotent": {
+ "value": false,
+ "description": "Running this operation multiple times with the same arguments may have additional effects or produce different results."
+ },
+ "openWorld": {
+ "value": false,
+ "description": "This tool's domain of interaction is closed and well-defined, limited to a specific set of entities."
+ },
+ "readOnly": {
+ "value": false,
+ "description": "This tool may modify its environment by creating, updating, or deleting data."
+ },
+ "secret": {
+ "value": false,
+ "description": "This tool does not handle sensitive or secret information."
+ },
+ "localRequired": {
+ "value": false,
+ "description": "This tool is available in both local and remote server modes."
+ }
+ },
+ "mappedToolList": [
+ "fileshares_fileshare_snapshot_create",
+ "fileshares_fileshare_snapshot_update",
+ "fileshares_fileshare_snapshot_delete"
+ ]
+ },
+ {
+ "name": "get_azure_file_shares_planning_information",
+ "description": "Get planning information for Azure File Shares including limits, quotas, provisioning recommendations, and usage data.",
+ "toolMetadata": {
+ "destructive": {
+ "value": false,
+ "description": "This tool performs only additive updates without deleting or modifying existing resources."
+ },
+ "idempotent": {
+ "value": true,
+ "description": "Running this operation multiple times with the same arguments produces the same result without additional effects."
+ },
+ "openWorld": {
+ "value": false,
+ "description": "This tool's domain of interaction is closed and well-defined, limited to a specific set of entities."
+ },
+ "readOnly": {
+ "value": true,
+ "description": "This tool only performs read operations without modifying any state or data."
+ },
+ "secret": {
+ "value": false,
+ "description": "This tool does not handle sensitive or secret information."
+ },
+ "localRequired": {
+ "value": false,
+ "description": "This tool is available in both local and remote server modes."
+ }
+ },
+ "mappedToolList": [
+ "fileshares_limits",
+ "fileshares_rec",
+ "fileshares_usage"
+ ]
+ },
{
"name": "get_azure_data_explorer_kusto_details",
"description": "Get details about Azure Data Explorer (Kusto). List clusters, execute KQL queries, manage databases, explore table schemas, and get data samples.",
diff --git a/servers/Azure.Mcp.Server/CHANGELOG.md b/servers/Azure.Mcp.Server/CHANGELOG.md
index 7d0404ecf0..667d2bf9f5 100644
--- a/servers/Azure.Mcp.Server/CHANGELOG.md
+++ b/servers/Azure.Mcp.Server/CHANGELOG.md
@@ -16,18 +16,26 @@ The Azure MCP Server updates automatically by default whenever a new release com
- `managedlustre_fs_blob_autoexport_cancel` - Cancel running autoexport jobs
- `managedlustre_fs_blob_autoexport_delete` - Delete autoexport job records
- Added support for listing tables in Azure Storage via command `azmcp_storage_table_list`. [[#743](https://github.com/microsoft/mcp/pull/743)]
+- Added Azure FileShares module with 12 commands for managing Azure managed file shares:
+ - **FileShare** commands (5): CheckNameAvailability, Create, Delete, Get, Update
+ - **FileShare Snapshot** commands (4): Create, Delete, Get, Update
+ - **Informational** commands (3): GetLimits, GetProvisioningRecommendation, GetUsageData
## 2.0.0-beta.9 (2026-01-06)
### Features Added
-- Added 18 Azure Storage Sync tools for managing cloud synchronization of file shares: [[#1419](https://github.com/microsoft/mcp/pull/1419)]
- - **StorageSyncService** tools (4): Create, Delete, Get, Update
- - **RegisteredServer** tools (3): Get, Unregister, Update
- - **SyncGroup** tools (3): Create, Delete, Get
- - **CloudEndpoint** tools (4): Create, Delete, Get, TriggerChangeDetection
- - **ServerEndpoint** tools (4): Create, Delete, Get, Update
-- Added support for logging to local files using the `--dangerously-write-support-logs-to-dir` option for troubleshooting and support scenarios. When enabled, detailed debug-level logs are written to automatically-generated timestamped log files (e.g., `azmcp_20251202_143052.log`) in the specified folder. All telemetry is automatically disabled when support logging is enabled to prevent sensitive debug information from being sent to telemetry endpoints. [[#1305](https://github.com/microsoft/mcp/pull/1305)]
+- Added Azure Storage Sync (StorageSync) module with 18 commands for managing cloud synchronization of file shares:
+ - **StorageSyncService** commands (4): Create, Delete, Get, Update
+ - **RegisteredServer** commands (3): Get, Unregister, Update
+ - **SyncGroup** commands (3): Create, Delete, Get
+ - **CloudEndpoint** commands (4): Create, Delete, Get, TriggerChangeDetection
+ - **ServerEndpoint** commands (4): Create, Delete, Get, Update
+
+- Added support logging capability with `--dangerously-write-support-logs-to-dir` option for troubleshooting and support scenarios. When enabled, detailed debug-level logs are written to automatically-generated timestamped log files (e.g., `azmcp_20251202_143052.log`) in the specified folder. All telemetry is automatically disabled when support logging is enabled to prevent sensitive debug information from being sent to telemetry endpoints.
+- Replace hard-coded strings for Azure.Mcp.Server with ones from IConfiguration. [[#1269](https://github.com/microsoft/mcp/pull/1269)]
+
+### Breaking Changes
### Bugs Fixed
diff --git a/servers/Azure.Mcp.Server/README.md b/servers/Azure.Mcp.Server/README.md
index fabd04e05a..b643570e9d 100644
--- a/servers/Azure.Mcp.Server/README.md
+++ b/servers/Azure.Mcp.Server/README.md
@@ -472,6 +472,26 @@ Microsoft Foundry and Microsoft Copilot Studio require remote MCP server endpoin
* "Publish an event with data '{\"name\": \"test\"}' to topic 'my-topic' using CloudEvents schema"
* "Send custom event data to Event Grid topic 'analytics-events' with EventGrid schema"
+### π Azure File Shares
+
+* "Get details about a specific file share in my resource group"
+* "Create a new Azure managed file share with NFS protocol"
+* "Create a file share with 64 GiB storage, 3000 IOPS, and 125 MiB/s throughput"
+* "Update the provisioned storage size of my file share"
+* "Update network access settings for my file share"
+* "Delete a file share from my resource group"
+* "Check if a file share name is available"
+* "Get details about a file share snapshot"
+* "Create a snapshot of my file share"
+* "Update tags on a file share snapshot"
+* "Delete a file share snapshot"
+* "Get a private endpoint connection for my file share"
+* "Update private endpoint connection status to Approved"
+* "Delete a private endpoint connection"
+* "Get file share limits and quotas for a region"
+* "Get provisioning recommendations for my file share workload"
+* "Get usage data and metrics for my file share"
+
### π Azure Key Vault
* "List all secrets in my key vault 'my-vault'"
@@ -552,6 +572,7 @@ The Azure MCP Server provides tools for interacting with **41+ Azure service are
- π¬ **Azure Database for MySQL** - MySQL database management
- π **Azure Database for PostgreSQL** - PostgreSQL database management
- π **Azure Event Grid** - Event routing and management
+- οΏ½ **Azure FileShares** - Azure managed file share operations
- β‘ **Azure Functions** - Function App management
- π **Azure Key Vault** - Secrets, keys, and certificates
- βΈοΈ **Azure Kubernetes Service (AKS)** - Container orchestration
@@ -572,7 +593,7 @@ The Azure MCP Server provides tools for interacting with **41+ Azure service are
- ποΈ **Azure SQL Elastic Pool** - Database resource sharing
- ποΈ **Azure SQL Server** - Server administration
- πΎ **Azure Storage** - Blob storage
-- π **Azure Storage Sync** - Azure File Sync management operations
+- **Azure Storage Sync** - Azure File Sync management operations
- π **Azure Subscription** - Subscription management
- ποΈ **Azure Terraform Best Practices** - Infrastructure as code guidance
- π₯οΈ **Azure Virtual Desktop** - Virtual desktop infrastructure
diff --git a/servers/Azure.Mcp.Server/docs/azmcp-commands.md b/servers/Azure.Mcp.Server/docs/azmcp-commands.md
index 4828d38d77..1861c9221b 100644
--- a/servers/Azure.Mcp.Server/docs/azmcp-commands.md
+++ b/servers/Azure.Mcp.Server/docs/azmcp-commands.md
@@ -1068,6 +1068,105 @@ azmcp eventhubs namespace update --subscription \
[--tags ]
```
+### Azure File Shares Operations
+
+```bash
+# Get a specific File Share or list all File Shares
+# β Destructive | β
Idempotent | β OpenWorld | β
ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare get --subscription \
+ --resource-group \
+ --name
+
+# Create a new File Share
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare create --subscription \
+ --resource-group \
+ --name \
+ --location \
+ [--mount-name ] \
+ [--media-tier ] \
+ [--redundancy ] \
+ [--protocol ] \
+ [--provisioned-storage-in-gib ] \
+ [--provisioned-io-per-sec ] \
+ [--provisioned-throughput-mib-per-sec ] \
+ [--public-network-access ] \
+ [--nfs-root-squash ] \
+ [--allowed-subnets ] \
+ [--tags ]
+
+# Update an existing File Share
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare update --subscription \
+ --resource-group \
+ --name \
+ [--provisioned-storage-in-gib ] \
+ [--provisioned-io-per-sec ] \
+ [--provisioned-throughput-mib-per-sec ] \
+ [--public-network-access ] \
+ [--nfs-root-squash ] \
+ [--allowed-subnets ] \
+ [--tags ]
+
+# Delete a File Share
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare delete --subscription \
+ --resource-group \
+ --name
+
+# Check File Share name availability
+azmcp fileshares fileshare checkname --subscription \
+ --name
+```
+
+```bash
+# Get a specific File Share snapshot
+# β Destructive | β
Idempotent | β OpenWorld | β
ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare snapshot get --subscription \
+ --resource-group \
+ --file-share-name \
+ --snapshot-name
+
+# Create a File Share snapshot
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare snapshot create --subscription \
+ --resource-group \
+ --file-share-name
+
+# Update a File Share snapshot
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare snapshot update --subscription \
+ --resource-group \
+ --file-share-name \
+ --snapshot-name \
+ [--tags ]
+
+# Delete a File Share snapshot
+# β
Destructive | β Idempotent | β OpenWorld | β ReadOnly | β Secret | β LocalRequired
+azmcp fileshares fileshare snapshot delete --subscription \
+ --resource-group \
+ --file-share-name \
+ --snapshot-name
+```
+
+```bash
+# Get File Shares limits and quotas for a region
+# β Destructive | β
Idempotent | β OpenWorld | β
ReadOnly | β Secret | β LocalRequired
+azmcp fileshares limits --subscription \
+ --location
+
+# Get provisioning recommendations for File Shares
+# β Destructive | β
Idempotent | β OpenWorld | β
ReadOnly | β Secret | β LocalRequired
+azmcp fileshares rec --subscription \
+ --location \
+ --provisioned-storage-in-gib
+
+# Get usage data and metrics for File Shares
+# β Destructive | β
Idempotent | β OpenWorld | β
ReadOnly | β Secret | β LocalRequired
+azmcp fileshares usage --subscription \
+ --location
+```
+
### Azure Function App Operations
```bash
diff --git a/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md b/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
index 695d2fda14..e1b0426e33 100644
--- a/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
+++ b/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
@@ -277,6 +277,48 @@ This file contains prompts used for end-to-end testing to ensure each tool is in
| eventhubs_namespace_update | Create an new namespace in my resource group |
| eventhubs_namespace_update | Update my namespace in my resource group |
+## Azure FileShares
+
+| Tool Name | Test Prompt |
+|:----------|:----------|
+| fileshares_fileshare_create | Create a new file share in storage account in resource group |
+| fileshares_fileshare_create | Create file share in account with quota 100 GB |
+| fileshares_fileshare_create | Create a file share named in storage account with access tier Hot |
+| fileshares_fileshare_create | Set up a new file share in storage account |
+| fileshares_fileshare_delete | Delete the file share from storage account in resource group |
+| fileshares_fileshare_delete | Remove file share from account |
+| fileshares_fileshare_get | List all file shares in storage account |
+| fileshares_fileshare_get | Show me the file shares in storage account in resource group |
+| fileshares_fileshare_get | Get details of file share in storage account |
+| fileshares_fileshare_get | Show me the file share in account |
+| fileshares_fileshare_get | What file shares exist in storage account ? |
+| fileshares_fileshare_limits_get | Get the file share limits for subscription |
+| fileshares_fileshare_limits_get | What are the file share limits in my subscription? |
+| fileshares_fileshare_limits_get | Show me the file share service limits |
+| fileshares_fileshare_nameavailability_check | Check if file share name is available in subscription |
+| fileshares_fileshare_nameavailability_check | Is the file share name available? |
+| fileshares_fileshare_nameavailability_check | Verify availability of file share name |
+| fileshares_fileshare_provisioningrecommendation_get | Get provisioning recommendations for file share in storage account |
+| fileshares_fileshare_provisioningrecommendation_get | Show me provisioning recommendations for file share |
+| fileshares_fileshare_provisioningrecommendation_get | What are the recommended provisioning settings for file share ? |
+| fileshares_fileshare_snapshot_create | Create a snapshot of file share in storage account |
+| fileshares_fileshare_snapshot_create | Create a snapshot for file share in account |
+| fileshares_fileshare_snapshot_create | Take a snapshot of file share |
+| fileshares_fileshare_snapshot_delete | Delete the snapshot from file share in storage account |
+| fileshares_fileshare_snapshot_delete | Remove snapshot from file share |
+| fileshares_fileshare_snapshot_get | List all snapshots for file share in storage account |
+| fileshares_fileshare_snapshot_get | Show me the snapshots of file share in account |
+| fileshares_fileshare_snapshot_get | Get snapshot for file share |
+| fileshares_fileshare_snapshot_update | Update the snapshot of file share in storage account |
+| fileshares_fileshare_snapshot_update | Update metadata for snapshot of file share |
+| fileshares_fileshare_update | Update file share in storage account |
+| fileshares_fileshare_update | Update the quota for file share to 200 GB |
+| fileshares_fileshare_update | Change the access tier of file share to Cool |
+| fileshares_fileshare_update | Modify file share in account with new settings |
+| fileshares_fileshare_usage_get | Get usage data for file share in storage account |
+| fileshares_fileshare_usage_get | Show me the usage statistics for file share |
+| fileshares_fileshare_usage_get | What is the current usage of file share ? |
+
## Azure Function App
| Tool Name | Test Prompt |
diff --git a/servers/Azure.Mcp.Server/src/Program.cs b/servers/Azure.Mcp.Server/src/Program.cs
index 7b77d56bbf..7946cb01da 100644
--- a/servers/Azure.Mcp.Server/src/Program.cs
+++ b/servers/Azure.Mcp.Server/src/Program.cs
@@ -95,6 +95,7 @@ private static IAreaSetup[] RegisterAreas()
new Azure.Mcp.Tools.CloudArchitect.CloudArchitectSetup(),
new Azure.Mcp.Tools.ConfidentialLedger.ConfidentialLedgerSetup(),
new Azure.Mcp.Tools.EventHubs.EventHubsSetup(),
+ new Azure.Mcp.Tools.FileShares.FileSharesSetup(),
new Azure.Mcp.Tools.Foundry.FoundrySetup(),
new Azure.Mcp.Tools.FunctionApp.FunctionAppSetup(),
new Azure.Mcp.Tools.Grafana.GrafanaSetup(),
diff --git a/tools/Azure.Mcp.Tools.FileShares/privatelinks.json b/tools/Azure.Mcp.Tools.FileShares/privatelinks.json
new file mode 100644
index 0000000000..32e41b3ec3
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/privatelinks.json
@@ -0,0 +1,202 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "title": "Common types",
+ "version": "6.0"
+ },
+ "paths": {},
+ "definitions": {
+ "PrivateEndpoint": {
+ "type": "object",
+ "description": "The private endpoint resource.",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ARM identifier for private endpoint.",
+ "readOnly": true
+ }
+ }
+ },
+ "PrivateEndpointConnection": {
+ "type": "object",
+ "description": "The private endpoint connection resource.",
+ "properties": {
+ "properties": {
+ "$ref": "#/definitions/PrivateEndpointConnectionProperties",
+ "description": "Resource properties.",
+ "x-ms-client-flatten": true
+ }
+ },
+ "allOf": [
+ {
+ "$ref": "../v5/types.json#/definitions/Resource"
+ }
+ ]
+ },
+ "PrivateEndpointConnectionListResult": {
+ "type": "object",
+ "description": "List of private endpoint connections associated with the specified resource.",
+ "properties": {
+ "value": {
+ "type": "array",
+ "description": "Array of private endpoint connections.",
+ "items": {
+ "$ref": "#/definitions/PrivateEndpointConnection"
+ }
+ },
+ "nextLink": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to get the next set of operation list results (if there are any).",
+ "readOnly": true
+ }
+ }
+ },
+ "PrivateEndpointConnectionProperties": {
+ "type": "object",
+ "description": "Properties of the private endpoint connection.",
+ "properties": {
+ "groupIds": {
+ "type": "array",
+ "description": "The group ids for the private endpoint resource.",
+ "items": {
+ "type": "string"
+ },
+ "readOnly": true
+ },
+ "privateEndpoint": {
+ "$ref": "#/definitions/PrivateEndpoint",
+ "description": "The private endpoint resource."
+ },
+ "privateLinkServiceConnectionState": {
+ "$ref": "#/definitions/PrivateLinkServiceConnectionState",
+ "description": "A collection of information about the state of the connection between service consumer and provider."
+ },
+ "provisioningState": {
+ "$ref": "#/definitions/PrivateEndpointConnectionProvisioningState",
+ "description": "The provisioning state of the private endpoint connection resource."
+ }
+ },
+ "required": [
+ "privateLinkServiceConnectionState"
+ ]
+ },
+ "PrivateEndpointConnectionProvisioningState": {
+ "type": "string",
+ "description": "The current provisioning state.",
+ "enum": [
+ "Succeeded",
+ "Creating",
+ "Deleting",
+ "Failed"
+ ],
+ "x-ms-enum": {
+ "name": "PrivateEndpointConnectionProvisioningState",
+ "modelAsString": true
+ },
+ "readOnly": true
+ },
+ "PrivateEndpointServiceConnectionStatus": {
+ "type": "string",
+ "description": "The private endpoint connection status.",
+ "enum": [
+ "Pending",
+ "Approved",
+ "Rejected"
+ ],
+ "x-ms-enum": {
+ "name": "PrivateEndpointServiceConnectionStatus",
+ "modelAsString": true
+ }
+ },
+ "PrivateLinkResource": {
+ "type": "object",
+ "description": "A private link resource.",
+ "properties": {
+ "properties": {
+ "$ref": "#/definitions/PrivateLinkResourceProperties",
+ "description": "Resource properties.",
+ "x-ms-client-flatten": true
+ }
+ },
+ "allOf": [
+ {
+ "$ref": "../v5/types.json#/definitions/Resource"
+ }
+ ]
+ },
+ "PrivateLinkResourceListResult": {
+ "type": "object",
+ "description": "A list of private link resources.",
+ "properties": {
+ "value": {
+ "type": "array",
+ "description": "Array of private link resources",
+ "items": {
+ "$ref": "#/definitions/PrivateLinkResource"
+ }
+ },
+ "nextLink": {
+ "type": "string",
+ "format": "uri",
+ "description": "URL to get the next set of operation list results (if there are any).",
+ "readOnly": true
+ }
+ }
+ },
+ "PrivateLinkResourceProperties": {
+ "type": "object",
+ "description": "Properties of a private link resource.",
+ "properties": {
+ "groupId": {
+ "type": "string",
+ "description": "The private link resource group id.",
+ "readOnly": true
+ },
+ "requiredMembers": {
+ "type": "array",
+ "description": "The private link resource required member names.",
+ "items": {
+ "type": "string"
+ },
+ "readOnly": true
+ },
+ "requiredZoneNames": {
+ "type": "array",
+ "description": "The private link resource private link DNS zone name.",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "PrivateLinkServiceConnectionState": {
+ "type": "object",
+ "description": "A collection of information about the state of the connection between service consumer and provider.",
+ "properties": {
+ "status": {
+ "$ref": "#/definitions/PrivateEndpointServiceConnectionStatus",
+ "description": "Indicates whether the connection has been Approved/Rejected/Removed by the owner of the service."
+ },
+ "description": {
+ "type": "string",
+ "description": "The reason for approval/rejection of the connection."
+ },
+ "actionsRequired": {
+ "type": "string",
+ "description": "A message indicating if changes on the service provider require any updates on the consumer."
+ }
+ }
+ }
+ },
+ "parameters": {
+ "PrivateEndpointConnectionName": {
+ "name": "privateEndpointConnectionName",
+ "in": "path",
+ "description": "The name of the private endpoint connection associated with the Azure resource.",
+ "required": true,
+ "type": "string",
+ "x-ms-parameter-location": "method"
+ }
+ }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/AssemblyInfo.cs b/tools/Azure.Mcp.Tools.FileShares/src/AssemblyInfo.cs
new file mode 100644
index 0000000000..32d59b2929
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Azure.Mcp.Tools.FileShares.UnitTests")]
+[assembly: InternalsVisibleTo("Azure.Mcp.Tools.FileShares.LiveTests")]
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Azure.Mcp.Tools.FileShares.csproj b/tools/Azure.Mcp.Tools.FileShares/src/Azure.Mcp.Tools.FileShares.csproj
new file mode 100644
index 0000000000..2b3c27ed3b
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Azure.Mcp.Tools.FileShares.csproj
@@ -0,0 +1,21 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/BaseFileSharesCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/BaseFileSharesCommand.cs
new file mode 100644
index 0000000000..161d34eca6
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/BaseFileSharesCommand.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Diagnostics.CodeAnalysis;
+using Azure.Mcp.Core.Commands;
+using Azure.Mcp.Core.Commands.Subscription;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+
+namespace Azure.Mcp.Tools.FileShares.Commands;
+
+///
+/// Base command class for all File Shares commands.
+/// Provides common command infrastructure and option registration.
+///
+public abstract class BaseFileSharesCommand<
+ [DynamicallyAccessedMembers(TrimAnnotations.CommandAnnotations)] TOptions>(
+ ILogger logger,
+ IFileSharesService fileSharesService)
+ : SubscriptionCommand where TOptions : BaseFileSharesOptions, new()
+{
+ protected readonly ILogger _logger = logger;
+ protected readonly IFileSharesService _fileSharesService = fileSharesService;
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ // Additional option registration can be added here for common File Shares options
+ }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCheckNameAvailabilityCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCheckNameAvailabilityCommand.cs
new file mode 100644
index 0000000000..fa5d615be8
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCheckNameAvailabilityCommand.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.FileShare;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.FileShare;
+
+///
+/// Checks if a file share name is available.
+///
+public sealed class FileShareCheckNameAvailabilityCommand(ILogger logger, IFileSharesService fileSharesService)
+ : BaseFileSharesCommand(logger, fileSharesService)
+{
+ public override string Id => "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d";
+ public override string Name => "check-name-availability";
+ public override string Description => "Check if a file share name is available";
+ public override string Title => "Check File Share Name Availability";
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Name.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Location.AsRequired());
+ }
+
+ protected override FileShareCheckNameAvailabilityOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Name.Name);
+ options.Location = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Location.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation(
+ "Checking name availability for file share {FileShareName} in location {Location}",
+ options.FileShareName,
+ options.Location);
+
+ var availabilityResult = await _fileSharesService.CheckNameAvailabilityAsync(
+ options.Subscription!,
+ options.FileShareName!,
+ options.Location!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new FileShareCheckNameAvailabilityCommandResult(availabilityResult.IsAvailable, availabilityResult.Reason, availabilityResult.Message);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareCheckNameAvailabilityCommandResult);
+
+ _logger.LogInformation(
+ "Name availability check completed. File share name {FileShareName} is {Status}",
+ options.FileShareName,
+ availabilityResult.IsAvailable ? "available" : "not available");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error checking file share name availability. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record FileShareCheckNameAvailabilityCommandResult(bool IsAvailable, string? Reason, string? Message);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCreateCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCreateCommand.cs
new file mode 100644
index 0000000000..60c57a8b7e
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareCreateCommand.cs
@@ -0,0 +1,150 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Models;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.FileShare;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.FileShare;
+
+public sealed class FileShareCreateCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Create File Share";
+
+ public override string Id => "b3c4d5e6-f7a8-4b9c-0d1e-2f3a4b5c6d7e";
+ public override string Name => "create";
+ public override string Description => "Create a new Azure managed file share resource in a resource group. This creates a high-performance, fully managed file share accessible via NFS protocol.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Name.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Location.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.MountName.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.MediaTier.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.Redundancy.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.Protocol.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedStorageGiB.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedIOPerSec.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedThroughputMiBPerSec.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.PublicNetworkAccess.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.NfsRootSquash.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.AllowedSubnets.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.Tags.AsOptional());
+ }
+
+ protected override FileShareCreateOrUpdateOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Name.Name);
+ options.Location = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Location.Name);
+ options.MountName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.MountName.Name);
+ options.MediaTier = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.MediaTier.Name);
+ options.Redundancy = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Redundancy.Name);
+ options.Protocol = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Protocol.Name);
+ options.ProvisionedStorageInGiB = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedStorageGiB.Name);
+ options.ProvisionedIOPerSec = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedIOPerSec.Name);
+ options.ProvisionedThroughputMiBPerSec = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedThroughputMiBPerSec.Name);
+ options.PublicNetworkAccess = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.PublicNetworkAccess.Name);
+ options.NfsRootSquash = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.NfsRootSquash.Name);
+ options.AllowedSubnets = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.AllowedSubnets.Name);
+ options.Tags = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Tags.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Creating file share. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName);
+
+ // Parse tags if provided
+ Dictionary? tags = null;
+ if (!string.IsNullOrEmpty(options.Tags))
+ {
+ try
+ {
+ tags = JsonSerializer.Deserialize(options.Tags, FileSharesJsonContext.Default.DictionaryStringString);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to parse tags JSON: {Tags}", options.Tags);
+ }
+ }
+
+ // Parse allowed subnets if provided
+ string[]? allowedSubnets = null;
+ if (!string.IsNullOrEmpty(options.AllowedSubnets))
+ {
+ allowedSubnets = options.AllowedSubnets.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ }
+
+ var fileShare = await _fileSharesService.CreateOrUpdateFileShareAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.Location!,
+ options.MountName,
+ options.MediaTier,
+ options.Redundancy,
+ options.Protocol,
+ options.ProvisionedStorageInGiB,
+ options.ProvisionedIOPerSec,
+ options.ProvisionedThroughputMiBPerSec,
+ options.PublicNetworkAccess,
+ options.NfsRootSquash,
+ allowedSubnets,
+ tags,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new FileShareCreateCommandResult(fileShare);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareCreateCommandResult);
+
+ _logger.LogInformation("File share created successfully. FileShare: {FileShareName}", options.FileShareName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to create file share");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record FileShareCreateCommandResult([property: JsonPropertyName("fileShare")] FileShareInfo FileShare);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareDeleteCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareDeleteCommand.cs
new file mode 100644
index 0000000000..0674e51b54
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareDeleteCommand.cs
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.FileShare;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.FileShare;
+
+///
+/// Deletes a file share.
+///
+public sealed class FileShareDeleteCommand(ILogger logger, IFileSharesService fileSharesService)
+ : BaseFileSharesCommand(logger, fileSharesService)
+{
+ public override string Id => "e9f0a1b2-c3d4-4e5f-6a7b-8c9d0e1f2a3b";
+ public override string Name => "delete";
+ public override string Description => "Delete a file share";
+ public override string Title => "Delete File Share";
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Name.AsRequired());
+ }
+
+ protected override FileShareDeleteOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Name.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation(
+ "Deleting file share {FileShareName} in resource group {ResourceGroup}, subscription {Subscription}",
+ options.FileShareName,
+ options.ResourceGroup,
+ options.Subscription);
+
+ await _fileSharesService.DeleteFileShareAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ context.Response.Results = ResponseResult.Create(
+ new FileShareDeleteCommandResult(true, options.FileShareName!),
+ FileSharesJsonContext.Default.FileShareDeleteCommandResult);
+
+ _logger.LogInformation(
+ "Successfully deleted file share {FileShareName}",
+ options.FileShareName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error deleting file share. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record FileShareDeleteCommandResult(bool Deleted, string FileShareName);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareGetCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareGetCommand.cs
new file mode 100644
index 0000000000..541b95ce29
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareGetCommand.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Commands;
+using Azure.Mcp.Tools.FileShares.Models;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.FileShare;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.FileShare;
+
+public sealed class FileShareGetCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Get File Share";
+
+
+ public override string Id => "c5d6e7f8-a9b0-4c1d-2e3f-4a5b6c7d8e9f";
+ public override string Name => "get";
+ public override string Description => "Get details of a specific file share or list all file shares. If --name is provided, returns a specific file share; otherwise, lists all file shares in the subscription or resource group.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Name.AsOptional());
+ }
+
+ protected override FileShareGetOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Name.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ // If file share name is provided, get specific file share
+ if (!string.IsNullOrEmpty(options.FileShareName))
+ {
+ _logger.LogInformation("Getting file share. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName);
+
+ var fileShare = await _fileSharesService.GetFileShareAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var singleResult = new FileShareGetCommandResult([fileShare]);
+ context.Response.Results = ResponseResult.Create(singleResult, FileSharesJsonContext.Default.FileShareGetCommandResult);
+
+ _logger.LogInformation("Successfully retrieved file share. FileShareName: {FileShareName}", options.FileShareName);
+ }
+ else
+ {
+ // List all file shares
+ _logger.LogInformation("Listing file shares. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}",
+ options.Subscription, options.ResourceGroup ?? "(all)");
+
+ var fileShares = await _fileSharesService.ListFileSharesAsync(
+ options.Subscription!,
+ options.ResourceGroup,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new FileShareGetCommandResult(fileShares ?? []);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareGetCommandResult);
+
+ _logger.LogInformation("Successfully listed {Count} file shares", fileShares?.Count ?? 0);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to get file share(s)");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record FileShareGetCommandResult([property: JsonPropertyName("fileShares")] List FileShares);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareUpdateCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareUpdateCommand.cs
new file mode 100644
index 0000000000..501dfbd747
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/FileShare/FileShareUpdateCommand.cs
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Commands;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.FileShare;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.FileShare;
+
+public sealed class FileShareUpdateCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Update File Share";
+
+ public override string Id => "d7e8f9a0-b1c2-4d3e-4f5a-6b7c8d9e0f1a";
+ public override string Name => "update";
+ public override string Description => "Update an existing Azure managed file share resource. Allows updating mutable properties like provisioned storage, IOPS, throughput, and network access settings.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.FileShare.Name.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedStorageGiB.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedIOPerSec.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedThroughputMiBPerSec.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.PublicNetworkAccess.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.NfsRootSquash.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.AllowedSubnets.AsOptional());
+ command.Options.Add(FileSharesOptionDefinitions.Tags.AsOptional());
+ }
+
+ protected override FileShareCreateOrUpdateOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.FileShare.Name.Name);
+ options.ProvisionedStorageInGiB = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedStorageGiB.Name);
+ options.ProvisionedIOPerSec = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedIOPerSec.Name);
+ options.ProvisionedThroughputMiBPerSec = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedThroughputMiBPerSec.Name);
+ options.PublicNetworkAccess = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.PublicNetworkAccess.Name);
+ options.NfsRootSquash = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.NfsRootSquash.Name);
+ options.AllowedSubnets = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.AllowedSubnets.Name);
+ options.Tags = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Tags.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Updating file share. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName);
+
+ // Parse tags if provided
+ Dictionary? tags = null;
+ if (!string.IsNullOrEmpty(options.Tags))
+ {
+ try
+ {
+ tags = JsonSerializer.Deserialize(options.Tags, FileSharesJsonContext.Default.DictionaryStringString);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to parse tags JSON: {Tags}", options.Tags);
+ }
+ }
+
+ // Parse allowed subnets if provided
+ string[]? allowedSubnets = null;
+ if (!string.IsNullOrEmpty(options.AllowedSubnets))
+ {
+ allowedSubnets = options.AllowedSubnets.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ }
+
+ var fileShare = await _fileSharesService.PatchFileShareAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.ProvisionedStorageInGiB,
+ options.ProvisionedIOPerSec,
+ options.ProvisionedThroughputMiBPerSec,
+ options.PublicNetworkAccess,
+ options.NfsRootSquash,
+ allowedSubnets,
+ tags,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new FileShareUpdateCommandResult(fileShare);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareUpdateCommandResult);
+
+ _logger.LogInformation("File share updated successfully. FileShare: {FileShareName}", options.FileShareName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to update file share");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record FileShareUpdateCommandResult([property: JsonPropertyName("fileShare")] FileShareInfo FileShare);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetLimitsCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetLimitsCommand.cs
new file mode 100644
index 0000000000..6df9929338
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetLimitsCommand.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Mcp.Core.Commands.Subscription;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Informational;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Informational;
+
+public sealed class FileShareGetLimitsCommand(ILogger logger, IFileSharesService service)
+ : SubscriptionCommand()
+{
+ private readonly ILogger _logger = logger;
+ private readonly IFileSharesService _service = service;
+
+ public override string Id => "a9e1f0b2-c3d4-4e5f-a6b7-c8d9e0f1a2b3";
+ public override string Name => "limits";
+ public override string Description => "Get file share limits for a subscription and location";
+ public override string Title => "Get File Share Limits";
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ Secret = false,
+ LocalRequired = false
+ };
+
+ ///
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(FileSharesOptionDefinitions.Location.AsRequired());
+ }
+
+ ///
+ protected override FileShareGetLimitsOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.Location = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Location.Name);
+ return options;
+ }
+
+ ///
+ public override async Task ExecuteAsync(
+ CommandContext context,
+ ParseResult parseResult,
+ CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Getting file share limits for subscription {Subscription} in location {Location}",
+ options.Subscription, options.Location);
+
+ var result = await _service.GetLimitsAsync(
+ options.Subscription!,
+ options.Location!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareLimitsResult);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting file share limits. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+}
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetProvisioningRecommendationCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetProvisioningRecommendationCommand.cs
new file mode 100644
index 0000000000..4e38db6912
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetProvisioningRecommendationCommand.cs
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Mcp.Core.Commands.Subscription;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Informational;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Informational;
+
+public sealed class FileShareGetProvisioningRecommendationCommand(ILogger logger, IFileSharesService service)
+ : SubscriptionCommand()
+{
+ private readonly ILogger _logger = logger;
+ private readonly IFileSharesService _service = service;
+
+ public override string Id => "3c5e1fb2-3a8d-4f8e-8b0a-1c2d3e4f5a6b";
+ public override string Name => "rec";
+ public override string Description => "Get provisioning parameter recommendations for a file share based on desired storage size";
+ public override string Title => "Get File Share Provisioning Recommendation";
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ Secret = false,
+ LocalRequired = false
+ };
+
+ ///
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(FileSharesOptionDefinitions.Location.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.ProvisionedStorageGiB.AsRequired());
+ }
+
+ ///
+ protected override FileShareGetProvisioningRecommendationOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.Location = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Location.Name);
+ options.ProvisionedStorageGiB = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.ProvisionedStorageGiB.Name);
+ return options;
+ }
+
+ ///
+ public override async Task ExecuteAsync(
+ CommandContext context,
+ ParseResult parseResult,
+ CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Getting provisioning recommendation for subscription {Subscription} in location {Location} with storage {StorageGiB} GiB",
+ options.Subscription, options.Location, options.ProvisionedStorageGiB);
+
+ var result = await _service.GetProvisioningRecommendationAsync(
+ options.Subscription!,
+ options.Location!,
+ options.ProvisionedStorageGiB!.Value,
+ options.Tenant!,
+ options.RetryPolicy,
+ cancellationToken);
+
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareProvisioningRecommendationResult);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting provisioning recommendation. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+}
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetUsageDataCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetUsageDataCommand.cs
new file mode 100644
index 0000000000..a40075bbd4
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Informational/FileShareGetUsageDataCommand.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Mcp.Core.Commands.Subscription;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Informational;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Informational;
+
+public sealed class FileShareGetUsageDataCommand(ILogger logger, IFileSharesService service)
+ : SubscriptionCommand()
+{
+ private readonly ILogger _logger = logger;
+ private readonly IFileSharesService _service = service;
+
+ public override string Id => "93d14ba8-5e75-4190-93dd-f47e932b849b";
+ public override string Name => "usage";
+ public override string Description => "Get file share usage data for a subscription and location";
+ public override string Title => "Get File Share Usage Data";
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ Secret = false,
+ LocalRequired = false
+ };
+
+ ///
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(FileSharesOptionDefinitions.Location.AsRequired());
+ }
+
+ ///
+ protected override FileShareGetUsageDataOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.Location = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Location.Name);
+ return options;
+ }
+
+ ///
+ public override async Task ExecuteAsync(
+ CommandContext context,
+ ParseResult parseResult,
+ CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Getting file share usage data for subscription {Subscription} in location {Location}",
+ options.Subscription, options.Location);
+
+ var result = await _service.GetUsageDataAsync(
+ options.Subscription!,
+ options.Location!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.FileShareUsageDataResult);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting file share usage data. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+}
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotCreateCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotCreateCommand.cs
new file mode 100644
index 0000000000..91e00cd026
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotCreateCommand.cs
@@ -0,0 +1,113 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Models;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Snapshot;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+
+public sealed class SnapshotCreateCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Create File Share Snapshot";
+
+ public override string Id => "f1a2b3c4-d5e6-4f7a-8b9c-0d1e2f3a4b5c";
+ public override string Name => "create";
+ public override string Description => "Create a snapshot of an Azure managed file share. Snapshots are read-only point-in-time copies used for backup and recovery.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.FileShareName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.SnapshotName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.Metadata.AsOptional());
+ }
+
+ protected override SnapshotCreateOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.FileShareName.Name);
+ options.SnapshotName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.SnapshotName.Name);
+ options.Metadata = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.Metadata.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Creating snapshot. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}, SnapshotName: {SnapshotName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName, options.SnapshotName);
+
+ // Parse metadata if provided
+ Dictionary? metadata = null;
+ if (!string.IsNullOrEmpty(options.Metadata))
+ {
+ try
+ {
+ metadata = JsonSerializer.Deserialize(options.Metadata, FileSharesJsonContext.Default.DictionaryStringString);
+ }
+ catch (JsonException ex)
+ {
+ throw new ArgumentException($"Invalid metadata JSON format: {ex.Message}", nameof(options.Metadata));
+ }
+ }
+
+ var snapshot = await _fileSharesService.CreateSnapshotAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.SnapshotName!,
+ metadata,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new SnapshotCreateCommandResult(snapshot);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.SnapshotCreateCommandResult);
+
+ _logger.LogInformation("Snapshot created successfully. SnapshotName: {SnapshotName}", options.SnapshotName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to create snapshot");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record SnapshotCreateCommandResult([property: JsonPropertyName("snapshot")] FileShareSnapshotInfo Snapshot);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotDeleteCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotDeleteCommand.cs
new file mode 100644
index 0000000000..5f904a533d
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotDeleteCommand.cs
@@ -0,0 +1,96 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Snapshot;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+
+///
+/// Deletes a file share snapshot.
+///
+public sealed class SnapshotDeleteCommand(ILogger logger, IFileSharesService fileSharesService)
+ : BaseFileSharesCommand(logger, fileSharesService)
+{
+ public override string Id => "c7d8e9f0-a1b2-4c3d-4e5f-6a7b8c9d0e1f";
+ public override string Name => "delete";
+ public override string Description => "Delete a file share snapshot permanently. This operation cannot be undone.";
+ public override string Title => "Delete File Share Snapshot";
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.FileShareName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.SnapshotName.AsRequired());
+ }
+
+ protected override SnapshotDeleteOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.FileShareName.Name);
+ options.SnapshotName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.SnapshotName.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation(
+ "Deleting snapshot {SnapshotName} for file share {FileShareName} in resource group {ResourceGroup}, subscription {Subscription}",
+ options.SnapshotName,
+ options.FileShareName,
+ options.ResourceGroup,
+ options.Subscription);
+
+ await _fileSharesService.DeleteSnapshotAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.SnapshotName!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ context.Response.Results = ResponseResult.Create(
+ new SnapshotDeleteCommandResult(true, options.SnapshotName!),
+ FileSharesJsonContext.Default.SnapshotDeleteCommandResult);
+
+ _logger.LogInformation(
+ "Successfully deleted snapshot {SnapshotName}",
+ options.SnapshotName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error deleting snapshot. Options: {@Options}", options);
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record SnapshotDeleteCommandResult(bool Deleted, string SnapshotName);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotGetCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotGetCommand.cs
new file mode 100644
index 0000000000..f650845650
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotGetCommand.cs
@@ -0,0 +1,118 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Models;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Snapshot;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+
+public sealed class SnapshotGetCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Get File Share Snapshot";
+
+ public override string Id => "a3b4c5d6-e7f8-4a9b-0c1d-2e3f4a5b6c7d";
+ public override string Name => "get";
+ public override string Description => "Get details of a specific file share snapshot or list all snapshots. If --snapshot-name is provided, returns a specific snapshot; otherwise, lists all snapshots for the file share.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = false,
+ Idempotent = true,
+ OpenWorld = false,
+ ReadOnly = true,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.FileShareName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.SnapshotName.AsOptional());
+ }
+
+ protected override SnapshotGetOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.FileShareName.Name);
+ options.SnapshotName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.SnapshotName.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ // If snapshot name is provided, get specific snapshot
+ if (!string.IsNullOrEmpty(options.SnapshotName))
+ {
+ _logger.LogInformation("Getting snapshot. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}, SnapshotName: {SnapshotName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName, options.SnapshotName);
+
+ var snapshot = await _fileSharesService.GetSnapshotAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.SnapshotName!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var singleResult = new SnapshotGetCommandResult([snapshot]);
+ context.Response.Results = ResponseResult.Create(singleResult, FileSharesJsonContext.Default.SnapshotGetCommandResult);
+
+ _logger.LogInformation("Successfully retrieved snapshot. SnapshotName: {SnapshotName}", options.SnapshotName);
+ }
+ else
+ {
+ // List all snapshots
+ _logger.LogInformation("Listing snapshots. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName);
+
+ var snapshots = await _fileSharesService.ListSnapshotsAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new SnapshotGetCommandResult(snapshots ?? []);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.SnapshotGetCommandResult);
+
+ _logger.LogInformation("Successfully listed {Count} snapshots for file share {FileShareName}", snapshots?.Count ?? 0, options.FileShareName);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to get snapshot(s)");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record SnapshotGetCommandResult([property: JsonPropertyName("snapshots")] List Snapshots);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotUpdateCommand.cs b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotUpdateCommand.cs
new file mode 100644
index 0000000000..cfda4a41ac
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Commands/Snapshot/SnapshotUpdateCommand.cs
@@ -0,0 +1,113 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Core.Extensions;
+using Azure.Mcp.Core.Models.Option;
+using Azure.Mcp.Tools.FileShares.Models;
+using Azure.Mcp.Tools.FileShares.Options;
+using Azure.Mcp.Tools.FileShares.Options.Snapshot;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.Logging;
+using Microsoft.Mcp.Core.Commands;
+using Microsoft.Mcp.Core.Models.Command;
+using Microsoft.Mcp.Core.Models.Option;
+
+namespace Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+
+public sealed class SnapshotUpdateCommand(ILogger logger, IFileSharesService service)
+ : BaseFileSharesCommand(logger, service)
+{
+ private const string CommandTitle = "Update File Share Snapshot";
+
+ public override string Id => "b5c6d7e8-f9a0-4b1c-2d3e-4f5a6b7c8d9e";
+ public override string Name => "update";
+ public override string Description => "Update properties and metadata of an Azure managed file share snapshot, such as tags or retention policies.";
+ public override string Title => CommandTitle;
+
+ public override ToolMetadata Metadata => new()
+ {
+ Destructive = true,
+ Idempotent = false,
+ OpenWorld = false,
+ ReadOnly = false,
+ LocalRequired = false,
+ Secret = false
+ };
+
+ protected override void RegisterOptions(Command command)
+ {
+ base.RegisterOptions(command);
+ command.Options.Add(OptionDefinitions.Common.ResourceGroup.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.FileShareName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.SnapshotName.AsRequired());
+ command.Options.Add(FileSharesOptionDefinitions.Snapshot.Metadata.AsOptional());
+ }
+
+ protected override SnapshotUpdateOptions BindOptions(ParseResult parseResult)
+ {
+ var options = base.BindOptions(parseResult);
+ options.ResourceGroup ??= parseResult.GetValueOrDefault(OptionDefinitions.Common.ResourceGroup.Name);
+ options.FileShareName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.FileShareName.Name);
+ options.SnapshotName = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.SnapshotName.Name);
+ options.Metadata = parseResult.GetValueOrDefault(FileSharesOptionDefinitions.Snapshot.Metadata.Name);
+ return options;
+ }
+
+ public override async Task ExecuteAsync(CommandContext context, ParseResult parseResult, CancellationToken cancellationToken)
+ {
+ if (!Validate(parseResult.CommandResult, context.Response).IsValid)
+ {
+ return context.Response;
+ }
+
+ var options = BindOptions(parseResult);
+
+ try
+ {
+ _logger.LogInformation("Updating snapshot. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, FileShareName: {FileShareName}, SnapshotName: {SnapshotName}",
+ options.Subscription, options.ResourceGroup, options.FileShareName, options.SnapshotName);
+
+ // Parse metadata if provided
+ Dictionary? metadata = null;
+ if (!string.IsNullOrEmpty(options.Metadata))
+ {
+ try
+ {
+ metadata = JsonSerializer.Deserialize(options.Metadata, FileSharesJsonContext.Default.DictionaryStringString);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to parse metadata JSON: {Metadata}", options.Metadata);
+ }
+ }
+
+ var snapshot = await _fileSharesService.PatchSnapshotAsync(
+ options.Subscription!,
+ options.ResourceGroup!,
+ options.FileShareName!,
+ options.SnapshotName!,
+ metadata,
+ options.Tenant,
+ options.RetryPolicy,
+ cancellationToken);
+
+ var result = new SnapshotUpdateCommandResult(snapshot);
+ context.Response.Results = ResponseResult.Create(result, FileSharesJsonContext.Default.SnapshotUpdateCommandResult);
+
+ _logger.LogInformation("Snapshot updated successfully. SnapshotName: {SnapshotName}", options.SnapshotName);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to update snapshot");
+ HandleException(context, ex);
+ }
+
+ return context.Response;
+ }
+
+ internal record SnapshotUpdateCommandResult([property: JsonPropertyName("snapshot")] FileShareSnapshotInfo Snapshot);
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/FileSharesJsonContext.cs b/tools/Azure.Mcp.Tools.FileShares/src/FileSharesJsonContext.cs
new file mode 100644
index 0000000000..2cc1171a34
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/FileSharesJsonContext.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Azure.Mcp.Tools.FileShares.Commands.FileShare;
+using Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+using Azure.Mcp.Tools.FileShares.Models;
+
+namespace Azure.Mcp.Tools.FileShares;
+
+[JsonSerializable(typeof(FileShareInfo))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(FileShareGetCommand.FileShareGetCommandResult))]
+[JsonSerializable(typeof(FileShareCreateCommand.FileShareCreateCommandResult))]
+[JsonSerializable(typeof(FileShareUpdateCommand.FileShareUpdateCommandResult))]
+[JsonSerializable(typeof(FileShareDeleteCommand.FileShareDeleteCommandResult))]
+[JsonSerializable(typeof(FileShareCheckNameAvailabilityCommand.FileShareCheckNameAvailabilityCommandResult))]
+[JsonSerializable(typeof(FileShareSnapshotInfo))]
+[JsonSerializable(typeof(List))]
+[JsonSerializable(typeof(SnapshotCreateCommand.SnapshotCreateCommandResult))]
+[JsonSerializable(typeof(SnapshotGetCommand.SnapshotGetCommandResult))]
+[JsonSerializable(typeof(SnapshotDeleteCommand.SnapshotDeleteCommandResult))]
+[JsonSerializable(typeof(SnapshotUpdateCommand.SnapshotUpdateCommandResult))]
+[JsonSerializable(typeof(FileShareDataSchema))]
+[JsonSerializable(typeof(PrivateEndpointConnectionDataSchema))]
+[JsonSerializable(typeof(FileShareLimitsResult))]
+[JsonSerializable(typeof(FileShareLimits))]
+[JsonSerializable(typeof(FileShareProvisioningConstants))]
+[JsonSerializable(typeof(FileShareUsageDataResult))]
+[JsonSerializable(typeof(LiveSharesUsageData))]
+[JsonSerializable(typeof(FileShareProvisioningRecommendationResult))]
+[JsonSerializable(typeof(Dictionary))]
+[JsonSerializable(typeof(JsonElement))]
+[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
+internal partial class FileSharesJsonContext : JsonSerializerContext
+{
+}
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/FileSharesSetup.cs b/tools/Azure.Mcp.Tools.FileShares/src/FileSharesSetup.cs
new file mode 100644
index 0000000000..90cf212865
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/FileSharesSetup.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Mcp.Tools.FileShares.Commands.FileShare;
+using Azure.Mcp.Tools.FileShares.Commands.Informational;
+using Azure.Mcp.Tools.FileShares.Commands.Snapshot;
+using Azure.Mcp.Tools.FileShares.Services;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Mcp.Core.Areas;
+using Microsoft.Mcp.Core.Commands;
+
+namespace Azure.Mcp.Tools.FileShares;
+
+public class FileSharesSetup : IAreaSetup
+{
+ public string Name => "fileshares";
+
+ public string Title => "Azure File Shares";
+
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ }
+
+ public CommandGroup RegisterCommands(IServiceProvider serviceProvider)
+ {
+ var fileShares = new CommandGroup(Name, "File Shares operations - Commands for managing Azure File Shares.", Title);
+
+ var fileShare = new CommandGroup("fileshare", "File share operations - Commands for managing file shares.");
+ fileShares.AddSubGroup(fileShare);
+
+ var fileShareGet = serviceProvider.GetRequiredService();
+ fileShare.AddCommand(fileShareGet.Name, fileShareGet);
+
+ var fileShareCreate = serviceProvider.GetRequiredService();
+ fileShare.AddCommand(fileShareCreate.Name, fileShareCreate);
+
+ var fileShareUpdate = serviceProvider.GetRequiredService();
+ fileShare.AddCommand(fileShareUpdate.Name, fileShareUpdate);
+
+ var fileShareDelete = serviceProvider.GetRequiredService();
+ fileShare.AddCommand(fileShareDelete.Name, fileShareDelete);
+
+ var checkName = serviceProvider.GetRequiredService();
+ fileShare.AddCommand(checkName.Name, checkName);
+
+ var snapshot = new CommandGroup("snapshot", "File share snapshot operations - Commands for managing file share snapshots.");
+ fileShare.AddSubGroup(snapshot);
+
+ var snapshotGet = serviceProvider.GetRequiredService();
+ snapshot.AddCommand(snapshotGet.Name, snapshotGet);
+
+ var snapshotCreate = serviceProvider.GetRequiredService();
+ snapshot.AddCommand(snapshotCreate.Name, snapshotCreate);
+
+ var snapshotUpdate = serviceProvider.GetRequiredService();
+ snapshot.AddCommand(snapshotUpdate.Name, snapshotUpdate);
+
+ var snapshotDelete = serviceProvider.GetRequiredService();
+ snapshot.AddCommand(snapshotDelete.Name, snapshotDelete);
+
+ // Register informational commands directly under fileshares
+ var limits = serviceProvider.GetRequiredService();
+ fileShares.AddCommand(limits.Name, limits);
+
+ var recommendation = serviceProvider.GetRequiredService();
+ fileShares.AddCommand(recommendation.Name, recommendation);
+
+ var usage = serviceProvider.GetRequiredService();
+ fileShares.AddCommand(usage.Name, usage);
+
+ return fileShares;
+ }
+}
+
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/GlobalUsings.cs b/tools/Azure.Mcp.Tools.FileShares/src/GlobalUsings.cs
new file mode 100644
index 0000000000..20a05c2e10
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/GlobalUsings.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+global using System.CommandLine;
+global using Azure.Mcp.Core.Commands;
+global using Azure.Mcp.Core.Options;
+global using Azure.Mcp.Core.Services.Azure;
+global using Azure.Mcp.Core.Services.Azure.Subscription;
+global using Azure.Mcp.Core.Services.Azure.Tenant;
+global using Azure.Mcp.Tools.FileShares.Models;
+global using Microsoft.Extensions.Logging;
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareDataSchema.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareDataSchema.cs
new file mode 100644
index 0000000000..ac9e90d430
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareDataSchema.cs
@@ -0,0 +1,104 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.ResourceManager.FileShares;
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Data transfer object for File Share information.
+///
+public sealed record FileShareDataSchema(
+ [property: JsonPropertyName("id")] string? Id = null,
+ [property: JsonPropertyName("name")] string? Name = null,
+ [property: JsonPropertyName("type")] string? Type = null,
+ [property: JsonPropertyName("location")] string? Location = null,
+ [property: JsonPropertyName("tags")] Dictionary? Tags = null,
+ [property: JsonPropertyName("systemData")] SystemDataSchema? SystemData = null,
+ [property: JsonPropertyName("properties")] FileSharePropertiesSchema? Properties = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public FileShareDataSchema() : this(null, null, null, null, null, null, null) { }
+
+ ///
+ /// Creates a FileShareDataSchema from a FileShareResource.
+ ///
+ public static FileShareDataSchema FromResource(FileShareResource resource)
+ {
+ var data = resource.Data;
+ var props = data.Properties;
+
+ return new FileShareDataSchema(
+ data.Id.ToString(),
+ data.Name,
+ data.ResourceType.ToString(),
+ data.Location.ToString(),
+ new Dictionary(data.Tags ?? new Dictionary()),
+ data.SystemData != null ? SystemDataSchema.FromSystemData(data.SystemData) : null,
+ props != null ? new FileSharePropertiesSchema(
+ props.MountName,
+ props.HostName,
+ props.MediaTier?.ToString(),
+ props.Redundancy?.ToString(),
+ props.Protocol?.ToString(),
+ props.ProvisionedStorageInGiB,
+ props.ProvisionedStorageNextAllowedDowngradeOn?.DateTime,
+ props.ProvisionedIOPerSec,
+ props.ProvisionedIOPerSecNextAllowedDowngradeOn?.DateTime,
+ props.ProvisionedThroughputMiBPerSec,
+ props.ProvisionedThroughputNextAllowedDowngradeOn?.DateTime,
+ props.IncludedBurstIOPerSec,
+ props.MaxBurstIOPerSecCredits,
+ props.NfsProtocolRootSquash != null ? new NfsProtocolPropertiesSchema(props.NfsProtocolRootSquash?.ToString()) : null,
+ props.PublicAccessAllowedSubnets?.Count > 0 ? new PublicAccessPropertiesSchema(props.PublicAccessAllowedSubnets.ToList()) : null,
+ props.ProvisioningState?.ToString(),
+ props.PublicNetworkAccess?.ToString(),
+ props.PrivateEndpointConnections?.Select(pec => PrivateEndpointConnectionDataSchema.FromModel(pec)).ToList()
+ ) : null
+ );
+ }
+}
+
+///
+/// Represents File Share properties schema.
+///
+public sealed record FileSharePropertiesSchema(
+ [property: JsonPropertyName("mountName")] string? MountName = null,
+ [property: JsonPropertyName("hostName")] string? HostName = null,
+ [property: JsonPropertyName("mediaTier")] string? MediaTier = null,
+ [property: JsonPropertyName("redundancy")] string? Redundancy = null,
+ [property: JsonPropertyName("protocol")] string? Protocol = null,
+ [property: JsonPropertyName("provisionedStorageGiB")] int? ProvisionedStorageGiB = null,
+ [property: JsonPropertyName("provisionedStorageNextAllowedDowngrade")] DateTime? ProvisionedStorageNextAllowedDowngrade = null,
+ [property: JsonPropertyName("provisionedIOPerSec")] int? ProvisionedIOPerSec = null,
+ [property: JsonPropertyName("provisionedIOPerSecNextAllowedDowngrade")] DateTime? ProvisionedIOPerSecNextAllowedDowngrade = null,
+ [property: JsonPropertyName("provisionedThroughputMiBPerSec")] int? ProvisionedThroughputMiBPerSec = null,
+ [property: JsonPropertyName("provisionedThroughputNextAllowedDowngrade")] DateTime? ProvisionedThroughputNextAllowedDowngrade = null,
+ [property: JsonPropertyName("includedBurstIOPerSec")] int? IncludedBurstIOPerSec = null,
+ [property: JsonPropertyName("maxBurstIOPerSecCredits")] long? MaxBurstIOPerSecCredits = null,
+ [property: JsonPropertyName("nfsProtocolProperties")] NfsProtocolPropertiesSchema? NfsProtocolProperties = null,
+ [property: JsonPropertyName("publicAccessProperties")] PublicAccessPropertiesSchema? PublicAccessProperties = null,
+ [property: JsonPropertyName("provisioningState")] string? ProvisioningState = null,
+ [property: JsonPropertyName("publicNetworkAccess")] string? PublicNetworkAccess = null,
+ [property: JsonPropertyName("privateEndpointConnections")] List? PrivateEndpointConnections = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public FileSharePropertiesSchema() : this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null) { }
+}
+
+///
+/// Represents NFS protocol-specific properties schema.
+///
+public sealed record NfsProtocolPropertiesSchema(
+ [property: JsonPropertyName("rootSquash")] string? RootSquash = null);
+
+///
+/// Represents public access properties schema for a file share.
+///
+public sealed record PublicAccessPropertiesSchema(
+ [property: JsonPropertyName("allowedSubnets")] List? AllowedSubnets = null);
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareInfo.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareInfo.cs
new file mode 100644
index 0000000000..4aa07164ed
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareInfo.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.ResourceManager.FileShares;
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Lightweight projection of FileShare data with commonly useful metadata.
+///
+public sealed record FileShareInfo(
+ [property: JsonPropertyName("id")] string Id,
+ [property: JsonPropertyName("name")] string Name,
+ [property: JsonPropertyName("location")] string? Location,
+ [property: JsonPropertyName("resourceGroup")] string? ResourceGroup,
+ [property: JsonPropertyName("type")] string? Type,
+ [property: JsonPropertyName("provisioningState")] string? ProvisioningState,
+ [property: JsonPropertyName("mountName")] string? MountName,
+ [property: JsonPropertyName("hostName")] string? HostName,
+ [property: JsonPropertyName("mediaTier")] string? MediaTier,
+ [property: JsonPropertyName("redundancy")] string? Redundancy,
+ [property: JsonPropertyName("protocol")] string? Protocol,
+ [property: JsonPropertyName("provisionedStorageInGiB")] int? ProvisionedStorageInGiB,
+ [property: JsonPropertyName("provisionedIOPerSec")] int? ProvisionedIOPerSec,
+ [property: JsonPropertyName("provisionedThroughputMiBPerSec")] int? ProvisionedThroughputMiBPerSec,
+ [property: JsonPropertyName("publicNetworkAccess")] string? PublicNetworkAccess)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public FileShareInfo() : this(string.Empty, string.Empty, null, null, null, null, null, null, null, null, null, null, null, null, null) { }
+
+ ///
+ /// Creates a FileShareInfo from a FileShareResource.
+ ///
+ public static FileShareInfo FromResource(FileShareResource resource)
+ {
+ var data = resource.Data;
+ var resourceGroup = Azure.Core.ResourceIdentifier.Parse(data.Id.ToString()).ResourceGroupName;
+ var props = data.Properties;
+
+ return new FileShareInfo(
+ Id: data.Id.ToString(),
+ Name: data.Name,
+ Location: data.Location.ToString(),
+ ResourceGroup: resourceGroup,
+ Type: data.ResourceType.ToString(),
+ ProvisioningState: props?.ProvisioningState?.ToString(),
+ MountName: props?.MountName,
+ HostName: props?.HostName,
+ MediaTier: props?.MediaTier?.ToString(),
+ Redundancy: props?.Redundancy?.ToString(),
+ Protocol: props?.Protocol?.ToString(),
+ ProvisionedStorageInGiB: props?.ProvisionedStorageInGiB,
+ ProvisionedIOPerSec: props?.ProvisionedIOPerSec,
+ ProvisionedThroughputMiBPerSec: props?.ProvisionedThroughputMiBPerSec,
+ PublicNetworkAccess: props?.PublicNetworkAccess?.ToString()
+ );
+ }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareLimitsResult.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareLimitsResult.cs
new file mode 100644
index 0000000000..c0ea4faecc
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareLimitsResult.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Result containing file share limits and provisioning constants.
+///
+public class FileShareLimitsResult
+{
+ public FileShareLimits Limits { get; set; } = new();
+ public FileShareProvisioningConstants ProvisioningConstants { get; set; } = new();
+}
+
+///
+/// File share limits for a subscription and location.
+///
+public class FileShareLimits
+{
+ public int MaxFileShares { get; set; }
+ public int MaxFileShareSnapshots { get; set; }
+ public int MaxFileShareSubnets { get; set; }
+ public int MaxFileSharePrivateEndpointConnections { get; set; }
+ public int MinProvisionedStorageGiB { get; set; }
+ public int MaxProvisionedStorageGiB { get; set; }
+ public int MinProvisionedIOPerSec { get; set; }
+ public int MaxProvisionedIOPerSec { get; set; }
+ public int MinProvisionedThroughputMiBPerSec { get; set; }
+ public int MaxProvisionedThroughputMiBPerSec { get; set; }
+}
+
+///
+/// Constants used for calculating recommended values of file share provisioning properties.
+///
+public class FileShareProvisioningConstants
+{
+ public int BaseIOPerSec { get; set; }
+ public double ScalarIOPerSec { get; set; }
+ public int BaseThroughputMiBPerSec { get; set; }
+ public double ScalarThroughputMiBPerSec { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareProvisioningRecommendationResult.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareProvisioningRecommendationResult.cs
new file mode 100644
index 0000000000..36190882d4
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareProvisioningRecommendationResult.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Result containing provisioning recommendations for a file share.
+///
+public class FileShareProvisioningRecommendationResult
+{
+ public int ProvisionedIOPerSec { get; set; }
+ public int ProvisionedThroughputMiBPerSec { get; set; }
+ public List AvailableRedundancyOptions { get; set; } = new();
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareSnapshotInfo.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareSnapshotInfo.cs
new file mode 100644
index 0000000000..79ebf17c6d
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareSnapshotInfo.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.ResourceManager.FileShares;
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Lightweight projection of FileShare Snapshot with commonly useful metadata.
+///
+public sealed record FileShareSnapshotInfo(
+ [property: JsonPropertyName("id")] string? Id = null,
+ [property: JsonPropertyName("name")] string? Name = null,
+ [property: JsonPropertyName("type")] string? Type = null,
+ [property: JsonPropertyName("snapshotTime")] string? SnapshotTime = null,
+ [property: JsonPropertyName("initiatorId")] string? InitiatorId = null,
+ [property: JsonPropertyName("resourceGroup")] string? ResourceGroup = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public FileShareSnapshotInfo() : this(null, null, null, null, null, null) { }
+
+ ///
+ /// Creates a FileShareSnapshotInfo from a FileShareSnapshotResource.
+ ///
+ public static FileShareSnapshotInfo FromResource(FileShareSnapshotResource resource)
+ {
+ var data = resource.Data;
+ var resourceGroup = Azure.Core.ResourceIdentifier.Parse(data.Id.ToString()).ResourceGroupName;
+ var props = data.Properties;
+
+ return new FileShareSnapshotInfo(
+ Id: data.Id.ToString(),
+ Name: data.Name,
+ Type: data.ResourceType.ToString(),
+ SnapshotTime: props?.SnapshotTime,
+ InitiatorId: props?.InitiatorId,
+ ResourceGroup: resourceGroup
+ );
+ }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareUsageDataResult.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareUsageDataResult.cs
new file mode 100644
index 0000000000..03bffabcfe
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/FileShareUsageDataResult.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Result containing file share usage data.
+///
+public class FileShareUsageDataResult
+{
+ public LiveSharesUsageData LiveShares { get; set; } = new();
+}
+
+///
+/// Usage data for live (active) file shares.
+///
+public class LiveSharesUsageData
+{
+ public int FileShareCount { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/PrivateEndpointConnectionDataSchema.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/PrivateEndpointConnectionDataSchema.cs
new file mode 100644
index 0000000000..2028ea1250
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/PrivateEndpointConnectionDataSchema.cs
@@ -0,0 +1,83 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.ResourceManager.FileShares.Models;
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Data transfer object for private endpoint connection information.
+///
+public sealed record PrivateEndpointConnectionDataSchema(
+ [property: JsonPropertyName("id")] string? Id = null,
+ [property: JsonPropertyName("name")] string? Name = null,
+ [property: JsonPropertyName("type")] string? Type = null,
+ [property: JsonPropertyName("systemData")] SystemDataSchema? SystemData = null,
+ [property: JsonPropertyName("properties")] PrivateEndpointConnectionPropertiesSchema? Properties = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public PrivateEndpointConnectionDataSchema() : this(null, null, null, null, null) { }
+
+ ///
+ /// Creates a PrivateEndpointConnectionDataSchema from a FileSharePrivateEndpointConnection.
+ ///
+ public static PrivateEndpointConnectionDataSchema FromModel(FileSharePrivateEndpointConnection connection)
+ {
+ var props = connection.Properties;
+
+ return new PrivateEndpointConnectionDataSchema(
+ connection.Id?.ToString(),
+ connection.Name,
+ connection.ResourceType.ToString(),
+ connection.SystemData != null ? SystemDataSchema.FromSystemData(connection.SystemData) : null,
+ props != null ? new PrivateEndpointConnectionPropertiesSchema(
+ null,
+ props.GroupIds?.ToList(),
+ props.PrivateLinkServiceConnectionState != null ? new PrivateLinkServiceConnectionStateSchema(
+ props.PrivateLinkServiceConnectionState.Status?.ToString(),
+ props.PrivateLinkServiceConnectionState.Description,
+ props.PrivateLinkServiceConnectionState.ActionsRequired
+ ) : null,
+ props.ProvisioningState?.ToString()
+ ) : null
+ );
+ }
+}
+
+///
+/// Properties of a private endpoint connection schema.
+///
+public sealed record PrivateEndpointConnectionPropertiesSchema(
+ [property: JsonPropertyName("privateEndpoint")] PrivateEndpointSchema? PrivateEndpoint = null,
+ [property: JsonPropertyName("groupIds")] List? GroupIds = null,
+ [property: JsonPropertyName("privateLinkServiceConnectionState")] PrivateLinkServiceConnectionStateSchema? PrivateLinkServiceConnectionState = null,
+ [property: JsonPropertyName("provisioningState")] string? ProvisioningState = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public PrivateEndpointConnectionPropertiesSchema() : this(null, null, null, null) { }
+}
+
+///
+/// Represents a private endpoint resource schema.
+///
+public sealed record PrivateEndpointSchema(
+ [property: JsonPropertyName("id")] string? Id = null);
+
+///
+/// State of the connection between service consumer and provider schema.
+///
+public sealed record PrivateLinkServiceConnectionStateSchema(
+ [property: JsonPropertyName("status")] string? Status = null,
+ [property: JsonPropertyName("description")] string? Description = null,
+ [property: JsonPropertyName("actionsRequired")] string? ActionsRequired = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public PrivateLinkServiceConnectionStateSchema() : this(null, null, null) { }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Models/SystemDataSchema.cs b/tools/Azure.Mcp.Tools.FileShares/src/Models/SystemDataSchema.cs
new file mode 100644
index 0000000000..8271dba4a8
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Models/SystemDataSchema.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+using Azure.ResourceManager.Models;
+
+namespace Azure.Mcp.Tools.FileShares.Models;
+
+///
+/// Represents Azure Resource Manager system metadata for created/modified tracking.
+/// Per ARM specification, systemData is automatically managed and tracks:
+/// - Creator and creation timestamp
+/// - Last modifier and modification timestamp
+/// - Creator/modifier types (User, Application, ManagedIdentity, Key)
+///
+public sealed record SystemDataSchema(
+ [property: JsonPropertyName("createdBy")] string? CreatedBy = null,
+ [property: JsonPropertyName("createdByType")] string? CreatedByType = null,
+ [property: JsonPropertyName("createdAt")] DateTime? CreatedAt = null,
+ [property: JsonPropertyName("lastModifiedBy")] string? LastModifiedBy = null,
+ [property: JsonPropertyName("lastModifiedByType")] string? LastModifiedByType = null,
+ [property: JsonPropertyName("lastModifiedAt")] DateTime? LastModifiedAt = null)
+{
+ ///
+ /// Default constructor for deserialization.
+ ///
+ public SystemDataSchema() : this(null, null, null, null, null, null) { }
+
+ ///
+ /// Creates a SystemDataSchema from SystemData.
+ ///
+ public static SystemDataSchema FromSystemData(SystemData systemData)
+ {
+ return new SystemDataSchema(
+ systemData.CreatedBy,
+ systemData.CreatedByType?.ToString(),
+ systemData.CreatedOn?.DateTime,
+ systemData.LastModifiedBy,
+ systemData.LastModifiedByType?.ToString(),
+ systemData.LastModifiedOn?.DateTime
+ );
+ }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/BaseFileSharesOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/BaseFileSharesOptions.cs
new file mode 100644
index 0000000000..003ec20bc6
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/BaseFileSharesOptions.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Azure.Mcp.Core.Options;
+
+namespace Azure.Mcp.Tools.FileShares.Options;
+
+///
+/// Base options for all File Shares commands.
+/// Provides common parameters used across the toolset.
+///
+public abstract class BaseFileSharesOptions : SubscriptionOptions
+{
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCheckNameAvailabilityOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCheckNameAvailabilityOptions.cs
new file mode 100644
index 0000000000..8f55701dfa
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCheckNameAvailabilityOptions.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Options.FileShare;
+
+///
+/// Options for FileShareCheckNameAvailabilityCommand.
+///
+public class FileShareCheckNameAvailabilityOptions : BaseFileSharesOptions
+{
+ ///
+ /// Gets or sets the name of the file share to check availability for.
+ ///
+ public string? FileShareName { get; set; }
+
+ ///
+ /// Gets or sets the location to check name availability in.
+ ///
+ public string? Location { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCreateOrUpdateOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCreateOrUpdateOptions.cs
new file mode 100644
index 0000000000..5913665f9c
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareCreateOrUpdateOptions.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Options.FileShare;
+
+///
+/// Options for FileShareCreateOrUpdateCommand.
+///
+public class FileShareCreateOrUpdateOptions : BaseFileSharesOptions
+{
+ ///
+ /// Gets or sets the name of the file share to create or update.
+ ///
+ public string? FileShareName { get; set; }
+
+ ///
+ /// Gets or sets the location for the file share.
+ ///
+ public string? Location { get; set; }
+
+ ///
+ /// Gets or sets the mount name of the file share as seen by the end user.
+ ///
+ public string? MountName { get; set; }
+
+ ///
+ /// Gets or sets the storage media tier (e.g., "SSD").
+ ///
+ public string? MediaTier { get; set; }
+
+ ///
+ /// Gets or sets the redundancy level (e.g., "Local", "Zone").
+ ///
+ public string? Redundancy { get; set; }
+
+ ///
+ /// Gets or sets the file sharing protocol (e.g., "NFS").
+ ///
+ public string? Protocol { get; set; }
+
+ ///
+ /// Gets or sets the provisioned storage size in GiB.
+ ///
+ public int? ProvisionedStorageInGiB { get; set; }
+
+ ///
+ /// Gets or sets the provisioned IOPS.
+ ///
+ public int? ProvisionedIOPerSec { get; set; }
+
+ ///
+ /// Gets or sets the provisioned throughput in MiB/sec.
+ ///
+ public int? ProvisionedThroughputMiBPerSec { get; set; }
+
+ ///
+ /// Gets or sets the public network access setting (e.g., "Enabled", "Disabled").
+ ///
+ public string? PublicNetworkAccess { get; set; }
+
+ ///
+ /// Gets or sets the NFS root squash setting (e.g., "NoRootSquash", "RootSquash", "AllSquash").
+ ///
+ public string? NfsRootSquash { get; set; }
+
+ ///
+ /// Gets or sets the allowed subnets for public access (comma-separated list).
+ ///
+ public string? AllowedSubnets { get; set; }
+
+ ///
+ /// Gets or sets the tags for the file share (JSON format).
+ ///
+ public string? Tags { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareDeleteOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareDeleteOptions.cs
new file mode 100644
index 0000000000..1057555b7f
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareDeleteOptions.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Options.FileShare;
+
+///
+/// Options for FileShareDeleteCommand.
+///
+public class FileShareDeleteOptions : BaseFileSharesOptions
+{
+ ///
+ /// Gets or sets the name of the file share to delete.
+ ///
+ public string? FileShareName { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareGetOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareGetOptions.cs
new file mode 100644
index 0000000000..2bdf6ba855
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareGetOptions.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Options.FileShare;
+
+///
+/// Options for FileShareGetCommand.
+///
+public class FileShareGetOptions : BaseFileSharesOptions
+{
+ ///
+ /// Gets or sets the name of the file share to retrieve.
+ ///
+ public string? FileShareName { get; set; }
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareListOptions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareListOptions.cs
new file mode 100644
index 0000000000..5bb069aac0
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileShare/FileShareListOptions.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Azure.Mcp.Tools.FileShares.Options.FileShare;
+
+///
+/// Options for FileShareListCommand.
+///
+public class FileShareListOptions : BaseFileSharesOptions
+{
+ // Note: ResourceGroup property is inherited from BaseFileSharesOptions -> SubscriptionOptions -> GlobalOptions
+}
diff --git a/tools/Azure.Mcp.Tools.FileShares/src/Options/FileSharesOptionDefinitions.cs b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileSharesOptionDefinitions.cs
new file mode 100644
index 0000000000..25bb972462
--- /dev/null
+++ b/tools/Azure.Mcp.Tools.FileShares/src/Options/FileSharesOptionDefinitions.cs
@@ -0,0 +1,171 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.CommandLine;
+
+namespace Azure.Mcp.Tools.FileShares.Options;
+
+///
+/// Static definitions for all File Shares command options.
+/// Provides centralized option definitions used across commands.
+///
+public static class FileSharesOptionDefinitions
+{
+ ///
+ /// Common Azure location option.
+ ///
+ public static readonly Option Location = new("--location", "-l")
+ {
+ Description = "The Azure region/location name (e.g., eastus, westeurope)",
+ Required = false
+ };
+
+ ///
+ /// Provisioned storage size in GiB.
+ ///
+ public static readonly Option ProvisionedStorageGiB = new("--provisioned-storage-in-gib")
+ {
+ Description = "The desired provisioned storage size of the share in GiB",
+ Required = false
+ };
+
+ ///