[azsdk-cli] add tsp list_topics and tsp get_topic_docs tools (mcp only)#12007
[azsdk-cli] add tsp list_topics and tsp get_topic_docs tools (mcp only)#12007chrisradek wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds two new MCP tools to enable retrieving TypeSpec and TypeSpec Azure documentation. The tools provide a way to list available documentation topics and fetch their content, allowing for targeted documentation retrieval instead of overwhelming context windows with all available content.
- Adds
azsdk_list_typespec_topicstool to list available documentation topics with descriptions - Adds
azsdk_get_typespec_topics_docstool to fetch documentation content for specified topics - Implements a TypeSpecDocsService with caching and thread-safe operations
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| TspInitTool.cs | Adds two new MCP tools with dependency injection for TypeSpecDocsService |
| TypeSpecDocsService.cs | Core service implementing documentation fetching with caching and concurrency management |
| ServiceRegistrations.cs | Registers HTTP client and TypeSpecDocsService in DI container |
| TypeSpecTopicDoc.cs | Model for topic documentation content |
| TypeSpecTopic.cs | Model for topic metadata |
| ListTypeSpecTopicsResponse.cs | Response model for listing topics |
| GetTypeSpecTopicsDocsResponse.cs | Response model for topic documentation |
| LlmsJsonItem.cs | Model for parsing llms.json files |
| TspInitToolTest.cs | Updates test constructor calls to include new service dependency |
| TypeSpecDocsServiceTests.cs | Comprehensive test suite for the new service |
| var task = inflightRequests.GetOrAdd(url, async (urlKey) => | ||
| { | ||
| try | ||
| { | ||
| using var httpClient = httpClientFactory.CreateClient(); | ||
| var response = await httpClient.GetStringAsync(urlKey, ct); | ||
| return response; | ||
| } | ||
| finally | ||
| { | ||
| // Remove from in-flight when done | ||
| inflightRequests.TryRemove(urlKey, out _); |
There was a problem hiding this comment.
The lambda function parameter name urlKey shadows the outer variable url. This could lead to confusion and potential bugs. Use the outer url parameter directly or choose a different parameter name.
| var task = inflightRequests.GetOrAdd(url, async (urlKey) => | |
| { | |
| try | |
| { | |
| using var httpClient = httpClientFactory.CreateClient(); | |
| var response = await httpClient.GetStringAsync(urlKey, ct); | |
| return response; | |
| } | |
| finally | |
| { | |
| // Remove from in-flight when done | |
| inflightRequests.TryRemove(urlKey, out _); | |
| var task = inflightRequests.GetOrAdd(url, async (dedupUrl) => | |
| { | |
| try | |
| { | |
| using var httpClient = httpClientFactory.CreateClient(); | |
| var response = await httpClient.GetStringAsync(dedupUrl, ct); | |
| return response; | |
| } | |
| finally | |
| { | |
| // Remove from in-flight when done | |
| inflightRequests.TryRemove(dedupUrl, out _); |
| // DI is causing `sources` to always be an empty enumerable instead of null when not provided | ||
| var sourceArray = sources?.ToArray(); | ||
| tspDocSources = (sourceArray?.Length > 0) ? sourceArray : defaultTspDocSources; |
There was a problem hiding this comment.
[nitpick] The comment indicates a workaround for a DI issue. Consider using a more explicit approach like checking sources.Any() or implementing a proper factory pattern to handle this dependency injection concern more clearly.
| fetchTasks.Add(FetchTopicContentAsync(topic, contentUrl, ct)); | ||
| } | ||
|
|
||
| if (unknownTopics.Count != 0) |
There was a problem hiding this comment.
[nitpick] Use .Any() instead of .Count != 0 for better readability and potential performance benefits when checking if a collection has elements.
| } | ||
|
|
||
| [McpServerTool(Name = "azsdk_list_typespec_topics"), | ||
| Description("Use this tool to list all available TypeSpec and TypeSpec Azure documentation topics with their descriptions.")] |
There was a problem hiding this comment.
When should this be called by LLM? Can you please share sample prompt from user that will invoke this tool?
There was a problem hiding this comment.
I feel that this description needs a bit more explanation to make it easier for LLM to decide.
| { | ||
| logger.LogInformation("Fetching TypeSpec documentation topics"); | ||
| var response = await docsService.GetTopicsAsync(ct); | ||
|
|
Resolves #11679
This PR adds 2 new MCP tools whose purpose is to allow retrieving TypeSpec and TypeSpec Azure documentation.
azsdk_list_typespec_topics
This tool returns a list of "topics" that the agent can request documentation for (e.g.
typespec-language-basics,typespec-azure-clients-how-tos) along with their descriptions.Currently, the TypeSpec/TypeSpec Azure doc websites have been updated to generate these topics whenever they are built:
azsdk_get_typespec_topics_docs
This tool takes in a list of "topics" (must be a topic returned by
list_typespec_topics), and returns the documentation for those topics.The documentation is hosted on the TypeSpec/TypeSpec Azure doc websites in llms-full.txt format - big markdown files.
Why 2 tools?
Trying to fit all the content currently spread across multiple llms-full.txt files would take hundreds of thousands of tokens - overwhelming a lot of context windows today. In my earlier testing, I found that it was also helpful to give targeted documentation. For example, only giving the azure core docs when working on a data plane service, instead of the ARM docs too.