185 lines
5.3 KiB
Markdown
185 lines
5.3 KiB
Markdown
# 🛠️ Development Conventions
|
|
|
|

|
|
|
|
All MCP servers in this repo follow a consistent set of conventions to ensure maintainability, testability, and compatibility with Roo Code tooling.
|
|
|
|
## Directory Structure
|
|
|
|
Each MCP server lives at `mcp/<server-name>/` with this layout:
|
|
|
|
```
|
|
mcp/<server-name>/
|
|
├── src/
|
|
│ ├── __init__.py
|
|
│ └── server.py ← FastMCP server entry point
|
|
├── tests/
|
|
│ ├── conftest.py ← sys.path + shared fixtures
|
|
│ └── test_server.py ← pytest test suite (100% mock coverage)
|
|
├── pyproject.toml ← uv-managed dependencies
|
|
├── README.md ← server documentation
|
|
├── PLAN.md ← architecture plan (pre-implementation)
|
|
└── ASSESSMENT.md ← pre-implementation assessment
|
|
```
|
|
|
|
## FastMCP Pattern
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
|
|
mcp = FastMCP("server-name")
|
|
|
|
@mcp.tool()
|
|
def my_tool(param: str) -> str:
|
|
"""Tool description shown to the AI."""
|
|
return result
|
|
|
|
if __name__ == "__main__":
|
|
mcp.run()
|
|
```
|
|
|
|
## Package Management
|
|
|
|
**All projects use `uv`** — never `pip` directly:
|
|
|
|
```bash
|
|
# Create new server
|
|
uv init mcp/my-server
|
|
cd mcp/my-server
|
|
uv add fastmcp httpx
|
|
|
|
# Sync dependencies
|
|
uv sync
|
|
|
|
# Run server
|
|
uv run python src/server.py
|
|
|
|
# Run tests
|
|
uv run pytest tests/ -v
|
|
```
|
|
|
|
## pyproject.toml Template
|
|
|
|
```toml
|
|
[project]
|
|
name = "mcp-my-server"
|
|
version = "0.1.0"
|
|
requires-python = ">=3.11"
|
|
dependencies = [
|
|
"fastmcp>=2.0.0",
|
|
"httpx",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
test = ["pytest", "pytest-mock", "pytest-cov"]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
```
|
|
|
|
## Testing Conventions
|
|
|
|
- Tests live in `tests/test_server.py`
|
|
- `conftest.py` sets `sys.path` so imports work without install
|
|
- Use `pytest` via `uv run pytest`
|
|
- Mock **all** external calls (HTTP, filesystem, subprocess) with `pytest-mock` or `respx`
|
|
- `monkeypatch` for env vars and module-level state
|
|
- Aim for 100% tool function coverage
|
|
- All tests must pass before committing
|
|
|
|
## Branching Strategy
|
|
|
|
**Never commit to main directly.**
|
|
|
|
```
|
|
Branch format: type/scope/short-description
|
|
|
|
Types: feat / fix / docs / chore / spike
|
|
Scopes: bigmind / webscraper / cannamanage / workshop / roo / plans / homelab
|
|
|
|
Examples:
|
|
feat/mcp/new-gitea-server
|
|
fix/bigmind/achievement-card-images
|
|
docs/wiki/update-conventions
|
|
chore/roo/update-mcp-json
|
|
```
|
|
|
|
Merge to main with `--no-ff` after push to Gitea.
|
|
|
|
## Commit Convention
|
|
|
|
Follow **Conventional Commits** format:
|
|
|
|
```
|
|
feat(mcp-webscraper): add webscraper_search_hint tool using Brave Search
|
|
fix(bigmind): achievement card images missing background-image CSS
|
|
docs(wiki): add Java projects pages
|
|
test(mcp-image-gen): add edge case tests for generate_image
|
|
refactor(bigmind): extract profile builder to separate module
|
|
chore(roo): update mcp.json with new server entry
|
|
```
|
|
|
|
## Wiki Update Workflow
|
|
|
|
Wiki pages live as real Markdown files in `docs/wiki/pages/`. To update and deploy:
|
|
|
|
```bash
|
|
# 1. Edit the .md files in docs/wiki/pages/
|
|
# 2. Deploy to Gitea wiki git repo:
|
|
./docs/wiki/deploy_wiki.sh
|
|
```
|
|
|
|
The deploy script clones the wiki git repo (`pi_mcps.wiki.git`), syncs all `.md` files, and pushes.
|
|
|
|
## Creating a New MCP Server
|
|
|
|
Use the `new-mcp-server` Roo skill in MCP Builder mode for full scaffolding:
|
|
|
|
```
|
|
1. Switch to 🔧 MCP Builder mode in Roo Code
|
|
2. Say: "Create a new MCP server for <purpose>"
|
|
3. Roo will load the new-mcp-server skill and scaffold everything
|
|
```
|
|
|
|
## Web Research with mcp-webscraper
|
|
|
|
Before asking Patrick for information about a library, framework, API, or technology — **search first**.
|
|
|
|
The webscraper MCP server provides `webscraper_search_hint` (Brave Search, no API key, always available) as the entry point for all research tasks. Use the two-step pattern:
|
|
|
|
```
|
|
Step 1: webscraper_search_hint("topic or error message") → get candidate URLs
|
|
Step 2: webscraper_fetch(best_url) → read the full page
|
|
```
|
|
|
|
### When to search
|
|
|
|
| Situation | Action |
|
|
|---|---|
|
|
| Need docs for a library or framework | `webscraper_search_hint("library-name official docs")` |
|
|
| Investigating an error or stack trace | `webscraper_search_hint("exact error message language")` |
|
|
| Planning a feature — need design patterns | `webscraper_search_hint("pattern-name best practices")` |
|
|
| Checking latest version / changelog | `webscraper_search_hint("library-name changelog release")` |
|
|
| Looking up API contracts | `webscraper_fetch(official_docs_url)` directly |
|
|
|
|
### Especially useful in
|
|
|
|
- **🏗️ Architect mode** — look up patterns and docs *before* designing. Don't design blind.
|
|
- **🪲 Debug mode** — search the exact error message before forming hypotheses.
|
|
- **🔧 MCP Builder mode** — check FastMCP changelog for new patterns before implementing.
|
|
|
|
### Known caveats
|
|
|
|
- Reddit and Stack Overflow may return empty snippets (platform blocks)
|
|
- Brave uses Svelte CSS classes that can change — if `webscraper_search_hint` returns 0 results, selectors may need updating (last verified: 2026-04-05)
|
|
|
|
## Gitea Repository
|
|
|
|
Code is hosted at: `http://192.168.188.119:30008/pplate/pi_mcps`
|
|
|
|
Push with the `gitea-push` Roo skill to ensure conventional commit format and correct branch workflow.
|