Skip to content

Commit d7e7f65

Browse files
Fix issue with MCPClient connection handling.
1 parent dbce572 commit d7e7f65

File tree

5 files changed

+27
-46
lines changed

5 files changed

+27
-46
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ jobs:
2121
- name: Set up Python
2222
uses: actions/setup-python@v4
2323
with:
24-
python-version: '3.9'
24+
python-version: '3.11'
25+
26+
- name: Upgrade pip
27+
run: python -m pip install --upgrade pip
2528

2629
- name: Cache pip
27-
uses: actions/cache@v3
30+
uses: actions/cache@v4
2831
with:
2932
path: ~/.cache/pip
3033
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
@@ -34,10 +37,10 @@ jobs:
3437
3538
- name: Install dependencies
3639
run: |
37-
python -m venv venv
38-
source venv/bin/activate || .\venv\Scripts\Activate.ps1
39-
pip install -r requirements.txt
40-
playwright install
40+
python -m pip install -r requirements.txt
41+
# If mcp is private, uncomment below:
42+
# python -m pip install git+https://github.com/your-org/mcp.git
43+
playwright install
4144
4245
4346
- name: Run tests

playwright-python-mcp

Lines changed: 0 additions & 1 deletion
This file was deleted.

playwright_mcp/mcp_adapter.py

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,11 @@
11
# playwright_mcp/mcp_adapter.py
22

33
import asyncio
4-
from playwright.sync_api import sync_playwright
5-
from playwright_mcp.mcp_client import MCPClient
4+
from .mcp_client import MCPClient
65

76
async def run_mcp_test_flow():
8-
"""Run Playwright test with MCP reasoning support."""
9-
# Connect to a local MCP server or model endpoint
10-
mcp = MCPClient("wss://mcp.openai.com/v1") # Example placeholder
11-
await mcp.connect()
12-
13-
from playwright.sync_api import sync_playwright
14-
with sync_playwright() as p:
15-
browser = p.chromium.launch(headless=True)
16-
page = browser.new_page()
17-
page.goto("https://example.com")
18-
title = page.title()
19-
20-
print(f"[Playwright] Page title: {title}")
21-
22-
# Send the title as context to MCP
23-
response = await mcp.send_context({"title": title})
24-
print(f"[MCP] Response: {response}")
25-
26-
browser.close()
27-
28-
await mcp.close()
29-
30-
if __name__ == "__main__":
31-
asyncio.run(run_mcp_test_flow())
7+
client = MCPClient("wss://mcp.openai.com/v1")
8+
await client.connect()
9+
response = await client.send_context({"page": "https://example.com"})
10+
print("MCP Response:", response)
11+
await client.close()

playwright_mcp/mcp_client.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# playwright_mcp/mcp_client.py
22

3-
from mcp import Client, connect_websocket
3+
from mcp import client as mcp_client # import the lowercase module
44
import asyncio
5-
import json
65

76
class MCPClient:
87
def __init__(self, server_url: str):
@@ -11,11 +10,11 @@ def __init__(self, server_url: str):
1110

1211
async def connect(self):
1312
print(f"[MCP] Connecting to {self.server_url}...")
14-
self.client = await connect_websocket(self.server_url)
13+
self.client = mcp_client.Client(self.server_url) # use Client via mcp_client
14+
await self.client.connect()
1515
print("[MCP] Connected.")
1616

1717
async def send_context(self, context_data: dict):
18-
"""Send context (like page title or state) to MCP model for reasoning."""
1918
if not self.client:
2019
raise RuntimeError("MCP client not connected.")
2120
response = await self.client.query({"context": context_data})

