Skip to content

Add IoT Hub device list command#3074

Open
Iris20050110 wants to merge 1 commit into
mainfrom
iothub-devicelist
Open

Add IoT Hub device list command#3074
Iris20050110 wants to merge 1 commit into
mainfrom
iothub-devicelist

Conversation

@Iris20050110

@Iris20050110 Iris20050110 commented Jul 16, 2026

Copy link
Copy Markdown

Adds the azmcp iothub device list command to list device identities in an Azure IoT Hub device registry. Returns device metadata without authentication keys, supports --max-count (default 100, maximum 100) with a truncated flag when more devices exist, and returns a validation error when --max-count is less than 1.

Includes the Azure.Mcp.Tools.IoTHub project (device list command, options, models, services, unit and live tests) and wires it into the server registration, command docs, e2e prompts, CHANGELOG, and consolidated-tools.json.

What does this PR do?

[Provide a clear, concise description of the changes]

[Add additional context, screenshots, or information that helps reviewers]

GitHub issue number?

[Link to the GitHub issue this PR addresses]

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
    • Created a changelog entry if the change falls among the following: new feature, bug fix, UI/UX update, breaking change, or updated dependencies. Follow the changelog entry guide
  • 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 running the script ./eng/scripts/Process-PackageReadMe.ps1. See Package README
    • 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 renamed tools, follow the Tool Rename Checklist and tag the PR with the breaking-change label
    • 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 command list in servers/Azure.Mcp.Server/docs/azmcp-commands.md
    • Ran ./eng/scripts/Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • 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

Adds the `azmcp iothub device list` command to list device identities in an Azure IoT Hub device registry. Returns device metadata without authentication keys, supports --max-count (default 100, maximum 100) with a truncated flag when more devices exist, and returns a validation error when --max-count is less than 1.

Includes the Azure.Mcp.Tools.IoTHub project (device list command, options, models, services, unit and live tests) and wires it into the server registration, command docs, e2e prompts, CHANGELOG, and consolidated-tools.json.
Copilot AI review requested due to automatic review settings July 16, 2026 20:47
@Iris20050110
Iris20050110 requested review from a team as code owners July 16, 2026 20:47

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 Hub toolset and wires it into Azure MCP Server so users can run azmcp iothub device list to list device identities (metadata-only) from an IoT Hub device registry.

Changes:

  • Introduces Azure.Mcp.Tools.IoTHub with a device-list command, models, and services for IoT Hub device registry listing.
  • Adds unit + live test projects and live-test infrastructure (Bicep + post-deploy script) for the IoT Hub toolset.
  • Registers the new area/tool and updates server docs, e2e prompts, consolidated tool mapping, and changelog.

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.

