Add Azure IoT Hub device and query read tools - #3180
Open
Iris20050110 wants to merge 5 commits into
Open
Conversation
Adds six read-only IoT Hub commands: device show, device stats, device twin get, query run, query compile, and query discover. Includes options, IIoTHubDeviceService/IoTHubDeviceService, query compiler and field discoverer, models, JSON context, setup registration, GetIoTHubKeys on IIoTHubService, package references, command docs, e2e prompts, consolidated tool mapping, changelog entry, and unit tests.
Iris20050110
requested review from
JasonYeMSFT,
alzimmermsft,
conniey,
jairmyree,
saikoumudi,
tmeschter and
xirzec
July 29, 2026 17:18
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a new set of read-only Azure IoT Hub “device registry + query” tools to the Azure MCP server, including data-plane calls for device identity/twin/statistics and a local query compile/discover workflow to help agents construct valid IoT Hub queries.
Changes:
- Added IoT Hub device registry commands (show, stats, twin get) and IoT Hub query commands (run, compile, discover), plus DI registration and JSON source-gen updates.
- Introduced a new
IIoTHubDeviceService/IoTHubDeviceServicethat resolves hub hostname + SAS keys via ARM, then calls IoT Hub REST endpoints for device/twin/query/statistics. - Updated documentation, consolidated tool mapping, changelog entry, and added unit tests for the new commands.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Query/IoTHubQueryRunCommandTests.cs | Adds unit tests for the query run command behavior and validation. |
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Query/IoTHubQueryDiscoverCommandTests.cs | Adds unit tests for query field discovery command behavior and error handling. |
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Query/IoTHubQueryCompileCommandTests.cs | Adds unit tests for compiling structured filters into IoT Hub query strings. |
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Device/IoTHubDeviceTwinGetCommandTests.cs | Adds unit tests for retrieving device twins from IoT Hub. |
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Device/IoTHubDeviceStatisticsCommandTests.cs | Adds unit tests for device registry statistics retrieval. |
| tools/Azure.Mcp.Tools.IoTHub/tests/Azure.Mcp.Tools.IoTHub.UnitTests/Device/IoTHubDeviceShowCommandTests.cs | Adds unit tests for device identity retrieval. |
| tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubService.cs | Extends ARM-based IoT Hub service to also list IoT Hub SAS keys. |
| tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubDeviceService.cs | Implements data-plane IoT Hub REST calls (device/twin/query/stats) with caching + timeouts. |
| tools/Azure.Mcp.Tools.IoTHub/src/Services/IIoTHubService.cs | Adds a service contract for retrieving IoT Hub SAS keys. |
| tools/Azure.Mcp.Tools.IoTHub/src/Services/IIoTHubDeviceService.cs | Introduces new service contract for device registry and query operations. |
| tools/Azure.Mcp.Tools.IoTHub/src/Query/IoTHubQueryFieldDiscoverer.cs | Adds logic to discover queryable fields/types/examples from sampled twin documents. |
| tools/Azure.Mcp.Tools.IoTHub/src/Query/IoTHubQueryCompiler.cs | Adds a structured predicate compiler to generate valid IoT Hub query strings. |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Query/IoTHubQueryRunOptions.cs | Adds options for running queries (query, max count, continuation token, hub, RG, etc.). |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Query/IoTHubQueryDiscoverOptions.cs | Adds options for field discovery sampling (hub, RG, max count, etc.). |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Query/IoTHubQueryCompileOptions.cs | Adds options for local query compilation from JSON filters (+ optional discovered fields). |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Device/IoTHubDeviceTwinGetOptions.cs | Adds options for device twin get (device id, hub, RG, subscription/tenant). |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Device/IoTHubDeviceStatisticsOptions.cs | Adds options for device statistics (hub, RG, subscription/tenant). |
| tools/Azure.Mcp.Tools.IoTHub/src/Options/Device/IoTHubDeviceShowOptions.cs | Adds options for device show (device id, hub, RG, subscription/tenant). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/RegistryStatistics.cs | Adds model for IoT Hub registry statistics response. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/QueryPredicate.cs | Adds structured predicate model for query compilation. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/QueryDiscoveredFields.cs | Adds model for discovered fields grouped by scope. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/QueryDiscoveredField.cs | Adds model for a single discovered field (path/type/examples). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/QueryCompileRequest.cs | Adds model representing a full compile request (filters/from/top/logical op/discovered fields). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/PredicateScope.cs | Adds enum for predicate scope (device/tags/desired/reported). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/PredicateOperator.cs | Adds enum for predicate operators. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubQueryRunResult.cs | Adds result model for query run (items/count/hasMore/continuationToken/message). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubQueryRequest.cs | Adds request model for IoT Hub query endpoint. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubQueryPage.cs | Adds internal page model for query results + continuation. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubQueryDiscoverResult.cs | Adds result model for discovered fields + sampling metadata. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubQueryCompileResult.cs | Adds result model for compiled query + maxCount hint. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubKey.cs | Adds internal model for IoT Hub SAS keys retrieved from ARM. |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/IoTHubDeviceCountStats.cs | Adds model for device-count metric stats (snapshot/peak/average). |
| tools/Azure.Mcp.Tools.IoTHub/src/Models/DeviceTwin.cs | Adds models for device identity/twin (and related nested types). |
| tools/Azure.Mcp.Tools.IoTHub/src/IoTHubSetup.cs | Registers new services and command groups/subcommands for iothub device/twin/query. |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Query/IoTHubQueryRunCommand.cs | Implements query run command (single-page behavior, max-count cap, continuation token validation). |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Query/IoTHubQueryDiscoverCommand.cs | Implements query discover command (sample + field discovery). |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Query/IoTHubQueryCompileCommand.cs | Implements local query compile command (JSON parsing + validation + compilation). |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/IoTHubJsonContext.cs | Expands JSON source-generation registrations for new models/results. |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Device/IoTHubDeviceTwinGetCommand.cs | Implements device twin get command. |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Device/IoTHubDeviceStatisticsCommand.cs | Implements device statistics command. |
| tools/Azure.Mcp.Tools.IoTHub/src/Commands/Device/IoTHubDeviceShowCommand.cs | Implements device show command and its metadata/description. |
| tools/Azure.Mcp.Tools.IoTHub/src/Azure.Mcp.Tools.IoTHub.csproj | Adds the Azure.ResourceManager.IotHub package reference. |
| servers/Azure.Mcp.Server/src/Resources/consolidated-tools.json | Adds a consolidated “get_azure_iot_hub_devices” tool mapping to the new commands. |
| servers/Azure.Mcp.Server/docs/e2eTestPrompts.md | Adds e2e prompts for the new IoT Hub device and query commands. |
| servers/Azure.Mcp.Server/docs/azmcp-commands.md | Adds CLI documentation entries for the new IoT Hub commands. |
| servers/Azure.Mcp.Server/changelog-entries/Iris20050110-iothub-read-tools.yaml | Adds changelog entry describing the new IoT Hub read tools. |
| Directory.Packages.props | Adds central package version for Azure.ResourceManager.IotHub. |
Comments suppressed due to low confidence (2)
tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubDeviceService.cs:174
- HttpResponseMessage should be disposed to promptly release the underlying connection/resources. This method currently keeps the response undisposed, unlike RunQuery which disposes its response.
tools/Azure.Mcp.Tools.IoTHub/src/Services/IoTHubDeviceService.cs:297 - HttpResponseMessage should be disposed to promptly release the underlying connection/resources. This method currently keeps the response undisposed after reading, which can increase socket pressure under repeated use.
| return Task.FromResult(context.Response); | ||
| } | ||
|
|
||
| var result = new IoTHubQueryCompileResult(query, options.Top); |
Author
There was a problem hiding this comment.
Applied the cap. But instead of hardcoding 100, I promoted run's limit to a shared MaxPageSize constant and referenced it from both compile and run
Comment on lines
+108
to
+127
| public void Add(string field, string type, JsonElement example) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(field)) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (!_fields.TryGetValue(field, out var state)) | ||
| { | ||
| state = new FieldState(field); | ||
| _fields.Add(field, state); | ||
| } | ||
|
|
||
| state.Add(type, example); | ||
| } | ||
|
|
||
| public List<QueryDiscoveredField> ToFields() => _fields.Values | ||
| .Select(state => new QueryDiscoveredField(state.Field, state.Type, state.Examples)) | ||
| .ToList(); | ||
| } |
Comment on lines
+24
to
+28
| public record TwinProperties( | ||
| [property: JsonPropertyName("desired")] JsonElement? Desired, | ||
| [property: JsonPropertyName("reported")] JsonElement? Reported); | ||
|
|
||
| public record DeviceCapabilities( |
Update device show description Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Add shared IoTHubQueryLimits.MaxPageSize and reference it from query run and compile so the compile page-size hint cannot exceed the run cap - Split DeviceTwin.cs into one type per file (DeviceIdentity, DeviceAuthentication, DeviceCapabilities, TwinProperties, TwinPatch, TwinPatchProperties) - Dispose HttpResponseMessage in IoTHubDeviceService GET calls (GetDevice, GetDeviceTwin, GetDeviceStatistics) - Route discover/compile field-path validation through shared IoTHubQueryCompiler.IsValidFieldPath so discover never emits a path compile would reject; add unit tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds six read-only IoT Hub commands: device show, device stats, device twin get, query run, query compile, and query discover. Includes options, IIoTHubDeviceService/IoTHubDeviceService, query compiler and field discoverer, models, JSON context, setup registration, GetIoTHubKeys on IIoTHubService, package references, command docs, e2e prompts, consolidated tool mapping, changelog entry, and unit tests.
What does this PR do?
[Provide a clear, concise description of the changes]Azure IoT Hub to Azure MCP Server
This is a read-only tool set which includes commands device show, twin get, device stats, and query run that reads devices registry and twin APIs in Iot Hub. The documentation will be published at https://learn.microsoft.com/en-us/cli/azure/iot/hub?view=azure-cli-latest#az-iot-hub-show
[Add additional context, screenshots, or information that helps reviewers]GitHub issue number?
[Link to the GitHub issue this PR addresses]#2917
Pre-merge Checklist
servers/Azure.Mcp.Server/README.mdand/orservers/Fabric.Mcp.Server/README.mddocumentationREADME.mdchanges running the script./eng/scripts/Process-PackageReadMe.ps1. See Package READMEToolDescriptionEvaluatorand obtained a score of0.4or more and a top 3 ranking for all related test promptsconsolidated-tools.jsonbreaking-changelabelservers/Azure.Mcp.Server/docs/azmcp-commands.md./eng/scripts/Update-AzCommandsMetadata.ps1to update tool metadata inazmcp-commands.md(required for CI)servers/Azure.Mcp.Server/docs/e2eTestPrompts.mdcrypto mining, spam, data exfiltration, etc.)/azp run mcp - pullrequest - liveto run Live Test Pipeline