-
Notifications
You must be signed in to change notification settings - Fork 28
Kick off seqcli skills install and seqcli mcp run
#458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
4d4940c
Mark SeqCli.EndToEnd as a non-test project so that it's not picked up…
184952b
seqcli skills install command
b3a4062
More skill WIP
f1784c6
More skill WIP
588230d
More skill and tool WIP
229bee3
More skill and tool WIP
f22d041
More fixes
9cb90ee
More WIP
1b47da1
Minor tweaks
aaaeb41
Remove .claude and add to .gitignore
2229605
Minimal tests for identifier generation
76a6cec
OTel property name accessor gotcha
c19d839
More gotchas; these are a useful catalog of papercuts we might actual…
9f131b9
Get the (implemented) integration tests running.
8ca84d5
Added a simple MCP end-to-end test case.
ae29b25
Add tests for SeqSyntaxFormatter.
093bccd
A first cut `mcp install` command.
c2eb030
Tidy up.
4d4f68f
Increase test coverage for McpSession.
cb5ed21
Add seq_new_session endpoint to clear state.
3380f5f
Factor some orthogonal API helpers out of the (crowded) tool class
4915842
Skill updates, add `mcp install` support for Qwen Code.
aa344ae
Use the example trace id consistently
6dd69db
More skill tweaks
40a1ae4
More skill tweaks
0e2de67
Update SKILL.md to remove deprecated operators
nblumhardt 9cf0288
Review feedback, reduce SKILL.md token count by dropping out table/gr…
nblumhardt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -292,3 +292,7 @@ __pycache__/ | |
| global.json | ||
|
|
||
| .DS_Store/ | ||
|
|
||
| .claude/ | ||
| .qwen/ | ||
| .agents/ | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Copyright © Datalust and contributors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| using System.Threading.Tasks; | ||
| using SeqCli.Mcp; | ||
| using SeqCli.Util; | ||
|
|
||
| namespace SeqCli.Cli.Commands.Mcp; | ||
|
|
||
| [Command("mcp", "install", "Install or update the Seq MCP server for an agent", | ||
| Example = "seqcli mcp install --global --agent claude")] | ||
| class InstallCommand : Command | ||
| { | ||
| bool _global; | ||
| string? _agent; | ||
| string? _profile; | ||
|
|
||
| public InstallCommand() | ||
| { | ||
| Options.Add( | ||
| "g|global", | ||
| "Install for the current user globally; the default is to install into the current project directory", | ||
| _ => _global = true); | ||
|
|
||
| Options.Add( | ||
| "a=|agent=", | ||
| "The agent name to install the MCP server for; the default is the generic name `agents`", | ||
| t => _agent = ArgumentString.Normalize(t)); | ||
|
|
||
| Options.Add( | ||
| "profile=", | ||
| "A connection profile to use; by default the `connection.serverUrl` and `connection.apiKey` config values will be used", | ||
| v => _profile = ArgumentString.Normalize(v)); | ||
| } | ||
|
|
||
| protected override Task<int> Run() | ||
| { | ||
| McpServerInstaller.Install(_agent?.ToLowerInvariant(), _global, _profile); | ||
| return Task.FromResult(0); | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // Copyright © Datalust and contributors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| using System; | ||
| using System.Threading.Tasks; | ||
| using Autofac.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Hosting; | ||
| using SeqCli.Api; | ||
| using SeqCli.Cli.Features; | ||
| using SeqCli.Config; | ||
| using SeqCli.Mcp; | ||
| using SeqCli.Mcp.Tools.Search; | ||
| using Serilog; | ||
|
|
||
| namespace SeqCli.Cli.Commands.Mcp; | ||
|
|
||
| [Command("mcp", "run", "Run an MCP (Model Context Protocol) server on STDIO")] | ||
| class RunCommand: Command | ||
| { | ||
| readonly ConnectionFeature _connection; | ||
| readonly StoragePathFeature _storagePath; | ||
| bool _debug; | ||
|
|
||
| public RunCommand() | ||
| { | ||
| _connection = Enable<ConnectionFeature>(); | ||
| _storagePath = Enable<StoragePathFeature>(); | ||
| Options.Add("debug", "Write diagnostic messages from the MCP server back through the connection", | ||
| _ => _debug = true); | ||
| } | ||
|
|
||
| protected override async Task<int> Run() | ||
| { | ||
| var config = RuntimeConfigurationLoader.Load(_storagePath); | ||
|
|
||
| if (_debug) | ||
| { | ||
| Log.Logger = new LoggerConfiguration() | ||
| .Enrich.WithProperty("Application", "seqcli mcp run") | ||
| .WriteTo.Seq(config.Connection.ServerUrl, apiKey: config.Connection.DecodeApiKey(config.Encryption.DataProtector())) | ||
| .CreateLogger(); | ||
|
|
||
| Log.Information("Seq MCP server starting up"); | ||
| } | ||
|
|
||
| try | ||
| { | ||
| var builder = Host.CreateApplicationBuilder(); | ||
| builder.ConfigureContainer(new AutofacServiceProviderFactory()); | ||
| builder.Services.AddSerilog(); | ||
| builder.Services.AddSingleton(_ => SeqConnectionFactory.Connect(_connection, config)); | ||
| builder.Services.AddSingleton<McpSession>(); | ||
| builder.Services | ||
| .AddMcpServer() | ||
| .WithStdioServerTransport() | ||
| .WithTools([ | ||
| typeof(SearchAndQueryToolType) | ||
| ]); | ||
|
|
||
| await builder.Build().RunAsync(); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Log.Fatal(ex, "Unhandled exception"); | ||
| return 1; | ||
| } | ||
| finally | ||
| { | ||
| await Log.CloseAndFlushAsync(); | ||
| } | ||
| return 0; | ||
| } | ||
| } |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // Copyright © Datalust and contributors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| using System.Threading.Tasks; | ||
| using SeqCli.Skills; | ||
| using SeqCli.Util; | ||
|
|
||
| namespace SeqCli.Cli.Commands.Skills; | ||
|
|
||
| [Command("skills", "install", "Install or update Seq agent skills", | ||
| Example = "seqcli skills install --global --agent claude")] | ||
| class InstallCommand : Command | ||
| { | ||
| bool _global; | ||
| string? _agent; | ||
|
|
||
| public InstallCommand() | ||
| { | ||
| Options.Add( | ||
| "g|global", | ||
| "Install skills globally, to `~/.{agent}/skills`; the default is to install locally, in `./{agent}/skills`", | ||
| _ => _global = true); | ||
|
|
||
| Options.Add( | ||
| "a=|agent=", | ||
| "The agent name to install skills for; the default is the generic name `agents`", | ||
| t => _agent = ArgumentString.Normalize(t)); | ||
| } | ||
|
|
||
| protected override Task<int> Run() | ||
| { | ||
| SkillInstaller.Install(_agent?.ToLowerInvariant(), _global); | ||
| return Task.FromResult(0); | ||
| } | ||
| } |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // Copyright © Datalust and contributors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| using System; | ||
| using System.Globalization; | ||
| using System.IO; | ||
| using System.Net.Http; | ||
| using System.Text; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Newtonsoft.Json; | ||
| using Seq.Api; | ||
| using Seq.Api.Model.Data; | ||
|
|
||
| namespace SeqCli.Mcp.Data; | ||
|
|
||
| public static class DataResourceGroupHelper | ||
| { | ||
| static readonly JsonSerializer Serializer = JsonSerializer.Create(new JsonSerializerSettings | ||
| { | ||
| DateParseHandling = DateParseHandling.None, | ||
| Culture = CultureInfo.InvariantCulture, | ||
| FloatParseHandling = FloatParseHandling.Decimal, | ||
| }); | ||
|
|
||
| public static async Task<QueryResultPart> QueryPreserveErrorResponsesAsync(SeqConnection connection, string query, CancellationToken cancellationToken = default) | ||
| { | ||
| // Unfortunately, the `Data.QueryAsync()` API throws when the server 400s, making this case tricky. Suggests | ||
| // we should make some API client improvements... | ||
| var request = new HttpRequestMessage | ||
| { | ||
| RequestUri = new Uri("api/data?q=" + Uri.EscapeDataString(query), UriKind.Relative), | ||
| Method = HttpMethod.Post, Content = new StringContent("{}", new UTF8Encoding(false), "application/json") | ||
| }; | ||
| var response = await connection.Client.HttpClient.SendAsync(request, cancellationToken); | ||
| return Serializer.Deserialize<QueryResultPart>( | ||
| new JsonTextReader(new StreamReader(await response.Content.ReadAsStreamAsync(cancellationToken))))!; | ||
| } | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| // Copyright © Datalust and contributors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Seq.Api.Model.Data; | ||
|
|
||
| namespace SeqCli.Mcp.Data; | ||
|
|
||
| public static class QueryResultHelper | ||
| { | ||
| /// <summary> | ||
| /// Convert <paramref name="result"/> into a flat table. Seq reduces browser-side processing and optimizes | ||
| /// response sizes by constructing result trees for some grouped/time-sliced query results. | ||
| /// </summary> | ||
| public static void Flatten(QueryResultPart result, Action<IEnumerable<object?>> writeRow) | ||
|
nblumhardt marked this conversation as resolved.
|
||
| { | ||
| if (result.Error != null) | ||
| return; | ||
|
|
||
| if (result.Rows != null) | ||
| { | ||
| writeRow(result.Columns!); | ||
| foreach (var row in result.Rows) | ||
| { | ||
| writeRow(row); | ||
| } | ||
| } | ||
| else if (result.Slices != null) | ||
| { | ||
| writeRow(new object[] {"time"}.Concat(result.Columns!)); | ||
|
|
||
| var empty = result.Columns!.Select(_ => "").ToArray(); | ||
| foreach (var slice in result.Slices) | ||
| { | ||
| var any = false; | ||
| foreach (var row in slice.Rows) | ||
| { | ||
| any = true; | ||
| writeRow(new object[] { DateTimeOffset.Parse(slice.Time).UtcDateTime }.Concat(row)); | ||
| } | ||
| if (!any) | ||
| { | ||
| writeRow(new object[] { DateTimeOffset.Parse(slice.Time).UtcDateTime }.Concat(empty)); | ||
| } | ||
| } | ||
| } | ||
| else if (result.Series != null) | ||
| { | ||
| writeRow(MergeColumns(result.Columns!, result.Series.FirstOrDefault())); | ||
| foreach (var series in result.Series) | ||
| { | ||
| foreach (var slice in series.Slices) | ||
| { | ||
| var empty = result.Columns!.Take(series.Key.Length).Select(_ => (object?)null).ToArray(); | ||
| var any = false; | ||
| foreach (var row in slice.Rows) | ||
| { | ||
| any = true; | ||
| writeRow(series.Key.Concat([DateTimeOffset.Parse(slice.Time).UtcDateTime]).Concat(row)); | ||
| } | ||
| if (!any) | ||
| { | ||
| writeRow(series.Key.Concat([DateTimeOffset.Parse(slice.Time).UtcDateTime]).Concat(empty)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| throw new NotImplementedException("Query result set does not conform to any expected pattern."); | ||
| } | ||
| } | ||
|
|
||
| static IEnumerable<object> MergeColumns(string[] columns, TimeseriesPart? firstSeries) | ||
| { | ||
| if (firstSeries == null) | ||
| yield break; | ||
|
|
||
| var i = 0; | ||
| for (; i < firstSeries.Key.Length; ++i) | ||
| { | ||
| yield return columns[i]; | ||
| } | ||
|
|
||
| yield return "time"; | ||
|
|
||
| for (; i < columns.Length; ++i) | ||
| { | ||
| yield return columns[i]; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.