We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bobmatnyc/mcp-skills'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Pytest configuration and fixtures for integration tests."""
import json
from collections.abc import Generator
from pathlib import Path
import git
import pytest
from mcp_skills.services.indexing import IndexingEngine
from mcp_skills.services.repository_manager import RepositoryManager
from mcp_skills.services.skill_manager import SkillManager
from mcp_skills.services.toolchain_detector import ToolchainDetector
@pytest.fixture
def temp_repos_dir(tmp_path: Path) -> Generator[Path, None, None]:
"""Create temporary directory for test repositories.
Args:
tmp_path: Pytest temporary path fixture
Yields:
Path to temporary repos directory
"""
repos_dir = tmp_path / "repos"
repos_dir.mkdir()
yield repos_dir
@pytest.fixture
def temp_storage_dir(tmp_path: Path) -> Generator[Path, None, None]:
"""Create temporary directory for ChromaDB storage.
Args:
tmp_path: Pytest temporary path fixture
Yields:
Path to temporary storage directory
"""
storage_dir = tmp_path / "storage"
storage_dir.mkdir()
yield storage_dir
@pytest.fixture
def sample_skill_content() -> dict[str, str]:
"""Return sample SKILL.md content for different skill types.
Returns:
Dictionary mapping skill type to SKILL.md content
"""
return {
"pytest": """---
name: pytest-testing
description: Run tests with pytest framework
category: testing
tags:
- python
- pytest
- testing
dependencies: []
version: "1.0.0"
author: Test Author
---
# Pytest Testing Skill
Use pytest to run Python tests with proper fixtures and assertions.
## Usage
Run pytest with:
```bash
pytest tests/
```
## Examples
```python
def test_example():
assert 1 + 1 == 2
```
""",
"flask": """---
name: flask-development
description: Build web applications with Flask
category: architecture
tags:
- python
- flask
- web
dependencies: []
version: "1.0.0"
author: Test Author
---
# Flask Development Skill
Build Flask web applications following best practices.
## Usage
Create Flask app:
```python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello World!'
```
## Examples
Run development server:
```bash
flask run --debug
```
""",
"debugging": """---
name: python-debugging
description: Debug Python applications effectively
category: debugging
tags:
- python
- debugging
- pdb
dependencies:
- sample-repo/testing/pytest
version: "1.0.0"
author: Test Author
---
# Python Debugging Skill
Use pdb and debugging tools to troubleshoot Python code.
## Usage
Insert breakpoint:
```python
import pdb; pdb.set_trace()
```
## Examples
Debug with breakpoint():
```python
def buggy_function():
breakpoint() # Python 3.7+
return result
```
""",
}
@pytest.fixture
def sample_skill_repo(
tmp_path: Path, sample_skill_content: dict[str, str]
) -> Generator[Path, None, None]:
"""Create a sample skill repository with multiple skills.
This creates a git repository with realistic skill structure:
- sample-repo/testing/pytest/SKILL.md
- sample-repo/web/flask/SKILL.md
- sample-repo/debugging/python/SKILL.md
Args:
tmp_path: Pytest temporary path fixture
sample_skill_content: Sample SKILL.md content fixture
Yields:
Path to the created git repository
"""
# Create repo directory
repo_dir = tmp_path / "sample_repo"
repo_dir.mkdir()
# Initialize git repo
repo = git.Repo.init(repo_dir)
# Create skill files
skills = {
"testing/pytest": sample_skill_content["pytest"],
"web/flask": sample_skill_content["flask"],
"debugging/python": sample_skill_content["debugging"],
}
for skill_path, content in skills.items():
skill_dir = repo_dir / skill_path
skill_dir.mkdir(parents=True, exist_ok=True)
skill_file = skill_dir / "SKILL.md"
skill_file.write_text(content)
# Create README
readme = repo_dir / "README.md"
readme.write_text(
"# Test Skills Repository\n\nTest skills for integration testing."
)
# Commit files
repo.index.add(["*"])
repo.index.commit("Initial commit with test skills")
yield repo_dir
# Cleanup is handled by tmp_path
@pytest.fixture
def populated_repos_dir(
temp_repos_dir: Path, sample_skill_content: dict[str, str]
) -> Generator[Path, None, None]:
"""Create a temporary repos directory with pre-populated skills.
This fixture creates skills directly in the repos directory structure
without needing git operations, making it faster for testing.
Args:
temp_repos_dir: Temporary repos directory fixture
sample_skill_content: Sample SKILL.md content fixture
Yields:
Path to populated repos directory
"""
# Create sample-repo structure directly in repos_dir
repo_dir = temp_repos_dir / "sample-repo"
repo_dir.mkdir()
# Create skill files
skills = {
"testing/pytest": sample_skill_content["pytest"],
"web/flask": sample_skill_content["flask"],
"debugging/python": sample_skill_content["debugging"],
}
for skill_path, content in skills.items():
skill_dir = repo_dir / skill_path
skill_dir.mkdir(parents=True, exist_ok=True)
skill_file = skill_dir / "SKILL.md"
skill_file.write_text(content)
yield temp_repos_dir
@pytest.fixture
def configured_repository_manager(
temp_repos_dir: Path,
) -> Generator[RepositoryManager, None, None]:
"""Create and configure a RepositoryManager for testing.
Args:
temp_repos_dir: Temporary repos directory fixture
Yields:
Configured RepositoryManager instance
"""
# Create base directory for metadata
manager = RepositoryManager(base_dir=temp_repos_dir)
yield manager
# Cleanup is handled by temp_repos_dir
@pytest.fixture
def configured_skill_manager(
temp_repos_dir: Path,
) -> Generator[SkillManager, None, None]:
"""Create and configure a SkillManager for testing.
Args:
temp_repos_dir: Temporary repos directory fixture
Yields:
Configured SkillManager instance
"""
manager = SkillManager(repos_dir=temp_repos_dir)
yield manager
@pytest.fixture
def configured_indexing_engine(
configured_skill_manager: SkillManager,
temp_storage_dir: Path,
) -> Generator[IndexingEngine, None, None]:
"""Create and configure an IndexingEngine for testing.
Args:
configured_skill_manager: Configured SkillManager fixture
temp_storage_dir: Temporary storage directory fixture
Yields:
Configured IndexingEngine instance
"""
engine = IndexingEngine(
skill_manager=configured_skill_manager,
storage_path=temp_storage_dir,
)
yield engine
@pytest.fixture
def configured_services(
configured_repository_manager: RepositoryManager,
configured_skill_manager: SkillManager,
configured_indexing_engine: IndexingEngine,
) -> tuple[RepositoryManager, SkillManager, IndexingEngine]:
"""Provide fully configured service instances.
Args:
configured_repository_manager: Repository manager fixture
configured_skill_manager: Skill manager fixture
configured_indexing_engine: Indexing engine fixture
Returns:
Tuple of (repository_manager, skill_manager, indexing_engine)
"""
return (
configured_repository_manager,
configured_skill_manager,
configured_indexing_engine,
)
@pytest.fixture
def populated_services(
populated_repos_dir: Path,
temp_storage_dir: Path,
) -> tuple[RepositoryManager, SkillManager, IndexingEngine]:
"""Provide fully configured services with pre-populated skills.
This fixture is optimized for tests that need skills but don't need
to test repository operations.
Args:
populated_repos_dir: Repos directory with pre-populated skills
temp_storage_dir: Temporary storage directory
Returns:
Tuple of (repository_manager, skill_manager, indexing_engine)
"""
repo_manager = RepositoryManager(base_dir=populated_repos_dir)
skill_manager = SkillManager(repos_dir=populated_repos_dir)
indexing_engine = IndexingEngine(
skill_manager=skill_manager,
storage_path=temp_storage_dir,
)
return repo_manager, skill_manager, indexing_engine
@pytest.fixture
def sample_python_project(tmp_path: Path) -> Generator[Path, None, None]:
"""Create a sample Python project for toolchain detection.
Args:
tmp_path: Pytest temporary path fixture
Yields:
Path to sample Python project
"""
project_dir = tmp_path / "python_project"
project_dir.mkdir()
# Create Python project markers
(project_dir / "pyproject.toml").write_text(
"""[project]
name = "test-project"
version = "1.0.0"
dependencies = ["flask>=3.0.0", "pytest>=7.0"]
"""
)
(project_dir / "requirements.txt").write_text("flask>=3.0.0\npytest>=7.0\n")
(project_dir / "pytest.ini").write_text("[pytest]\ntestpaths = tests\n")
# Create source files
src_dir = project_dir / "src"
src_dir.mkdir()
(src_dir / "app.py").write_text(
"""from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World!'
"""
)
# Create test directory
tests_dir = project_dir / "tests"
tests_dir.mkdir()
(tests_dir / "test_app.py").write_text(
"""def test_example():
assert 1 + 1 == 2
"""
)
yield project_dir
@pytest.fixture
def sample_typescript_project(tmp_path: Path) -> Generator[Path, None, None]:
"""Create a sample TypeScript project for toolchain detection.
Args:
tmp_path: Pytest temporary path fixture
Yields:
Path to sample TypeScript project
"""
project_dir = tmp_path / "typescript_project"
project_dir.mkdir()
# Create TypeScript project markers
(project_dir / "package.json").write_text(
json.dumps(
{
"name": "test-project",
"version": "1.0.0",
"devDependencies": {
"typescript": "^5.0.0",
"jest": "^29.0.0",
"@types/node": "^20.0.0",
},
}
)
)
(project_dir / "tsconfig.json").write_text(
json.dumps(
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": True,
}
}
)
)
# Create source files
src_dir = project_dir / "src"
src_dir.mkdir()
(src_dir / "index.ts").write_text(
"""export function greet(name: string): string {
return `Hello, ${name}!`;
}
"""
)
yield project_dir
@pytest.fixture
def old_json_metadata(tmp_path: Path) -> Generator[Path, None, None]:
"""Create old-style JSON metadata file for migration testing.
Args:
tmp_path: Pytest temporary path fixture
Yields:
Path to JSON metadata file
"""
json_file = tmp_path / "repos.json"
metadata = {
"repositories": [
{
"id": "test/repo1",
"url": "https://github.com/test/repo1.git",
"local_path": str(tmp_path / "repos" / "test" / "repo1"),
"priority": 100,
"last_updated": "2024-01-01T00:00:00Z",
"skill_count": 5,
"license": "MIT",
},
{
"id": "test/repo2",
"url": "https://github.com/test/repo2.git",
"local_path": str(tmp_path / "repos" / "test" / "repo2"),
"priority": 90,
"last_updated": "2024-01-01T00:00:00Z",
"skill_count": 3,
"license": "Apache-2.0",
},
]
}
json_file.write_text(json.dumps(metadata, indent=2))
yield json_file
@pytest.fixture
def configured_toolchain_detector() -> ToolchainDetector:
"""Create a configured ToolchainDetector instance.
Returns:
ToolchainDetector instance
"""
return ToolchainDetector()