feat: enhance documentation tools with code example extraction and re… - #1765
Open
dkalinovInfra wants to merge 1 commit into
Open
feat: enhance documentation tools with code example extraction and re…#1765dkalinovInfra wants to merge 1 commit into
dkalinovInfra wants to merge 1 commit into
Conversation
…solution improvements - Added new functions to extract code examples from documentation, allowing users to retrieve runnable code snippets without accompanying prose. - Implemented `resolveDoc` function to streamline document resolution, incorporating fuzzy matching for better search results. - Updated `sanitizeSearchDocsQuery` to strip natural-language stopwords, improving search accuracy. - Enhanced `normalizeDocName` to handle kebab-case and underscore conversions more effectively. - Introduced `applyCompactGridPrefix` to manage Angular-specific grid documentation naming conventions. - Improved logging and error handling in documentation retrieval processes. - Updated constants and descriptions for new functionality in the documentation tools.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR enhances the Ignite UI docs MCP server (@igniteui/mcp-server) by adding a new get_example tool that returns code-only snippets (optionally language-filtered) and by refactoring doc-name resolution into a shared resolveDoc() path used by both get_doc and get_example. It also improves search recall by stripping common natural-language stopwords before FTS4 matching, and adds a benchmark script to quantify token savings.
Changes:
- Add
get_exampleMCP tool that extracts and formats fenced code blocks (grouped/labeled by section headings), with optional fence-language filtering. - Refactor doc resolution into
resolveDoc()with Angular-specific compact grid-prefix rewriting and a guarded FTS search fallback (with explicit substitution notice when fuzzy). - Improve
search_docsrecall by removing natural-language stopwords from multi-term queries; expand unit tests and add a token benchmarking script.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/igniteui-mcp/igniteui-doc-mcp/src/tools/doc-tools.ts | Adds stopword-aware query sanitization, shared resolveDoc() logic, Angular compact grid-prefix rewrite, and code example extraction/formatting utilities. |
| packages/igniteui-mcp/igniteui-doc-mcp/src/tools/constants.ts | Adds the get_example tool description and usage guidance (including language filter recommendation). |
| packages/igniteui-mcp/igniteui-doc-mcp/src/index.ts | Registers get_example, routes get_doc through resolveDoc(), and emits a substitution notice for fuzzy resolutions. |
| packages/igniteui-mcp/igniteui-doc-mcp/src/tests/tools/doc-tools.test.ts | Adds extensive unit tests covering stopwords, doc resolution behavior, and code extraction/formatting helpers. |
| packages/igniteui-mcp/igniteui-doc-mcp/scripts/benchmark-tool-tokens.ts | Adds a script to benchmark token counts for get_doc vs get_example across the corpus. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const merged: CodeExample[] = []; | ||
| for (const ex of examples) { | ||
| const last = merged[merged.length - 1]; | ||
| if (last && last.heading === ex.heading) { |
Comment on lines
+192
to
+194
| const requested = topic | ||
| ? `${normalizeDocName(component.trim())}-${topic.trim().toLowerCase().replace(/[\s_]+/g, "-")}` | ||
| : component.trim(); |
Comment on lines
+156
to
+160
| server.registerTool( | ||
| "get_example", | ||
| { | ||
| description: TOOL_DESCRIPTIONS.get_example, | ||
| annotations: { readOnlyHint: true, openWorldHint: false }, |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Adds a new
get_exampleMCP tool that returns only the runnable code examples for a component doc, with no prose. It resolves a component (plus optional sub-featuretopic) to a single doc, extracts the fenced code blocks, groups them per example, and labels each with its section heading. An optionallanguagefilter narrows the response to one fence language.Motivation: most Ignite UI questions are "show me how to use X in code".
get_docanswers those by returning the entire document, which is dominated by content the model does not need for a code answer. Measured across all 1,230 docs in the shipped DB,get_examplereturns 36% fewer tokens thanget_docon average, and 59% fewer when alanguageis passed.Along the way this PR extracts the doc-name resolution that
get_dochad inline into a sharedresolveDoc(), so both tools resolve names identically, and fixes two accuracy problems that the shared path exposed:Angular grid-variant docs resolved to the wrong doc. Angular keys these docs with a compact prefix (
treegrid-filtering), while the user-facing component name is hyphenated (tree-grid). Composing component + topic produced names no doc uses, which fell through to the search fallback and landed on a plausible-but-wrong doc —tree-grid-editingservedtreegrid-batch-editing. A newapplyCompactGridPrefix()rewrites the prefix before the fallback runs. Measured over all 80 Angular tree/hierarchical/pivot-grid topic docs: 13 wrong (16%) → 0 wrong (0%).Silent wrong-doc substitution. When the search fallback serves a doc other than the one requested, the response now says so instead of reading as an exact hit.
resolveDoc()returns afuzzyflag set only on the search path, so deterministic resolutions (direct hit, alias, prefix rewrite) stay silent and produce no noise.Related Issue
Closes
Type of Change
Affected Packages
igniteui-cli(packages/cli)@igniteui/cli-core(packages/core)@igniteui/angular-templates(packages/igx-templates)@igniteui/angular-schematics(packages/ng-schematics)@igniteui/mcp-server(packages/igniteui-mcp)Behavior changes to existing tools
Two shipped tools change behavior. Neither is a schema change, but both are visible to callers:
get_docgains the search fallback. It previously returnedisErrorwhen a name did not map mechanically; via the sharedresolveDoc()it now runs a full-text search as a last resort and can serve the closest related doc. Those responses are prefixed with an explicit notice:search_docsdrops natural-language stopwords. FTS4 uses implicit AND, so leavinghow/do/iin "how do I enable row editing" forced those words to appear in a doc and collapsed recall to near zero. Stopwords are now stripped, falling back to the full term list when every term is a stopword.and/or/butare deliberately kept as ordinary terms.Checklist
npm run test)npm run build)npm run lint)Exactly what was run, since two of these need qualification:
npm testinpackages/igniteui-mcp/igniteui-doc-mcpnpm run build(root)tsc, config-schema, andbuild:mcpall succeednpm run lint(root)npm run testwas not run to completion: itspretesthook runsnpm run lint, which currently fails on ~11,984 parse errors originating entirely from the documentation git submodules (webcomponents/igniteui-webcomponents, etc.) being picked up by the root ESLint config. That is pre-existing onmasterand unrelated to this PR. The monorepo Jasmine suite also has 11 known pre-existingng-schematics"migration-0X not found" failures.igniteui-doc-mcp/src,igniteui-doc-mcp/scripts) and returns zero matches.Additional Context
Measured token savings
scripts/benchmark-tool-tokens.ts(added in this PR) counts tokens withjs-tiktoken/o200k_baseon the exact string each tool places incontent[0].text, so the numbers carry no model or tool-call overhead:get_docget_exampleget_example+ languageCorpus totals over the 1,188 docs that contain examples: 4,277,559 → 2,800,996 tokens (−35%), so the 3% of docs with no examples are not skewing the mean.
The
languagefilter is doing most of the work, which follows from the pipeline: LLM compression already strips most prose, so a compressed doc is largely code blocks. Dropping prose alone cannot save much; dropping the other language variants of every sample can. The tool and parameter descriptions were written to push the model toward always passinglanguagewhen the target language is known.Run it with:
Sample output
Known gaps, deliberately not addressed here
get_examplecalls still return >8k tokens; the worst isangular/types-stacked-chart(19,849 → 17,001, only 14% saved) because those chart docs are almost entirely code already. Mitigated by pushinglanguagein the descriptions, which is a softer guarantee than a cap. A follow-up could cap at ~6–8k tokens with a "N more examples — narrow withtopic/language" footer.extractCodeExamples()groups consecutive blocks into examples, butmergeExamplesByHeading()then collapses every adjacent same-heading example, so the two mechanisms cancel — verified across real docs to produce byte-identical output either way. It is dead complexity rather than a bug, so it is left for a cleanup PR.Files in this PR
src/index.tsget_example; routeget_docthroughresolveDoc(); emit the substitution noticesrc/tools/doc-tools.tsresolveDoc(),applyCompactGridPrefix(),formatSubstitutionNotice(),extractCodeExamples(),mergeExamplesByHeading(),formatCodeExamples(),canonicalLang(); stopwords insanitizeSearchDocsQuery();normalizeDocName()now trims and folds spaces/underscoressrc/tools/constants.tsget_exampletool descriptionsrc/__tests__/tools/doc-tools.test.tsscripts/benchmark-tool-tokens.tstsconfig.json'sinclude: ["src/**/*"], consistent with the otherscripts/files; typechecked separately)