Skip to content

Best PracticesΒΆ

Input and output santitizationΒΆ

Ensure your inputs and outputs are sanitized. In Python, we recommend using Pydantic V2.

πŸ“¦ Self-ContainmentΒΆ

Each MCP server must be a standalone repository that includes all necessary code and documentation. Example: git clone; make serve

πŸ›  Makefile RequirementsΒΆ

All MCP repositories must include a Makefile with the following standard targets. These targets ensure consistency, enable automation, and support local development and containerization.

βœ… Required Make TargetsΒΆ

Make targets are grouped by functionality. Use make help to see them all in your terminal.

🌱 VIRTUAL ENVIRONMENT & INSTALLATION¢

Target Description
make venv Create a new Python virtual environment in ~/.venv/<project>.
make activate Output the command to activate the virtual environment.
make install Install all dependencies using uv from pyproject.toml.
make clean Remove virtualenv, Python artifacts, build files, and containers.

▢️ RUN SERVER & TESTINGΒΆ

Target Description
make serve Run the MCP server locally (e.g., mcp-time-server).
make test Run all unit and integration tests with pytest.
make test-curl Run public API integration tests using a curl script.

πŸ“š DOCUMENTATION & SBOMΒΆ

Target Description
make docs Generate project documentation and SBOM using handsdown.
make sbom Create a software bill of materials (SBOM) and scan dependencies.

πŸ” LINTING & STATIC ANALYSISΒΆ

Target Description
make lint Run all linters (e.g., ruff check, ruff format).

🐳 CONTAINER BUILD & RUN¢

Target Description
make podman Build a production-ready container image with Podman.
make podman-run Run the container locally and expose it on port 8080.
make podman-stop Stop and remove the running container.
make podman-test Test the container with a curl script.

πŸ›‘οΈ SECURITY & PACKAGE SCANNINGΒΆ

Target Description
make trivy Scan the container image for vulnerabilities using Trivy.

Tip: These commands should work out-of-the-box after cloning a repo and running make venv install serve.

🐳 Containerfile¢

Each repo must include a Containerfile (Podman-compatible, Docker-compatible) to support containerized execution.

Containerfile Requirements:ΒΆ

  • Must start from a secure base (e.g., latest Red Hat UBI9 minimal image registry.access.redhat.com/ubi9-minimal:9.5-1741850109)
  • Should use uv or pdm to install dependencies via pyproject.toml
  • Must run the server using the same entry point as make serve
  • Should expose relevant ports (EXPOSE 8080)
  • Should define a non-root user for runtime

πŸ“š Dependency ManagementΒΆ

  • All Python projects must use pyproject.toml and follow PEP standards.
  • Dependencies must either be:
  • Included in the repo
  • Pulled from PyPI (no external links)

🎯 Clear Role Definition¢

  • State the specific role of the server (e.g., GitHub tools).
  • Group related tools together.
  • Do not mix roles (e.g., GitHub β‰  Jira β‰  GitLab).

🧰 Standardized Tools¢

Each MCP server should expose tools that follow the MCP conventions, e.g.:

  • create_ticket
  • create_pr
  • read_file

πŸ“ Consistent StructureΒΆ

Repos must follow a common structure. For example, from the time_server

time_server/
β”œβ”€β”€ Containerfile                  # Container build definition (Podman/Docker compatible)
β”œβ”€β”€ Makefile                       # Build, run, test, and container automation targets
β”œβ”€β”€ pyproject.toml                 # Python project and dependency configuration (PEP 621)
β”œβ”€β”€ README.md                      # Main documentation: overview, setup, usage, env vars
β”œβ”€β”€ CONTRIBUTING.md                # Guidelines for contributing, PRs, and issue management
β”œβ”€β”€ .gitignore                     # Exclude venvs, artifacts, and secrets from Git
β”œβ”€β”€ docs/                          # (Optional) Diagrams, specs, and additional documentation
β”œβ”€β”€ tests/                         # Unit and integration tests
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ test_main.py               # Tests for main entrypoint behavior
β”‚   └── test_tools.py              # Tests for core tool functionality
└── src/                           # Application source code
    └── mcp_time_server/           # Main package named after your server
        β”œβ”€β”€ __init__.py            # Marks this directory as a Python package
        β”œβ”€β”€ main.py                # Entrypoint that wires everything together
        β”œβ”€β”€ mcp_server_base.py     # Optional base class for shared server behavior
        β”œβ”€β”€ server.py              # Server logic (e.g., tool registration, lifecycle hooks)
        └── tools/                 # Directory for all MCP tool implementations
            β”œβ”€β”€ __init__.py
            β”œβ”€β”€ tools.py           # Tool business logic (e.g., `get_time`, `format_time`)
            └── tools_registration.py # Registers tools into the MCP framework

πŸ“ DocumentationΒΆ

Each repo must include:

  • A comprehensive README.md
  • Setup and usage instructions
  • Environment variable documentation

🧩 Modular Design¢

Code should be cleanly separated into modules for easier maintenance and scaling.

βœ… TestingΒΆ

Include unit and integration tests to validate functionality.

🀝 Contribution Guidelines¢

Add a CONTRIBUTING.md with:

  • How to file issues
  • How to submit pull requests
  • Review and merge process

🏷 Versioning and Releases¢

Use semantic versioning. Include release notes for all changes.

πŸ”„ Pull Request ProcessΒΆ

Submit new MCP servers via pull request to the org's main repo. PR must:

  • Follow all standards
  • Include all documentation

πŸ” Environment Variables and SecretsΒΆ

  • Use environment variables for secrets
  • Use a clear, role-based prefix (e.g., MCP_GITHUB_)

Example:

MCP_GITHUB_ACCESS_TOKEN=...
MCP_GITHUB_BASE_URL=...

🏷 Required Capabilities (README Metadata Tags)¢

Add tags at the top of README.md between YAML markers to declare your server's required capabilities.

Available Tags:ΒΆ

  • needs_filesystem_access Indicates the server requires access to the local filesystem (e.g., for reading/writing files).

  • needs_api_key_user Requires a user-specific API key to interact with external services on behalf of the user.

  • needs_api_key_central Requires a centrally managed API key, typically provisioned and stored by the platform.

  • needs_database The server interacts with a persistent database (e.g., PostgreSQL, MongoDB).

  • needs_network_access_inbound The server expects to receive inbound network requests (e.g., runs a web server or webhook listener).

  • needs_network_access_outbound The server needs to make outbound network requests (e.g., calling external APIs or services).

Example:ΒΆ

---
tags:
  - needs_filesystem_access
  - needs_api_key_user
---