Skip to content

Add Azure IoT Operations toolset (instance list and get) - #3171

Open
Byron Jin (byronjinmsft) wants to merge 4 commits into
mainfrom
users/byronjin/add-iotoperations-toolset
Open

Add Azure IoT Operations toolset (instance list and get)#3171
Byron Jin (byronjinmsft) wants to merge 4 commits into
mainfrom
users/byronjin/add-iotoperations-toolset

Conversation

@byronjinmsft

Copy link
Copy Markdown

Summary

Adds a new Azure IoT Operations toolset (Azure.Mcp.Tools.IoTOperations, area iotoperations) as a POC, exposing two read-only commands over Microsoft.IoTOperations/instances via Azure Resource Graph:

  • azmcp iotoperations instance list — lists instances in a subscription or resource group.
  • azmcp iotoperations instance get — gets a specific instance by name, resource group, and subscription.

Both project a lightweight model (name, id, location, resource group, type, provisioning state, AIO version, description, schema registry resource ID). Commands follow the two-generic SubscriptionCommand<TOptions, TResult> pattern, use [Option] attributes, BaseAzureResourceService Resource Graph queries, HandleException, secure logging (no {@Options}), and instance-name validation.

Changes

  • New toolset: options, service (+interface), models, JSON context, two commands, IoTOperationsSetup.
  • Registered in Program.cs RegisterAreas() and solution files.
  • Unit tests (21 passing) + recorded live-test scaffolding, test-resources.bicep, post-deployment script, assets.json.
  • Docs: azmcp-commands.md (+ regenerated metadata), e2eTestPrompts.md, README.md, CHANGELOG.md, consolidated-tools.json, CODEOWNERS, cspell.json.

Validation

  • dotnet build of the full server — 0 warnings / 0 errors.
  • 21 unit tests pass; dotnet format clean; cspell clean; az bicep build clean.
  • Manually verified against subscription d4ccd08b-0809-446d-a8b7-7af8a90109cd: instance list returns real AIO instances and instance get returns a specific instance.

Note: An Azure IoT Operations instance is a projection onto an Azure Arc-enabled Kubernetes cluster and cannot be provisioned via a standalone Bicep template, so recorded live-test recordings require an existing AIO environment.

Invoking Livetests

Copilot submitted PRs are not trustworthy by default. Users with write access to the repo need to validate the contents of this PR before leaving a comment with the text /azp run mcp - pullrequest - live. This will trigger the necessary livetest workflows to complete required validation.

Adds a new Azure.Mcp.Tools.IoTOperations toolset exposing two read-only
commands over Microsoft.IoTOperations/instances via Azure Resource Graph:

- azmcp iotoperations instance list (subscription, optional resource-group)
- azmcp iotoperations instance get (subscription, resource-group, instance)

Includes options, service, models, JSON context, setup registration,
unit tests, recorded live-test scaffolding, test-resources Bicep, and
documentation (azmcp-commands, e2e prompts, README, changelog,
consolidated-tools, CODEOWNERS, cspell).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

Comment thread .github/CODEOWNERS Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Azure IoT Operations toolset (Azure.Mcp.Tools.IoTOperations, area iotoperations) to the Azure MCP Server, providing read-only discovery of Microsoft.IoTOperations/instances via Azure Resource Graph.

