Three findings from a fresh code review on the PR:
- /mcp now goes through the existing cors middleware (same one applied
to /api by routes-setup.ts) and gains an OPTIONS preflight handler.
Current MCP clients aren't browsers so this doesn't fix anything live,
but it brings the new endpoint in line with prior CORS-centralisation
work and unblocks browser-hosted MCP clients in future.
- list_libraries now wraps the apiHandler.getLibrariesAsArray call in a
try/catch. The underlying ApiHandler throws via unwrap() if options
haven't been loaded yet (brief startup window before setOptions runs).
The HTTP /api handler already guards this; the MCP path didn't, so a
request landing in that window would surface as an opaque internal
error rather than a structured MCP isError response. Test added that
pokes the error path with a throwing fake apiHandler.
- getSafeHash no longer mutates its input. It used to set
config.nonce = tries directly on the caller's object when the
profanity-rehash loop ran. No caller relies on the mutation (the
nonce reaches storage via the returned config string, not via the
input object), but the side effect was easy to miss now that the
function is exported at module scope. Shallow clone at the top
removes the surprise; observable behaviour for callers is unchanged.
A comment was also added to createMcpServer noting that the captured
req object is safe to thread through tool callbacks because the SDK is
in stateless mode and handleRequest resolves before the route handler
exits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>