Context
The current dummyOptimizer (pkg/vmcp/optimizer/dummy_optimizer.go) uses an in-memory map with simple case-insensitive substring matching. This doesn't scale to production workloads and duplicates tool state across every optimizer instance (one per MCP session).
Prototype reference: #3516 (see pkg/vmcp/optimizer/internal/db/ for prior art on SQLite + FTS5)
Requirements
- Introduce a storage interface that abstracts how tools are stored and searched. The
dummyOptimizer should depend on this interface rather than directly on SQLite. This enables:
- Unit testing the optimizer with a mock/in-memory store
- Integration testing the SQLite implementation independently
- Implement the storage interface with a shared SQLite backend backed by FTS5 full-text search. The SQLite instance must be shared across all optimizer instances created by the
OptimizerFactory (pkg/vmcp/server/server.go:134), deduplicating tool storage.
- Despite the shared database, each optimizer instance must only return tools for the capabilities passed at factory creation time (i.e., the
[]server.ServerTool slice passed to NewDummyOptimizer). This preserves per-session scoping.
- Implement a basic BM25/FTS5-based similarity search in
FindTool, replacing the current substring matching.
- The
Optimizer interface (pkg/vmcp/optimizer/optimizer.go) should gain a Close() method so the database can be cleaned up. Update the server integration in pkg/vmcp/server/server.go to call Close() on session teardown.
- The factory function signature in
server.Config.OptimizerFactory may need to change to accept a shared storage reference. Consider a two-phase pattern: a top-level "optimizer manager" (holds the storage instance) and per-session optimizer instances.
High-Level Implementation
- Define a storage interface (e.g.,
ToolStore) in pkg/vmcp/optimizer/ with methods for tool ingestion, search, and cleanup
- Create an internal SQLite implementation under
pkg/vmcp/optimizer/internal/db/ that satisfies the interface:
- A single shared
*sql.DB connection with FTS5 virtual table for tool search
- Tool ingestion (upsert tools with name, description, input schema)
- FTS5-based search that returns ranked results
- Update
dummyOptimizer to accept a ToolStore and a scoping set of tool names
FindTool queries the store, filters to the scoped tool set, and returns matches
CallTool remains unchanged (direct tool handler invocation)
- Update
cmd/vmcp/app/commands.go to create the shared SQLite-backed store and pass it into the factory closure
Acceptance Tests
Context
The current
dummyOptimizer(pkg/vmcp/optimizer/dummy_optimizer.go) uses an in-memory map with simple case-insensitive substring matching. This doesn't scale to production workloads and duplicates tool state across every optimizer instance (one per MCP session).Prototype reference: #3516 (see
pkg/vmcp/optimizer/internal/db/for prior art on SQLite + FTS5)Requirements
dummyOptimizershould depend on this interface rather than directly on SQLite. This enables:OptimizerFactory(pkg/vmcp/server/server.go:134), deduplicating tool storage.[]server.ServerToolslice passed toNewDummyOptimizer). This preserves per-session scoping.FindTool, replacing the current substring matching.Optimizerinterface (pkg/vmcp/optimizer/optimizer.go) should gain aClose()method so the database can be cleaned up. Update the server integration inpkg/vmcp/server/server.goto callClose()on session teardown.server.Config.OptimizerFactorymay need to change to accept a shared storage reference. Consider a two-phase pattern: a top-level "optimizer manager" (holds the storage instance) and per-session optimizer instances.High-Level Implementation
ToolStore) inpkg/vmcp/optimizer/with methods for tool ingestion, search, and cleanuppkg/vmcp/optimizer/internal/db/that satisfies the interface:*sql.DBconnection with FTS5 virtual table for tool searchdummyOptimizerto accept aToolStoreand a scoping set of tool namesFindToolqueries the store, filters to the scoped tool set, and returns matchesCallToolremains unchanged (direct tool handler invocation)cmd/vmcp/app/commands.goto create the shared SQLite-backed store and pass it into the factory closureAcceptance Tests
ToolStore— verifies search delegation, scoping, and error handling without any databaseToolStoreimplementation tested independently — verifies FTS5 indexing, upsert behavior, and search rankingToolStoreand can see each other's tools[]server.ServerToolslice, even when the store contains tools from other sessionsFindToolwith a natural-language description returns relevant tools (not just substring matches)Close()on an optimizer properly releases resourcesFindToolandCallToolon different optimizer instances simultaneously without data racesfind_toolandcall_toolMCP tools exposed viapkg/vmcp/server/adapter/optimizer_adapter.gocontinue to work unchanged