Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/ci/tests/.azure-devops-tests-templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ jobs:

- job: Dotnet_Tests_Validate_DevServerCli
displayName: 'DevServer CLI Tests'
timeoutInMinutes: 120
timeoutInMinutes: 25
cancelTimeoutInMinutes: 1

pool:
Expand Down
2 changes: 1 addition & 1 deletion doc/articles/get-started-ai-claude.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This guide will walk you through the setup process for getting started with Clau

```bash
claude mcp add --transport http uno https://mcp.platform.uno/v1
claude mcp add --transport stdio "uno-app" -- dnx -y uno.devserver --mcp-app
claude mcp add --transport stdio "uno-app" -- dotnet dnx -y uno.devserver --mcp-app
```

1. Open Claude and run:
Expand Down
2 changes: 1 addition & 1 deletion doc/articles/get-started-ai-codex.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This guide will walk you through the setup process for getting started with Code

```bash
codex mcp add "uno" --url "https://mcp.platform.uno/v1"
codex mcp add "uno-app" "dnx -y uno.devserver --mcp-app"
codex mcp add "uno-app" -- dotnet dnx -y uno.devserver --mcp-app
```

1. Start Codex CLI and type the following:
Expand Down
2 changes: 1 addition & 1 deletion doc/articles/get-started-ai-gh-copilot-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ To get started with GitHub Copilot CLI:
1. Type `/mcp` again and register the following (app-specific MCP):
1. Unique Name: `uno-app`
1. Server Type: Local
1. Command: `dnx -y uno.devserver --mcp-app`
1. Command: `dotnet dnx -y uno.devserver --mcp-app`
1. Skip Environment Variables and leave tools with `*`

## Next Steps
Expand Down
10 changes: 9 additions & 1 deletion src/Uno.UI.DevServer.Cli/CliManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ private async Task<int> RunMcpProxyAsync(string[] args)
_logger.LogInformation("Starting MCP Mode");

int requestedPort = 0;
bool mcpWaitToolsList = false;
var forwardedArgs = new List<string>();

for (int i = 0; i < args.Length; i++)
{
var a = args[i];
Expand All @@ -142,10 +144,16 @@ private async Task<int> RunMcpProxyAsync(string[] args)
i++; // skip value
continue; // do not forward port arguments to controller
}
else if (a == "--mcp-wait-tools-list")
{
mcpWaitToolsList = true;
continue; // do not forward mcp-specific arguments to controller
}
forwardedArgs.Add(a);
}

return await _services.GetRequiredService<McpProxy>().RunAsync(Environment.CurrentDirectory, requestedPort, forwardedArgs, CancellationToken.None);
var waitForTools = mcpWaitToolsList;
return await _services.GetRequiredService<McpProxy>().RunAsync(Environment.CurrentDirectory, requestedPort, forwardedArgs, waitForTools, CancellationToken.None);
}
catch (Exception ex)
{
Expand Down
22 changes: 21 additions & 1 deletion src/Uno.UI.DevServer.Cli/Mcp/McpProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ internal class McpProxy
private readonly ILogger<McpProxy> _logger;
private readonly DevServerMonitor _devServerMonitor;
private readonly McpClientProxy _mcpClientProxy;
private bool _waitForTools;

// Clients that don't support the list_updated notification
private static readonly string[] ClientsWithoutListUpdateSupport = ["claude-code", "codex"];

public McpProxy(ILogger<McpProxy> logger, DevServerMonitor mcpServerMonitor, McpClientProxy mcpClientProxy)
{
Expand All @@ -26,8 +30,9 @@ public McpProxy(ILogger<McpProxy> logger, DevServerMonitor mcpServerMonitor, Mcp
_mcpClientProxy = mcpClientProxy;
}

public async Task<int> RunAsync(string currentDirectory, int port, List<string> forwardedArgs, CancellationToken ct)
public async Task<int> RunAsync(string currentDirectory, int port, List<string> forwardedArgs, bool waitForTools, CancellationToken ct)
{
_waitForTools = waitForTools;
_devServerMonitor.StartMonitoring(currentDirectory, port, forwardedArgs);

try
Expand All @@ -44,6 +49,8 @@ public async Task<int> RunAsync(string currentDirectory, int port, List<string>

private async Task<int> StartMcpStdIoProxyAsync(CancellationToken ct)
{
var tcs = new TaskCompletionSource();

var builder = Host.CreateApplicationBuilder();
builder.Services
.AddMcpServer()
Expand Down Expand Up @@ -73,6 +80,17 @@ private async Task<int> StartMcpStdIoProxyAsync(CancellationToken ct)
})
.WithListToolsHandler(async (ctx, ct) =>
{
// Claude Code and Codex do not support the list_updated notification.
// To avoid tool invocation failures, we wait for the tools to be available
// after the dev server has started.
if (_waitForTools
|| ClientsWithoutListUpdateSupport.Contains(ctx.Server.ClientInfo?.Name))
{
_logger.LogTrace("Client without list_updated support detected, waiting for upstream server to start");

await tcs.Task;
}

var upstreamClient = _mcpClientProxy.UpstreamClient;

if (upstreamClient is null)
Expand Down Expand Up @@ -103,6 +121,8 @@ private async Task<int> StartMcpStdIoProxyAsync(CancellationToken ct)

_mcpClientProxy.RegisterToolListChangedCallback(async () =>
{
tcs.TrySetResult();

await host.Services.GetRequiredService<IMcpServer>().SendNotificationAsync(
NotificationMethods.ToolListChangedNotification,
new ResourceUpdatedNotificationParams()
Expand Down
15 changes: 8 additions & 7 deletions src/Uno.UI.DevServer.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ private static async Task<int> Main(string[] args)
Console.WriteLine("Usage: dnx -y uno.devserver [options] [command]");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" --help, -h Show this help message and exit");
Console.WriteLine(" --log-level, -l <level> Set the log level (Trace, Debug, Information, Warning, Error, Critical, None). Default is Information.");
Console.WriteLine(" --file-log, -fl <path> Enable file logging to the provided file path (supports {Date} token). Required path argument.");
Console.WriteLine(" --mcp Start in MCP STDIO mode");
Console.WriteLine(" --help, -h Show this help message and exit");
Console.WriteLine(" --log-level, -l <level> Set the log level (Trace, Debug, Information, Warning, Error, Critical, None). Default is Information.");
Console.WriteLine(" --file-log, -fl <path> Enable file logging to the provided file path (supports {Date} token). Required path argument.");
Console.WriteLine(" --mcp Start in MCP STDIO mode");
Console.WriteLine(" --mcp-wait-tools-list Wait for upstream server tools before responding to list_tools (MCP mode only)");
Console.WriteLine();
Console.WriteLine("Commands:");
Console.WriteLine(" start Start the DevServer for the current folder");
Console.WriteLine(" stop Stop the DevServer for the current folder");
Console.WriteLine(" list List active DevServer instances");
Console.WriteLine(" start Start the DevServer for the current folder");
Console.WriteLine(" stop Stop the DevServer for the current folder");
Console.WriteLine(" list List active DevServer instances");
Console.WriteLine();
return 0;
}
Expand Down
Loading