Skip to main content
Glama

Gemini MCP Server

test_file_protection.pyโ€ข12.8 kB
""" Test file protection mechanisms to ensure MCP doesn't scan: 1. Its own directory 2. User's home directory root 3. Excluded directories """ from pathlib import Path from unittest.mock import patch from utils.file_utils import ( expand_paths, get_user_home_directory, is_home_directory_root, is_mcp_directory, ) class TestMCPDirectoryDetection: """Test MCP self-detection to prevent scanning its own code.""" def test_detect_mcp_directory_dynamically(self, tmp_path): """Test dynamic MCP directory detection based on script location.""" # The is_mcp_directory function now uses __file__ to detect MCP location # It checks if the given path is a subdirectory of the MCP server from pathlib import Path import utils.file_utils # Get the actual MCP server directory mcp_server_dir = Path(utils.file_utils.__file__).parent.parent.resolve() # Test that the MCP server directory itself is detected assert is_mcp_directory(mcp_server_dir) is True # Test that a subdirectory of MCP is also detected if (mcp_server_dir / "tools").exists(): assert is_mcp_directory(mcp_server_dir / "tools") is True def test_no_detection_on_non_mcp_directory(self, tmp_path): """Test no detection on directories outside MCP.""" # Any directory outside the MCP server should not be detected non_mcp_dir = tmp_path / "some_other_project" non_mcp_dir.mkdir() assert is_mcp_directory(non_mcp_dir) is False def test_no_detection_on_regular_directory(self, tmp_path): """Test no detection on regular project directories.""" # Create some random Python files (tmp_path / "app.py").touch() (tmp_path / "main.py").touch() (tmp_path / "utils.py").touch() assert is_mcp_directory(tmp_path) is False def test_no_detection_on_file(self, tmp_path): """Test no detection when path is a file, not directory.""" file_path = tmp_path / "test.py" file_path.touch() assert is_mcp_directory(file_path) is False def test_mcp_directory_excluded_from_scan(self, tmp_path): """Test that MCP directories are excluded during path expansion.""" # For this test, we need to mock is_mcp_directory since we can't # actually create the MCP directory structure in tmp_path from unittest.mock import patch as mock_patch # Create a project with a subdirectory we'll pretend is MCP project_root = tmp_path / "my_project" project_root.mkdir() # Add some project files (project_root / "app.py").write_text("# My app") (project_root / "config.py").write_text("# Config") # Create a subdirectory that we'll mock as MCP fake_mcp_dir = project_root / "gemini-mcp-server" fake_mcp_dir.mkdir() (fake_mcp_dir / "server.py").write_text("# MCP server") (fake_mcp_dir / "test.py").write_text("# Should not be included") # Mock is_mcp_directory to return True for our fake MCP dir def mock_is_mcp(path): return str(path).endswith("gemini-mcp-server") # Scan the project with mocked MCP detection with mock_patch("utils.file_utils.is_mcp_directory", side_effect=mock_is_mcp): files = expand_paths([str(project_root)]) # Verify project files are included but MCP files are not file_names = [Path(f).name for f in files] assert "app.py" in file_names assert "config.py" in file_names assert "test.py" not in file_names # From MCP dir assert "server.py" not in file_names # From MCP dir class TestHomeDirectoryProtection: """Test protection against scanning user's home directory root.""" def test_detect_exact_home_directory(self): """Test detection of exact home directory path.""" with patch("utils.file_utils.get_user_home_directory") as mock_home: mock_home.return_value = Path("/Users/testuser") assert is_home_directory_root(Path("/Users/testuser")) is True assert is_home_directory_root(Path("/Users/testuser/")) is True def test_allow_home_subdirectories(self): """Test that subdirectories of home are allowed.""" with patch("utils.file_utils.get_user_home_directory") as mock_home: mock_home.return_value = Path("/Users/testuser") assert is_home_directory_root(Path("/Users/testuser/projects")) is False assert is_home_directory_root(Path("/Users/testuser/Documents/code")) is False def test_detect_home_patterns_macos(self): """Test detection of macOS home directory patterns.""" # Test various macOS home patterns assert is_home_directory_root(Path("/Users/john")) is True assert is_home_directory_root(Path("/Users/jane")) is True # But subdirectories should be allowed assert is_home_directory_root(Path("/Users/john/projects")) is False def test_detect_home_patterns_linux(self): """Test detection of Linux home directory patterns.""" assert is_home_directory_root(Path("/home/ubuntu")) is True assert is_home_directory_root(Path("/home/user")) is True # But subdirectories should be allowed assert is_home_directory_root(Path("/home/ubuntu/code")) is False def test_detect_home_patterns_windows(self): """Test detection of Windows home directory patterns.""" assert is_home_directory_root(Path("C:\\Users\\John")) is True assert is_home_directory_root(Path("C:/Users/Jane")) is True # But subdirectories should be allowed assert is_home_directory_root(Path("C:\\Users\\John\\Documents")) is False def test_home_directory_excluded_from_scan(self, tmp_path): """Test that home directory root is excluded during path expansion.""" with patch("utils.file_utils.get_user_home_directory") as mock_home: mock_home.return_value = tmp_path # Try to scan home directory files = expand_paths([str(tmp_path)]) # Should return empty as home root is skipped assert files == [] class TestUserHomeEnvironmentVariable: """Test USER_HOME environment variable handling.""" def test_user_home_from_pathlib(self): """Test that get_user_home_directory uses Path.home().""" with patch("pathlib.Path.home") as mock_home: mock_home.return_value = Path("/Users/testuser") home = get_user_home_directory() assert home == Path("/Users/testuser") def test_get_home_directory_uses_pathlib(self): """Test that get_user_home_directory always uses Path.home().""" with patch("pathlib.Path.home") as mock_home: mock_home.return_value = Path("/home/testuser") home = get_user_home_directory() assert home == Path("/home/testuser") # Verify Path.home() was called mock_home.assert_called_once() def test_home_directory_on_different_platforms(self): """Test home directory detection on different platforms.""" # Test different platform home directories test_homes = [ Path("/Users/john"), # macOS Path("/home/ubuntu"), # Linux Path("C:\\Users\\John"), # Windows ] for test_home in test_homes: with patch("pathlib.Path.home") as mock_home: mock_home.return_value = test_home home = get_user_home_directory() assert home == test_home class TestExcludedDirectories: """Test that excluded directories are properly filtered.""" def test_excluded_dirs_not_scanned(self, tmp_path): """Test that directories in EXCLUDED_DIRS are skipped.""" # Create a project with various directories project = tmp_path / "project" project.mkdir() # Create some allowed files (project / "main.py").write_text("# Main") (project / "app.py").write_text("# App") # Create excluded directories with files for excluded in ["node_modules", ".git", "build", "__pycache__", ".venv"]: excluded_dir = project / excluded excluded_dir.mkdir() (excluded_dir / "test.py").write_text("# Should not be included") (excluded_dir / "data.json").write_text("{}") # Create a nested allowed directory src = project / "src" src.mkdir() (src / "utils.py").write_text("# Utils") files = expand_paths([str(project)]) file_names = [Path(f).name for f in files] # Check allowed files are included assert "main.py" in file_names assert "app.py" in file_names assert "utils.py" in file_names # Check excluded files are not included assert "test.py" not in file_names assert "data.json" not in file_names def test_new_excluded_directories(self, tmp_path): """Test newly added excluded directories like .next, .nuxt, etc.""" project = tmp_path / "webapp" project.mkdir() # Create files in new excluded directories for excluded in [".next", ".nuxt", "bower_components", ".expo"]: excluded_dir = project / excluded excluded_dir.mkdir() (excluded_dir / "generated.js").write_text("// Generated") # Create an allowed file (project / "index.js").write_text("// Index") files = expand_paths([str(project)]) file_names = [Path(f).name for f in files] assert "index.js" in file_names assert "generated.js" not in file_names class TestIntegrationScenarios: """Test realistic integration scenarios.""" def test_project_with_mcp_clone_inside(self, tmp_path): """Test scanning a project that has MCP cloned inside it.""" # Setup: User project with MCP cloned as a tool user_project = tmp_path / "my-awesome-project" user_project.mkdir() # User's project files (user_project / "README.md").write_text("# My Project") (user_project / "main.py").write_text("print('Hello')") src = user_project / "src" src.mkdir() (src / "app.py").write_text("# App code") # MCP cloned inside the project mcp = user_project / "tools" / "gemini-mcp-server" mcp.mkdir(parents=True) # Create typical MCP files (mcp / "server.py").write_text("# MCP server code") (mcp / "config.py").write_text("# MCP config") tools_dir = mcp / "tools" tools_dir.mkdir() (tools_dir / "chat.py").write_text("# Chat tool") (mcp / "LICENSE").write_text("MIT License") (mcp / "README.md").write_text("# Gemini MCP") # Also add node_modules (should be excluded) node_modules = user_project / "node_modules" node_modules.mkdir() (node_modules / "package.json").write_text("{}") # Mock is_mcp_directory for this test def mock_is_mcp(path): return "gemini-mcp-server" in str(path) with patch("utils.file_utils.is_mcp_directory", side_effect=mock_is_mcp): files = expand_paths([str(user_project)]) file_paths = [str(f) for f in files] # User files should be included assert any("my-awesome-project/README.md" in p for p in file_paths) assert any("my-awesome-project/main.py" in p for p in file_paths) assert any("src/app.py" in p for p in file_paths) # MCP files should NOT be included assert not any("gemini-mcp-server" in p for p in file_paths) assert not any("server.py" in p for p in file_paths) # node_modules should NOT be included assert not any("node_modules" in p for p in file_paths) def test_security_without_workspace_root(self, tmp_path): """Test that security still works with the new security model.""" # The system now relies on is_dangerous_path and is_home_directory_root # for security protection # Test that we can scan regular project directories project_dir = tmp_path / "my_project" project_dir.mkdir() (project_dir / "app.py").write_text("# App") files = expand_paths([str(project_dir)]) assert len(files) == 1 assert "app.py" in files[0] # Test that home directory root is still protected with patch("utils.file_utils.get_user_home_directory") as mock_home: mock_home.return_value = tmp_path # Scanning home root should return empty files = expand_paths([str(tmp_path)]) assert files == []

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BeehiveInnovations/gemini-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server