Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/mcp_scan/MCPScanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@

from httpx import HTTPStatusError

from mcp_scan.models import Issue, RemoteServer, ScanError, ScanPathResult, ServerScanResult, StdioServer, UnknownMCPConfig
from mcp_scan.direct_scanner import direct_scan, is_direct_scan
from mcp_scan.mcp_client import check_server_with_timeout, scan_mcp_config_file
from mcp_scan.models import (
Issue,
RemoteServer,
ScanError,
ScanPathResult,
ServerScanResult,
StdioServer,
UnknownMCPConfig,
)
from mcp_scan.Storage import Storage
from mcp_scan.verify_api import analyze_machine
from mcp_scan.well_known_clients import get_builtin_tools

from .direct_scanner import direct_scan, is_direct_scan
from .mcp_client import check_server_with_timeout, scan_mcp_config_file
from .Storage import Storage
from .verify_api import analyze_machine

# Set up logger for this module
logger = logging.getLogger(__name__)

Expand Down
4 changes: 2 additions & 2 deletions src/mcp_scan/Storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from filelock import FileLock
from pydantic import ValidationError

from .models import Entity, ScannedEntities, ScannedEntity, entity_type_to_str, hash_entity
from mcp_scan.models import Entity, ScannedEntities, ScannedEntity, entity_type_to_str, hash_entity

try:
from mcp_scan_server.models import DEFAULT_GUARDRAIL_CONFIG, GuardrailConfigFile
Expand All @@ -28,7 +28,7 @@ def __init__(self, path: str):
logger.debug("Expanded path: %s", self.path)
self.scanned_entities: ScannedEntities = ScannedEntities({})
self.whitelist: dict[str, str] = {}

if GuardrailConfigFile is not None:
self.guardrails_config: GuardrailConfigFile = GuardrailConfigFile()
else:
Expand Down
6 changes: 3 additions & 3 deletions src/mcp_scan/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .lib import inspect, scan
from .MCPScanner import MCPScanner
from .version import version_info
from mcp_scan.lib import inspect, scan
from mcp_scan.MCPScanner import MCPScanner
from mcp_scan.version import version_info

__all__ = ["MCPScanner", "inspect", "scan"]
__version__ = version_info
21 changes: 10 additions & 11 deletions src/mcp_scan/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@
import rich
from rich.logging import RichHandler

from mcp_scan.MCPScanner import MCPScanner
from mcp_scan.printer import print_scan_result
from mcp_scan.Storage import Storage
from mcp_scan.upload import upload

from .MCPScanner import MCPScanner
from .printer import print_scan_result
from .Storage import Storage
from .utils import parse_headers
from .version import version_info
from .well_known_clients import WELL_KNOWN_MCP_PATHS, client_shorthands_to_paths
from mcp_scan.utils import parse_headers
from mcp_scan.version import version_info
from mcp_scan.well_known_clients import WELL_KNOWN_MCP_PATHS, client_shorthands_to_paths

# Proxy-related imports (require [proxy] extra)
_PROXY_AVAILABLE = None
Expand All @@ -32,7 +31,7 @@ def check_proxy_dependencies():
global _PROXY_AVAILABLE
if _PROXY_AVAILABLE is not None:
return _PROXY_AVAILABLE

try:
import invariant # noqa: F401
import invariant_sdk # noqa: F401
Expand All @@ -45,7 +44,7 @@ def check_proxy_dependencies():
def require_proxy_dependencies(command_name: str):
"""
Raise an error if proxy dependencies are not installed.

Args:
command_name: Name of the command that requires proxy dependencies
"""
Expand Down Expand Up @@ -593,7 +592,7 @@ def main():
async def install():
require_proxy_dependencies("install-proxy")
from mcp_scan.gateway import MCPGatewayConfig, MCPGatewayInstaller

try:
check_install_args(args)
except argparse.ArgumentError as e:
Expand All @@ -616,7 +615,7 @@ async def install():
async def uninstall():
require_proxy_dependencies("uninstall-proxy")
from mcp_scan.gateway import MCPGatewayInstaller

installer = MCPGatewayInstaller(paths=args.files)
await installer.uninstall(verbose=True)

Expand Down
2 changes: 1 addition & 1 deletion src/mcp_scan/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def uninstall_gateway(
raise MCPServerIsNotGateway()

assert isinstance(server.args, list), "args is not a list"
args, unknown = parser.parse_known_args(server.args[2:])
args, _ = parser.parse_known_args(server.args[2:])
if server.env is None:
new_env = None
else:
Expand Down
6 changes: 3 additions & 3 deletions src/mcp_scan/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

from typing import TYPE_CHECKING, Any

from .MCPScanner import MCPScanner
from .upload import upload as _upload
from .utils import parse_headers
from mcp_scan.MCPScanner import MCPScanner
from mcp_scan.upload import upload as _upload
from mcp_scan.utils import parse_headers

if TYPE_CHECKING:
from collections.abc import Sequence
Expand Down
3 changes: 1 addition & 2 deletions src/mcp_scan/mcp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
VSCodeConfigFile,
VSCodeMCPConfig,
)

from .utils import rebalance_command_args
from mcp_scan.utils import rebalance_command_args

# Set up logger for this module
logger = logging.getLogger(__name__)
Expand Down
4 changes: 2 additions & 2 deletions src/mcp_scan/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ class UnknownMCPConfig(MCPConfig):
This type intentionally resolves to an empty server set.
"""
model_config = ConfigDict()

def get_servers(self) -> dict[str, StdioServer | RemoteServer]:
return {}

def set_servers(self, servers: dict[str, StdioServer | RemoteServer]) -> None:
pass

Expand Down
10 changes: 9 additions & 1 deletion src/mcp_scan/printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@
from rich.traceback import Traceback as rTraceback
from rich.tree import Tree

from .models import Entity, Issue, ScanError, ScanPathResult, ToxicFlowExtraData, entity_type_to_str, hash_entity
from mcp_scan.models import (
Entity,
Issue,
ScanError,
ScanPathResult,
ToxicFlowExtraData,
entity_type_to_str,
hash_entity,
)

MAX_ENTITY_NAME_LENGTH = 25
MAX_ENTITY_NAME_TOXIC_FLOW_LENGTH = 30
Expand Down
4 changes: 2 additions & 2 deletions src/mcp_scan/upload.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import asyncio
import getpass
import logging
import os
import getpass

import rich
import aiohttp
import rich

from mcp_scan.identity import IdentityManager
from mcp_scan.models import ScanPathResult, ScanPathResultsCreate, ScanUserInfo
Expand Down
14 changes: 7 additions & 7 deletions src/mcp_scan/verify_api.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import asyncio
import getpass
import logging
import os
import ssl

import getpass
import asyncio
import aiohttp
import certifi
from mcp_scan.well_known_clients import get_client_from_path
import rich

from .identity import IdentityManager
from .models import (
from mcp_scan.identity import IdentityManager
from mcp_scan.models import (
ScanError,
ScanPathResult,
ScanUserInfo,
ScanPathResultsCreate,
ScanUserInfo,
)
import rich
from mcp_scan.well_known_clients import get_client_from_path

logger = logging.getLogger(__name__)
identity_manager = IdentityManager()
Expand Down
9 changes: 4 additions & 5 deletions src/mcp_scan_server/routes/policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,17 @@
)
from pydantic import ValidationError

from mcp_scan_server.activity_logger import ActivityLogger, get_activity_logger
from mcp_scan_server.session_store import SessionStore, to_session

from ..models import (
from mcp_scan_server.models import (
DEFAULT_GUARDRAIL_CONFIG,
BatchCheckRequest,
BatchCheckResponse,
DatasetPolicy,
GuardrailConfigFile,
PolicyCheckResult,
)
from ..parse_config import parse_config
from mcp_scan_server.parse_config import parse_config
from mcp_scan_server.activity_logger import ActivityLogger, get_activity_logger
from mcp_scan_server.session_store import SessionStore, to_session

router = APIRouter()
session_store = SessionStore()
Expand Down
11 changes: 5 additions & 6 deletions src/mcp_scan_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
import uvicorn
from fastapi import FastAPI, Response

from mcp_scan_server.routes.policies import router as policies_router # type: ignore
from mcp_scan_server.routes.push import router as push_router
from mcp_scan_server.routes.trace import router as dataset_trace_router
from mcp_scan_server.routes.user import router as user_router
from mcp_scan_server.activity_logger import setup_activity_logger # type: ignore

from .routes.policies import router as policies_router # type: ignore
from .routes.push import router as push_router
from .routes.trace import router as dataset_trace_router
from .routes.user import router as user_router


class MCPScanServer:
"""
Expand Down Expand Up @@ -68,7 +67,7 @@ async def on_startup(self):
# setup activity logger
setup_activity_logger(self.app, pretty=self.pretty)

from .routes.policies import load_guardrails_config_file
from mcp_scan_server.routes.policies import load_guardrails_config_file

await load_guardrails_config_file(self.config_file_path)

Expand Down