Frontmatter
| id | 7950 |
| title | Refactor ToolService to Class-based Architecture |
| state | Closed |
| labels | enhancementairefactoring |
| assignees | tobiu |
| createdAt | Nov 30, 2025, 3:38 PM |
| updatedAt | Nov 30, 2025, 4:10 PM |
| githubUrl | https://github.com/neomjs/neo/issues/7950 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 7931 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Nov 30, 2025, 4:10 PM |
Refactor ToolService to Class-based Architecture
tobiu added parent issue #7931 on Nov 30, 2025, 3:38 PM
tobiu assigned to @tobiu on Nov 30, 2025, 3:38 PM

tobiu
Nov 30, 2025, 4:10 PM
Input from Gemini 2.5 pro:
✦ I have successfully completed the singleton-to-class refactoring for
ToolService.Refactoring Details
- Class Architecture:
ai/mcp/ToolService.mjsis now a class extendingNeo.core.Base.
- State (
toolMapping,allToolsForListing) is instance-scoped.- Configuration (
openApiFilePath) is handled viastatic configandconstruct.- Server Migration: All three MCP servers (
github-workflow,knowledge-base,memory-core) now instantiate anew ToolService(...)in their respectiveservices/toolService.mjswrappers, ensuring isolation.- Client Migration:
Neo.ai.mcp.client.Clientnow creates a privateToolServiceinstance for each connection (initAsync). This enables the Client to maintain separate validation contexts (e.g., separate Zod schemas) for different internal servers within the same process.Verification
The
mcp-demo-agent.mjsruns successfully, confirming that:
- Servers initialize correctly with the new class-based service.
- The Client connects and executes tools (using the new class-based validation logic).
- The architecture handles the multi-server setup without state pollution.
I am ready to close this ticket.
tobiu closed this issue on Nov 30, 2025, 4:10 PM
Context
In #7949, we moved
toolService.mjsto a shared location to support client-side validation. However, the service remains a singleton module with module-level state (toolMapping). This prevents a single process (like an Agent) from initializing multiple internal server contexts (Zod schemas) simultaneously, as subsequent initializations overwrite the global state.Goal
Refactor
ai/mcp/toolService.mjsinto a class-basedNeo.ai.mcp.ToolServiceextendingNeo.core.Base. This allows each Server or Client connection to maintain its own independent tool registry and validation context.Requirements
ai/mcp/toolService.mjstoai/mcp/ToolService.mjs. Convert it to export aToolServiceclass extendingNeo.core.Base.openApiFilePath: Define as a non-reactive config (no trailing underscore) to allow prototype or instance-level overrides.serviceMapping: Define as a class field.toolMapping&allToolsForListing: Define as instance properties (lazy-loaded state).github-workflow,knowledge-base,memory-core) to instantiatenew ToolService({ serviceMapping, openApiFilePath })(or similar config pattern) in their local service wrappers.Neo.ai.mcp.client.Clientto:ToolServicefor each connection.openApiFilePath(retrieved from config) to theToolServiceif available, enabling robust Zod validation for internal servers.Deliverables
ai/mcp/ToolService.mjs(Class-based).