You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Issue 1: Replace anonymous rate-limit body with typed McpRateLimitErrorEnvelope records;
use JsonSerializer.SerializeAsync instead of WriteAsync(Serialize(...))
- Issue 2: Strip prose default values from all tool Description attributes
- Issue 3: Merge GetGuidelinesByTopic into GetCSharpGuidelines via optional 'topic' param;
delete redundant GetGuidelinesByTopic tool
- Issue 4: Make /mcp-setup page dynamic — inject IEnumerable<McpServerTool> into
McpSetupController; replace 330+ lines of static HTML cards with Razor @foreach loop
- Issue 5: Add listing search pattern minimum validation (>=2 alphanumeric chars or
recognized C# operator)
- Issues 6+7: Extract duplicated FormatGuidelineType/FormatType to shared
GuidelineTypeExtensions.ToDisplayString() extension method; delete private copies
Fix 3 subagent-found bugs: trimmedPattern in search, Razor HTML escaping, whitespace-only type guard
- BookListingTool.cs: use trimmedPattern (not pattern) in Contains() search call
- Index.cshtml: fix Razor HTML escaping of optional badge via @if block
- BookGuidelinesTool.cs: use IsNullOrWhiteSpace guard for type param
- BookGuidelinesTool.cs: fix description to say substring match not exact text
Use MCP SDK JsonRpcError/JsonRpcErrorDetail instead of custom records
Replace McpRateLimitErrorEnvelope and McpRateLimitErrorDetail private
records with the SDK's built-in ModelContextProtocol.Protocol types,
as suggested in PR review.
Copy file name to clipboardExpand all lines: EssentialCSharp.Web/Tools/BookContentTool.cs
+2-11Lines changed: 2 additions & 11 deletions
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,7 @@ public BookContentTool(
37
37
Description("Retrieve the prose content of a specific book section identified by its slug/key (e.g., 'hello-world', 'creating-editing-compiling-and-running-c-source-code'). Returns the section text with code examples preserved. Use GetChapterSections to discover available slugs.")]
38
38
publicasyncTask<string>GetSectionContent(
39
39
[Description("The section slug/key (e.g., 'hello-world'). Use GetChapterSections to get valid slugs.")]stringsectionKey,
40
-
[Description("Maximum number of characters to return (500–8000, default 4000). Long sections are truncated.")]intmaxChars=4000,
40
+
[Description("Maximum number of characters to return (500–8000). Long sections are truncated.")]intmaxChars=4000,
41
41
CancellationTokencancellationToken=default)
42
42
{
43
43
maxChars=Math.Clamp(maxChars,500,8000);
@@ -365,7 +365,7 @@ public string GetChapterSummary(
Description("Retrieve C# coding guidelines from the Essential C# book. Optionally filter by keyword, chapter number, or guideline type (do/consider/avoid/donot). The book contains guidelines covering naming conventions, error handling, LINQ, async/await, generics, and many other topics. Each guideline includes its chapter and subsection context.")]
21
+
Description("Retrieve C# coding guidelines from the Essential C# book. Filter by keyword (case-insensitive substring match), chapter number, or guideline type. Use the 'topic' parameter for relevance-ranked discovery by concept (e.g., 'exception handling', 'naming', 'async'). Each guideline includes its chapter and subsection context. Tip: use 'topic' for broad discovery; use 'keyword' for precise substring matching.")]
21
22
publicstringGetCSharpGuidelines(
22
-
[Description("Optional keyword to filter guidelines by (searched in guideline text and subsection name).")]string?keyword=null,
23
+
[Description("Optional keyword for case-insensitive substring search in guideline text and subsection name.")]string?keyword=null,
23
24
[Description("Optional chapter number to restrict results to a specific chapter.")]int?chapter=null,
[Description("Maximum number of guidelines to return (1–50, default 20).")]intmaxResults=20)
26
+
[Description("Optional topic or concept for relevance-ranked search (e.g., 'exception handling', 'naming', 'async'). Results are ordered by relevance. Use for broad discovery; use 'keyword' for substring text matching.")]string?topic=null,
27
+
[Description("Maximum number of guidelines to return (1–50).")]intmaxResults=20)
[McpServerTool(Title="Get Guidelines By Topic",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
71
-
Description("Search C# coding guidelines from the Essential C# book by topic or concept. More discoverable than filtering by chapter — finds all guidelines related to exceptions, naming, async, LINQ, generics, interfaces, and more. Results are ordered by relevance to the topic.")]
72
-
publicstringGetGuidelinesByTopic(
73
-
[Description("The topic or concept to search guidelines for (e.g., 'exception handling', 'naming', 'async', 'LINQ', 'generics', 'interface').")]stringtopic,
74
-
[Description("Maximum number of guidelines to return (1–30, default 15).")]intmaxResults=15)
Copy file name to clipboardExpand all lines: EssentialCSharp.Web/Tools/BookListingTool.cs
+9-2Lines changed: 9 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -39,14 +39,21 @@ public async Task<string> GetListingSourceCode(
39
39
Description("Search all code listings in the Essential C# book for a specific code pattern, keyword, or identifier. Searches actual C# source code (not prose). Useful for finding examples of Task.WhenAll, yield return, IDisposable, pattern matching, and similar code constructs.")]
40
40
publicasyncTask<string>SearchListingsByCode(
41
41
[Description("The code pattern or keyword to search for in listing source code (case-insensitive substring match).")]stringpattern,
42
-
[Description("Maximum number of matching listings to return (1–20, default 10).")]intmaxResults=10,
42
+
[Description("Maximum number of matching listings to return (1–20).")]intmaxResults=10,
43
43
CancellationTokencancellationToken=default)
44
44
{
45
45
if(string.IsNullOrWhiteSpace(pattern))
46
46
{
47
47
return"Pattern must not be empty.";
48
48
}
49
49
50
+
stringtrimmedPattern=pattern.Trim();
51
+
boolisKnownOperator=trimmedPatternis"=>" or "??" or "?." or "::" or "??=" or "==" or "!=" or "<=" or ">=" or "&&" or "||";
0 commit comments