Conversation
- new file : src/utils/nlp.js & src/utils/regexPatterns.js
- New file : src/utils/fuzzy.js
- update zod to latest - add a jsconfig.json file in packages/mcp
|
@Shreehari-Acharya is attempting to deploy a commit to the binit2-1's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
This PR refactors the monolithic packages/mcp/lib/factory.js file into a modular architecture by splitting it into dedicated service layers, utilities, and tool registration modules. The refactoring aims to improve code maintainability and testability without introducing functional changes.
Changes:
- Extracted API and catalog data fetching into separate service modules (
api.js,catalog.js) - Isolated natural language processing, fuzzy matching, formatting, and regex patterns into utility modules
- Split tool registration into modular files (
tools/general.js,tools/components.js) with centralized initialization - Attempted to upgrade Zod dependency from v3.23.0 to v4.3.5
- Added
jsconfig.jsonfor IDE support
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/mcp/lib/factory.js | Removed all implementation code, now only imports and delegates to tool registration |
| packages/mcp/src/services/api.js | New service module for authenticated API requests |
| packages/mcp/src/services/catalog.js | New service module for component and category data fetching |
| packages/mcp/src/utils/nlp.js | New utility for natural language query processing |
| packages/mcp/src/utils/fuzzy.js | New utility for fuzzy matching logic |
| packages/mcp/src/utils/formatting.js | New utility for output formatting |
| packages/mcp/src/utils/regexPatterns.js | New utility containing regex pattern definitions |
| packages/mcp/src/tools/index.js | New entry point for tool registration |
| packages/mcp/src/tools/general.js | New module for general tool registration |
| packages/mcp/src/tools/components.js | New module for component-related tool registration |
| packages/mcp/package.json | Updated Zod dependency version |
| package-lock.json | Updated lock file with new Zod version |
| packages/mcp/jsconfig.json | New configuration file for IDE type support |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const normalized = title.toLowerCase(); | ||
| const fuzzyMatch = categoryComponents?.find(c => | ||
| c.title.toLowerCase().includes(normalized) | ||
| ); |
There was a problem hiding this comment.
The fuzzy matching logic here is inconsistent with the logic used in nlp.js (lines 108-111). This implementation only checks if the component title includes the normalized input in one direction, and uses simple toLowerCase() instead of the normalizeText() utility function.
For consistency and better matching behavior, this should use the normalizeText() function from fuzzy.js and check bidirectional inclusion, matching the pattern used in nlp.js.
packages/mcp/src/services/api.js
Outdated
| @@ -0,0 +1,26 @@ | |||
| import { getAuthToken, getBaseUrl } from "../../lib/auth"; | |||
There was a problem hiding this comment.
The import statement is missing the .js file extension. In ES modules, it's a best practice to include file extensions in import statements. While Node.js may resolve this without the extension in some cases, explicit extensions improve clarity and avoid potential issues.
Consider changing to: import { getAuthToken, getBaseUrl } from "../../lib/auth.js";
| import { getAuthToken, getBaseUrl } from "../../lib/auth"; | |
| import { getAuthToken, getBaseUrl } from "../../lib/auth.js"; |
|
|
||
| let component = await getComponent(categoryName, title.trim()); | ||
|
|
||
| // Fuzzy logic remains same |
There was a problem hiding this comment.
This comment states "Fuzzy logic remains same" but the fuzzy matching logic is actually inconsistent with the implementation in nlp.js. The comment is misleading because the logic here is simplified (using only toLowerCase() and one-directional matching) compared to the more sophisticated bidirectional matching with normalizeText() used elsewhere.
Consider updating this comment to accurately describe what the code does, or better yet, extract this logic into a shared utility function to ensure consistency.
| // Fuzzy logic remains same | |
| // Simple, case-insensitive, one-directional fuzzy match on component titles |
| const categoryComponents = await getComponentsByCategory(categoryName); | ||
| if (categoryComponents) { | ||
| const normalized = normalizeText(titleInput); | ||
| const fuzzyMatch = categoryComponents.find(c => | ||
| normalizeText(c.title).includes(normalized) || | ||
| normalized.includes(normalizeText(c.title)) | ||
| ); | ||
| if (fuzzyMatch) { | ||
| component = await getComponent(categoryName, fuzzyMatch.title); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (!component) { | ||
| const categoryComponents = await getComponentsByCategory(categoryName); |
There was a problem hiding this comment.
The getComponentsByCategory function is called twice when a component is not found - once on line 106 for fuzzy matching, and again on line 120 for generating suggestions. This results in a redundant API call that impacts performance.
The result from line 106 should be cached and reused on line 120 to avoid the duplicate API call.
| if (component.dependencies && Object.keys(component.dependencies).length > 0) { | ||
| const deps = Object.entries(component.dependencies) | ||
| .map(([pkg, ver]) => ` • \`${pkg}\`: ${ver}`) | ||
| .join("\n"); | ||
|
|
||
| const installCmd = Object.keys(component.dependencies).join(" "); | ||
| depsSection = ` | ||
| --- | ||
|
|
||
| ### 📦 Dependencies | ||
|
|
||
| ${deps} | ||
|
|
||
| **Install command:** | ||
| \`\`\`bash | ||
| npm install ${installCmd} | ||
| \`\`\` | ||
| `; |
There was a problem hiding this comment.
The dependencies check assumes component.dependencies is already an object, but based on the getDepsCount function (lines 1-11), dependencies can be a string that needs to be parsed. This will cause a runtime error when trying to call Object.keys() on a string.
The code should parse the dependencies first if they are a string, similar to how it's done in getDepsCount.
| if (component.dependencies && Object.keys(component.dependencies).length > 0) { | |
| const deps = Object.entries(component.dependencies) | |
| .map(([pkg, ver]) => ` • \`${pkg}\`: ${ver}`) | |
| .join("\n"); | |
| const installCmd = Object.keys(component.dependencies).join(" "); | |
| depsSection = ` | |
| --- | |
| ### 📦 Dependencies | |
| ${deps} | |
| **Install command:** | |
| \`\`\`bash | |
| npm install ${installCmd} | |
| \`\`\` | |
| `; | |
| if (component.dependencies) { | |
| try { | |
| const deps = typeof component.dependencies === "string" | |
| ? JSON.parse(component.dependencies) | |
| : component.dependencies; | |
| if (deps && typeof deps === "object" && !Array.isArray(deps) && Object.keys(deps).length > 0) { | |
| const depsList = Object.entries(deps) | |
| .map(([pkg, ver]) => ` • \`${pkg}\`: ${ver}`) | |
| .join("\n"); | |
| const installCmd = Object.keys(deps).join(" "); | |
| depsSection = ` | |
| --- | |
| ### 📦 Dependencies | |
| ${depsList} | |
| **Install command:** | |
| \`\`\`bash | |
| npm install ${installCmd} | |
| \`\`\` | |
| `; | |
| } | |
| } catch { | |
| // If dependencies cannot be parsed, skip the dependencies section | |
| } |
…harya/Composter into modularize-factory-monolith
name: 🔧 Refactor
about: Code refactor with no functional changes
Description
This pull request refactors the packages/mcp package to improve modularity, maintainability, and type safety. The logic has been decoupled into dedicated service layers and utilities, and the tool registration system has been updated to use the modern MCP SDK patterns.
Related Issue
Closes #65 #67 #68 #69 #70
Motivation
The previous implementation of the MCP tools was becoming a monolithic file that was difficult to test and extend. As the number of supported tools grew, the complexity of managing natural language parsing, fuzzy matching, and API calls in a single location became a bottleneck.
Changes Made
Refactored Component and Category Management:
api.jsandcatalog.jsservice modules. This centralizes authenticated API requests and provides a cleaner interface for retrieving categories, components, and search results.Optimized Query Processing & Fuzzy Matching:
nlp.jsto handle query routing more efficiently.fuzzy.jsutility, ensuring consistent title and category resolution across all tools.Modernized Tool Architecture:
tools/general.jsandtools/components.js.server.registerToolsyntax and modernized Zod schema patterns as supported by the latest@modelcontextprotocol/sdk.src/tools/index.jswith aregisterTools(server)function to streamline server setup.Improved Formatting & Tooling:
formatting.jsto ensure uniform output for code blocks, dependency lists, and user guidance.jsconfig.jsonto enhance IDE IntelliSense and type checking.zodto v3.24+ / v4.x to leverage improved schema validation and performance.Impact
Breaking Changes
How Has This Been Tested?
Checklist