Part of the twat collection of tools.
twat-mcp is a plugin for the twat application, designed to bring the rich, interactive world of MUDs (Multi-User Dungeons) to your terminal through the power of the MUD Client Protocol (MCP).
A MUD (Multi-User Dungeon) is a text-based online multiplayer game that combines elements of role-playing games, interactive fiction, and online chat. Players connect to a server, typically using a client application, and interact with a virtual world by typing commands. Imagine a vast, descriptive novel where you are the protagonist, and your actions, typed as text, shape your adventure in a world shared with other players. MUDs offer deep, complex gameplay and vibrant communities, existing long before graphical MMORPGs.
The MUD Client Protocol (MCP) is a special communication language that allows MUD servers and MUD clients (like twat when equipped with this plugin) to exchange structured information beyond simple text. Think of it as an upgrade to the basic MUD experience:
- Plain Telnet: You send text commands, you get text responses.
- With MCP: The server can send your client data like your character's health points, the items in your inventory, or details about your location. Your client can then display this information in dedicated UI elements (e.g., health bars, inventory lists, dynamic maps) or trigger notifications.
twat-mcp implements MCP, specifically targeting version 2.1. This enables twat to:
- Offer Richer Interactions: Go beyond basic text with features like clickable links for MUD actions, enhanced character status displays, or even simple graphical elements if
twatsupports them. - Improve User Experience: Make playing MUDs more intuitive and engaging by providing information in a more organized and accessible way.
- Enable Advanced Features: Support out-of-band communication for things like editing MUD world content directly from the client or secure authentication.
- MUD Players using
twat: If you use the (hypothetical)twatapplication as your MUD client,twat-mcpenhances your gameplay experience on MCP-enabled MUDs. - MUD Administrators and Developers: If you run or develop a MUD that supports MCP,
twat-mcpensures that users connecting viatwatcan take full advantage of your MUD's features. - Developers extending
twat: This plugin serves as an example of how to extendtwatwith protocol-specific capabilities.
The twat application, a versatile (hypothetical) terminal/text-based interaction tool, can be extended with plugins to support various protocols and functionalities. This plugin, twat-mcp, specifically adds support for MCP, enabling twat users to connect to MUDs that use MCP for enhanced features.
The goal is to provide a modern, well-tested, and easy-to-maintain implementation of MCP for the twat ecosystem.
- MCP 2.1 Support: Implements the MUD Client Protocol version 2.1.
- Seamless
twatIntegration: Designed as a plugin for thetwatapplication, discoverable via Python entry points. - Modern Python Stack: Built with Python 3.10+ using
pyproject.toml(PEP 621) and Hatch for project management. - Quality Assured: Fully type-hinted (Mypy), linted and formatted (Ruff), and tested (Pytest).
- Automated Processes: Features automated versioning from Git tags (
hatch-vcs) and CI/CD via GitHub Actions.
To use twat-mcp, you'll need Python 3.10 or newer. You can install the plugin using uv (a fast Python package installer, recommended) or pip (Python's standard package installer).
It's also assumed that you have the main twat application installed. If not, please refer to the twat installation guide.
# Using uv (recommended)
uv pip install twat-mcp
# Or using pip
pip install twat-mcpThis command installs twat-mcp and its dependencies. The twat application should then be able to automatically discover and load the plugin if its plugin system is set up to find plugins registered via Python entry points (which twat-mcp uses).
The twat-mcp plugin is designed to integrate seamlessly with the twat application. Once installed, twat should automatically detect and make MCP capabilities available when you connect to a MUD server that supports MCP.
The exact way to enable or use MCP features will depend on the twat application's design. For example, twat might:
- Automatically attempt MCP negotiation when a new MUD connection is established.
- Provide a command or UI option within
twatto enable/disable MCP for the current session. - Have a configuration setting where you can specify preferred protocols like MCP.
Example: Connecting to a MUD with twat (Conceptual CLI)
Imagine you're using twat from your terminal to connect to a MUD:
# This is a hypothetical twat CLI command
twat connect mymud.com:4000 --enable-mcpOr, twat might have an internal command after connecting:
/connect mymud.com:4000
... connected to mymud.com ...
/mcp start
During the connection, if the MUD server starts an MCP handshake, twat-mcp would handle the communication in the background. You would then see MCP-driven features come to life, such as custom UI elements, status updates, or special MUD-specific commands becoming available.
The twat-mcp plugin registers itself using an entry point defined in pyproject.toml. The twat application would typically use Python's importlib.metadata or a similar mechanism to find and load such plugins.
The core of the plugin is the TwatMcpPlugin class (expected to be defined in src/twat_mcp/__init__.py).
Conceptual Python Snippet (How twat might interact with the plugin):
# Within the twat application's codebase (hypothetical)
# twat would have a plugin manager or discovery mechanism
# For example, using entry points:
from importlib.metadata import entry_points
def load_twat_plugins():
loaded_plugins = {}
try:
# For Python 3.10+
discovered_plugins = entry_points(group="twat.plugins")
except TypeError: # Fallback for older way of calling or if group is not a kwarg
discovered_plugins = entry_points().select(group="twat.plugins")
except AttributeError: # Fallback for Python < 3.10 using importlib_metadata
from importlib_metadata import entry_points
discovered_plugins = entry_points(group="twat.plugins")
for entry_point in discovered_plugins:
if entry_point.name == "mcp": # Name defined in twat-mcp's pyproject.toml
try:
plugin_class = entry_point.load()
# Assuming the plugin class has an __init__ that twat calls,
# possibly passing some twat-specific context or API.
# plugin_instance = plugin_class(twat_api_handle=get_twat_api())
plugin_instance = plugin_class() # Or however twat expects to init
loaded_plugins[entry_point.name] = plugin_instance
# Assuming a get_version method or __version__ attribute
# version = getattr(plugin_instance, "get_version", lambda: getattr(plugin_instance, "__version__", "unknown"))()
# print(f"Loaded plugin: {entry_point.name} - version {version}")
print(f"Loaded plugin: {entry_point.name}")
# twat might then call methods on plugin_instance, e.g.:
# plugin_instance.initialize_mcp_session(connection_id)
except Exception as e:
print(f"Failed to load plugin {entry_point.name}: {e}")
return loaded_plugins
# Later, when twat receives a message that might be MCP:
# active_mcp_plugin = loaded_plugins.get("mcp")
# if active_mcp_plugin and hasattr(active_mcp_plugin, 'is_mcp_message'):
# if active_mcp_plugin.is_mcp_message(server_data):
# mcp_response = active_mcp_plugin.handle_mcp_message(server_data)
# if mcp_response:
# send_to_server(mcp_response)
# This is a simplified, conceptual illustration. The actual methods and interaction
# flow would be defined by twat's plugin API. The TwatMcpPlugin class would
# implement the necessary methods to conform to that API, handling MCP negotiation,
# message parsing, and state management.The TwatMcpPlugin would be responsible for:
- Initiating the MCP handshake with the MUD server.
- Processing incoming MCP messages from the server.
- Dispatching these messages to appropriate handlers (e.g., for updating UI elements managed by
twat, or for handling specific MCP packages). - Sending MCP messages generated by the client (or by
twatthrough the plugin) back to the server.
This section provides a deeper dive into the internal workings of twat-mcp.
twat-mcp is designed as a plugin for the twat application. Its primary responsibility is to manage all aspects of MUD Client Protocol (MCP) communication for twat.
-
Plugin Discovery and Loading:
twat-mcpregisters itself as a plugin using a standard Python entry point:twat.plugins. This is defined in thepyproject.tomlfile:[project.entry-points."twat.plugins"] mcp = "twat_mcp:TwatMcpPlugin"
- The
twatapplication is expected to look for entry points in this group. Upon discoveringtwat-mcp, it would load theTwatMcpPluginclass fromsrc/twat_mcp/__init__.py.
-
Main Plugin Class:
TwatMcpPlugin:- The
TwatMcpPluginclass is the central hub of the plugin. An instance of this class will be created bytwat. - It will hold the state of the MCP connection for a given MUD session.
- It will expose methods for
twatto call, for example, to:- Notify the plugin of new data received from the server.
- Request the plugin to send an MCP message to the server.
- Query the status of the MCP session.
- It will likely interact with a
twat-provided API to:- Send data back to the MUD server.
- Update
twat's UI elements based on MCP messages (e.g., display a health bar, update a map). - Log messages or errors.
- The
-
Dependencies:
mcp-openapi-proxy: This dependency suggests thattwat-mcpmight leverage OpenAPI specifications for MCP messages. It could be used to generate client-side code for message validation, serialization, and deserialization, ensuring that the plugin correctly implements various MCP packages based on a formal specification.mcp[cli]>=1.2.1: This indicates a dependency on an MCP library, potentially providing core MCP parsing, state management, or utilities. The[cli]extra suggests it might also come with command-line tools useful for debugging or development.twat: The plugin naturally depends on the maintwatapplication, expecting it to provide the necessary environment and APIs for a plugin to function.
twat-mcp aims to implement MCP version 2.1. This involves several key aspects:
-
MCP Handshake (Negotiation):
- When
twatconnects to a MUD, and MCP is enabled, the plugin needs to listen for the server initiating the MCP handshake. This typically starts with the server sending a#$#mcp version: 2.1 to: 2.1message. - The
TwatMcpPluginwill be responsible for recognizing this handshake and responding appropriately to establish an MCP session. - It will also handle the initial exchange of supported MCP packages.
- When
-
Message Handling:
- Parsing: Incoming data from the MUD server must be inspected for MCP messages. MCP messages are typically prefixed with
#$#. The plugin will parse these messages to extract the command, arguments, and any key-value pairs. - Dispatching: Once an MCP message is parsed (e.g.,
#$#dns-com-awns-status-update room_name: "The Grand Hall" room_id: "gh123"), the plugin will dispatch it to a handler specific to that MCP package and command (e.g., a handler fordns-com-awns-status-update). - State Management: The plugin will need to maintain state related to the MCP session, such as negotiated packages, authentication status (if using MCP auth), and any data received from the server that needs to be tracked (e.g., current character stats).
- Parsing: Incoming data from the MUD server must be inspected for MCP messages. MCP messages are typically prefixed with
-
MCP Packages:
- MCP is a framework, and its functionality is extended through various "packages" (e.g.,
mcp-negotiate,dns-com-awns-status,dns-com-awns-display). - The plugin will need to declare which MCP packages it supports.
- Implementation of handlers for specific MCP packages will define the plugin's capabilities. For example:
- A handler for
dns-com-awns-statusmight update variables intwatthat display the character's current status. - A handler for
mcp-negotiatewould manage the list of supported packages with the server.
- A handler for
- The
mcp-openapi-proxydependency suggests that the structure and validation of these packages might be defined by OpenAPI schemas.
- MCP is a framework, and its functionality is extended through various "packages" (e.g.,
-
Sending MCP Messages:
- The plugin will provide methods for
twat(or internal components of the plugin) to construct and send valid MCP messages to the MUD server. This could be in response to server messages or initiated by user actions withintwat.
- The plugin will provide methods for
The typical data flow involving twat-mcp would be:
Server to Client (MUD -> twat -> twat-mcp -> twat UI):
- MUD server sends data containing an MCP message (e.g.,
#$#char-status-update hp: 100 max_hp: 100). twatreceives this data from the network connection.twatpasses the data to theTwatMcpPlugininstance.TwatMcpPluginparses the data, identifies it as an MCP message, and extracts its content.- The plugin processes the message (e.g., notes that HP is 100/100).
- The plugin might then use a
twatAPI to update a UI element (e.g., set a health bar to full) or store the state internally for other uses.
Client to Server (twat UI/Action -> twat-mcp -> twat -> MUD):
- A user action in
twat(e.g., clicking a button defined by an MCP package) or an internaltwatevent triggers the need to send an MCP message. twatcalls a method on theTwatMcpPlugininstance, requesting it to send a specific MCP message (e.g.,mcp-edit-savefor an object).TwatMcpPluginconstructs the valid MCP message string (e.g.,#$#mcp-edit-save object_name: "sword" content: "A gleaming sword.").- The plugin passes this string to
twat's networking layer. twatsends the message to the MUD server.
-
pyproject.toml:- Defines project metadata, dependencies (including
mcp-openapi-proxy,mcp[cli],twat). - Crucially, contains the
[project.entry-points."twat.plugins"]definition that allowstwatto discovertwat-mcp. - Configures development tools like Hatch, Ruff, Mypy, and Pytest.
- Defines project metadata, dependencies (including
-
src/twat_mcp/__init__.py:- This is the main entry point of the installable package.
- It is expected to define the
TwatMcpPluginclass. This class will encapsulate all MCP logic. - It also includes version information, typically managed by
hatch-vcsby writing tosrc/twat_mcp/__version__.py.
-
src/twat_mcp/mcp_search.py:- This file is currently empty. Its intended purpose is not clear from the existing codebase.
- Possible uses could have been for implementing client-side discovery of MCP services or packages if a MUD supported such a mechanism (which is not standard MCP 2.1 but could be a custom extension).
- Alternatively, it might have been a placeholder for helper functions related to searching or processing MCP data.
- For now, its role is undefined in this documentation. If it's developed, this documentation should be updated.
-
tests/:- Contains Pytest tests for the plugin.
test_package.py: Likely contains basic tests confirming package integrity, version, etc.test_plugin.py: Should contain tests for theTwatMcpPluginclass, MCP message parsing, state changes, and interaction with a mockedtwatAPI.
We welcome contributions to twat-mcp! Please follow these guidelines to ensure a smooth and effective development process. Our goal is to maintain a high-quality, modern, and robust plugin.
- Clarity and Readability: Write code that is easy to understand and maintain.
- Test Coverage: Aim for comprehensive test coverage for all new features and bug fixes.
- Type Safety: Leverage Python's type hinting system to improve code reliability.
- Consistency: Adhere to the project's coding style and conventions.
-
Prerequisites:
-
Clone the Repository:
git clone https://github.com/twardoch/twat-mcp.git cd twat-mcp -
Install Hatch (if not already installed):
# Using uv (recommended) uv pip install hatch # Or using pip pip install hatch
-
Activate the Development Environment with Hatch: Hatch will create and manage a virtual environment for the project, installing all necessary dependencies, including development and testing tools.
hatch shell
This command:
- Creates a virtual environment (if it doesn't exist) using the Python version specified in
pyproject.toml(defaulting to 3.10). - Installs the
twat-mcppackage in editable mode (-e .) along with itsdevandtestoptional dependencies. - Activates the virtual environment, making tools like
pytest,ruff, andmypydirectly available.
You can also run commands within the Hatch environment without explicitly activating the shell using
hatch run <script_name>. For example,hatch run test. - Creates a virtual environment (if it doesn't exist) using the Python version specified in
-
Install Pre-commit Hooks: This project uses pre-commit hooks to automatically check and format your code before each commit. This helps ensure that all committed code adheres to the project's standards.
# Ensure you are in the hatch shell or your manually activated venv pre-commit installThe hooks are defined in
.pre-commit-config.yaml.
pyproject.toml: Defines project metadata, dependencies, build system (hatchling), and configurations for tools like Ruff, Mypy, Pytest, and Hatch environments/scripts.src/twat_mcp/: Contains the main source code for the plugin.__init__.py: Main module for the package, expected to define theTwatMcpPluginclass.__version__.py: Version file automatically generated/updated byhatch-vcs.mcp_search.py: Currently an empty module; its future role will be documented here if developed.
tests/: Contains the Pytest test suite..github/workflows/: GitHub Actions workflows for Continuous Integration (CI) and releases..pre-commit-config.yaml: Configuration for pre-commit hooks (Ruff, Mypy, etc.).LICENSE: The MIT License file.README.md: This file – project documentation.
- Formatting: Code formatting is enforced by Ruff using the configuration in
pyproject.toml.- Run
hatch run formatorruff format . && ruff check . --fixto format your code. - The pre-commit hook will also attempt to auto-format changed files.
- Run
- Linting: Code quality and style are checked by Ruff.
- Run
hatch run lint:styleorruff check .to identify and fix linting issues.
- Run
- Type Checking: Static type checking is performed by Mypy using the configuration in
pyproject.toml.- Run
hatch run type-checkormypy src/twat_mcp teststo check types. - All new code should include type hints. Aim for
disallow_untyped_defs = true.
- Run
Comprehensive testing is crucial. This project uses Pytest.
- To run all tests with coverage reporting:
This command (defined in
hatch run test:test-cov
pyproject.tomlundertool.hatch.envs.default.scripts) runs Pytest, measures code coverage, and generates a report. - To run specific tests:
(Arguments after
hatch run test -- tests/test_plugin.py::TestMyFeature -k "some_test_name"
--are passed directly to Pytest). - Ensure new features are accompanied by tests, and that all tests pass before submitting changes.
- Maintain or improve the existing code coverage level (see
tool.coverage.report.fail_underinpyproject.toml).
- Versioning Scheme: The project uses Semantic Versioning (SemVer -
MAJOR.MINOR.PATCH) based on Git tags. - Automatic Versioning: The version is managed automatically by
hatch-vcs.- When a new commit is made on
mainafter a release tag,hatch-vcsderives a development version (e.g.,0.1.0.post1+g123abc). - The official version string is written to
src/twat_mcp/__version__.pyat build time.
- When a new commit is made on
- Making a Release (for maintainers):
- Ensure the
mainbranch is up-to-date, all tests are passing, and documentation is current. - Create an annotated Git tag for the new version:
(e.g.,
git tag -a vX.Y.Z -m "Version X.Y.Z Release Notes"git tag -a v0.2.0 -m "Release version 0.2.0: Added feature X and fixed bug Y.") - Push the tag to GitHub:
git push origin vX.Y.Z
v*.*.*(e.g.,v0.1.0) will trigger therelease.ymlGitHub Actions workflow. This workflow builds the package (sdist and wheel) and publishes it to PyPI. It also creates a GitHub Release based on the tag. - Ensure the
- Fork the Repository: Create a fork of
twardoch/twat-mcpon GitHub. - Create a Feature Branch:
(Choose a descriptive branch name, e.g.,
git checkout -b your-feature-name main
feat/add-mcp-edit-packageorfix/handle-malformed-input). - Implement Your Changes:
- Write clear, maintainable code.
- Add comprehensive tests for new functionality or bug fixes.
- Ensure your code passes all linting, formatting, and type checks:
(This script typically runs formatting, type checking, and tests with coverage).
hatch run lint-all
- Update
README.mdor other documentation if your changes affect usage, architecture, or add new features.
- Commit Your Changes:
- Write clear and concise commit messages. Follow conventional commit message formats if possible (e.g.,
feat: Implement MCP package X,fix: Resolve issue with Y). - Ensure pre-commit hooks run successfully.
- Write clear and concise commit messages. Follow conventional commit message formats if possible (e.g.,
- Push to Your Fork:
git push origin your-feature-name
- Submit a Pull Request (PR):
- Open a PR from your feature branch on your fork to the
mainbranch of thetwardoch/twat-mcprepository. - Provide a clear description of your changes in the PR. Reference any relevant issues.
- Ensure all automated checks (GitHub Actions CI) pass for your PR.
- Be prepared to discuss and iterate on your changes based on feedback.
- Open a PR from your feature branch on your fork to the
twat-mcp is licensed under the MIT License. By contributing to twat-mcp, you agree that your contributions will be licensed under the same MIT License that covers the project.
- This plugin is designed for the (hypothetical)
twatapplication. - Inspired by the MUD Client Protocol (MCP).
- Utilizes modern Python tooling including Hatch, Ruff, Mypy, and Pytest.