Skip to main content
Glama
xcollantes

MCP Template

by xcollantes
README.md
# MCP Template

MY_MCP_DESCRIPTION

## Template Setup

*Remove the Template Setup section after you have replaced all the variables.*

Find All and Replace these variables throughout the project:

| Variable | Description | Example |
|----------|-------------|---------|
| `TODO` | General placeholders |  |
| `MY_MCP_NAME` | Human-readable name | `Weather MCP` |
| `MY_MCP_DESCRIPTION` | One-liner description | `MCP server for interacting with the Weather API.` |
| `MY_MCP_REPO_URL` | Full GitHub repo URL | `https://github.com/xcollantes/weather-mcp` |
| `MY_MCP_PACKAGE_NAME` | Package name for CLI/binaries | `weather-mcp` |
| `MY_MCP_SERVER_KEY` | Key in mcpServers JSON config | `weather` |
| `MY_MCP_ENV_VAR_PREFIX` | Prefix for environment variables | `WEATHER` |
| `MY_MCP_AUTHOR` | Author name for LICENSE | `Xavier Collantes` |

**See more under [Development](#development) section for CI/CD, formatting,
tests, logging, and setup for pre-commit hooks.**

## Installation

### Install MY_MCP_NAME

MY_MCP_NAME requires no additional dependencies to be installed.

TODO: Add any additional installation instructions for your MCP server. For
example, many MCPs may use the CLI tool.

### MCP Server: Option 1: Download binaries (Recommended)

Download the latest release for your operating system from the [Releases
page](MY_MCP_REPO_URL/releases).

| Operating System | Binary |
|------------------|--------|
| Linux | `MY_MCP_PACKAGE_NAME-linux` |
| Windows | `MY_MCP_PACKAGE_NAME-windows.exe` |
| macOS (Apple Silicon) | `MY_MCP_PACKAGE_NAME-macos-apple-silicon-arm64` |
| macOS (Intel) | `MY_MCP_PACKAGE_NAME-macos-x64` |

#### Linux

```bash
# Download the binary.
curl -L -o MY_MCP_PACKAGE_NAME-linux MY_MCP_REPO_URL/releases/latest/download/MY_MCP_PACKAGE_NAME-linux

# Make it executable.
chmod +x MY_MCP_PACKAGE_NAME-linux

# Move to a directory in your PATH (optional).
sudo mv MY_MCP_PACKAGE_NAME-linux /usr/local/bin/
```

Add to your LLM client configuration:

**NOTE:** Make sure to replace `/usr/local/bin/MY_MCP_PACKAGE_NAME-linux` with
the path to the binary on your machine if you moved it to a different location.

```json
{
  "mcpServers": {
    "MY_MCP_SERVER_KEY": {
      "command": "/usr/local/bin/MY_MCP_PACKAGE_NAME-linux"
    }
  }
}
```

#### macOS

```bash
# For Apple Silicon (M1/M2/M3).
curl -L -o MY_MCP_PACKAGE_NAME MY_MCP_REPO_URL/releases/latest/download/MY_MCP_PACKAGE_NAME-macos-apple-silicon-arm64

# For Intel Macs.
curl -L -o MY_MCP_PACKAGE_NAME MY_MCP_REPO_URL/releases/latest/download/MY_MCP_PACKAGE_NAME-macos-x64

# Make it executable.
chmod +x MY_MCP_PACKAGE_NAME

# Move to a directory in your PATH (optional).
sudo mv MY_MCP_PACKAGE_NAME /usr/local/bin/
```

**Note:** macOS may block the binary on first run. If you see a security
warning, go to **System Settings > Privacy & Security** and click **Allow
Anyway**, or run:

```bash
xattr -d com.apple.quarantine /usr/local/bin/MY_MCP_PACKAGE_NAME
```

Add to your LLM client configuration:

**NOTE:** Make sure to replace `/usr/local/bin/MY_MCP_PACKAGE_NAME` with the
path to the binary on your machine if you moved it to a different location.

```json
{
  "mcpServers": {
    "MY_MCP_SERVER_KEY": {
      "command": "/usr/local/bin/MY_MCP_PACKAGE_NAME"
    }
  }
}
```

#### Windows

1. Download `MY_MCP_PACKAGE_NAME-windows.exe` from the [Releases
   page](MY_MCP_REPO_URL/releases).
2. Move the executable to a convenient location (e.g., `C:\Program
   Files\MY_MCP_PACKAGE_NAME\`).

Add to your LLM client configuration:

```json
{
  "mcpServers": {
    "MY_MCP_SERVER_KEY": {
      "command": "C:\\Program Files\\MY_MCP_PACKAGE_NAME\\MY_MCP_PACKAGE_NAME-windows.exe"
    }
  }
}
```

**NOTE:** Make sure to replace `C:\\Program
Files\\MY_MCP_PACKAGE_NAME\\MY_MCP_PACKAGE_NAME-windows.exe` with the path to
the binary on your machine if you moved it to a different location.

### MCP Server: Option 2: Development setup with uv

Get repo:

```bash
git clone MY_MCP_REPO_URL.git
cd MY_MCP_PACKAGE_NAME
```

Add MCP server to your choice of LLM client:

**NOTE:** You will need to look up for your specific client on how to add MCPs.

Usually the JSON file for the LLM client will look like this:

```json
{
  "mcpServers": {
    "MY_MCP_SERVER_KEY": {
      "command": "uv",
      "args": ["--directory", "/ABSOLUTE/PATH/TO/REPO/ROOT", "run", "python", "-m", "src.main"]
    }
  }
}
```

This will tell your LLM client application that there's a tool that can be
called by calling `uv --directory /ABSOLUTE/PATH/TO/REPO run python -m
src.main`.

Install UV: <https://docs.astral.sh/uv/getting-started/installation/>

### MCP Server: Option 3: Install globally with pipx

```bash
# Install pipx if you haven't already.
brew install pipx
pipx ensurepath

# Clone and install the MCP server.
git clone MY_MCP_REPO_URL.git
cd MY_MCP_PACKAGE_NAME
pipx install -e .
```

## How it works

1. You enter some questions or prompt to a LLM Client such as the Claude
   Desktop, Cursor, Windsurf, or ChatGPT.
2. The client sends your question to the LLM model (Sonnet, Grok, ChatGPT)
3. LLM analyzes the available tools and decides which one(s) to use
   - The LLM you're using will have a context of the tools and what each tool is
     meant for in human language.
   - Alternatively without MCPs, you could include in the prompt the endpoints
     and a description on each endpoint for the LLM to "call on". Then you could
     copy and paste the text commands into the terminal on your machine.
   - MCPs provide a more deterministic and standardized method on LLM-to-server
     interactions.
4. The client executes the chosen tool(s) through the MCP server.
   - The MCP server is either running local on your machine or an endpoint
     hosting the MCP server remotely.
5. The results are sent back to LLM.
6. LLM formulates a natural language response and one or both of the following
   happen:
   - The response is displayed to you with data from the MCP server
   - Some action is performed using the MCP server

## Development

### Testing In Cursor/Windsurf

To test the MCP server in Cursor/Windsurf, you can use the MCP client to test
the MCP server.

Add this to the MCP client configuration in Cursor/Windsurf:

```json
{
  "mcpServers": {
    "MY_MCP_SERVER_KEY": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/REPO/ROOT",
        "run",
        "python",
        "-m",
        "src.main",
        "--debug"
      ]
    }
  }
}
```

This will start the MCP server and you can then use the MCP server in
Cursor/Windsurf. You may need to restart in the MCP settings to see the changes.

### CI/CD

Setup for CI/CD to build and release the MCP server on multiple operating
systems and architectures.

- The `.github/workflows/ci.yml` file is used to run the tests and linting
  checks.
- The `.github/workflows/release.yml` file is used to build and release the MCP
server on multiple operating systems and architectures.
  - Tag the release with the format `vX.X.X`.
  - The release will be built and released to the Releases page on your GitHub
    repository.

### Formatting

This project uses [ruff](https://docs.astral.sh/ruff/) for linting and
formatting. The `.pre-commit-config.yaml` file is used to run the linting and
formatting checks before each commit.

To set up pre-commit hooks:

```bash
uv sync
uv run pre-commit install
```

Once installed, ruff will automatically run when you commit. To run checks
manually on all files:

```bash
uv run pre-commit run --all-files
```

NOTE: A developer can skip installing pre-commit hook and formatting checks but
the CI/CD workflow will fail if the checks are not passed.

### Tests

This project uses [pytest](https://docs.pytest.org/) for testing. The `tests`
directory is used to store the test files.

To run the tests:

```bash
uv run pytest
```

To run the tests with coverage:

```bash
uv run pytest --cov=src
```

### Logging

Do not use `print` statements for logging. Use the logging module instead.
Writing to stdout will corrupt the JSON-RPC messages and break your server.

### Pre-commit

This project uses [pre-commit](https://pre-commit.com/) to run
[ruff](https://docs.astral.sh/ruff/) linting and formatting checks, and
[pytest](https://docs.pytest.org/) tests before each commit.

To set up pre-commit hooks:

```bash
uv sync
uv run pre-commit install
```

Once installed, ruff and pytest will automatically run when you commit. To run
checks manually on all files:

```bash
uv run pre-commit run --all-files
```

## Docstrings / Tool decorator parameters

MCP.tools decorator parameters are especially important as this is the human
readable text that the LLM has context of. This will be treated as part of the
prompt when fed to the LLM and this will decide when to use each tool.

## Architecture

MCP follows a client-server architecture where an **MCP host** (an AI
application like Cursor or ChatGPT desktop) establishes connections to one or
more **MCP servers**. The **MCP host** accomplishes this by creating one **MCP
client** for each **MCP server**. Each MCP client maintains a dedicated
connection with its corresponding MCP server.

<https://modelcontextprotocol.io/docs/learn/architecture>

## Pitfalls / Troubleshooting

### Edit the jira-cli config file

On MacOS:

```text
/Users/<your-username>/.config/.jira/.config.yml
```

### 404 error when using `jira init`

If you get a 404 error when using `jira init`, you may need to edit the jira-cli
config file to point to the correct Jira instance. There are only 3 possible
values for the auth type so try each one. `basic`, `password`, or `bearer`.

### Environment Variables

Make sure to set any required environment variables. Copy `env.example` to
`.env` and fill in the values:

```bash
cp env.example .env
```

### Server Not Starting

If the MCP server is not starting, check:

1. You have Python 3.12+ installed
2. All dependencies are installed (`uv sync`)
3. Environment variables are set correctly

TDQS

B3.4/5.0

Scored across 3 tools

Disambiguation2/5

The tools 'get_forecast' and 'get_weather' have significant overlap in purpose, as both retrieve weather forecast data from the National Weather Service for a location. The descriptions are similar, with 'get_forecast' specifying multi-period details and 'get_weather' being more general, which could cause confusion for an agent trying to select the appropriate tool. 'get_alerts' is distinct, focusing on active warnings rather than forecasts.

Naming Consistency5/5

All tool names follow a consistent 'verb_noun' pattern using snake_case: 'get_alerts', 'get_forecast', and 'get_weather'. There are no deviations in naming conventions, making the set predictable and easy to parse for an agent.

Tool Count3/5

With 3 tools, the count is borderline for a weather service server. It feels thin, as it lacks operations like updating or managing alerts, or providing historical data, which might be expected for a more comprehensive weather API. However, it covers basic retrieval needs, so it's not severely mismatched.

Completeness2/5

Inferring the domain as weather data access, there are significant gaps in the tool surface. The server only provides retrieval operations (get_alerts, get_forecast, get_weather) with no create, update, or delete capabilities, and it lacks tools for other common weather functions like radar data, historical trends, or location-based searches beyond coordinates. This incompleteness could lead to agent failures when more advanced operations are needed.

Maintenance

ActivityInactive
ResponsivenessNo issues