88)
99
1010// CachedInventory provides a cached inventory builder that builds tool definitions
11- // only once, regardless of how many times NewInventoryBuilder is called.
11+ // only once, regardless of how many times CachedInventoryBuilder is called.
1212//
1313// This is particularly useful for stateless server patterns (like the remote server)
1414// where a new server instance is created per request. Without caching, every request
@@ -33,10 +33,11 @@ import (
3333// Per-request configuration (read-only, toolsets, feature flags, filters) is still
3434// applied when building the Inventory from the cached data.
3535type CachedInventory struct {
36- once sync.Once
37- tools []inventory.ServerTool
38- resources []inventory.ServerResourceTemplate
39- prompts []inventory.ServerPrompt
36+ once sync.Once
37+ initialized bool // set to true after init completes
38+ tools []inventory.ServerTool
39+ resources []inventory.ServerResourceTemplate
40+ prompts []inventory.ServerPrompt
4041}
4142
4243// global singleton for caching
@@ -111,14 +112,17 @@ func (c *CachedInventory) init(
111112 if len (extraPrompts ) > 0 {
112113 c .prompts = append (c .prompts , extraPrompts ... )
113114 }
115+
116+ c .initialized = true
114117 })
115118}
116119
117120// CachedInventoryBuilder returns an inventory.Builder pre-populated with cached
118121// tool/resource/prompt definitions.
119122//
120- // The cache must be initialized via InitInventoryCache before calling this function.
121- // If the cache is not initialized, this will initialize it with NullTranslationHelper.
123+ // The cache should typically be initialized via InitInventoryCache at startup.
124+ // If not already initialized when this function is called, it will automatically
125+ // initialize with NullTranslationHelper as a fallback.
122126//
123127// Per-request configuration can still be applied via the builder methods:
124128// - WithReadOnly(bool) - filter to read-only tools
@@ -147,14 +151,15 @@ func CachedInventoryBuilder() *inventory.Builder {
147151// IsCacheInitialized returns true if the inventory cache has been initialized.
148152// This is primarily useful for testing.
149153func IsCacheInitialized () bool {
150- // We can't directly check sync.Once state, but we can check if tools are populated
151- return len (globalInventoryCache .tools ) > 0
154+ return globalInventoryCache .initialized
152155}
153156
154157// ResetInventoryCache resets the global inventory cache, allowing it to be
155- // reinitialized with a different translator. This should only be used in tests.
158+ // reinitialized with a different translator.
156159//
157- // WARNING: This is not thread-safe and should never be called in production code.
160+ // WARNING: This function is for testing only. It is NOT thread-safe and must only
161+ // be called when no other goroutines are accessing the cache. Tests using this
162+ // function must not use t.Parallel().
158163func ResetInventoryCache () {
159164 globalInventoryCache = & CachedInventory {}
160165}
0 commit comments