Dify reinitializes MCP session per tool call → multi-step tools fail (e.g. browser_navigate + screenshot) #16294

Open
opened 2026-02-21 19:25:30 -05:00 by yindo · 3 comments
Owner

Originally created by @55Kamiryo on GitHub (Aug 20, 2025).

Originally assigned to: @55Kamiryo on GitHub.

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.7.2

Cloud or Self Hosted

Cloud

Steps to reproduce

  • Start MCP server locally

    npx @playwright/mcp@latest --port 8931 --output-dir=./mcp-out --save-session --save-trace
    

    (server runs on http://localhost:8931)

  • Expose via ngrok (to allow Dify cloud instance to connect)

    ngrok http 8931
    

    Example: https://xxxx-xxx-xxx.ngrok-free.app/mcp (or sse)

  • Connect Dify workflow agent with a tool node pointing to the ngrok-exposed MCP endpoint.

  • First tool call

    • browser_navigate to https://www.yahoo.co.jp/
    • Works fine, response includes Mcp-Session-Id in headers, and page opens.

【Result】
Image

【browser_navigate/sse】
Image

【browser_navigate/mcp】
Image

  • Second tool call
    • browser_take_screenshot in the same workflow execution.
    • Dify re-initializes (initialize) and gets a new Mcp-Session-Id.
    • Screenshot fails with:
      Error: No open pages available. Use the "browser_navigate" tool to navigate to a page first.
      

【Result】
Image

【initialize/sse】
Image

【browser_take_screenshot/sse】
Image

【initialize/mcp】
Image

【browser_take_screenshot/mcp】
Image

✔️ Expected Behavior

  • Dify should keep the same MCP session ID across tool calls in a single workflow.

  • Multi-step tools (e.g., navigate → screenshot) should work seamlessly.

Actual Behavior

  • Dify re-initializes a new MCP session per tool call.

  • The previous session state (open browser/page) is lost.

  • Tools that require multi-step state fail with errors like "No open pages available".

Originally created by @55Kamiryo on GitHub (Aug 20, 2025). Originally assigned to: @55Kamiryo on GitHub. ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.7.2 ### Cloud or Self Hosted Cloud ### Steps to reproduce * **Start MCP server locally** ``` npx @playwright/mcp@latest --port 8931 --output-dir=./mcp-out --save-session --save-trace ``` (server runs on `http://localhost:8931`) * **Expose via ngrok** (to allow Dify cloud instance to connect) ``` ngrok http 8931 ``` Example: `https://xxxx-xxx-xxx.ngrok-free.app/mcp (or sse)` * **Connect Dify workflow agent** with a tool node pointing to the ngrok-exposed MCP endpoint. * **First tool call** * `browser_navigate` to `https://www.yahoo.co.jp/` * Works fine, response includes `Mcp-Session-Id` in headers, and page opens. **【Result】** <img width="379" height="264" alt="Image" src="https://github.com/user-attachments/assets/2563c310-a74e-4552-9f1a-96e040f53860" /> **【browser_navigate/sse】** <img width="1184" height="601" alt="Image" src="https://github.com/user-attachments/assets/3bfc760b-9134-4ae4-90ce-be31944b7c81" /> **【browser_navigate/mcp】** <img width="1190" height="450" alt="Image" src="https://github.com/user-attachments/assets/9ba3e82d-6f6c-4513-a111-2f8a9eeaf370" /> * **Second tool call** * `browser_take_screenshot` in the same workflow execution. * Dify re-initializes (`initialize`) and gets a new `Mcp-Session-Id`. * Screenshot fails with: ``` Error: No open pages available. Use the &quot;browser_navigate&quot; tool to navigate to a page first. ``` **【Result】** <img width="374" height="258" alt="Image" src="https://github.com/user-attachments/assets/f78486b4-c09b-4d73-82bf-23b3696160e7" /> **【initialize/sse】** <img width="1186" height="504" alt="Image" src="https://github.com/user-attachments/assets/8c642c53-0e06-4fe1-b275-11d1176017fd" /> **【browser_take_screenshot/sse】** <img width="1186" height="442" alt="Image" src="https://github.com/user-attachments/assets/2932b017-2ea7-4d3e-8845-e79e2ca094b3" /> **【initialize/mcp】** <img width="1190" height="432" alt="Image" src="https://github.com/user-attachments/assets/5491d99f-4138-46a6-a0af-a9dd76402a57" /> **【browser_take_screenshot/mcp】** <img width="1194" height="415" alt="Image" src="https://github.com/user-attachments/assets/b9f8b2b6-e436-46b9-a747-685f9e0fc129" /> ### ✔️ Expected Behavior - Dify should keep the same MCP session ID across tool calls in a single workflow. - Multi-step tools (e.g., navigate → screenshot) should work seamlessly. ### ❌ Actual Behavior - Dify re-initializes a new MCP session per tool call. - The previous session state (open browser/page) is lost. - Tools that require multi-step state fail with errors like "No open pages available".
yindo added the 🐞 bug label 2026-02-21 19:25:30 -05:00
Author
Owner

@55Kamiryo commented on GitHub (Aug 20, 2025):

This issue seems related to the MCP session handling behavior.
We have also reported the corresponding server-side perspective in the Playwright MCP repository:
microsoft/playwright-mcp#913

@55Kamiryo commented on GitHub (Aug 20, 2025): This issue seems related to the MCP session handling behavior. We have also reported the corresponding server-side perspective in the Playwright MCP repository: [microsoft/playwright-mcp#913](https://github.com/microsoft/playwright-mcp/issues/913)
Author
Owner

@Vivecccccc commented on GitHub (Sep 19, 2025):

Similar issue occurred to me as well, so I turned to Copilot for some help :-) I think it kinda makes sense.


Root cause and a concrete path to fix

Short answer

  • This is reproducible and expected with Dify’s current MCP client lifecycle: each workflow MCP node creates a brand‑new MCPClient and tears it down after the single tool call. In Streamable HTTP mode, the transport terminates the server session on context exit, so the next node re‑initializes and gets a fresh Mcp-Session-Id. Any server state (like an open browser/page in playwright-mcp) is lost between nodes.

Why this happens (code references)

Impact

  • Multi-step tools (e.g., playwright-mcp: browser_navigate → screenshot) fail on the second node, because the first node’s session (holding the open page) was terminated when the MCPClient context exited.
@Vivecccccc commented on GitHub (Sep 19, 2025): Similar issue occurred to me as well, so I turned to Copilot for some help :-) I think it kinda makes sense. --- Root cause and a concrete path to fix Short answer - This is reproducible and expected with Dify’s current MCP client lifecycle: each workflow MCP node creates a brand‑new MCPClient and tears it down after the single tool call. In Streamable HTTP mode, the transport terminates the server session on context exit, so the next node re‑initializes and gets a fresh Mcp-Session-Id. Any server state (like an open browser/page in playwright-mcp) is lost between nodes. Why this happens (code references) - Per-call MCPClient context in MCPTool: - Each tool invocation uses a short-lived context: with MCPClient(...) as mcp_client: … so a new session is created and then cleaned up for every node call. - File: core/tools/mcp_tool/tool.py (_invoke) - https://github.com/langgenius/dify/blob/87394d2512f630cb0ea752b3e8ab95c3dab2c8f6/api/core/tools/mcp_tool/tool.py#L47-L65 - Streamable HTTP session is explicitly terminated on context exit: - streamablehttp_client’s context manager calls terminate_session(client) if a session_id exists and terminate_on_close=True (default). - File: core/mcp/client/streamable_client.py (streamablehttp_client yield/finally) - https://github.com/langgenius/dify/blob/87394d2512f630cb0ea752b3e8ab95c3dab2c8f6/api/core/mcp/client/streamable_client.py#L455-L472 - Session termination (DELETE with mcp-session-id): - https://github.com/langgenius/dify/blob/87394d2512f630cb0ea752b3e8ab95c3dab2c8f6/api/core/mcp/client/streamable_client.py#L318-L333 - New session per client init: - MCPClient builds a new transport and ClientSession on each enter and calls initialize() immediately. - File: core/mcp/mcp_client.py (connect_server + initialize) - https://github.com/langgenius/dify/blob/87394d2512f630cb0ea752b3e8ab95c3dab2c8f6/api/core/mcp/mcp_client.py#L91-L113 - https://github.com/langgenius/dify/blob/87394d2512f630cb0ea752b3e8ab95c3dab2c8f6/api/core/mcp/mcp_client.py#L115-L129 Impact - Multi-step tools (e.g., playwright-mcp: browser_navigate → screenshot) fail on the second node, because the first node’s session (holding the open page) was terminated when the MCPClient context exited.
Author
Owner

@55Kamiryo commented on GitHub (Nov 24, 2025):

Closing the previous PR and opening a new one. The main branch’s MCP session behavior changed, so I reworked the implementation to align with the current spec (persistent sessions per workflow, fixed cleanup/race issues). Please check the new PR linked

@55Kamiryo commented on GitHub (Nov 24, 2025): Closing the previous PR and opening a new one. The main branch’s MCP session behavior changed, so I reworked the implementation to align with the current spec (persistent sessions per workflow, fixed cleanup/race issues). Please check the new PR linked
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#16294