ワンクリックで
mcp-structured-content
Pattern for migrating MCP tools from string returns to UseStructuredContent typed returns
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Pattern for migrating MCP tools from string returns to UseStructuredContent typed returns
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Investigate .NET CI failures using the hlx CLI tool via bash. USE FOR: checking Helix job status, searching build logs, downloading test results, AzDO build timeline analysis — when MCP tools aren't loaded, when the MCP server isn't configured or fails to start, or when scripting with JSON output and jq. DO NOT USE FOR: tasks where Helix/AzDO MCP tools are already available in context (prefer ci-analysis skill when MCP server is loaded). INVOKES: bash (hlx CLI commands with --json output).
{what this skill teaches agents}
Audit pattern for comparing WorkItemSummary (list API) fields against WorkItemDetails (per-item API) after a Helix.Client SDK bump
Domain-layer normalizer + JSON-stable cache key pattern for filter types with server-side defaults and case-insensitive fields.
Strict unknown-parameter rejection for MCP tools: Stage A (UnmappedMemberHandling.Disallow) + Stage B (did-you-mean CallToolFilter).
Audit MCP/CLI tool parameter surface against underlying REST API capabilities to find silently-dropped params.
| name | mcp-structured-content |
| description | Pattern for migrating MCP tools from string returns to UseStructuredContent typed returns |
| domain | mcp-server-design |
| confidence | low |
| source | earned |
When upgrading an MCP server from manual JSON serialization (Task<string> + JsonSerializer.Serialize) to the SDK's UseStructuredContent = true feature, there is a systematic migration pattern that preserves wire compatibility while gaining auto-generated output schemas.
Define MCP result types in a separate file (e.g., McpToolResults.cs) — not inline in the tool class or co-located with service-layer models. MCP result types are a presentation concern, distinct from domain models.
Every property on result types MUST have a [JsonPropertyName("camelCaseName")] attribute matching the previous serialized output. The SDK's default naming policy may differ from the manual JsonSerializerOptions that were used before. Explicit attributes make the wire format independent of SDK configuration.
Tools that return raw text content (console logs, file contents) should NOT use UseStructuredContent. Return Task<string> directly. Structured content wrapping adds noise to text that consumers display verbatim.
Replace return JsonSerializer.Serialize(new { error = "..." }) with throw new McpException("..."). The MCP SDK translates exceptions into proper error responses. Use McpException for tool-level errors and ArgumentException for parameter validation.
Critical: Service-layer exceptions (e.g., custom domain exceptions like HelixException) are NOT automatically surfaced to MCP clients. The SDK wraps non-McpException exceptions as generic "An error occurred invoking '{tool}'" messages. Tool handlers MUST catch domain exceptions and rethrow as McpException:
try
{
var result = await _svc.DoSomethingAsync(...);
}
catch (MyDomainException ex)
{
throw new McpException(ex.Message);
}
Avoid collisions with BCL types (e.g., System.IO.FileInfo) by using domain-specific prefixes (e.g., HelixFileInfo) rather than suffixes or underscores. The C# type name doesn't affect the wire format but should still follow conventions for maintainability.
Do NOT copy all fields from service-layer records into MCP result types and keep them in sync manually. Map only the fields the MCP consumer needs. If the tool adds computed fields (like formatted duration or Helix URLs), those belong only in the MCP result type.
Relying on the SDK's default naming convention instead of explicit [JsonPropertyName] creates a hidden coupling. If the SDK changes its default or a different JsonNamingPolicy is configured, the wire format breaks silently.