Bug Description
_init() in kagent-feast-mcp/mcp-server/server.py performs unsynchronised
lazy initialisation. Under concurrent tool calls, multiple threads can observe
model is None simultaneously and each create a separate SentenceTransformer
instance, wasting memory and causing non-deterministic behaviour.
Root Cause
The check-then-act sequence has no lock, making it a classic TOCTOU race:
def _init():
global model, client
if model is None: # thread A and B both see None here
model = SentenceTransformer(EMBEDDING_MODEL) # both initialise
if client is None:
client = MilvusClient(...) # both initialise
Impact
Redundant model loads under burst traffic increase memory pressure
Non-deterministic which instance ends up in the global, making behaviour hard to reason about in production
Proposed Fix
Apply the double-checked locking pattern with a module-level threading.Lock(): a fast unsynchronised check on the hot path, with a safe re-check under the lock to guarantee single initialisation.
I will submit a PR with this fix.
Bug Description
_init()inkagent-feast-mcp/mcp-server/server.pyperforms unsynchronisedlazy initialisation. Under concurrent tool calls, multiple threads can observe
model is Nonesimultaneously and each create a separateSentenceTransformerinstance, wasting memory and causing non-deterministic behaviour.
Root Cause
The check-then-act sequence has no lock, making it a classic TOCTOU race:
Impact
Redundant model loads under burst traffic increase memory pressure
Non-deterministic which instance ends up in the global, making behaviour hard to reason about in production
Proposed Fix
Apply the double-checked locking pattern with a module-level
threading.Lock():a fast unsynchronised check on the hot path, with a safe re-check under the lock to guarantee single initialisation.I will submit a PR with this fix.