Skip to content

Commit 8d9024c

Browse files
committed
expand detection signatures from agent infrastructure research
Infra domains (12 -> 45): add MCP registries (registry.smithery.ai, server.smithery.ai, registry.modelcontextprotocol.io, mcp.run, mcp.so, pulsemcp.com, mcphub.tools, opentools.com, mcpindex.net), observability platforms (cloud.langfuse.com, eu.api.smith.langchain.com, braintrust, agentops, wandb weave, arize phoenix, llamatrace), deployment/sandbox (e2b, toolhouse, composio backend), IDE agent backends (cursor.sh, githubcopilot.com, windsurf.com) Domain suffixes (9 -> 16): add .run.tools (Smithery remote MCP), .e2b.dev (sandbox), .modal.run, .fly.dev, .replit.dev, .repl.co, .gcpp.cursor.sh (Cursor regional endpoints) Frameworks (58 -> 69): add anthropic_sdk (x-stainless-* headers), google_genai_sdk, claude_desktop, opencode, blackboxai, mcp_inspector, strands_agents, google_adk, vercel_ai_sdk, e2b, agentops. Expand existing: cursor (x-cursor-* headers, x-ghost-mode), copilot (GithubCopilot UA, Editor-Version/Plugin-Version headers), claude_code (anthropic-beta header), openai_assistants (x-stainless-* headers, OpenAI-Beta), helicone (full Helicone-* header family), portkey (full x-portkey-* header family), braintrust (x-bt-* headers). Add mcp_client_name field for MCP initialize fingerprinting. MCP detector: add MCP-Protocol-Version header detection (definitive MCP indicator), streamable HTTP transport headers, /events and /message paths for legacy SSE transport Endpoint prober: add MEMORY.md and .well-known/agent-identity.json to metadata paths MCP methods: add sampling/createMessage
1 parent ce1b904 commit 8d9024c

10 files changed

Lines changed: 226 additions & 30 deletions

File tree

agentsniff/cli.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from agentsniff.baseline import NetworkBaseline
1717
from agentsniff.config import ScanConfig, default_config_yaml
18-
from agentsniff.signatures import get_signature_data, VERIFIED, INVALID, UNVERIFIED
18+
from agentsniff.signatures import get_signature_data, VERIFIED, INVALID
1919
from agentsniff.notifier import should_alert, send_alerts
2020
from agentsniff.scanner import run_scan
2121
from agentsniff.storage import ScanStore
@@ -72,7 +72,6 @@ def _print_signature_status():
7272

7373
invalid = [k for k, v in status.items() if v == INVALID]
7474
verified = [k for k, v in status.items() if v == VERIFIED]
75-
unverified = [k for k, v in status.items() if v == UNVERIFIED]
7675

7776
if invalid:
7877
print(

agentsniff/detectors/dns_monitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import struct
1414
from datetime import datetime, timezone
1515

16-
from agentsniff.config import AGENT_INFRA_DOMAINS, LLM_API_DOMAIN_SUFFIXES, ScanConfig
16+
from agentsniff.config import LLM_API_DOMAIN_SUFFIXES, ScanConfig
1717
from agentsniff.detectors.base import BaseDetector, DetectorRegistry
1818
from agentsniff.models import Confidence, DetectionSignal, DetectorType
1919

agentsniff/detectors/endpoint_prober.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
"/.well-known/agents.json",
3030
"/.well-known/ai-plugin.json",
3131
"/.well-known/clawhub.json",
32+
"/.well-known/agent-identity.json",
3233
"/AGENTS.md",
3334
"/SKILL.md",
3435
"/SOUL.md",
36+
"/MEMORY.md",
3537
]
3638

3739
# Paths that indicate OpenAPI/Swagger specs (common in agent API frameworks)

agentsniff/detectors/mcp_detector.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
logger = logging.getLogger("agentsniff.mcp_detector")
2020

2121
# 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"]
2323

2424
# Common MCP ports
2525
MCP_PORTS = [3000, 3001, 8080, 8000, 8001, 5000, 9000]
@@ -119,21 +119,49 @@ async def _try_jsonrpc_init(
119119
}
120120

121121
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+
}
122128
async with session.post(
123129
url,
124130
json=init_request,
125-
headers={"Content-Type": "application/json"},
131+
headers=headers,
126132
) as resp:
127133
if resp.status not in (200, 201):
128134
return []
129135

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+
130140
body = await resp.text()
131141
try:
132142
data = json.loads(body)
133143
except json.JSONDecodeError:
134144
return []
135145

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
137165

138166
except (aiohttp.ClientError, asyncio.TimeoutError, OSError):
139167
return []

agentsniff/signatures/agent_infra_domains.json

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,43 @@
55
"api.moltyverse.email",
66
"moltyverse.app",
77
"smithery.ai",
8+
"registry.smithery.ai",
9+
"server.smithery.ai",
810
"glama.ai",
11+
"registry.modelcontextprotocol.io",
12+
"staging.registry.modelcontextprotocol.io",
13+
"mcp.run",
14+
"mcp.so",
15+
"pulsemcp.com",
16+
"mcphub.tools",
17+
"mcp.composio.dev",
18+
"opentools.com",
19+
"mcpindex.net",
920
"api.langfuse.com",
21+
"cloud.langfuse.com",
22+
"us.cloud.langfuse.com",
1023
"api.smith.langchain.com",
24+
"eu.api.smith.langchain.com",
25+
"hub.langchain.com",
1126
"api.helicone.ai",
27+
"gateway.helicone.ai",
28+
"ai-gateway.helicone.ai",
29+
"api.braintrust.dev",
30+
"api.agentops.ai",
31+
"otlp.agentops.ai",
32+
"trace.wandb.ai",
33+
"app.phoenix.arize.com",
34+
"llamatrace.com",
1235
"api.composio.dev",
13-
"app.composio.dev"
36+
"app.composio.dev",
37+
"backend.composio.dev",
38+
"app.toolhouse.ai",
39+
"api.e2b.dev",
40+
"api.portkey.ai",
41+
"api2.cursor.sh",
42+
"api4.cursor.sh",
43+
"cursor.sh",
44+
"api.githubcopilot.com",
45+
"api.business.githubcopilot.com",
46+
"windsurf.com"
1447
]

agentsniff/signatures/domain_suffixes.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,12 @@
77
".ml.cloud.ibm.com",
88
".cognitiveservices.azure.com",
99
".inference.ai.azure.com",
10-
".volces.com"
10+
".volces.com",
11+
".run.tools",
12+
".e2b.dev",
13+
".modal.run",
14+
".fly.dev",
15+
".replit.dev",
16+
".repl.co",
17+
".gcpp.cursor.sh"
1118
]

0 commit comments

Comments
 (0)