Reviewed changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tools/Azure.Mcp.Tools.IoTHub/tests/test-resources.bicep Adds Bicep template to provision an IoT Hub for live tests.
tools/Azure.Mcp.Tools.IoTHub/tests/test-resources-post.ps1 Adds post-deploy script to create test devices.
tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Device/IoTHubDeviceListCommandTests.cs Adds unit tests for the device list command behavior.
tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Azure.Mcp.Tools.IoTHub.UnitTests.csproj Adds unit test project for the IoT Hub toolset.
tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.LiveTests/IoTHubCommandTests.cs Adds live test coverage for iothub_device_list.
tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.LiveTests/Azure.Mcp.Tools.IoTHub.LiveTests.csproj Adds live test project for IoT Hub toolset.
tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubService.cs Implements ARM-side IoT Hub discovery and key retrieval helpers.
tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubDeviceService.cs Implements data-plane device registry listing via IoT Hub REST + SAS auth.
tools/Azure.Mcp.Tools.IoTHub/src/Services/IIoTHubService.cs Adds IoT Hub service contract (hub lookup + keys).
tools/Azure.Mcp.Tools.IoTHub/src/Services/IIoTHubDeviceService.cs Adds device registry service contract (list devices).
tools/Azure.Mcp.Tools.IoTHub/src/Options/IoTHubOptionDefinitions.cs Defines CLI options for IoT Hub commands (name, max-count).
tools/Azure.Mcp.Tools.IoTHub/src/Options/Device/IoTHubDeviceListOptions.cs Adds options POCO for the device list command.
tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubKey.cs Adds model to represent IoT Hub SAS policies/keys (internal plumbing).
tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubDescription.cs Adds model for IoT Hub metadata returned from ARM query.
tools/Azure.Mcp.Tools.IoTHub/src/Models/DeviceListResult.cs Adds response model (devices + truncated flag).
tools/Azure.Mcp.Tools.IoTHub/src/Models/DeviceIdentity.cs Adds device identity DTO (intentionally excluding auth keys).
tools/Azure.Mcp.Tools.IoTHub/src/IoTHubSetup.cs Registers IoT Hub services + commands into the area system.
tools/Azure.Mcp.Tools.IoTHub/src/GlobalUsings.cs Adds global usings for the new toolset.
tools/Azure.Mcp.Tools.IoTHub/src/Commands/IoTHubJsonContext.cs Adds STJ source-gen context for IoT Hub models (AOT-safe).
tools/Azure.Mcp.Tools.IoTHub/src/Commands/Device/IoTHubDeviceListCommand.cs Adds azmcp iothub device list command implementation.
tools/Azure.Mcp.Tools.IoTHub/src/Commands/BaseIoTHubCommand.cs Adds IoT Hub command base to share common subscription/resource-group options.
tools/Azure.Mcp.Tools.IoTHub/src/Azure.Mcp.Tools.IoTHub.csproj Adds new toolset project and dependencies.
tools/Azure.Mcp.Tools.IoTHub/src/AssemblyInfo.cs Adds InternalsVisibleTo for new test projects.
servers/Azure.Mcp.Server/src/Program.cs Registers the new IoT Hub area and adjusts console logging behavior.
servers/Azure.Mcp.Server/README.md Adds IoT Hub to the supported services list.
servers/Azure.Mcp.Server/docs/e2eTestPrompts.md Adds e2e prompts for IoT Hub device list tool.
servers/Azure.Mcp.Server/docs/azmcp-commands.md Documents the new azmcp iothub device list command.
servers/Azure.Mcp.Server/CHANGELOG.md Adds changelog entry for the new IoT Hub command.
package.json Adds root Node dependency on @azure/mcp.
package-lock.json Locks root Node dependency graph for @azure/mcp.
dotnet-tools.json Adds a dotnet tool manifest with the azmcp tool.
Directory.Packages.props Adds IoTHub ARM SDK package version and bumps OTel exporter version.
core/Azure.Mcp.Core/src/Services/Http/HttpClientService.cs Redirects debug output to stderr to avoid corrupting stdout JSON.
core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json Adds consolidated mapping entry for the new IoT Hub device list tool.
.vscode/settings.json Adds VS Code MCP sampling config for a local IoT Hub-only server profile.
.vscode/mcp.json Adds a local MCP server config to run Azure.Mcp.Server filtered to iothub.
.github/CODEOWNERS Adds CODEOWNERS entries for the new IoT Hub toolset.

