mirror of
https://github.com/GH05TCREW/pentestagent.git
synced 2026-03-07 22:33:38 +00:00
mcp: SSETransport discovers messages POST endpoint from /sse and uses it for POSTs
This commit is contained in:
@@ -174,6 +174,7 @@ class SSETransport(MCPTransport):
|
||||
self.url = url
|
||||
self.session: Optional[Any] = None # aiohttp.ClientSession
|
||||
self._connected = False
|
||||
self._post_url: Optional[str] = None
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool:
|
||||
@@ -186,6 +187,48 @@ class SSETransport(MCPTransport):
|
||||
import aiohttp
|
||||
|
||||
self.session = aiohttp.ClientSession()
|
||||
|
||||
# Try to discover the POST endpoint for sending messages.
|
||||
# Many MCP SSE servers (including MetasploitMCP) expose an SSE
|
||||
# endpoint (e.g. /sse) which returns an initial `endpoint` event
|
||||
# with a `data: /messages/?session_id=...` value. We perform a
|
||||
# short GET to read that event and extract the messages POST URL.
|
||||
try:
|
||||
async with self.session.get(self.url, timeout=5) as resp:
|
||||
if resp.status != 200:
|
||||
# Still consider connected (we may only need POST),
|
||||
# but leave discovery to send() which will give clearer
|
||||
# errors if the server isn't compatible.
|
||||
self._connected = True
|
||||
return
|
||||
|
||||
# Read a few lines to find `data:`
|
||||
for _ in range(20):
|
||||
line = await resp.content.readline()
|
||||
if not line:
|
||||
break
|
||||
try:
|
||||
text = line.decode(errors="ignore").strip()
|
||||
except Exception:
|
||||
continue
|
||||
if text.startswith("data:"):
|
||||
endpoint = text.split("data:", 1)[1].strip()
|
||||
# Build absolute POST URL from the discovered endpoint
|
||||
from urllib.parse import urlparse
|
||||
|
||||
p = urlparse(self.url)
|
||||
if endpoint.startswith("http"):
|
||||
self._post_url = endpoint
|
||||
elif endpoint.startswith("/"):
|
||||
self._post_url = f"{p.scheme}://{p.netloc}{endpoint}"
|
||||
else:
|
||||
self._post_url = f"{p.scheme}://{p.netloc}/{endpoint.lstrip('/') }"
|
||||
break
|
||||
|
||||
except Exception:
|
||||
# Discovery failed — still create session and let send() report errors.
|
||||
pass
|
||||
|
||||
self._connected = True
|
||||
except ImportError as e:
|
||||
raise RuntimeError(
|
||||
@@ -206,8 +249,9 @@ class SSETransport(MCPTransport):
|
||||
raise RuntimeError("Transport not connected")
|
||||
|
||||
try:
|
||||
post_target = self._post_url or self.url
|
||||
async with self.session.post(
|
||||
self.url, json=message, headers={"Content-Type": "application/json"}
|
||||
post_target, json=message, headers={"Content-Type": "application/json"}
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
raise RuntimeError(f"HTTP error: {response.status}")
|
||||
|
||||
Reference in New Issue
Block a user