Skip to content

Add MCP Apps UI support with SDK dashboard#413

Merged
jongalloway merged 6 commits intomainfrom
feature/mcp-apps-ui
Mar 21, 2026
Merged

Add MCP Apps UI support with SDK dashboard#413
jongalloway merged 6 commits intomainfrom
feature/mcp-apps-ui

Conversation

@jongalloway
Copy link
Copy Markdown
Owner

Implement MCP Apps (SEP-1865) support for the DotnetSdk tool, rendering an interactive HTML dashboard inline in VS Code chat.

  • Add McpAppsResources with ui:// resource returning themed HTML dashboard
  • Add both modern nested and legacy flat McpMeta keys on DotnetSdk tool (VS Code requires the legacy 'ui/resourceUri' flat key)
  • Register McpAppsResources in Program.cs
  • Add wire format tests validating both _meta key formats
  • Add doc/mcp-apps.md implementation guide

Implement MCP Apps (SEP-1865) support for the DotnetSdk tool, rendering
an interactive HTML dashboard inline in VS Code chat.

- Add McpAppsResources with ui:// resource returning themed HTML dashboard
- Add both modern nested and legacy flat McpMeta keys on DotnetSdk tool
  (VS Code requires the legacy 'ui/resourceUri' flat key)
- Register McpAppsResources in Program.cs
- Add wire format tests validating both _meta key formats
- Add doc/mcp-apps.md implementation guide
@jongalloway
Copy link
Copy Markdown
Owner Author

@copilot address comments

… catch clause

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Agent-Logs-Url: https://github.com/jongalloway/dotnet-mcp/sessions/09222802-7404-459d-a12c-088bc75feba3
Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 21, 2026

@copilot address comments

Addressed both GitHub Advanced Security alerts in DotNetCliTools.Sdk.Consolidated.cs (commit 863abe4):

  1. Useless assignment: Removed the unused runtimeContent local variable — the BuildListRuntimesStructuredContent() result was assigned but never read, since the code directly parses runtimeTextResult below.
  2. Generic catch clause: Changed bare catch to catch (Exception) to be more specific.

CodeQL now reports 0 alerts.

Comment on lines +615 to +619
catch (Exception)
{
// If runtime fetch fails, return SDKs only — dashboard will show what it can
return sdkContent;
}

Check notice

Code scanning / CodeQL

Generic catch clause Note

Generic catch clause.

Copilot Autofix

AI 7 days ago

To fix the problem, we should replace the generic catch (Exception) with more specific exception handlers that reflect the likely failure modes of invoking and parsing dotnet --list-runtimes. Specifically, failures may come from the process execution (I/O, invalid operation, Task cancellation) or from string/array operations while parsing (argument/out-of-range/format). We can group these into a small, explicit set of exception types and still preserve the current behavior: on these known failures, return sdkContent so the dashboard can show SDKs only.

The best minimal-change fix is:

  • Replace catch (Exception) with catch clauses for a chosen set of expected exceptions, all of which perform the same fallback to sdkContent.
  • Optionally add a final catch for OperationCanceledException if cancellation should also result in a graceful fallback; if cancellation should propagate, we omit that.
  • Do not alter imports or method signatures; only adjust the catch section of BuildListSdksWithRuntimesStructuredContentAsync.

Concretely, in DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs, around lines 578–619:

  • Replace the single catch (Exception) block with a grouped catch that handles common runtime and parsing errors, e.g. IOException, InvalidOperationException, FormatException, ArgumentException, and IndexOutOfRangeException, all with identical bodies returning sdkContent. This narrows the catch surface while keeping the observable behavior for these failure types unchanged.
Suggested changeset 1
DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs b/DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs
--- a/DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs
+++ b/DotNetMcp/Tools/Sdk/DotNetCliTools.Sdk.Consolidated.cs
@@ -612,11 +612,31 @@
 
             return new { sdks, runtimes };
         }
-        catch (Exception)
+        catch (System.IO.IOException)
         {
-            // If runtime fetch fails, return SDKs only — dashboard will show what it can
+            // If runtime fetch fails due to I/O issues, return SDKs only — dashboard will show what it can
             return sdkContent;
         }
+        catch (InvalidOperationException)
+        {
+            // If runtime fetch fails due to process invocation issues, return SDKs only
+            return sdkContent;
+        }
+        catch (FormatException)
+        {
+            // If runtime output cannot be parsed as expected, return SDKs only
+            return sdkContent;
+        }
+        catch (ArgumentException)
+        {
+            // If runtime parsing encounters bad arguments (e.g., Split), return SDKs only
+            return sdkContent;
+        }
+        catch (IndexOutOfRangeException)
+        {
+            // If runtime parsing encounters unexpected field counts, return SDKs only
+            return sdkContent;
+        }
     }
 
     private static object? BuildListRuntimesStructuredContent(string textResult)
EOF
@@ -612,11 +612,31 @@

return new { sdks, runtimes };
}
catch (Exception)
catch (System.IO.IOException)
{
// If runtime fetch fails, return SDKs only — dashboard will show what it can
// If runtime fetch fails due to I/O issues, return SDKs only — dashboard will show what it can
return sdkContent;
}
catch (InvalidOperationException)
{
// If runtime fetch fails due to process invocation issues, return SDKs only
return sdkContent;
}
catch (FormatException)
{
// If runtime output cannot be parsed as expected, return SDKs only
return sdkContent;
}
catch (ArgumentException)
{
// If runtime parsing encounters bad arguments (e.g., Split), return SDKs only
return sdkContent;
}
catch (IndexOutOfRangeException)
{
// If runtime parsing encounters unexpected field counts, return SDKs only
return sdkContent;
}
}

private static object? BuildListRuntimesStructuredContent(string textResult)
Copilot is powered by AI and may make mistakes. Always verify output.
@jongalloway jongalloway merged commit 7071b14 into main Mar 21, 2026
4 checks passed
@jongalloway jongalloway deleted the feature/mcp-apps-ui branch March 21, 2026 21:43
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