Changes:

  • Introduces azmcp iotoperations instance list and azmcp iotoperations instance get commands (two-generic SubscriptionCommand<TOptions, TResult> pattern).
  • Adds toolset wiring: DI setup, JSON source-gen context (AOT), server area registration, and consolidated tool mapping.
  • Adds unit tests plus recorded/live-test scaffolding and updates docs/metadata (command reference, prompts, README, changelog, CODEOWNERS, spelling).

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources.bicep Test RBAC assignment template + outputs for IoTOperations test infra.
tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources-post.ps1 Post-deploy script for test resource deployment.
tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/IoTOperationsCommandTests.cs Recorded/live tool E2E tests for list/get.
tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/Instance/InstanceListCommandTests.cs Unit tests for InstanceListCommand.
tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/Instance/InstanceGetCommandTests.cs Unit tests for InstanceGetCommand.
tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/Azure.Mcp.Tools.IoTOperations.Tests.csproj Test project definition + live/unit test flags.
tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/assets.json Enables recorded test infrastructure (assets repo metadata).
tools/Azure.Mcp.Tools.IoTOperations/src/Services/Models/IoTOperationsInstanceProperties.cs Resource Graph “properties” model for deserialization.
tools/Azure.Mcp.Tools.IoTOperations/src/Services/Models/IoTOperationsInstanceData.cs Resource Graph instance data model + source-gen deserialization entrypoint.
tools/Azure.Mcp.Tools.IoTOperations/src/Services/IoTOperationsService.cs Resource Graph query implementation for list/get.
tools/Azure.Mcp.Tools.IoTOperations/src/Services/IIoTOperationsService.cs Service contract for list/get operations.
tools/Azure.Mcp.Tools.IoTOperations/src/Options/Instance/InstanceListOptions.cs CLI/tool options for instance listing.
tools/Azure.Mcp.Tools.IoTOperations/src/Options/Instance/InstanceGetOptions.cs CLI/tool options for instance get.
tools/Azure.Mcp.Tools.IoTOperations/src/Models/IoTOperationsInstanceInfo.cs Lightweight output model for commands.
tools/Azure.Mcp.Tools.IoTOperations/src/IoTOperationsSetup.cs Area setup: DI + command group registration.
tools/Azure.Mcp.Tools.IoTOperations/src/Commands/IoTOperationsJsonContext.cs STJ source-gen context registrations for AOT-safe serialization.
tools/Azure.Mcp.Tools.IoTOperations/src/Commands/Instance/InstanceListCommand.cs Implements iotoperations instance list command.
tools/Azure.Mcp.Tools.IoTOperations/src/Commands/Instance/InstanceGetCommand.cs Implements iotoperations instance get command + instance name validation.
tools/Azure.Mcp.Tools.IoTOperations/src/Azure.Mcp.Tools.IoTOperations.csproj New toolset project definition and dependencies.
tools/Azure.Mcp.Tools.IoTOperations/src/AssemblyInfo.cs Adds InternalsVisibleTo for the toolset test assembly.
servers/Azure.Mcp.Server/src/Resources/consolidated-tools.json Adds mapped “get_azure_iot_operations” tool entry.
servers/Azure.Mcp.Server/src/Program.cs Registers the IoTOperations area with the server.
servers/Azure.Mcp.Server/README.md Adds IoTOperations example prompts + service area list entry.
servers/Azure.Mcp.Server/docs/e2eTestPrompts.md Adds E2E prompts for the new tool(s).
servers/Azure.Mcp.Server/docs/azmcp-commands.md Adds command reference section for IoTOperations.
servers/Azure.Mcp.Server/CHANGELOG.md Notes new IoTOperations toolset feature addition.
servers/Azure.Mcp.Server/Azure.Mcp.Server.slnx Adds toolset projects to the server solution.
Microsoft.Mcp.slnx Adds toolset projects to the repo-wide solution.
.vscode/cspell.json Adds iotoperations to spelling allowlist.
.github/CODEOWNERS Adds ownership/labels for the new toolset path.
Comments suppressed due to low confidence (2)

tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/IoTOperationsCommandTests.cs:31

  • This test inherits from RecordedCommandTestsBase but the toolset currently has no checked-in session recordings. In Playback/Record modes this will fail when starting playback/record. If recordings aren't available yet, mark this test as [LiveTestOnly].
    [Fact]

tools/Azure.Mcp.Tools.IoTOperations/tests/Azure.Mcp.Tools.IoTOperations.Tests/IoTOperationsCommandTests.cs:64

  • This test inherits from RecordedCommandTestsBase but there are no session recordings in the repo for Playback/Record. Marking it [LiveTestOnly] avoids failures in recorded/playback test runs until recordings can be committed.
    [Fact]

Comment on lines +17 to +21
// NOTE: An Azure IoT Operations instance (Microsoft.IoTOperations/instances) is a projection of
// a deployment onto an Azure Arc-enabled Kubernetes cluster and cannot be provisioned directly
// via a standalone Bicep/ARM template. The list/get commands query Azure Resource Graph, so the
// only infrastructure required for the recorded tests is read access to the target subscription.
// This template assigns the Reader role to the test application at the resource group scope.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in aacb45df5: clarified the comment to accurately describe the Reader assignment. It now notes that instance get and instance list --resource-group query at resource group scope (covered by this RG-scoped Reader), while subscription-wide instance list additionally needs a subscription-scoped Reader assignment granted by the test harness.

Comment thread servers/Azure.Mcp.Server/docs/azmcp-commands.md Outdated
@byronjinmsft

Copy link
Copy Markdown
Author

You can run dotnet run --project servers/Azure.Mcp.Server/src -- iotoperations instance list --subscription <SUB> to test functionality on your own sub.

…icep RBAC scope, fix docs header

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
_ => base.GetStatusCode(ex)
};

private static bool IsValidInstanceName(string value)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Copilot Let's not do validation on the instance name. This logic may change as the typespec change and we don't want that cross repo dependency.
Simply if the name is invalid and won't come up with any results, then return no results.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Updated in 74d5c5c: removed instance-name format validation from instance get and adjusted tests so name format is not command-validated.

@byronjinmsft

Copy link
Copy Markdown
Author

Copilot what is the function of the files tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources.bicep and tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources-post.ps1 ? Where are these files referenced?

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Copilot what is the function of the files tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources.bicep and tools/Azure.Mcp.Tools.IoTOperations/tests/test-resources-post.ps1 ? Where are these files...

test-resources.bicep defines the Azure live-test infrastructure for this toolset (here, RG-scoped Reader assignment + outputs used by tests). test-resources-post.ps1 is the optional post-deployment hook that runs after template deployment (currently just logs outputs).

They’re wired through the shared test-resource harness:

  • eng/pipelines/templates/jobs/live-test.yml passes TestResourcesDirectory into deploy-test-resources.
  • eng/common/TestResources/deploy-test-resources.yml calls eng/common/TestResources/New-TestResources.ps1 -TestResourcesDirectory ....
  • eng/common/TestResources/New-TestResources.ps1 discovers test-resources.bicep in that directory and executes test-resources-post.ps1 if present.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants