Skip to content

Conversation

@colbytimm
Copy link
Contributor

What does this PR do?

Adds azmcp functionapp create command to create Azure Function Apps with automatic dependency provisioning.

Features

  • Multiple hosting plans: Consumption (default), Flex Consumption, Premium, App Service, Container App
  • Runtime support: .NET, Node.js, Python, Java, PowerShell with automatic OS selection
  • Auto-provisioning: Creates Storage accounts and App Service plans when not specified
  • Smart defaults: Appropriate SKUs and configurations per hosting type

GitHub issue number?

#77

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Updated servers/Azure.Mcp.Server/CHANGELOG.md and/or servers/Fabric.Mcp.Server/CHANGELOG.md for product changes (features, bug fixes, UI/UX, updated dependencies)
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes using script at eng/scripts/Process-PackageReadMe.ps1. See Package README
    • Updated command list in /servers/Azure.Mcp.Server/docs/azmcp-commands.md and/or /docs/fabric-commands.md
    • Run .\eng\scripts\Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For tools with new names, including new tools or renamed tools, update consolidated-tools.json
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated test prompts in /servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

@github-project-automation github-project-automation bot moved this to Untriaged in Azure MCP Server Dec 8, 2025
@colbytimm colbytimm mentioned this pull request Dec 8, 2025
17 tasks
@colbytimm colbytimm marked this pull request as ready for review December 8, 2025 04:16
@colbytimm colbytimm requested review from a team and jongio as code owners December 8, 2025 04:16
Copilot AI review requested due to automatic review settings December 8, 2025 04:16
@colbytimm colbytimm requested a review from a team as a code owner December 8, 2025 04:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds the azmcp functionapp create command to enable creating Azure Function Apps with comprehensive automatic dependency provisioning and flexible hosting options.

Key Changes

  • Introduces the FunctionAppCreateCommand with support for multiple hosting plans (Consumption, Flex Consumption, Premium, App Service, Container Apps)
  • Implements automatic provisioning of Storage accounts and App Service plans when not specified
  • Adds intelligent runtime and OS selection logic with sensible defaults for .NET, Node.js, Python, Java, and PowerShell
  • Extends FunctionAppInfo model with operating system field for better resource tracking

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
FunctionAppService.cs Core service implementation with create logic, validation, OS resolution, and dual strategies for App Service vs Container Apps hosting
FunctionAppCreateCommand.cs Command implementation with comprehensive option definitions, validation, and error handling
FunctionAppCreateCommandTests.cs Extensive unit tests covering validation, parameter combinations, configuration building, and edge cases
FunctionAppCommandTests.cs Live integration tests for various hosting plans and runtime combinations
FunctionAppInfo.cs Model update adding operating system property
IFunctionAppService.cs Interface extension for the create operation
FunctionAppCreateOptions.cs New options class for create command parameters
FunctionAppOptionDefinitions.cs Option definitions for location, plan, runtime, and storage parameters
FunctionAppSetup.cs Registration of the new create command
FunctionAppJsonContext.cs JSON serialization context update
Azure.Mcp.Tools.FunctionApp.csproj Package references for Storage and AppContainers SDKs
ResourceGroupService.cs / IResourceGroupService.cs New method for resource group creation (though not used by FunctionApp service)
azmcp-commands.md Command documentation addition
e2eTestPrompts.md Test prompts for the new command
consolidated-tools.json Tool metadata for create_azure_app_resource
cspell.json Dictionary additions for new terms

* python -> 3.12
* node -> 22
* dotnet -> 8.0
* java -> 21.0
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation inconsistency: The command description states the default Java version is "21.0" (line 72), but the code implementation in GetDefaultRuntimeVersion returns "17" for Java runtime (line 55 in FunctionAppService.cs). These should match.

Suggested change
* java -> 21.0
* java -> 17.0

