Skip to content

Add web deployment support and fix event loop handling#76

Open
LucasOnTheHub wants to merge 14 commits intomassive-com:masterfrom
LucasOnTheHub:claude/fix-mcp-prefect-compatibility-VbA5k
Open

Add web deployment support and fix event loop handling#76
LucasOnTheHub wants to merge 14 commits intomassive-com:masterfrom
LucasOnTheHub:claude/fix-mcp-prefect-compatibility-VbA5k

Conversation

@LucasOnTheHub
Copy link

Summary

This PR adds support for web/ASGI deployments (FastMCP Cloud, Prefect Horizon) while fixing event loop conflicts in nested async contexts. It introduces graceful async shutdown, replaces blocking locks with async locks, and improves environment variable handling for hosted runtimes.

Key Changes

  • Web Deployment Support: Added app.py entrypoint for FastMCP cloud/streamable-http hosting with proper environment variable injection and secret cleanup
  • Async Lock for Index Building: Replaced threading.Lock with asyncio.Lock in _get_index() to prevent blocking the event loop in ASGI contexts
  • Graceful HTTP Client Shutdown:
    • Added shutdown_http_client() async function for ASGI lifespan handlers
    • Kept _close_http_client_sync() as atexit fallback for CLI usage
    • Removed automatic atexit registration from _get_http_client()
  • Event Loop Detection & Threading Fallback: Enhanced run() function to detect already-running event loops and spawn a dedicated thread with its own event loop, preventing RuntimeError: Already running asyncio in this thread
  • Environment Variable Security: Changed from aggressive os.environ.clear() to a targeted keep-list approach, preserving system variables needed by hosted runtimes (PATH, HOME, SSL_CERT_FILE, etc.) while removing only secrets
  • Removed Environment Variable Dependency: build_index() no longer reads MASSIVE_LLMS_TXT_URL from environment; it must be passed explicitly via configure_credentials()
  • Metadata Updates: Bumped version to 1.0.3, improved project description, added license and project URLs to pyproject.toml
  • Docker Base Image: Updated from Python 3.13.3 to 3.12 for better compatibility

Implementation Details

  • Fast-path optimization in _get_index() checks if index is already built before acquiring the async lock
  • Thread-based fallback in run() handles frameworks (AWS Lambda, Prefect, Jupyter) where event loops exist but aren't detected by asyncio.get_running_loop()
  • Secrets are removed at import time in app.py to prevent exposure in hosted environments
  • All async shutdown logic is properly integrated with ASGI lifespan handlers while maintaining backward compatibility with CLI/stdio transport

https://claude.ai/code/session_01FrTHwD3YLpyRocAauKvATX

claude and others added 14 commits March 16, 2026 15:14
- Add --host/--port CLI args and MCP_HOST/MCP_PORT env vars for HTTP transports
- Add configure_server() to set FastMCP host/port settings
- Update Dockerfile to default to streamable-http transport and expose port 8000
- Add docker-compose.web.yml for easy HTTP deployment

https://claude.ai/code/session_01SqUoq1cMV7cZArVK5wRWgr
Add streamable-http web deployment support for Claude web connector
…tmcp-YGe80

Revert "Add streamable-http web deployment support for Claude web con…
- Align pyproject.toml version to 1.0.3 (was 0.8.3, manifest.json already 1.0.3)
- Replace generic description with proper project description
- Add missing license, keywords, and project URLs to pyproject.toml
- Update README install URLs from v0.8.3 to v1.0.3
- Fix Dockerfile base image to Python 3.12 (matches requires-python)
- Remove dead os.environ fallback in index.py (env cleared at startup)
- Remove unused os import from index.py

https://claude.ai/code/session_01QhkJLFSZANGg1bcgK1aEQW
…pdates-c5NoD

Sync versions, metadata, and fix stale references
The FastMCP cloud hosting expects `app.py:mcp` as the entrypoint.
This file loads env vars, configures credentials, and exposes
the FastMCP server instance as `mcp`.

https://claude.ai/code/session_01L6iEMsSTcMkAhB5hftm51q
…or-BRBit

Add app.py entrypoint for FastMCP web deployment
When run() is called inside an environment that already has an active
asyncio event loop (Prefect Horizon, AWS Lambda, Jupyter), the
anyio.run() call inside FastMCP.run() raises RuntimeError.

Detect the running loop and spin up a dedicated thread with its own
event loop to run the async server, avoiding the conflict.

https://claude.ai/code/session_01FYaDEf5J1UWrbg3KL8DRas
…rror-xSCef

Fix "Already running asyncio in this thread" error in Prefect/Lambda
The existing asyncio.get_running_loop() check can miss event loops in
certain environments (AWS Lambda, Prefect, etc.) where the loop exists
but isn't detectable from a synchronous call site. When mass_mcp.run()
then tries anyio.run()/asyncio.run(), it fails with a RuntimeError.

Add a try/except fallback around mass_mcp.run() that catches the asyncio
conflict error and retries in a dedicated thread with its own event loop,
matching the behavior of the existing proactive detection path.

https://claude.ai/code/session_01Ky8mRZVDKbTyZ16YRnQn2W
…rror-MROKc

Fix "Already running asyncio in this thread" error with retry fallback
… hosting

- Replace os.environ.clear() with selective secret removal: the total wipe
  broke PATH, HOME, SSL_CERT_FILE and other vars needed by hosted runtimes
  (ASGI servers, Prefect Horizon, FastMCP Cloud) for SSL, subprocess
  spawning, and HTTP transport.

- Replace threading.Lock in _get_index() with asyncio.Lock to avoid
  blocking the event loop in concurrent web request contexts.

- Split httpx client cleanup: expose async shutdown_http_client() for ASGI
  lifespan handlers, keep sync _close_http_client_sync() as atexit fallback
  for CLI/stdio mode only.

- Improve app.py: add security (remove secret env vars after capture),
  import shutdown_http_client for lifespan use, add logging.

https://claude.ai/code/session_01FrTHwD3YLpyRocAauKvATX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants