From 90807da61f3b5f18560ec33cec033f5052ff9fe1 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 20 Oct 2026 14:14:30 +1000 Subject: [PATCH] Include the Seq instance title in MCP server info and server instructions, so that human users and agents can distinguish between MCP servers running over multiple different Seq instances. Assisted-by: Claude:claude-opus-5-5 --- src/SeqCli/Cli/Commands/Mcp/RunCommand.cs | 42 ++++++++++++++++++- .../Mcp/McpInstanceTitleTestCase.cs | 34 +++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 test/SeqCli.EndToEnd/Mcp/McpInstanceTitleTestCase.cs diff --git a/src/SeqCli/Cli/Commands/Mcp/RunCommand.cs b/src/SeqCli/Cli/Commands/Mcp/RunCommand.cs index 109b2265..684fde51 100644 --- a/src/SeqCli/Cli/Commands/Mcp/RunCommand.cs +++ b/src/SeqCli/Cli/Commands/Mcp/RunCommand.cs @@ -13,9 +13,14 @@ // limitations under the License. using System; +using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using ModelContextProtocol.Protocol; +using Seq.Api; +using Seq.Api.Model.Settings; using SeqCli.Api; using SeqCli.Cli.Features; using SeqCli.Config; @@ -65,10 +70,25 @@ protected override async Task Run() var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true }); builder.Services.AddSerilog(); - builder.Services.AddSingleton(_ => SeqConnectionFactory.Connect(_connection, config)); + var connection = SeqConnectionFactory.Connect(_connection, config); + var instanceTitle = await TryGetInstanceTitleAsync(connection); + + builder.Services.AddSingleton(connection); builder.Services.AddSingleton(); builder.Services - .AddMcpServer() + .AddMcpServer(options => + { + var identity = instanceTitle != null ? $"Seq ({instanceTitle})" : "Seq"; + var assemblyName = Assembly.GetEntryAssembly()?.GetName(); + options.ServerInfo = new Implementation + { + Name = identity, + Version = assemblyName?.Version?.ToString() ?? "0.0.0" + }; + + if (instanceTitle != null) + options.ServerInstructions = $"Connected to {identity}"; + }) .WithStdioServerTransport() .WithTools([ typeof(SearchTools), @@ -91,4 +111,22 @@ protected override async Task Run() } return 0; } + + static async Task TryGetInstanceTitleAsync(SeqConnection connection) + { + try + { + // Not really any good options, here - we might have a 1-2 second deadline for first-turn availability, + // and 30-60 second absolute deadline. It's likely the call will be subsecond, but if we miss the first + // turn, might as well keep waiting, the tool won't work if Seq is down, anyway. + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)); + var setting = await connection.Settings.FindNamedAsync(SettingName.InstanceTitle, cts.Token); + return setting.Value is string title && !string.IsNullOrWhiteSpace(title) ? title.Trim() : null; + } + catch (Exception ex) + { + Log.Information(ex, "Could not retrieve the Seq instance title"); + return null; + } + } } \ No newline at end of file diff --git a/test/SeqCli.EndToEnd/Mcp/McpInstanceTitleTestCase.cs b/test/SeqCli.EndToEnd/Mcp/McpInstanceTitleTestCase.cs new file mode 100644 index 00000000..e221aadd --- /dev/null +++ b/test/SeqCli.EndToEnd/Mcp/McpInstanceTitleTestCase.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; +using ModelContextProtocol.Client; +using Seq.Api; +using Seq.Api.Model.Settings; +using SeqCli.EndToEnd.Support; +using Serilog; +using Xunit; + +namespace SeqCli.EndToEnd.Mcp; + +// ReSharper disable once UnusedType.Global +public class McpInstanceTitleTestCase : ICliTestCase +{ + public async Task ExecuteAsync(SeqConnection connection, ILogger logger, CliCommandRunner runner) + { + const string instanceTitle = "Test Instance"; + + var setting = await connection.Settings.FindNamedAsync(SettingName.InstanceTitle); + setting.Value = instanceTitle; + await connection.Settings.UpdateAsync(setting); + + var transport = new StdioClientTransport(new StdioClientTransportOptions + { + Name = "seqcli mcp run", + Command = "dotnet", + Arguments = [TestConfiguration.TestedBinary, "mcp", "run", $"--server={connection.Client.ServerUrl}"] + }); + + await using var client = await McpClient.CreateAsync(transport); + + Assert.EndsWith($" ({instanceTitle})", client.ServerInfo.Name); + Assert.Equal($"Connected to Seq ({instanceTitle})", client.ServerInstructions); + } +}