|
19 | 19 | logger = logging.getLogger("agentsniff.mcp_detector") |
20 | 20 |
|
21 | 21 | # Common MCP server paths |
22 | | -MCP_PATHS = ["/mcp", "/sse", "/mcp/sse", "/jsonrpc", "/rpc", "/api/mcp", "/v1/mcp"] |
| 22 | +MCP_PATHS = ["/mcp", "/sse", "/events", "/mcp/sse", "/message", "/jsonrpc", "/rpc", "/api/mcp", "/v1/mcp"] |
23 | 23 |
|
24 | 24 | # Common MCP ports |
25 | 25 | MCP_PORTS = [3000, 3001, 8080, 8000, 8001, 5000, 9000] |
@@ -119,21 +119,49 @@ async def _try_jsonrpc_init( |
119 | 119 | } |
120 | 120 |
|
121 | 121 | try: |
| 122 | + # Use streamable HTTP transport headers (MCP 2025-03-26+) |
| 123 | + headers = { |
| 124 | + "Content-Type": "application/json", |
| 125 | + "Accept": "application/json, text/event-stream", |
| 126 | + "MCP-Protocol-Version": "2025-03-26", |
| 127 | + } |
122 | 128 | async with session.post( |
123 | 129 | url, |
124 | 130 | json=init_request, |
125 | | - headers={"Content-Type": "application/json"}, |
| 131 | + headers=headers, |
126 | 132 | ) as resp: |
127 | 133 | if resp.status not in (200, 201): |
128 | 134 | return [] |
129 | 135 |
|
| 136 | + # Check for MCP-Protocol-Version in response headers |
| 137 | + resp_mcp_version = resp.headers.get("MCP-Protocol-Version") |
| 138 | + resp_session_id = resp.headers.get("Mcp-Session-Id") |
| 139 | + |
130 | 140 | body = await resp.text() |
131 | 141 | try: |
132 | 142 | data = json.loads(body) |
133 | 143 | except json.JSONDecodeError: |
134 | 144 | return [] |
135 | 145 |
|
136 | | - return self._analyze_jsonrpc_response(data, host, port, path, url) |
| 146 | + signals = self._analyze_jsonrpc_response(data, host, port, path, url) |
| 147 | + |
| 148 | + # MCP-Protocol-Version header is a definitive MCP indicator |
| 149 | + if resp_mcp_version and not signals: |
| 150 | + signals.append(DetectionSignal( |
| 151 | + detector=DetectorType.MCP_DETECTOR, |
| 152 | + signal_type="mcp_protocol_header", |
| 153 | + description=f"MCP-Protocol-Version header: {resp_mcp_version}", |
| 154 | + confidence=Confidence.CONFIRMED, |
| 155 | + evidence={ |
| 156 | + "host": host, |
| 157 | + "port": port, |
| 158 | + "path": path, |
| 159 | + "protocol_version": resp_mcp_version, |
| 160 | + "session_id": resp_session_id, |
| 161 | + }, |
| 162 | + )) |
| 163 | + |
| 164 | + return signals |
137 | 165 |
|
138 | 166 | except (aiohttp.ClientError, asyncio.TimeoutError, OSError): |
139 | 167 | return [] |
|
0 commit comments