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
fix: restore Destructive = false on all MCP tool annotations
The MCP spec (and C# SDK) default destructiveHint to true.
Explicitly setting Destructive = false is required so clients
know these read-only book search tools are non-destructive.
Note: per spec, destructiveHint is 'only meaningful when
readOnlyHint == false', but the SDK still emits the value
on the wire so explicit false is the safe, correct choice.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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,
@@ -145,7 +145,7 @@ public async Task<string> GetSectionContent(
145
145
returnbody.Length==0?$"No content found after section heading '{mapping.RawHeading}'.":header.Append(body).ToString();
146
146
}
147
147
148
-
[McpServerTool(Title="Get Listing With Context",ReadOnly=true,Idempotent=true,OpenWorld=false),
148
+
[McpServerTool(Title="Get Listing With Context",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
149
149
Description("Retrieve a specific book listing's source code together with the semantic book content that explains it. Combines code from GetListingSourceCode with related explanatory text found via search. Ideal for understanding what a listing demonstrates.")]
150
150
publicasyncTask<string>GetListingWithContext(
151
151
[Description("The chapter number of the listing.")]intchapter,
@@ -191,7 +191,7 @@ public async Task<string> GetListingWithContext(
Description("Get the navigation context for a book section: its breadcrumb path, the previous and next sections, its parent section, and its sibling sections. Useful for understanding where a section sits in the book's structure.")]
196
196
publicstringGetNavigationContext(
197
197
[Description("The section slug/key (e.g., 'hello-world'). Use GetChapterSections to get valid slugs.")]stringsectionKey)
@@ -325,7 +325,7 @@ public string GetNavigationContext(
Description("Get a structural overview of a book chapter: its top-level section headings in reading order, and the coding guidelines associated with that chapter. Useful for understanding what a chapter covers before diving in.")]
330
330
publicstringGetChapterSummary(
331
331
[Description("The chapter number (e.g., 5 for Chapter 5).")]intchapter)
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
21
publicstringGetCSharpGuidelines(
22
22
[Description("Optional keyword to filter guidelines by (searched in guideline text and subsection name).")]string?keyword=null,
@@ -67,7 +67,7 @@ public string GetCSharpGuidelines(
67
67
returnsb.ToString();
68
68
}
69
69
70
-
[McpServerTool(Title="Get Guidelines By Topic",ReadOnly=true,Idempotent=true,OpenWorld=false),
70
+
[McpServerTool(Title="Get Guidelines By Topic",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
71
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
72
publicstringGetGuidelinesByTopic(
73
73
[Description("The topic or concept to search guidelines for (e.g., 'exception handling', 'naming', 'async', 'LINQ', 'generics', 'interface').")]stringtopic,
Description("Retrieve the complete source code for a specific numbered listing from the Essential C# book. Example: chapter=5, listing=3 retrieves Listing 5.3. Returns the code and its file type.")]
23
23
publicasyncTask<string>GetListingSourceCode(
24
24
[Description("The chapter number containing the listing (e.g., 5 for Chapter 5).")]intchapter,
@@ -35,7 +35,7 @@ public async Task<string> GetListingSourceCode(
[McpServerTool(Title="Search Listings By Code",ReadOnly=true,Idempotent=true,OpenWorld=false),
38
+
[McpServerTool(Title="Search Listings By Code",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
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,
Copy file name to clipboardExpand all lines: EssentialCSharp.Web/Tools/BookSearchTool.cs
+10-10Lines changed: 10 additions & 10 deletions
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
usingSystem.ComponentModel;
1
+
usingSystem.ComponentModel;
2
2
usingSystem.Globalization;
3
3
usingSystem.Text;
4
4
usingSystem.Text.RegularExpressions;
@@ -35,7 +35,7 @@ public BookSearchTool(IServiceProvider serviceProvider, ISiteMappingService site
35
35
_guidelinesService=guidelinesService;
36
36
}
37
37
38
-
[McpServerTool(Title="Search Book Content",ReadOnly=true,Idempotent=true,OpenWorld=false),
38
+
[McpServerTool(Title="Search Book Content",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
39
39
Description("Search the Essential C# book content using semantic vector search. Returns relevant text chunks with chapter and heading context. Use this to find information about C# programming concepts covered in the book.")]
40
40
publicasyncTask<string>SearchBookContent(
41
41
[Description("The search query describing the C# concept or topic to find in the book.")]stringquery,
@@ -87,7 +87,7 @@ public async Task<string> SearchBookContent(
Description("Get all sections and subsections in a specific chapter of the Essential C# book, in reading order. Returns each section's heading, slug, anchor link, and indent level. Use the returned slugs with other tools like GetSectionContent or GetNavigationContext.")]
123
123
publicstringGetChapterSections(
124
124
[Description("The chapter number (e.g., 5 for Chapter 5).")]intchapter)
@@ -150,7 +150,7 @@ public string GetChapterSections(
150
150
returnsb.ToString();
151
151
}
152
152
153
-
[McpServerTool(Title="Get Direct Content URL",ReadOnly=true,Idempotent=true,OpenWorld=false),
153
+
[McpServerTool(Title="Get Direct Content URL",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
154
154
Description("Get the canonical deep-link URL for a specific book section or subsection. Returns a clickable URL that navigates directly to the section. Use this to include precise references in responses.")]
155
155
publicstringGetDirectContentUrl(
156
156
[Description("The section slug/key (e.g., 'hello-world'). Use GetChapterSections or GetChapterList to find valid slugs.")]stringsectionKey)
@@ -175,7 +175,7 @@ public string GetDirectContentUrl(
175
175
$"URL: {url}";
176
176
}
177
177
178
-
[McpServerTool(Title="Get Book Metadata",ReadOnly=true,Idempotent=true,OpenWorld=false),
178
+
[McpServerTool(Title="Get Book Metadata",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
179
179
Description("Get citation-quality metadata for the Essential C# book: title, authors, edition, C# version covered, ISBN, publisher, and website URL. Use this when generating citations or when asked which edition or C# version the book covers.")]
180
180
publicstringGetBookMetadata()
181
181
{
@@ -192,7 +192,7 @@ public string GetBookMetadata()
Description("Find all sections in the Essential C# book that cover a specific C# concept. Combines section heading search with semantic vector search (when available) to give broad coverage. Returns section slugs, chapter numbers, and direct links.")]
197
197
publicasyncTask<string>LookupConcept(
198
198
[Description("The C# concept, feature, or topic to find in the book (e.g., 'LINQ', 'async/await', 'pattern matching', 'generics').")]stringconcept,
@@ -267,7 +267,7 @@ public async Task<string> LookupConcept(
Description("Determine whether and how thoroughly the Essential C# book covers a given topic. Returns a coverage assessment: 'Comprehensive', 'Mentioned', or 'Not found in headings'. Use this before citing the book to calibrate confidence.")]
272
272
publicasyncTask<string>CheckTopicCoverage(
273
273
[Description("The C# topic, feature, or concept to check (e.g., 'source generators', 'records', 'LINQ').")]stringtopic,
@@ -337,7 +337,7 @@ public async Task<string> CheckTopicCoverage(
337
337
returnsb.ToString();
338
338
}
339
339
340
-
[McpServerTool(Title="Find Book Help For Diagnostic",ReadOnly=true,Idempotent=true,OpenWorld=false),
340
+
[McpServerTool(Title="Find Book Help For Diagnostic",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
341
341
Description("Find Essential C# book sections, content, and coding guidelines that help explain a C# compiler error, warning, or runtime exception. Accepts a CS diagnostic code (e.g., 'CS8600') or a plain description (e.g., 'null reference exception', 'cannot implicitly convert'). Returns relevant sections, explanatory prose, and related guidelines.")]
@@ -437,7 +437,7 @@ public async Task<string> FindBookHelpForDiagnostic(
437
437
returnsb.ToString();
438
438
}
439
439
440
-
[McpServerTool(Title="Find Related Sections",ReadOnly=true,Idempotent=true,OpenWorld=false),
440
+
[McpServerTool(Title="Find Related Sections",ReadOnly=true,Destructive=false,Idempotent=true,OpenWorld=false),
441
441
Description("Find other sections in the Essential C# book that are semantically related to a given section. Uses the section heading as a search query to discover thematically connected content across the entire book. Requires AI services to be configured.")]
442
442
publicasyncTask<string>FindRelatedSections(
443
443
[Description("The section slug/key to find related content for (e.g., 'async-await'). Use GetChapterSections to get valid slugs.")]stringsectionKey,
0 commit comments