Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
155 commits
Select commit Hold shift + click to select a range
386fa99
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
945d3ff
clean up v2/mcp
HzaRashid Nov 27, 2025
9afc891
ruff (mcp)
HzaRashid Nov 27, 2025
98235f4
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
5d4a5f3
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
07909c4
fix mcp auto install tests
HzaRashid Nov 28, 2025
9295f06
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2025
9583ee7
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Nov 28, 2025
c3e0f0a
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
6a7c5e9
clean up v2/mcp
HzaRashid Nov 27, 2025
c73c033
ruff (mcp)
HzaRashid Nov 27, 2025
d25e2fb
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
d9c5a2b
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
dcc4a23
fix mcp auto install tests
HzaRashid Nov 28, 2025
1a515c2
misc
HzaRashid Nov 28, 2025
592923c
refactor mcp and mcp_projects
HzaRashid Nov 28, 2025
a6ac93a
fix mcp ctx mgmt in main.py
HzaRashid Nov 29, 2025
023b007
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
e44bf85
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
953e260
return noop response in streamable dispatcher
HzaRashid Nov 30, 2025
dca3f83
docs
HzaRashid Nov 30, 2025
fb77727
docs (main.py)
HzaRashid Nov 30, 2025
4228eb1
use classes for http mgrs
HzaRashid Dec 1, 2025
cf8cd4c
use asyncio tg for mcp projects session mgrs mgmt
HzaRashid Dec 1, 2025
e3b717f
docs
HzaRashid Dec 1, 2025
edbdf19
clean up project tasks class
HzaRashid Dec 1, 2025
bc5df6a
recover original behaviour for /{project_id} endpoint
HzaRashid Dec 1, 2025
1554c3a
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
6f873b6
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 1, 2025
49db8c5
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 1, 2025
e44d9b9
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 1, 2025
e69f395
fix for backwards compatilibility for sse requests
HimavarshaVS Dec 1, 2025
dbe619b
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
8b599f2
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
625499d
clean up v2/mcp
HzaRashid Nov 27, 2025
3edd952
ruff (mcp)
HzaRashid Nov 27, 2025
716207f
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
1b7146b
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
88d1f2a
fix mcp auto install tests
HzaRashid Nov 28, 2025
cb3d1a6
misc
HzaRashid Nov 28, 2025
78faaf7
refactor mcp and mcp_projects
HzaRashid Nov 28, 2025
6baa7dd
fix mcp ctx mgmt in main.py
HzaRashid Nov 29, 2025
fc2e11b
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
d93ccf7
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
c261a29
return noop response in streamable dispatcher
HzaRashid Nov 30, 2025
66e449e
docs
HzaRashid Nov 30, 2025
a9ecfc3
docs (main.py)
HzaRashid Nov 30, 2025
6624dc0
use classes for http mgrs
HzaRashid Dec 1, 2025
c1a7618
use asyncio tg for mcp projects session mgrs mgmt
HzaRashid Dec 1, 2025
e96266a
docs
HzaRashid Dec 1, 2025
719b7e6
clean up project tasks class
HzaRashid Dec 1, 2025
84e48e9
recover original behaviour for /{project_id} endpoint
HzaRashid Dec 1, 2025
565ae37
implement asyncio.TaskGroup backport for python 3.10
HzaRashid Dec 1, 2025
c8a9352
remove unused const
HzaRashid Dec 1, 2025
9cfeca4
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
981f85e
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 1, 2025
6fb668f
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 1, 2025
e310825
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 2, 2025
2941572
replace asyncio with anyio
HzaRashid Dec 2, 2025
f7e574f
touch ups
HzaRashid Dec 2, 2025
7402173
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 2, 2025
f892748
Merge branch 'main' into feat/http-stream-mcp
HimavarshaVS Dec 3, 2025
c0ebc4f
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 3, 2025
d0f0489
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 3, 2025
f2146eb
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 3, 2025
4c2d301
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 3, 2025
bbc3584
handle shutdown properly
HimavarshaVS Dec 3, 2025
71513e4
Merge branch 'main' into feat/http-stream-mcp
HimavarshaVS Dec 3, 2025
40df8e2
Update test_mcp_projects.py
erichare Dec 3, 2025
d606968
Fix mypy errors
erichare Dec 3, 2025
f06a9ed
rollback start manager changes
HimavarshaVS Dec 3, 2025
04914c5
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 3, 2025
75ade96
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
ae02720
return noop response in streamable dispatcher
HzaRashid Nov 30, 2025
b91ace6
docs
HzaRashid Nov 30, 2025
06d40b5
docs (main.py)
HzaRashid Nov 30, 2025
4a4920e
use classes for http mgrs
HzaRashid Dec 1, 2025
379a487
use asyncio tg for mcp projects session mgrs mgmt
HzaRashid Dec 1, 2025
ca4fe98
docs
HzaRashid Dec 1, 2025
c05de69
clean up project tasks class
HzaRashid Dec 1, 2025
d1c39e4
recover original behaviour for /{project_id} endpoint
HzaRashid Dec 1, 2025
f5441c0
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
1a1b2ce
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 1, 2025
60da51d
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 1, 2025
64b35d8
fix for backwards compatilibility for sse requests
HimavarshaVS Dec 1, 2025
8117663
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
27f8ab5
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
2cc0fec
clean up v2/mcp
HzaRashid Nov 27, 2025
23c6046
ruff (mcp)
HzaRashid Nov 27, 2025
b37b6fe
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
e49e5fe
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
144bd01
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
7a83a76
clean up v2/mcp
HzaRashid Nov 27, 2025
3a493b1
ruff (mcp)
HzaRashid Nov 27, 2025
c2ee46b
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
04bd598
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
3966682
fix mcp auto install tests
HzaRashid Nov 28, 2025
3b59b7e
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2025
dfd52ff
refactor mcp and mcp_projects
HzaRashid Nov 28, 2025
bbc5daf
fix mcp ctx mgmt in main.py
HzaRashid Nov 29, 2025
77d0804
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
2a7edeb
fix mcp auto install tests
HzaRashid Nov 28, 2025
d47c259
misc
HzaRashid Nov 28, 2025
873916f
refactor mcp and mcp_projects
HzaRashid Nov 28, 2025
e4059fc
fix mcp ctx mgmt in main.py
HzaRashid Nov 29, 2025
07a8666
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
6a9a3b2
use global exit stack mcp project servers
HzaRashid Nov 29, 2025
aca1ece
return noop response in streamable dispatcher
HzaRashid Nov 30, 2025
166d974
docs
HzaRashid Nov 30, 2025
c76cfb1
docs (main.py)
HzaRashid Nov 30, 2025
0f0257d
use classes for http mgrs
HzaRashid Dec 1, 2025
3d7ff92
use asyncio tg for mcp projects session mgrs mgmt
HzaRashid Dec 1, 2025
323258f
docs
HzaRashid Dec 1, 2025
6add199
clean up project tasks class
HzaRashid Dec 1, 2025
58d621f
recover original behaviour for /{project_id} endpoint
HzaRashid Dec 1, 2025
c52fbd5
implement asyncio.TaskGroup backport for python 3.10
HzaRashid Dec 1, 2025
c5c8fcd
remove unused const
HzaRashid Dec 1, 2025
13deb16
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 1, 2025
2321075
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 1, 2025
eefbc02
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 1, 2025
78885b6
replace asyncio with anyio
HzaRashid Dec 2, 2025
52142dd
touch ups
HzaRashid Dec 2, 2025
81c847d
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 3, 2025
924f59a
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 3, 2025
a0663e5
handle shutdown properly
HimavarshaVS Dec 3, 2025
040ca64
rollback start manager changes
HimavarshaVS Dec 3, 2025
c206c0a
Update test_mcp_projects.py
erichare Dec 3, 2025
8935e53
Fix mypy errors
erichare Dec 3, 2025
1694e3b
graceful termination of mcp projects /streamable endpoint
HzaRashid Dec 3, 2025
5654ceb
delete removed file
HzaRashid Dec 3, 2025
9f7014d
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 3, 2025
6d75e3b
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Nov 28, 2025
fad1b43
migrate mcp transport to http streamable
HzaRashid Nov 26, 2025
ca2941f
clean up v2/mcp
HzaRashid Nov 27, 2025
44ed389
ruff (mcp)
HzaRashid Nov 27, 2025
8b191e0
add back ensure_session_mgr_running handler
HzaRashid Nov 27, 2025
245e3c9
refactor mcp server and set default mcp settings on project creation
HzaRashid Nov 28, 2025
bb5faba
misc
HzaRashid Nov 28, 2025
02d5319
Merge branch 'main' into feat/http-stream-mcp
HimavarshaVS Dec 4, 2025
44b185f
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 4, 2025
2aa111e
Merge branch 'feat/http-stream-mcp' of https://github.com/langflow-ai…
HimavarshaVS Dec 4, 2025
3b4c4bd
build component index
HimavarshaVS Dec 4, 2025
173a2d1
Merge remote-tracking branch 'origin' into feat/http-stream-mcp
HimavarshaVS Dec 4, 2025
3d3def6
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 4, 2025
aea5f78
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 1, 2025
510cc65
add health check endpoint for streamable
HzaRashid Dec 4, 2025
99705e0
sync starter projects with main
HzaRashid Dec 4, 2025
1c2f734
remove unused delete method from sse transport
HzaRashid Dec 4, 2025
eea4849
Merge remote-tracking branch 'upstream/main' into feat/http-stream-mcp
HzaRashid Dec 5, 2025
269dd1e
get user-level files in handle_list_resources
HzaRashid Dec 7, 2025
0c709b3
Merge remote-tracking branch 'upstream/main' into feat/http-stream-mcp
HzaRashid Dec 8, 2025
b943b6e
add backwards compat tests for sse transport
HzaRashid Dec 8, 2025
d0925df
merge with main
HzaRashid Dec 8, 2025
d458fc2
fix frontend tests
HzaRashid Dec 8, 2025
b973b41
fix lfx test
HzaRashid Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
graceful termination of mcp projects /streamable endpoint
  • Loading branch information
