Repository navigation
MCP over HTTP picks up source changes without a restart - #337
Merged
Merged
Conversation
…tart (@architect) Ola, 2026-10-22: "yes, make the server reload sources". Finding: every tool call already runs a fresh child that reads the catalogue, so the sources tool and sources named by id follow the file over both transports. What is stale is HTTP's read roots, computed once in build_app: a probe showed a source added after start refused when read by path, and a removed one still readable. Design: SharedRoots in tin_engine.mcp.http compares the content of the user's sources file at each call's start (17 us on Ola's 8.6 KB file); on a change it re-reads the roots (3.1 ms), under a lock, off the event loop. A refused file or an overlap with --out-root keeps the last good roots and logs one warning; a running call keeps its scope; links and tokens are never reloaded. scope_for becomes async. Short path, about 40 counted lines. Tests U1-U7 (unit, no server) and S1-S2 (over HTTP). Applied with the design: README "Serving over HTTP" paragraph replacing "Changing the sources takes a restart", increment 69 section 5.2, and the ROADMAP row (designed). Co-Authored-By: Claude Opus 5.5 <[email protected]>
… applied Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tester) New tests/python/test_mcp_reload_sources.py, the design's section 7: U1 added source, U2 removed source, U3 broken file keeps the last good roots and warns once naming the file, then heals; U4 a source inside the output root is refused with "overlap"; U5 unchanged or only touched file reloads nothing; U6 ten concurrent arrivals reload once; U7 a missing file leaves the cache plus the plugins' local sources (computed from plugin_source_files(), so it holds once a source plugin is installed); S1 over HTTP, an added path runs the child, a removed one is refused before it; S2 a link made before a reload still downloads. Added beyond the list: U8, a reload cancelled while it reads the catalogue is retried by the next call (the stamp is stored after the load). It holds the load by patching tin_engine.mcp.http._shared_roots. Red at this commit: U1-U8 (no SharedRoots) and S1 (b.tif refused, "outside your folder"). S2 green, as the design says. Checked against the design's fix applied in a scratch copy (SharedRoots, async scope_for, three awaits): all 10 green five times in a row; the whole Python suite 9554 passed, 0 failed; storing the stamp before the load turns U8 red. mcp_http_driver.py: rasputin_server's docstring now says RASPUTIN_DATA holds for the server's life, since the app copies the environment. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…(@developer) SharedRoots (tin_engine.mcp.http) holds the read roots every user shares. Each call's scope_for awaits current(): under one asyncio lock it reads the sources-file candidates' bytes in a worker thread and compares them with the stored stamp; on a change it reloads through the module-level _shared_roots plus the --out-root overlap check, in a worker thread. A refused file or an overlap logs one warning and keeps the last good roots; that stamp is stored so the same content is judged once. The stamp of a good file is stored only after the load, so a cancelled reload is retried (planted the early store: the cancelled-reload test fails). build_app copies os.environ once. scope_for becomes async in build_server; stdio's default is an async def. HTTP_INSTRUCTIONS: a change to the sources applies from the next call. Counted lines (tools/count_loc.py 94a157b): 49 net (http.py 47, server.py 2), against the design's estimate of about 40, worst case 55; __all__ and the sources import are split over lines by ruff format (14 of the 49 lines). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…pplied Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Increment 90: rasputin mcp --http recomputes its read roots (the folders a call may read besides the caller's own) when the sources file changes, checked at each call's start, so a new or removed source applies from the next call with no restart and download links stay valid. A broken file keeps the last good roots and logs one warning; a running call keeps its roots; tokens and links are never reloaded. The catalogue itself was already fresh per call (each call is a child process). 49 counted lines; tests U1-U8, S1-S2; full suite 9,573 passed. Review: design APPROVED WITH WORDINGS on 721dfbb, code APPROVED WITH WORDINGS on 38940a4 (@Reviewer), applied in 831d126.
🤖 Generated with Claude Code