# Setting Up MCP Server Entry Points with pyproject.toml

> Learn to set up MCP server entry points using pyproject.toml. Define console scripts in [project.scripts] to automatically launch your FastMCP server with a simple CLI command.

- Repository: [CSK/mcp-wordle-python](https://github.com/cr2007/mcp-wordle-python)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Define console scripts under `[project.scripts]` in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) to generate a CLI command that launches your FastMCP server automatically upon execution.**

The **mcp-wordle-python** repository demonstrates how to package a FastMCP server using modern Python packaging standards. Configuring the entry point in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) eliminates the need for manual script wrappers and ensures your server starts with a simple, memorable command after installation.

## Configuring the Entry Point in pyproject.toml

The `[project.scripts]` table in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) maps executable names to Python callables. In this repository, the configuration creates the `mcp-wordle` command by targeting the FastMCP instance's run method.

According to the source code in [[`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml)](https://github.com/cr2007/mcp-wordle-python/blob/master/pyproject.toml#L23-L25), the entry point is defined as:

```toml
[project.scripts]
mcp-wordle = "mcp_wordle.main:mcp.run"

```

When you install the package, the build system generates an executable stub that imports `mcp_wordle.main` and invokes `mcp.run()`, starting the HTTP server immediately.

### Build System Requirements

The project uses **hatchling** as its build backend, specified in the `[build-system]` section of [[`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml)](https://github.com/cr2007/mcp-wordle-python/blob/master/pyproject.toml#L16-L22). This modern backend correctly packages the `src/mcp_wordle` directory structure and processes the console script metadata during wheel creation.

## Implementing the Server Logic

The entry point target `mcp_wordle.main:mcp.run` requires a FastMCP instance named `mcp` in the main module, along with registered tools.

### FastMCP Instance Creation

In [[`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py)](https://github.com/cr2007/mcp-wordle-python/blob/master/src/mcp_wordle/main.py#L13-L14), the server is instantiated:

```python
from fastmcp import FastMCP

mcp = FastMCP("WordleMCP")

```

This object exposes the `run()` method referenced in the entry point configuration.

### Tool Registration

The repository registers a single tool using the `@mcp.tool` decorator. As shown in lines 30-38 of [[`main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/main.py)](https://github.com/cr2007/mcp-wordle-python/blob/master/src/mcp_wordle/main.py#L30-L38), the `get_wordle_data` function becomes accessible as `get_wordle_solution`:

```python
@mcp.tool(
    name="get_wordle_solution",
    description="Get the Wordle solution for a specific date",
)
async def get_wordle_data(target_date: str) -> dict:
    # Implementation performs GET request to NYTimes endpoint

    ...

```

The decorator provides the metadata required by MCP clients to discover and invoke the tool.

## Installing and Running the Server

With the entry point configured in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml), deployment requires only standard Python packaging commands.

### Development Installation

Install the package in editable mode to test changes without reinstallation:

```bash
pip install -e .

```

This creates a symlink for the `mcp-wordle` command that reflects source code modifications immediately.

### Launching via the Entry Point

Execute the generated console script to start the FastMCP server:

```bash
mcp-wordle

```

This command resolves to the equivalent of `python -m mcp_wordle.main`, invoking `mcp.run()` and starting the HTTP server on the default host and port (typically `127.0.0.1:8000`). The server now exposes the `get_wordle_solution` tool to MCP clients.

## Connecting to the Running Server

Once launched via the entry point, the server accepts tool invocations through HTTP requests.

### Using a FastMCP Client

Connect programmatically using the FastMCP client library:

```python
from fastmcp import FastMCPClient

client = FastMCPClient("http://127.0.0.1:8000")
response = client.run_tool(
    "get_wordle_solution",
    {"target_date": "2024-02-20"}
)
print(response)

```

### Direct HTTP Debugging

For troubleshooting, send raw POST requests to the endpoint:

```bash
curl -X POST http://127.0.0.1:8000/run_tool \
    -H "Content-Type: application/json" \
    -d '{"tool_name":"get_wordle_solution","args":{"target_date":"2024-02-20"}}'

```

The server returns the JSON payload fetched from the NYTimes Wordle API.

## Summary

- **Entry point configuration** in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) under `[project.scripts]` transforms your FastMCP server into a system command like `mcp-wordle` that users can execute directly.
- **Build backends** such as hatchling process these definitions during wheel creation, generating executable stubs that call your specified Python callable.
- **Target structure** requires the entry point to reference a valid callable path, such as `mcp_wordle.main:mcp.run`, where `mcp` is the FastMCP instance.
- **Installation** via `pip install` creates the CLI command automatically, making deployment consistent across development and production environments.

## Frequently Asked Questions

### How do I specify multiple entry points for different server modes?

Define additional keys under `[project.scripts]` in [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml). Each key becomes a separate shell command. For example, you could add `mcp-wordle-debug = "mcp_wordle.main:run_debug"` to launch the server with verbose logging enabled, creating distinct entry points for production and development workflows.

### Why does my entry point fail with "ModuleNotFoundError" after installation?

This error occurs when the build system cannot locate the specified module path. Ensure your [`pyproject.toml`](https://github.com/cr2007/mcp-wordle-python/blob/main/pyproject.toml) includes the correct `[tool.hatch.build.targets.wheel]` configuration (or equivalent for your build backend) to package the `src` directory. The repository uses hatchling with `packages = ["src/mcp_wordle"]` to ensure the import path `mcp_wordle.main` resolves correctly after installation.

### Can I use setuptools instead of hatchling for the entry point?

Yes. While this repository uses hatchling, the `[project.scripts]` syntax is standardized in PEP 621 and works with setuptools, flit, and poetry. Simply ensure your `[build-system]` table specifies `requires = ["setuptools>=61.0"]` and `build-backend = "setuptools.build_meta"`. The entry point machinery functions identically across compliant build backends.

### What is the difference between executing `mcp-wordle` and `python -m mcp_wordle.main`?

There is no functional difference in server behavior. The repository includes a standard Python idiom at the bottom of [[`src/mcp_wordle/main.py`](https://github.com/cr2007/mcp-wordle-python/blob/main/src/mcp_wordle/main.py)](https://github.com/cr2007/mcp-wordle-python/blob/master/src/mcp_wordle/main.py#L70-L71) that calls `mcp.run()` when the module is executed directly. The entry point simply provides a convenient alias that eliminates the need to type the full module path or remember Python syntax.