HzaRashid committed Dec 3, 2025
commit 1694e3b2dfac3f1b67a3d5ee88a6340311637cef
32 changes: 15 additions & 17 deletions src/backend/base/langflow/api/v1/mcp_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ async def _dispatch_project_streamable_http(
current_project_ctx.reset(project_token)
current_user_ctx.reset(user_token)

return Response()
return ResponseNoOp(status_code=200)


@router.get("/{project_id}/sse", response_class=HTMLResponse)
Expand Down Expand Up @@ -434,11 +434,14 @@ async def handle_project_messages(


# Streamable HTTP transport
streamable_http_methods = ["GET", "POST", "DELETE"]
streamable_http_route_config = {
"methods": ["GET", "POST", "DELETE"],
"response_class": ResponseNoOp,
}


@router.api_route("/{project_id}/streamable", methods=streamable_http_methods)
@router.api_route("/{project_id}/streamable/", methods=streamable_http_methods)
@router.api_route("/{project_id}/streamable", **streamable_http_route_config)
@router.api_route("/{project_id}/streamable/", **streamable_http_route_config)
async def handle_project_streamable_http(
project_id: UUID,
request: Request,
Expand Down Expand Up @@ -1030,12 +1033,7 @@ def _args_reference_urls(args: Sequence[Any] | None, urls: list[str]) -> bool:
"""Check whether the given args list references any of the provided URLs."""
if not args or not urls:
return False
args_strings = [arg for arg in args if isinstance(arg, str)]
if not args_strings:
return False
args_set = set(args_strings)
last_arg = args_strings[-1]
return any((url == last_arg) or (url in args_set) for url in urls)
return bool({arg for arg in args if isinstance(arg, str)}.intersection(urls))


def config_contains_server_url(config_data: dict, urls: Sequence[str] | str) -> bool:
Expand Down Expand Up @@ -1249,8 +1247,8 @@ async def _run_session_manager(self, *, task_status: TaskStatus[None] = anyio.TA
"""Own the lifecycle of the project's Streamable HTTP session manager."""
try:
async with self.session_manager.run():
self._manager_started = True
task_status.started()
self._manager_started = True # set flag before unblocking task (ensures waiting requests proceed)
task_status.started() # unblock
await anyio.sleep_forever()
except anyio.get_cancelled_exc_class():
await logger.adebug(f"Streamable HTTP manager cancelled for project {self.project_id}")
Expand Down Expand Up @@ -1313,11 +1311,11 @@ async def stop(self) -> None:
async with self._start_stop_lock:
if not self._started:
return
try:
if self._task_group is not None:
self._task_group.cancel_scope.cancel()
if self._tg_task is not None:
await self._tg_task
try: # https://anyio.readthedocs.io/en/stable/cancellation.html, https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel
self._task_group.cancel_scope.cancel() # type: ignore[union-attr]
await self._tg_task # type: ignore[misc]
except Exception as e: # noqa: BLE001
await logger.aexception(f"Failed to stop project task group: {e}")
finally:
self._cleanup()
await logger.adebug("Project MCP task group stopped")
Expand Down
28 changes: 26 additions & 2 deletions src/backend/tests/unit/api/v1/test_mcp_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from httpx import AsyncClient
from langflow.api.v1.mcp_projects import (
ProjectMCPServer,
_args_reference_urls,
get_project_mcp_server,
init_mcp_servers,
project_mcp_servers,
Expand All @@ -28,6 +29,26 @@
pytestmark = pytest.mark.asyncio


@pytest.mark.parametrize(
("args", "urls", "expected"),
[
(None, ["https://langflow.local/sse"], False),
([], ["https://langflow.local/sse"], False),
([123, {"url": "foo"}], ["https://langflow.local/sse"], False),
(["https://langflow.local/sse", 42], ["https://langflow.local/sse"], True),
(["alpha", "beta"], [], False),
],
)
def test_args_reference_urls_filters_strings_only(args, urls, expected):
assert _args_reference_urls(args, urls) is expected


def test_args_reference_urls_matches_non_last_string_argument():
args = ["match-me", "other"]
urls = ["match-me"]
assert _args_reference_urls(args, urls) is True


@pytest.fixture
def mock_project(active_user):
"""Fixture to provide a mock project linked to the active user."""
Expand Down Expand Up @@ -82,8 +103,11 @@ def mock_streamable_http_manager():
async_cm = AsyncContextManagerMock()
manager_instance.run = MagicMock(return_value=async_cm)

# Mock handle_request as an async method (this is what gets called, not handle_post_message)
manager_instance.handle_request = AsyncMock()
async def _fake_handle_request(scope, receive, send): # noqa: ARG001
await send({"type": "http.response.start", "status": 200, "headers": []})
await send({"type": "http.response.body", "body": b"", "more_body": False})

manager_instance.handle_request = AsyncMock(side_effect=_fake_handle_request)

# Make the class constructor return our mocked instance
mock_class.return_value = manager_instance
Expand Down