Harden MCP server: fix routing, validation, and usage metering#341
Merged
nicoloboschi merged 6 commits intomainfrom Feb 11, 2026
Merged
Harden MCP server: fix routing, validation, and usage metering#341nicoloboschi merged 6 commits intomainfrom
nicoloboschi merged 6 commits intomainfrom
Conversation
Mental model validation hooks (validate_mental_model_get, validate_mental_model_refresh) were only called in REST HTTP handlers, not in the engine. MCP tools call engine methods directly, so usage metering was skipped entirely for MCP mental model operations. Moved pre-validation and post-completion hooks into memory_engine.py (matching the retain/recall/reflect pattern) and removed the duplicate code from http.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…al checks - Remove pre-validation from create_mental_model since callers always call submit_async_refresh_mental_model next (which validates), preventing double credit checks - Add is_internal checks to mental model metering validators (matching the existing pattern for recall/reflect) so background worker tasks skip billing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Starlette's Mount class redirects /mcp to /mcp/ with a 307 Temporary Redirect. Many MCP clients don't follow POST redirects, which causes tool discovery to fail (0 tools discovered despite successful auth). Add _MCPPathRewriteMiddleware that rewrites /mcp to /mcp/ at the ASGI level before routing, preventing the redirect entirely. Both /mcp and /mcp/ now work identically. Add regression test test_mcp_no_trailing_slash_works to verify URLs with and without trailing slashes discover tools correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove MCP_ENDPOINTS blocklist so banks named "sse"/"messages" route correctly - Scope SSE body rewriting to text/event-stream responses only to prevent data corruption - Add _validate_mental_model_inputs for name, source_query, max_tokens validation in MCP tools - Improve "not found" error messages to include bank_id context - Fix fragile tool count assertions (exact → minimum bounds) - Add integration tests: tool execution, input validation, edge-case bank names - Add unit tests for validation helper and tool-level validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Starlette's Mount class redirects /mcp -> /mcp/ with 307, which MCP clients don't follow. Previously we patched this with _MCPPathRewriteMiddleware. Now MCPMiddleware wraps the FastAPI app directly via add_middleware, intercepting /mcp* requests before they reach Starlette's router. No Mount means no redirect. - Remove _MCPPathRewriteMiddleware (no longer needed) - Remove app.mount() call - Add prefix parameter to MCPMiddleware - Use app.add_middleware() for proper Starlette integration - Simplify path stripping (just remove prefix, no mount/root_path handling) - Update routing test to match current behavior (no MCP_ENDPOINTS blocklist) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ware Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nicoloboschi
approved these changes
Feb 11, 2026
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.
Summary
Mount+ path-rewrite middleware with a single wrappingMCPMiddlewarethat intercepts/mcp*requests directly. This preventsPOST /mcp(no trailing slash) from getting a 307 redirect that breaks MCP client tool discovery.http.pyintomemory_engine.pyso MCP operations are billed correctly. Fix double validation oncreate_mental_modeland addis_internalchecks so background workers skip billing.MCP_ENDPOINTSblocklist that prevented banks named "sse" or "messages", scope SSE body rewriting totext/event-streamonly._validate_mental_model_inputshelper.Test plan
ruff checkandruff formatclean🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com