Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,12 @@ cd agent_uno
uv run mcp install server.py
```

> [!TIP]
> The above command updates the MCP config in Claude desktop. Whilst Claude Desktop only supports `stdio` transport the server can be directly executed with communication via `sse` transport and HTTP requests. For documentation on how to do this see [direct_execution.md](docs/direct_execution.md).

> [!NOTE]
> If you have Claude Desktop open when you run the above command, you will need to restart it for the server to be available.

> [!WARNING]
> Common Issues:
> 1. `ENOENT` error when opening Claude Desktop.
> - This is due to Claude Desktop facing issues with running the server with a relative path to `uv`. To fix this, you need to change the `command` in the `claude_desktop_config.json` config to an absolute path. You can find the absolute path by running `which uv` in your terminal.
> 2. Not having `coreutils` installed.
> - This is required for the `realpath` command. You will see the following error in Claude logs: `realpath: command not found`. You can install it using `brew install coreutils`.

2. Interact with MCP server with Claude Desktop.

:chess_pawn: Agent vs. Stockfish Bot :robot::
Expand All @@ -59,3 +55,10 @@ uv run mcp install server.py
2. Once the game has been created and the opponent has connected and made their first move, the agent will make their move.

> Once the game has been created the opponent will make the first move. Can you use the previous moves and the layout of the board to determine what an optimal next move will be and then make your own move playing continuously back and forth until completion? Please use the UCI chess standard for your moves, e.g., e2e4.

> [!WARNING]
> Common Issues:
> 1. `ENOENT` error when opening Claude Desktop.
> - This is due to Claude Desktop facing issues with running the server with a relative path to `uv`. To fix this, you need to change the `command` in the `claude_desktop_config.json` config to an absolute path. You can find the absolute path by running `which uv` in your terminal.
> 2. Not having `coreutils` installed.
> - This is required for the `realpath` command. You will see the following error in Claude logs: `realpath: command not found`. You can install it using `brew install coreutils`.
9 changes: 8 additions & 1 deletion agent_uno/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,17 @@ async def get_board() -> str:
return cast(str, board.__str__())


@mcp.tool(description="Get the current board as an ASCII representation.") # type: ignore
@mcp.tool(
description="""Get the current board as an ASCII representation and all previous
moves."""
) # type: ignore
async def get_board_representation() -> BoardRepresentation | GameStateMsg:
"""An endpoint for getting the current board as an ASCII representation."""
board = await get_board()
previous_moves = await get_previous_moves()

return BoardRepresentation(board=board, previous_moves=previous_moves)


if __name__ == "__main__":
mcp.run()
122 changes: 122 additions & 0 deletions docs/direct_execution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Direct Execution

## Inspector Tool

Currently testing of endpoints can be performed with the following command:

```bash
uv run mcp dev server.py
```

This will start a local server running `Inspector` than can be used to interact with the MCP tools.

![inspector](imgs/inspector.png)

## Under the hood

You can run the server directly with the following command:

```bash
uv run mcp run server.py --transport sse
```

> [!NOTE]
> This will start a local MCP server on port `8000`.

Setting `sse` allows us to communicate with the server via HTTP using the `Server-Sent Events` protocol. This is a one-way communication channel from the server to the client. The client can send messages to the server using the `POST` method, but the server can only send messages to the client using the `GET` method.

We can establish an MCP client by making a request to the `sse` endpoint of the server:

```bash
curl http://0.0.0.0:8000/sse
```

This will return an output of the form:

```
event: endpoint
data: /messages/?session_id=<session_id>
```

and then ping incrementally.

As per the MCP docmentation, a client-server lifecycle consists of three stages: connection, exchange, and termination.

> The lifecycle of an MCP connection involves three main stages:
>
> Initialization:
>
> * The client sends an initialize request, including its protocol version and capabilities.
> * The server responds with its protocol version and capabilities.
> * The client sends an initialized notification to acknowledge.
> * Normal message exchange begins.
>
> Message Exchange: After initialization, clients and servers can exchange messages using these patterns:
>
> * Request-Response: The client sends a request, and the server responds.
> * Notifications: Either side sends one-way messages (no response expected).
>
> Termination: The connection can be terminated in several ways:
>
> * Clean shutdown via a close() method.
> * Transport disconnection.
> * Error conditions.

### Initialisation Requests

1. Send an initialisation request.

```bash
curl "http://0.0.0.0:8000/messages/?session_id=<session_id>" \
-X POST \
-H "Content-Type: application/json" \
-d '{
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {},
"roots": {
"listChanged":true
}
},
"clientInfo": {
"name": "mcp-inspector",
"version": "0.8.0"
}
},
"jsonrpc":"2.0",
"id":0
}
}'
```

2. Send an initialisation notification.

```bash
curl "http://0.0.0.0:8000/messages/?session_id=<session_id>" \
-X POST \
-H "Content-Type: application/json" \
-d '{
"method": "notifications/initialized",
"jsonrpc": "2.0"
}'
```

Now the server and client are initialised and ready to exchange messages.

### Message Exchange

1. We can now start to interact with the server. Typically, the client might start by listing the tools.

```bash
curl "http://0.0.0.0:8000/messages/?session_id=<session_id>" \
-X POST \
-H "Content-Type: application/json" \
-d '{
"method": "tools/list",
"params": {},
"jsonrpc": "2.0",
"id": 1
}'
```
Binary file added docs/imgs/inspector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ dependencies = [
"mcp[cli]>=1.6.0",
"pydantic>=2.11.1",
"python-chess>=1.999",
"python-dotenv (>=1.1.0,<2.0.0)"
"python-dotenv (>=1.1.0,<2.0.0)",
]

[dependency-groups]
Expand Down Expand Up @@ -99,6 +99,9 @@ extend-exclude = [".gitignore", "LICENSE", ".*"]
[tool.typos.default.extend-words]
center = "center"
color = "color"
initialization = "initialization"
initialize = "initialize"
initialized = "initialized"

[tool.typos.default]
locale = "en-gb"
Expand Down