Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/plugins/azure-skills/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "azure",
"description": "Microsoft Azure MCP and Skills integration for cloud resource management, deployments, and Azure services. Manage your Azure infrastructure, monitor applications, and deploy resources directly from Claude Code.",
"version": "1.1.67",
"version": "1.1.68",
"author": {
"name": "Microsoft",
"url": "https://www.microsoft.com"
Expand Down
2 changes: 1 addition & 1 deletion .github/plugins/azure-skills/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "azure",
"description": "Microsoft Azure MCP and Skills integration for cloud resource management, deployments, and Azure services. Manage your Azure infrastructure, monitor applications, and deploy resources directly from Cursor.",
"version": "1.1.67",
"version": "1.1.68",
"author": {
"name": "Microsoft",
"url": "https://www.microsoft.com"
Expand Down
2 changes: 1 addition & 1 deletion .github/plugins/azure-skills/.plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "azure",
"description": "Microsoft Azure MCP and Skills integration for cloud resource management, deployments, and Azure services. Manage your Azure infrastructure, monitor applications, and deploy resources directly from your development environment.",
"version": "1.1.67",
"version": "1.1.68",
"author": {
"name": "Microsoft",
"url": "https://www.microsoft.com"
Expand Down
4 changes: 4 additions & 0 deletions .github/plugins/azure-skills/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.1.68

- feat(azure-compute): add VM creation workflow with approval gate before deploy ([#2297](https://github.com/microsoft/GitHub-Copilot-for-Azure/pull/2297))

## 1.1.67

- feat: (azure-cost) add storage optimization guide and fix token limit ([#2554](https://github.com/microsoft/GitHub-Copilot-for-Azure/pull/2554))
Expand Down
69 changes: 26 additions & 43 deletions .github/plugins/azure-skills/skills/azure-compute/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,46 @@
---
name: azure-compute
description: "Azure VM and VMSS router for recommendations, pricing, autoscale, orchestration, connectivity troubleshooting, capacity reservations, and Essential Machine Management. WHEN: Azure VM, VMSS, scale set, recommend, compare, server, website, burstable, lightweight, VM family, workload, GPU, learning, simulation, dev/test, backend, autoscale, load balancer, Flexible orchestration, Uniform orchestration, cost estimate, connect, refused, Linux, black screen, reset password, reach VM, port 3389, NSG, troubleshoot, capacity reservation, CRG, reserve VMs, guarantee capacity, pre-provision capacity, CRG association, CRG disassociation, essential machine management, EMM, machine enrollment."
description: "Azure VM/VMSS router. WHEN: create / provision / deploy / spin-up VM, recommend VM size, compare VM pricing, VMSS, scale set, autoscale, burstable, lightweight server, website, backend, GPU, machine learning, HPC simulation, dev/test, workload, family, load balancer, Flexible orchestration, Uniform orchestration, cost estimate, can't connect / RDP / SSH, refused, black screen, reset password, reach VM, port 3389, NSG, security, Linux, troubleshoot, troubleshooting, connectivity, capacity reservation (CRG), reserve, guarantee capacity, pre-provision, CRG association, CRG disassociation, machine enrollment (EMM), Essential Machine Management, monitor. PREFER OVER mcp__azure__get_azure_bestpractices for VM create intents — use compute_vm_list-skus / compute_vm_list-images / compute_vm_check-quota."
license: MIT
metadata:
author: Microsoft
version: "2.4.2"
version: "2.4.3"
---

# Azure Compute Skill

Routes Azure VM requests to the appropriate workflow based on user intent.
Routes Azure VM and Virtual Machine Scale Set (VMSS) requests to the right workflow.

## When to Use This Skill

Activate this skill when the user:
- Asks about Azure Virtual Machines (VMs) or VM Scale Sets (VMSS)
- Asks about choosing a VM, VM sizing, pricing, or cost estimates
- Needs a workload-based recommendation for scenarios like database, GPU, deep learning, HPC, web tier, or dev/test
- Mentions VM families, autoscale, load balancing, or Flexible versus Uniform orchestration
- Wants to troubleshoot Azure VM connectivity issues such as unreachable VMs, RDP/SSH failures, black screens, NSG/firewall issues, or credential resets
- Asks about Capacity Reservation Groups (CRGs), reserving VM capacity, associating/disassociating VMs with a CRG, or guaranteeing compute capacity
- Asks about Essential Machine Management (EMM), machine enrollment, onboarding VMs for monitoring/security, or enabling machine management at subscription level
- Uses prompts like "Help me choose a VM"
- User wants to **recommend, compare, or price** a VM or VMSS
- User wants to **create, provision, or deploy** a VM or VMSS
- User **can't connect** to a VM (RDP / SSH / port refused / black screen / password reset)
- User asks about **Capacity Reservation Groups** (CRG) — reserve, guarantee capacity, pre-provision
- User asks about **Essential Machine Management** (EMM) — machine enrollment, monitor

**Disambiguate with `azure-prepare`:** if the user wants to deploy an **application** (Docker service, web app, API, serverless workload), route to `azure-prepare`. `vm-creator` is for **bare VM/VMSS infrastructure** only.

## Routing

```text
User intent?
├─ Recommend / choose / compare / price a VM or VMSS
│ └─ Route to [VM Recommender](workflows/vm-recommender/vm-recommender.md)
├─ Can't connect / RDP / SSH / troubleshoot a VM
│ └─ Route to [VM Troubleshooter](workflows/vm-troubleshooter/vm-troubleshooter.md)
├─ Capacity reservation / CRG / reserve capacity / associate VM with CRG
│ └─ Route to [Capacity Reservation](workflows/capacity-reservation/capacity-reservation.md)
├─ Essential Machine Management / EMM / machine enrollment
│ └─ Route to [Essential Machine Management](workflows/essential-machine-management/essential-machine-management.md)
└─ Unclear
└─ Ask: "Are you looking for a VM recommendation, troubleshooting a connectivity issue, managing capacity reservations, or enabling Essential Machine Management?"
```
Azure compute intent?
├── Recommend / compare / price a VM or VMSS → VM Recommender
├── Create / provision / deploy a VM or VMSS → VM Creator
├── Can't connect / RDP / SSH / port refused → VM Troubleshooter
├── Reserve / guarantee capacity (CRG) → Capacity Reservation
├── Machine enrollment / Essential Machine Management → Essential Machine Management
└── Unclear → Ask which of the above
```

| Signal | Workflow |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| "recommend VM", "which VM", "VM size", "VM pricing", "VMSS", "scale set" | [VM Recommender](workflows/vm-recommender/vm-recommender.md) |
| "can't connect", "RDP", "SSH", "NSG blocking", "reset password", "black screen" | [VM Troubleshooter](workflows/vm-troubleshooter/vm-troubleshooter.md) |
| "capacity reservation", "CRG", "reserve capacity", "guarantee capacity", "associate VM with CRG" | [Capacity Reservation](workflows/capacity-reservation/capacity-reservation.md) |
| "essential machine management", "EMM", "machine enrollment" | [Essential Machine Management](workflows/essential-machine-management/essential-machine-management.md) |

> **Routing rule:** Always read the matched workflow file before accessing any reference files. The workflow file contains the step-by-step guidance and the reference routing table for the user's request.
**Routing rule:** read the matched workflow file before any reference file. The workflow owns the step-by-step guidance; references are looked up on demand.

## Workflows

| Workflow | Purpose | References |
| ------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------- |
| **VM Recommender** | Recommend VM sizes, VMSS, pricing using public APIs/docs | [vm-families](references/vm-families.md), [retail-prices-api](references/retail-prices-api.md), [vmss-guide](references/vmss-guide.md), [vm-quotas](references/vm-quotas.md) |
| **VM Troubleshooter** | Diagnose and resolve VM connectivity failures (RDP/SSH) | [cannot-connect-to-vm](workflows/vm-troubleshooter/references/cannot-connect-to-vm.md) |
| **Capacity Reservation** | Create and manage Capacity Reservation Groups (CRGs) | [capacity-reservation-overview](workflows/capacity-reservation/references/capacity-reservation-overview.md), [association-disassociation](workflows/capacity-reservation/references/association-disassociation.md) |
| **Essential Machine Management** | Enable and manage EMM for subscription-level VM onboarding | [emm-overview](workflows/essential-machine-management/references/emm-overview.md), [emm-prerequisites](workflows/essential-machine-management/references/emm-prerequisites.md), [emm-enable-flow-portal-guidance](workflows/essential-machine-management/references/emm-enable-flow-portal-guidance.md), [emm-enable-flow](workflows/essential-machine-management/references/emm-enable-flow.md) |

| Workflow | File | Use when |
|---|---|---|
| **VM Recommender** | [vm-recommender.md](workflows/vm-recommender/vm-recommender.md) | User asks which VM/VMSS to choose, wants pricing, or wants to compare options |
| **VM Creator** | [vm-creator.md](workflows/vm-creator/vm-creator.md) | User wants to provision a bare VM or VMSS (not an app deployment) |
| **VM Troubleshooter** | [vm-troubleshooter.md](workflows/vm-troubleshooter/vm-troubleshooter.md) | User can't connect, RDP/SSH refused, black screen, needs password reset |
| **Capacity Reservation** | [capacity-reservation.md](workflows/capacity-reservation/capacity-reservation.md) | User needs to reserve / guarantee VM capacity (CRG create / associate / disassociate) |
| **Essential Machine Management** | [essential-machine-management.md](workflows/essential-machine-management/essential-machine-management.md) | User asks about EMM / machine enrollment / monitor |
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# {vm-name} — Bicep

Deploys a single Linux VM with VNet, subnet, NSG (SSH allow), public IP, and NIC.

## Prerequisites
- Azure CLI (`az login`)
- An existing resource group
- SSH public key at `~/.ssh/id_rsa.pub`

## Quickstart

```bash
az deployment group what-if \
--resource-group {resourceGroup} \
--template-file main.bicep \
--parameters vmName={vmName} adminUsername={adminUsername} adminPublicKey="$(cat ~/.ssh/id_rsa.pub)"

az deployment group create \
--resource-group {resourceGroup} \
--template-file main.bicep \
--parameters vmName={vmName} adminUsername={adminUsername} adminPublicKey="$(cat ~/.ssh/id_rsa.pub)"
```

## Parameters

| Name | Required | Default | Notes |
|---|---|---|---|
| `vmName` | * | — | VM resource name |
| `adminUsername` | * | — | Linux admin user |
| `adminPublicKey` | * | — | Contents of `id_rsa.pub` (secure) |
| `location` | | resourceGroup location | Azure region |
| `vmSize` | | `Standard_D2s_v5` | Verify availability with `compute_vm_list-skus` |
| `osDiskSizeGb` | | `30` | |
| `osDiskType` | | `Premium_LRS` | |
| `zone` | | `''` | `1`/`2`/`3`, or empty for regional |
| `tags` | | `{}` | |

## Outputs
- `vmId` — full ARM resource ID
- `publicIpAddress` — connect with `ssh {adminUsername}@{publicIpAddress}`

## VMSS variant
Swap `Microsoft.Compute/virtualMachines` for `Microsoft.Compute/virtualMachineScaleSets@2024-07-01`, add `sku: { name: vmSize, capacity: instanceCount }`, `properties.orchestrationMode: 'Flexible'`, and move `osProfile`/`storageProfile`/`networkProfile` inside `properties.virtualMachineProfile`.

## Cleanup
```bash
az group delete --name {resourceGroup} --yes --no-wait
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
@description('Name of the VM')
param vmName string

@description('Azure region')
param location string = resourceGroup().location

@description('VM size, e.g. Standard_D2s_v5')
param vmSize string = 'Standard_D2s_v5'

@description('Admin username')
param adminUsername string

@description('SSH public key contents')
@secure()
param adminPublicKey string

@description('Address space for the new VNet')
param vnetAddressPrefix string = '10.0.0.0/16'

@description('Subnet prefix')
param subnetAddressPrefix string = '10.0.0.0/24'

@description('OS disk size in GB')
param osDiskSizeGb int = 30

@description('OS disk storage type')
param osDiskType string = 'Premium_LRS'

@description('Availability zone (1, 2, or 3); empty for regional')
param zone string = ''

@description('Tags applied to all resources')
param tags object = {}

@description('Source address prefix allowed for SSH inbound (CIDR or IP). Required — supply your public IP (e.g. "203.0.113.42/32") or a trusted CIDR range. "*" exposes port 22 to the entire internet; only pass it explicitly when you have accepted that risk.')
param sshSourceAddressPrefix string

var vnetName = '${vmName}-vnet'
var subnetName = 'default'
var nsgName = '${vmName}-nsg'
var publicIpName = '${vmName}-ip'
var nicName = '${vmName}-nic'

resource nsg 'Microsoft.Network/networkSecurityGroups@2024-05-01' = {
name: nsgName
location: location
tags: tags
properties: {
securityRules: [
{
name: 'AllowSSH'
properties: {
priority: 1000
access: 'Allow'
direction: 'Inbound'
protocol: 'Tcp'
sourceAddressPrefix: sshSourceAddressPrefix
sourcePortRange: '*'
destinationAddressPrefix: '*'
destinationPortRange: '22'
}
}
]
}
}

resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' = {
name: vnetName
location: location
tags: tags
properties: {
addressSpace: { addressPrefixes: [vnetAddressPrefix] }
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetAddressPrefix
networkSecurityGroup: { id: nsg.id }
}
}
]
}
}

resource publicIp 'Microsoft.Network/publicIPAddresses@2024-05-01' = {
name: publicIpName
location: location
tags: tags
sku: { name: 'Standard' }
properties: { publicIPAllocationMethod: 'Static' }
}

resource nic 'Microsoft.Network/networkInterfaces@2024-05-01' = {
name: nicName
location: location
tags: tags
properties: {
ipConfigurations: [
{
name: 'ipconfig1'
properties: {
subnet: { id: '${vnet.id}/subnets/${subnetName}' }
publicIPAddress: { id: publicIp.id }
privateIPAllocationMethod: 'Dynamic'
}
}
]
}
}

resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = {
name: vmName
location: location
tags: tags
zones: empty(zone) ? null : [zone]
properties: {
hardwareProfile: { vmSize: vmSize }
storageProfile: {
imageReference: {
publisher: 'Canonical'
offer: 'ubuntu-24_04-lts'
sku: 'server'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
diskSizeGB: osDiskSizeGb
managedDisk: { storageAccountType: osDiskType }
}
}
osProfile: {
computerName: vmName
adminUsername: adminUsername
linuxConfiguration: {
disablePasswordAuthentication: true
ssh: {
publicKeys: [
{
path: '/home/${adminUsername}/.ssh/authorized_keys'
keyData: adminPublicKey
}
]
}
}
}
networkProfile: {
networkInterfaces: [
{ id: nic.id }
]
}
}
}

output vmId string = vm.id
output publicIpAddress string = publicIp.properties.ipAddress
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# {vm-name} — Terraform

Deploys a Linux VM (RG, VNet, subnet, NSG with SSH allow, public IP, NIC).

## Prerequisites
- `terraform >= 1.5`
- `az login`
- Exported `AZ_SUB=<subscription-id>` env var
- SSH public key at `~/.ssh/id_rsa.pub`

## Quickstart

```bash
MY_IP=$(curl -s ifconfig.me)/32 # your current public IP, locked to /32
terraform init
terraform plan -var "vm_name=dev-vm" -var "admin_public_key=$(cat ~/.ssh/id_rsa.pub)" -var "subscription_id=$AZ_SUB" -var "resource_group_name=dev-vm-rg" -var "ssh_source_address_prefix=$MY_IP"
terraform apply -var "vm_name=dev-vm" -var "admin_public_key=$(cat ~/.ssh/id_rsa.pub)" -var "subscription_id=$AZ_SUB" -var "resource_group_name=dev-vm-rg" -var "ssh_source_address_prefix=$MY_IP"
```

## Variables (see `variables.tf`)

| Variable | Type | Default | Notes |
|---|---|---|---|
| `subscription_id` * | string | — | Azure subscription |
| `resource_group_name` * | string | — | RG will be created |
| `vm_name` * | string | — | VM resource name |
| `admin_public_key` * | string (sensitive) | — | Contents of `id_rsa.pub` |
| `ssh_source_address_prefix` * | string | — | Your public IP as `<ip>/32` or a trusted CIDR. `"*"` opens port 22 to the internet — only pass it if you have accepted that risk. |
| `location` | string | `eastus` | Azure region |
| `size` | string | `Standard_D2s_v5` | Verify with `compute_vm_list-skus` |
| `admin_username` | string | `azureuser` | |
| `zone` | string | `""` | `1`/`2`/`3`, or empty for regional |
| `os_disk_type` | string | `Premium_LRS` | |
| `os_disk_size_gb` | number | `30` | |
| `tags` | map(string) | `{}` | |

`*` = required (no default).

## Outputs (see `outputs.tf`)
- `vm_id` — full ARM resource ID
- `public_ip` — connect with `ssh {admin_username}@{public_ip}`

## VMSS variant
Replace `azurerm_linux_virtual_machine` with `azurerm_linux_virtual_machine_scale_set`; add `instances`, `upgrade_mode = "Manual" | "Automatic" | "Rolling"`. Inline NIC inside the scale set via `network_interface { ip_configuration { ... } }`.

## Notes
`ssh_source_address_prefix` is required because an open SSH port is a credential-stuffing target within minutes of going public. Always pass `<your-ip>/32` (or a trusted CIDR) — even for dev. For production, also add managed identity, diagnostics, and backup.

## Cleanup
```bash
terraform destroy -var "vm_name=dev-vm" -var "admin_public_key=$(cat ~/.ssh/id_rsa.pub)" -var "subscription_id=$AZ_SUB" -var "resource_group_name=dev-vm-rg" -var "ssh_source_address_prefix=$MY_IP" -auto-approve
```
Loading
Loading