Comment on lines +19 to +33
public class IoTHubDeviceService(
IIoTHubService ioTHubService,
IAzureTokenCredentialProvider credentialProvider,
IHttpClientService httpClientService,
ITenantService tenantService,
ICacheService cacheService,
ILogger<IoTHubDeviceService> logger)
: BaseAzureService(tenantService), IIoTHubDeviceService
{
private readonly IIoTHubService _ioTHubService = ioTHubService ?? throw new ArgumentNullException(nameof(ioTHubService));
private readonly IAzureTokenCredentialProvider _credentialProvider = credentialProvider ?? throw new ArgumentNullException(nameof(credentialProvider));
private readonly IHttpClientService _httpClientService = httpClientService ?? throw new ArgumentNullException(nameof(httpClientService));
private readonly ITenantService _tenantService = tenantService ?? throw new ArgumentNullException(nameof(tenantService));
private readonly ICacheService _cacheService = cacheService ?? throw new ArgumentNullException(nameof(cacheService));
private readonly ILogger<IoTHubDeviceService> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
Comment on lines +7 to +13
using Azure.Mcp.Core.Options;
using Azure.Mcp.Core.Services.Azure;
using Azure.Mcp.Core.Services.Azure.Authentication;
using Azure.Mcp.Core.Services.Azure.Tenant;
using Azure.Mcp.Core.Services.Caching;
using Azure.Mcp.Core.Services.Http;
using Azure.Mcp.Tools.IoTHub.Commands;
Comment on lines +4 to +23
using System.Text.Json;
using Azure.Mcp.Core.Options;
using Azure.Mcp.Core.Services.Azure;
using Azure.Mcp.Core.Services.Azure.Subscription;
using Azure.Mcp.Core.Services.Azure.Tenant;
using Azure.Mcp.Tools.IoTHub.Models;
using Azure.ResourceManager.IotHub;
using Microsoft.Extensions.Logging;

namespace Azure.Mcp.Tools.IoTHub.Services;

public class IoTHubService(
ISubscriptionService subscriptionService,
ITenantService tenantService,
ILogger<IoTHubService> logger)
: BaseAzureResourceService(subscriptionService, tenantService), IIoTHubService
{
private readonly ISubscriptionService _subscriptionService = subscriptionService;
private readonly ILogger<IoTHubService> _logger = logger ?? throw new ArgumentNullException(nameof(logger));

Comment on lines +4 to +17
using System.CommandLine;
using System.Net;
using Azure.Mcp.Core.Commands;
using Azure.Mcp.Core.Commands.Subscription;
using Azure.Mcp.Core.Extensions;
using Azure.Mcp.Core.Models.Command;
using Azure.Mcp.Core.Models.Option;
using Azure.Mcp.Core.Options;
using Azure.Mcp.Tools.IoTHub.Options;
using Azure.Mcp.Tools.IoTHub.Options.Device;
using Azure.Mcp.Tools.IoTHub.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Mcp.Core.Models.Option;

Comment on lines +25 to +30
public override string Description => "List devices in an IoT Hub device registry. Returns each device identity metadata without authentication keys. " +
"This is the preferred command for listing devices, including when the user asks for a small, specific number of devices (e.g. 'list 2 devices'); set --max-count to the requested number. " +
"Use --max-count to set the page size (default 100, maximum 100). Values greater than 100 are capped at 100, so one call returns at most 100 devices. " +
"For natural-language user requests to list all devices, the rest of the devices, more than 100 devices, or any large device set, use the 'iothub query run' command (MCP tool iothub_query_run) with a compact projection instead of this list command, but still return only one page and do not loop for additional pages. " +
"For normal list/show responses, present a compact summary with deviceId, status, connectionState, and any user-requested tags or fields. Do not include full raw JSON unless the user explicitly asks for raw device identity metadata. " +
"Hub names/IDs are case-sensitive and must match exactly.";
public sealed class IoTHubDeviceListCommand(IIoTHubDeviceService service, ILogger<IoTHubDeviceListCommand> logger)
: BaseIoTHubCommand<IoTHubDeviceListOptions>
{
public override string Id => "iothub-device-list";
Comment on lines +218 to +224
Assert.Contains("more than 100 devices", _command.Description, StringComparison.Ordinal);
Assert.Contains("iothub query run", _command.Description, StringComparison.Ordinal);
Assert.Contains("iothub_query_run", _command.Description, StringComparison.Ordinal);
Assert.Contains("compact projection", _command.Description, StringComparison.Ordinal);
Assert.Contains("compact summary", _command.Description, StringComparison.Ordinal);
Assert.Contains("return only one page", _command.Description, StringComparison.Ordinal);
Assert.Contains("do not loop", _command.Description, StringComparison.Ordinal);
Comment on lines +11 to +13
# Create test devices for device registry tests
$testDevices = @('test-device-1', 'test-device-2', 'test-device-3')

Comment thread .vscode/settings.json
Comment on lines +2 to +6
"chat.mcp.serverSampling": {
"mcp-pr/.vscode/mcp.json: iris-local-mcp": {
"allowedDuringChat": true
}
}
@Iris20050110

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="Microsoft"

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.

2 participants