report.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@
328328
</head>
329329
<body>
330330
<h1 id="title">report.html</h1>
331-
<p>Report generated on 13-Oct-2025 at 21:50:40 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
331+
<p>Report generated on 14-Oct-2025 at 00:36:47 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
332332
v4.1.1</p>
333333
<div id="environment-header">
334334
<h2>Environment</h2>
@@ -382,7 +382,7 @@ <h2>Environment</h2>
382382
<h2>Summary</h2>
383383
<div class="additional-summary prefix">
384384
</div>
385-
<p class="run-count">0 test took 0 ms.</p>
385+
<p class="run-count">2 tests took 00:00:22.</p>
386386
<p class="filter">(Un)check the boxes to filter the results.</p>
387387
<div class="summary__reload">
388388
<div class="summary__reload__button hidden" onclick="location.reload()">
@@ -392,18 +392,18 @@ <h2>Summary</h2>
392392
<div class="summary__spacer"></div>
393393
<div class="controls">
394394
<div class="filters">
395-
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="failed" disabled/>
396-
<span class="failed">0 Failed,</span>
397-
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="passed" disabled/>
398-
<span class="passed">0 Passed,</span>
395+
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="failed" />
396+
<span class="failed">1 Failed,</span>
397+
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="passed" />
398+
<span class="passed">1 Passed,</span>
399399
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="skipped" disabled/>
400400
<span class="skipped">0 Skipped,</span>
401401
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xfailed" disabled/>
402402
<span class="xfailed">0 Expected failures,</span>
403403
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xpassed" disabled/>
404404
<span class="xpassed">0 Unexpected passes,</span>
405-
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="error" />
406-
<span class="error">1 Errors,</span>
405+
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="error" disabled/>
406+
<span class="error">0 Errors,</span>
407407
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="rerun" disabled/>
408408
<span class="rerun">0 Reruns</span>
409409
</div>
@@ -429,7 +429,7 @@ <h2>Summary</h2>
429429
</table>
430430
</body>
431431
<footer>
432-
<div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.13.2&#34;, &#34;Platform&#34;: &#34;Windows-11-10.0.26100-SP0&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.4.2&#34;, &#34;pluggy&#34;: &#34;1.6.0&#34;}, &#34;Plugins&#34;: {&#34;anyio&#34;: &#34;4.11.0&#34;, &#34;html&#34;: &#34;4.1.1&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;}, &#34;JAVA_HOME&#34;: &#34;C:\\Program Files\\Java\\jdk-19&#34;}, &#34;tests&#34;: {&#34;tests/test_example.py&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Error&#34;, &#34;testId&#34;: &#34;tests/test_example.py::collect&#34;, &#34;duration&#34;: &#34;0 ms&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Error&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_example.py::collect&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;0 ms&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;ImportError while importing test module &amp;#x27;C:\\Users\\krish\\workspace-kp\\playwright-python-mcp\\tests\\test_example.py&amp;#x27;.\nHint: make sure your test modules/packages have valid Python names.\nTraceback:\n..\\..\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\importlib\\__init__.py:88: in import_module\n return _bootstrap._gcd_import(name[level:], package, level)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\ntests\\test_example.py:1: in &amp;lt;module&amp;gt;\n from playwright_mcp.browser import launch_and_get_title\nE ModuleNotFoundError: No module named &amp;#x27;playwright_mcp&amp;#x27;\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;report.html&#34;}"></div>
432+
<div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.13.2&#34;, &#34;Platform&#34;: &#34;Windows-11-10.0.26100-SP0&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.4.2&#34;, &#34;pluggy&#34;: &#34;1.6.0&#34;}, &#34;Plugins&#34;: {&#34;anyio&#34;: &#34;4.11.0&#34;, &#34;base-url&#34;: &#34;2.1.0&#34;, &#34;html&#34;: &#34;4.1.1&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;, &#34;playwright&#34;: &#34;0.7.1&#34;}, &#34;JAVA_HOME&#34;: &#34;C:\\Program Files\\Java\\jdk-19&#34;, &#34;Base URL&#34;: &#34;&#34;}, &#34;tests&#34;: {&#34;tests/test_example.py::test_example_title&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;tests/test_example.py::test_example_title&#34;, &#34;duration&#34;: &#34;00:00:22&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_example.py::test_example_title&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:22&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;No log output captured.&#34;}], &#34;tests/test_mcp_integration.py::test_mcp_integration&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Failed&#34;, &#34;testId&#34;: &#34;tests/test_mcp_integration.py::test_mcp_integration&#34;, &#34;duration&#34;: &#34;3 ms&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Failed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_mcp_integration.py::test_mcp_integration&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;3 ms&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;def test_mcp_integration():\n &amp;quot;&amp;quot;&amp;quot;Ensure MCP integration and Playwright flow work end-to-end.&amp;quot;&amp;quot;&amp;quot;\n&amp;gt; asyncio.run(run_mcp_test_flow())\n\ntests\\test_mcp_integration.py:7: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n..\\..\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\asyncio\\runners.py:195: in run\n return runner.run(main)\n ^^^^^^^^^^^^^^^^\n..\\..\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\asyncio\\runners.py:118: in run\n return self._loop.run_until_complete(task)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n..\\..\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\asyncio\\base_events.py:725: in run_until_complete\n return future.result()\n ^^^^^^^^^^^^^^^\nplaywright_mcp\\mcp_adapter.py:8: in run_mcp_test_flow\n await client.connect()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = &amp;lt;playwright_mcp.mcp_client.MCPClient object at 0x0000026C9D7956A0&amp;gt;\n\n async def connect(self):\n print(f&amp;quot;[MCP] Connecting to {self.server_url}...&amp;quot;)\n&amp;gt; self.client = mcp_client.Client(self.server_url) # use Client via mcp_client\n ^^^^^^^^^^^^^^^^^\nE AttributeError: module &amp;#x27;mcp.client&amp;#x27; has no attribute &amp;#x27;Client&amp;#x27;\n\nplaywright_mcp\\mcp_client.py:13: AttributeError\n\n----------------------------- Captured stdout call -----------------------------\n[MCP] Connecting to wss://mcp.openai.com/v1...\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;report.html&#34;}"></div>
433433
<script>
434434
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
435435
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')

0 commit comments

Comments
 (0)