Skip to content

Commit 9364d79

Browse files
committed
2 parents 8197965 + 1b7fb88 commit 9364d79

File tree

10 files changed

+498
-9
lines changed

10 files changed

+498
-9
lines changed

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
🔍 **Supercharge Your AI Coding Assistant with Deep .NET Codebase Understanding**
66

7-
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
88
[![Built with .NET](https://img.shields.io/badge/Built%20with-.NET-512BD4)](https://dotnet.microsoft.com/)
99
[![MCP Compatible](https://img.shields.io/badge/MCP-Compatible-brightgreen)](https://modelcontextprotocol.io/)
1010
[![.NET Build and Test](https://github.com/willibrandon/NetContextServer/actions/workflows/ci.yaml/badge.svg)](https://github.com/willibrandon/NetContextServer/actions/workflows/ci.yaml)
@@ -161,17 +161,22 @@ dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-di
161161
dotnet run --project src/NetContextClient/NetContextClient.csproj -- get-base-dir
162162
```
163163

164-
3. **List Projects**:
164+
3. **Get Version Information**:
165+
```bash
166+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- version
167+
```
168+
169+
4. **List Projects**:
165170
```bash
166171
dotnet run --project src/NetContextClient/NetContextClient.csproj -- list-projects-in-dir --directory "D:\YourProject\src"
167172
```
168173

169-
4. **List Source Files**:
174+
5. **List Source Files**:
170175
```bash
171176
dotnet run --project src/NetContextClient/NetContextClient.csproj -- list-source-files --project-dir "D:\YourProject\src\YourProject"
172177
```
173178

174-
5. **Analyze Packages**:
179+
6. **Analyze Packages**:
175180
```bash
176181
# Set your base directory first
177182
dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-dir --directory "path/to/your/project"
@@ -201,7 +206,7 @@ Project: MyProject.csproj
201206
└─ Microsoft.Extensions.DependencyInjection.Abstractions
202207
```
203208

204-
6. **Analyze Test Coverage**:
209+
7. **Analyze Test Coverage**:
205210
```bash
206211
# Set your base directory first
207212
dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-dir --directory "path/to/your/project"
@@ -302,22 +307,27 @@ The following patterns are ignored by default to protect sensitive information:
302307
dotnet run --project src/NetContextClient/NetContextClient.csproj -- set-base-dir --directory "D:\Projects\MyApp"
303308
```
304309

305-
2. Set up custom ignore patterns:
310+
2. Check server version and configuration:
311+
```bash
312+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- version
313+
```
314+
315+
3. Set up custom ignore patterns:
306316
```bash
307317
dotnet run --project src/NetContextClient/NetContextClient.csproj -- add-ignore-patterns --patterns "*.generated.cs" "*.designer.cs"
308318
```
309319

310-
3. List all projects:
320+
4. List all projects:
311321
```bash
312322
dotnet run --project src/NetContextClient/NetContextClient.csproj -- list-projects-in-dir --directory "D:\Projects\MyApp\src"
313323
```
314324

315-
4. Analyze your project's package dependencies:
325+
5. Analyze your project's package dependencies:
316326
```bash
317327
dotnet run --project src/NetContextClient/NetContextClient.csproj -- analyze-packages
318328
```
319329

320-
5. Search for authentication-related code:
330+
6. Search for authentication-related code:
321331
```bash
322332
dotnet run --project src/NetContextClient/NetContextClient.csproj -- semantic-search --query "user authentication and authorization logic"
323333
```

docs/tool-reference.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,44 @@ Simple health check endpoint that returns a greeting message.
269269
dotnet run --project src/NetContextClient/NetContextClient.csproj -- hello
270270
```
271271

272+
### `version`
273+
Gets version and configuration information about the NetContextServer.
274+
275+
**Parameters:** None
276+
277+
**Example:**
278+
```bash
279+
dotnet run --project src/NetContextClient/NetContextClient.csproj -- version
280+
```
281+
282+
**Output Example:**
283+
```
284+
NetContextServer v1.0.0
285+
──────────────────────────────────────────────────────
286+
287+
System Information:
288+
• Runtime: .NET 9.0.0
289+
• OS: Unix 24.1.0
290+
291+
Features:
292+
• Semantic Search: ✗ Disabled
293+
294+
Active Configuration:
295+
• Base Directory: /Users/username/projects/myapp
296+
• Has Ignore Patterns: true
297+
• State File Location: /Users/username/projects/myapp/ignore_patterns.json
298+
```
299+
300+
**Response Fields:**
301+
- `version`: Current version of NetContextServer
302+
- `runtimeVersion`: Current .NET runtime version
303+
- `operatingSystem`: Current operating system information
304+
- `semanticSearchEnabled`: Whether semantic search is configured and available
305+
- `activeConfiguration`: Dictionary of current configuration settings including:
306+
- `BaseDirectory`: Current base directory for file operations
307+
- `HasIgnorePatterns`: Whether custom ignore patterns are defined
308+
- `StateFileLocation`: Path to the ignore patterns state file
309+
272310
### `think`
273311
Provides a space for structured thinking during complex operations, allowing AI models to reason about actions, verify compliance with rules, and plan next steps without making any state changes.
274312

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace NetContextClient.Models;
4+
5+
/// <summary>
6+
/// Response model for version information.
7+
/// </summary>
8+
public class VersionResponse
9+
{
10+
/// <summary>
11+
/// Gets the current version of NetContextServer.
12+
/// </summary>
13+
[JsonPropertyName("version")]
14+
public string Version { get; init; } = string.Empty;
15+
16+
/// <summary>
17+
/// Gets the current .NET runtime version.
18+
/// </summary>
19+
[JsonPropertyName("runtimeVersion")]
20+
public string RuntimeVersion { get; init; } = string.Empty;
21+
22+
/// <summary>
23+
/// Gets whether semantic search is configured and available.
24+
/// </summary>
25+
[JsonPropertyName("semanticSearchEnabled")]
26+
public bool SemanticSearchEnabled { get; init; }
27+
28+
/// <summary>
29+
/// Gets the current operating system.
30+
/// </summary>
31+
[JsonPropertyName("operatingSystem")]
32+
public string OperatingSystem { get; init; } = string.Empty;
33+
34+
/// <summary>
35+
/// Gets active configuration settings.
36+
/// </summary>
37+
[JsonPropertyName("activeConfiguration")]
38+
public Dictionary<string, string> ActiveConfiguration { get; init; } = new();
39+
}

src/NetContextClient/Program.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,76 @@ static async Task<int> Main(string[] args)
923923
}
924924
}, reportPathOption, formatOption);
925925

926+
// Version command
927+
var versionCommand = new Command("version", "Get version and configuration information");
928+
versionCommand.SetHandler(async () =>
929+
{
930+
try
931+
{
932+
var result = await client.CallToolAsync("version", new Dictionary<string, object?>());
933+
var jsonText = result.Content.First(c => c.Type == "text").Text;
934+
if (jsonText != null)
935+
{
936+
var response = JsonSerializer.Deserialize<VersionResponse>(jsonText, DefaultJsonOptions);
937+
if (response != null)
938+
{
939+
// Parse state file location first if it exists
940+
if (response.ActiveConfiguration.TryGetValue("StateFileLocation", out var stateFileJson))
941+
{
942+
var stateFile = JsonSerializer.Deserialize<StateFileLocationResponse>(stateFileJson);
943+
response.ActiveConfiguration["StateFileLocation"] = stateFile?.StateFilePath ?? stateFileJson;
944+
}
945+
946+
// Header with version
947+
await Console.Out.WriteLineAsync($"\u001b[1;36mNetContextServer\u001b[0m v{response.Version}");
948+
await Console.Out.WriteLineAsync(new string('─', 50));
949+
950+
// System Information
951+
await Console.Out.WriteLineAsync("\u001b[1;33mSystem Information:\u001b[0m");
952+
await Console.Out.WriteLineAsync($" \u001b[90m•\u001b[0m Runtime: \u001b[32m.NET {response.RuntimeVersion}\u001b[0m");
953+
await Console.Out.WriteLineAsync($" \u001b[90m•\u001b[0m OS: \u001b[32m{response.OperatingSystem}\u001b[0m");
954+
955+
// Features
956+
await Console.Out.WriteLineAsync("\n\u001b[1;33mFeatures:\u001b[0m");
957+
await Console.Out.WriteLineAsync($" \u001b[90m•\u001b[0m Semantic Search: {(response.SemanticSearchEnabled ? "\u001b[32m✓ Enabled\u001b[0m" : "\u001b[31m✗ Disabled\u001b[0m")}");
958+
959+
// Configuration
960+
if (response.ActiveConfiguration.Count > 0)
961+
{
962+
await Console.Out.WriteLineAsync("\n\u001b[1;33mActive Configuration:\u001b[0m");
963+
foreach (var (key, value) in response.ActiveConfiguration)
964+
{
965+
// Format key in a more readable way
966+
var displayKey = string.Join(" ", key.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
967+
.Select(word => char.ToUpper(word[0]) + word.Substring(1)));
968+
969+
// Special formatting for boolean values and paths
970+
string displayValue = value;
971+
if (bool.TryParse(value, out bool boolValue))
972+
{
973+
displayValue = boolValue ? "\u001b[32m✓ Yes\u001b[0m" : "\u001b[31m✗ No\u001b[0m";
974+
}
975+
else if (value.Contains(Path.DirectorySeparatorChar))
976+
{
977+
displayValue = $"\u001b[36m{value}\u001b[0m";
978+
}
979+
980+
await Console.Out.WriteLineAsync($" \u001b[90m•\u001b[0m {displayKey}: {displayValue}");
981+
}
982+
}
983+
984+
// Footer
985+
await Console.Out.WriteLineAsync(new string('─', 50));
986+
}
987+
}
988+
}
989+
catch (Exception ex)
990+
{
991+
await Console.Error.WriteLineAsync($"\u001b[31mError: {ex.Message}\u001b[0m");
992+
Environment.Exit(1);
993+
}
994+
});
995+
926996
rootCommand.AddCommand(helloCommand);
927997
rootCommand.AddCommand(setBaseDirCommand);
928998
rootCommand.AddCommand(getBaseDirCommand);
@@ -943,6 +1013,7 @@ static async Task<int> Main(string[] args)
9431013
rootCommand.AddCommand(thinkCommand);
9441014
rootCommand.AddCommand(coverageAnalysisCommand);
9451015
rootCommand.AddCommand(coverageSummaryCommand);
1016+
rootCommand.AddCommand(versionCommand);
9461017

9471018
return await rootCommand.InvokeAsync(args);
9481019
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace NetContextServer.Models;
4+
5+
/// <summary>
6+
/// Represents version and configuration information for the NetContextServer.
7+
/// </summary>
8+
public class VersionInfo
9+
{
10+
/// <summary>
11+
/// Gets the current version of NetContextServer.
12+
/// </summary>
13+
[JsonPropertyName("version")]
14+
public string Version { get; init; } = typeof(VersionInfo).Assembly.GetName().Version?.ToString() ?? "unknown";
15+
16+
/// <summary>
17+
/// Gets the current .NET runtime version.
18+
/// </summary>
19+
[JsonPropertyName("runtimeVersion")]
20+
public string RuntimeVersion { get; init; } = Environment.Version.ToString();
21+
22+
/// <summary>
23+
/// Gets whether semantic search is configured and available.
24+
/// </summary>
25+
[JsonPropertyName("semanticSearchEnabled")]
26+
public bool SemanticSearchEnabled { get; init; }
27+
28+
/// <summary>
29+
/// Gets the current operating system.
30+
/// </summary>
31+
[JsonPropertyName("operatingSystem")]
32+
public string OperatingSystem { get; init; } = Environment.OSVersion.ToString();
33+
34+
/// <summary>
35+
/// Gets active configuration settings.
36+
/// </summary>
37+
[JsonPropertyName("activeConfiguration")]
38+
public Dictionary<string, string> ActiveConfiguration { get; init; } = new();
39+
}

src/NetContextServer/Services/IgnorePatternService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,13 @@ public static bool ShouldIgnoreFile(string filePath)
241241
return Path.GetFileName(filePath).Equals(pattern, StringComparison.OrdinalIgnoreCase);
242242
});
243243
}
244+
245+
/// <summary>
246+
/// Checks if there are any user-defined ignore patterns.
247+
/// </summary>
248+
/// <returns>True if there are user-defined patterns, false otherwise.</returns>
249+
public static bool HasUserDefinedPatterns()
250+
{
251+
return UserIgnorePatterns.Count > 0;
252+
}
244253
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using NetContextServer.Models;
2+
3+
namespace NetContextServer.Services;
4+
5+
/// <summary>
6+
/// Service for retrieving version and configuration information about the NetContextServer.
7+
/// </summary>
8+
public static class VersionService
9+
{
10+
/// <summary>
11+
/// Gets the current version information for NetContextServer.
12+
/// </summary>
13+
/// <returns>A VersionInfo object containing current version and configuration details.</returns>
14+
public static VersionInfo GetVersionInfo()
15+
{
16+
return new VersionInfo
17+
{
18+
SemanticSearchEnabled = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")) &&
19+
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")),
20+
ActiveConfiguration = new Dictionary<string, string>
21+
{
22+
["BaseDirectory"] = FileValidationService.BaseDirectory ?? "Not set",
23+
["HasIgnorePatterns"] = IgnorePatternService.HasUserDefinedPatterns().ToString(),
24+
["StateFileLocation"] = IgnorePatternService.GetStateFileLocation()
25+
}
26+
};
27+
}
28+
}

src/NetContextServer/Tools/GeneralTools.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using ModelContextProtocol.Server;
2+
using NetContextServer.Services;
23
using System.ComponentModel;
4+
using System.Text.Json;
35

46
namespace NetContextServer.Tools;
57

@@ -9,11 +11,28 @@ namespace NetContextServer.Tools;
911
[McpServerToolType]
1012
public static class GeneralTools
1113
{
14+
/// <summary>
15+
/// Default JSON serializer options used for version information output.
16+
/// </summary>
17+
private static readonly JsonSerializerOptions DefaultJsonOptions = new()
18+
{
19+
WriteIndented = true
20+
};
21+
1222
/// <summary>
1323
/// Simple health check endpoint that returns a greeting message.
1424
/// </summary>
1525
/// <returns>A greeting message indicating the server is operational.</returns>
1626
[McpServerTool("hello")]
1727
[Description("Simple health check endpoint that returns a greeting message.")]
1828
public static string Hello() => "hello, claude.";
29+
30+
/// <summary>
31+
/// Gets version and configuration information about the NetContextServer.
32+
/// </summary>
33+
/// <returns>A JSON string containing version information and current configuration.</returns>
34+
[McpServerTool("version")]
35+
[Description("Gets version and configuration information about the NetContextServer.")]
36+
public static string GetVersion() =>
37+
JsonSerializer.Serialize(VersionService.GetVersionInfo(), DefaultJsonOptions);
1938
}

0 commit comments

Comments
 (0)