Copilot uses AI. Check for mistakes.
{
baseName = "func";
}
var trimmed = baseName.Length > 18 ? baseName.Substring(0, 18) : baseName;
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using baseName[..18] instead of baseName.Substring(0, 18) for consistency with modern C# range syntax used elsewhere in the file (e.g., line 526 uses version[..^2]).

Suggested change
var trimmed = baseName.Length > 18 ? baseName.Substring(0, 18) : baseName;
var trimmed = baseName.Length > 18 ? baseName[..18] : baseName;

Copilot uses AI. Check for mistakes.
[Theory]
[InlineData("invalid")]
[InlineData("mac")]
[InlineData("WINDOWS")]
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case issue: The test expects "WINDOWS" (uppercase) to throw an ArgumentException, but the code normalizes the OS input to lowercase in ValidateAndNormalizeInputs (line 109 in FunctionAppService.cs: os.Trim().ToLowerInvariant()). After normalization, "WINDOWS" becomes "windows" which is a valid value, so this test will fail. Either update the test to use a truly invalid value like "mac" or "invalid", or verify that uppercase values are actually rejected before normalization.

Suggested change
[InlineData("WINDOWS")]

Copilot uses AI. Check for mistakes.
* flex / flexconsumption -> FC1 (FlexConsumption, Linux only)
* premium / functionspremium -> EP1 (Elastic Premium)
* appservice -> B1 (Basic) unless overridden by --plan-sku
* containerapp -> Creates a Container App instead of an App Service plan/site (no plan created). Container App will reuse the function-app name.
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation formatting: Line 56 starts with an asterisk (*) instead of proper indentation/formatting like the lines above it. This should be indented consistently with the other bullets (lines 52-55) to maintain proper documentation structure.

Suggested change
* containerapp -> Creates a Container App instead of an App Service plan/site (no plan created). Container App will reuse the function-app name.
* containerapp -> Creates a Container App instead of an App Service plan/site (no plan created). Container App will reuse the function-app name.

Copilot uses AI. Check for mistakes.
Comment on lines +690 to +694
foreach (var p in parts)
{
if (p.StartsWith("AccountName=", StringComparison.OrdinalIgnoreCase))
return p[12..];
}
Copy link

Copilot AI Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.

Copilot uses AI. Check for mistakes.
},
"readOnly": {
"value": false,
"description": "This tool only performs read operations without modifying any state or data."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description should describe what the tool/tools will do to support this metadata value. Given that readOnly is false, it shouldn't say this tool only performs read operations. You can look at other tools with readOnly=false.

Same comment for other metadata descriptions.

- os: windows|linux. Default: windows unless runtime/plan requires linux (python, flex consumption, containerapp). Overridden to linux automatically when required. Python & flex consumption do not support Windows.
Automatic resources & defaults:
- Storage account: Always created (Standard_LRS, HTTPS only, blob public access disabled). Name pattern: <sanitized-functionapp>[random6]. Connection string injected as AzureWebJobsStorage.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Azure Function supports using managed identity to connect to storage account. If it is not too hard we should recommend users to use that instead of the connection string since connection strings use storage account keys.

https://learn.microsoft.com/en-us/azure/azure-functions/storage-considerations?tabs=azure-cli#storage-account-connection-setting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I was following what Azure Portal does by default. That's been my pattern. I don't disagree that using managed identities are best practices.

public const string RuntimeVersionName = "runtime-version";
public const string OperatingSystemName = "os";
public const string StorageAccountName = "storage-account";
public const string ContainerAppsEnvironmentName = "container-apps-environment";
Copy link
Member

@JasonYeMSFT JasonYeMSFT Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, this option will be ignored when not using the containerapp plan, if not rejected by the argument validation logic.

I don't feel good that some arguments will be completely ignored depending on the value of some other arguments. This looks like a signal that there should be two commands. One is for creating a traditional Azure Function App using an App Service Plan. The other is for creating a container app that runs an Azure Function App.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see how that would be clearer. I'll work on breaking these out into two separate commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

2 participants