Setting Up MCP Server Entry Points with pyproject.toml

Define console scripts under [project.scripts] in 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 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 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/master/pyproject.toml#L23-L25), the entry point is defined as:

[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/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/master/src/mcp_wordle/main.py#L13-L14), the server is instantiated:

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/master/src/mcp_wordle/main.py#L30-L38), the get_wordle_data function becomes accessible as get_wordle_solution:

@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, deployment requires only standard Python packaging commands.

Development Installation

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

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:

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:

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:

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 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. 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 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/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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →