Skip to content

Commit cb2326c

Browse files
author
Richard Lack
committed
created
1 parent 128bfd4 commit cb2326c

File tree

5 files changed

+198
-2
lines changed

5 files changed

+198
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ venv/
135135
ENV/
136136
env.bak/
137137
venv.bak/
138+
venv-*
138139

139140
# Spyder project settings
140141
.spyderproject

DOCKERFILE

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Use Ubuntu as the base image
2+
FROM ubuntu:22.04
3+
4+
# Set non-interactive mode during build
5+
ENV DEBIAN_FRONTEND=noninteractive
6+
7+
# Update and install Python 3.10 and essential dependencies
8+
RUN apt-get update && \
9+
apt-get install -y --no-install-recommends \
10+
python3.10 \
11+
python3-pip \
12+
python3.10-dev \
13+
&& ln -sf /usr/bin/python3.10 /usr/bin/python \
14+
&& ln -sf /usr/bin/python3.10 /usr/bin/python3 \
15+
&& apt-get clean \
16+
&& rm -rf /var/lib/apt/lists/*
17+
18+
# Verify Python version
19+
RUN python --version
20+
21+
# Create directory for volume mounting
22+
RUN mkdir -p /usr/code
23+
24+
# Set the working directory
25+
WORKDIR /usr/code
26+
27+
# Volume configuration for code mounting
28+
VOLUME ["/usr/code"]
29+
30+
# Default command to run when the container starts
31+
CMD ["bash"]
32+
33+
34+
#--- Build instructions, podman or docker:
35+
# podman build --tag linux-lab-08b --file DOCKERFILE .
36+
37+
#--- Run instructions
38+
# Run the following with podman or docker, replacing "your-src-path" with the path to your src/:
39+
# podman run -it --rm -v "your-src-path:/usr/code" linux-lab-08b bash
40+
# Then from the vm:
41+
# cd /usr/code
42+
# python mcp_client.py

README.md

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,75 @@
1-
# mcp-client-python-issue
2-
Repo to diagnose an issue we're having with mcp python client
1+
# MCP SDK Client Python Issue
2+
3+
This repo is to demonstrate and diagnose an issue we're having with the Python MCP stdio
4+
client. What happens is it never finishes initializes the server. What I expect to
5+
happen is for it to initialize the server successfully so that we can start
6+
communicating with it.
7+
8+
I have tried this in many configurations, including Python 3.10 windows,
9+
Python 3.12 windows, Python 3.12 under WSL, and running Linux in a container,
10+
using the latest main branch and also the latest releases,
11+
and various forms of UV and global Python installations. I have also tried
12+
it using `asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())`
13+
in various Windows configurations. Under some configurations this leads
14+
to a new `NotImplementedError`, but under no circumstances was I able to make
15+
it work.
16+
17+
I haven't been able to make a Python client work yet. I can get node client
18+
and server working without difficulties, though.
19+
20+
## Repro steps, Windows and UV
21+
From the root directory of the project (above src):
22+
```Powershell
23+
uv venv --python=3.10 venv
24+
.\venv\Scripts\activate.ps1
25+
uv pip install mcp
26+
```
27+
28+
Output under windows:
29+
```
30+
(venv) PS C:\Users\rilack\code\mcp-client-python-issue\src> python mcp_client.py
31+
Ultra Basic MCP Client
32+
sys.executable='C:\\Users\\rilack\\code\\mcp-client-python-issue\\venv\\Scripts\\python.exe'
33+
Python version 3.10.16 (main, Mar 17 2025, 20:54:03) [MSC v.1943 64 bit (AMD64)]
34+
Initializing session...
35+
```
36+
And that is the last thing that we see.
37+
38+
## Repro steps, Docker, Ubuntu
39+
To eliminate the variables that this could be an issue with Windows or UV,
40+
I also tested this with Linux. I have tried this both with Python 3.12 and 3.10
41+
with the same results.
42+
43+
### Build container
44+
I used `podman` to build and run my containers, but you can use `docker` instead.
45+
46+
From the root of the project:
47+
```bash
48+
podman build --tag mcp-lab-08c --file DOCKERFILE .
49+
```
50+
51+
### Run container
52+
Replace `your-src-path` to the directory of your local machine where this project is installed.
53+
```bash
54+
podman run -it --rm -v "your-src-path:/usr/code" mcp-lab-08c bash
55+
```
56+
So for me, I used:
57+
```bash
58+
podman run -it --rm -v "c:\Users\rilack\code\mcp-client-python-issue:/usr/code" mcp-lab-08c bash
59+
```
60+
61+
Then from the container:
62+
```bash
63+
pip install mcp
64+
cd src
65+
python mcp_client.py
66+
```
67+
68+
Output:
69+
```
70+
root@85b6bb0ac0e8:/usr/code/src# python mcp_client.py
71+
Ultra Basic MCP Client
72+
sys.executable='/usr/bin/python'
73+
Python version 3.10.12 (main, Feb 4 2025, 14:57:36) [GCC 11.4.0]
74+
Initializing session...
75+
```

src/mcp_client.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import asyncio
2+
import sys
3+
4+
from mcp import ClientSession, StdioServerParameters, types
5+
from mcp.client.stdio import stdio_client
6+
7+
# From https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#writing-mcp-clients
8+
9+
10+
# Create server parameters for stdio connection
11+
server_params = StdioServerParameters(
12+
command=sys.executable, # Leverage the parent python environment so the child also uses python 3.10 with the same libraries.
13+
args=["mcp_echo_server.py"], # Optional command line arguments
14+
env=None, # Optional environment variables
15+
)
16+
17+
# Removed the optional sampling callback for simplicity.
18+
19+
async def run():
20+
async with stdio_client(server_params) as (read, write):
21+
async with ClientSession(read, write) as session:
22+
# Initialize the connection
23+
print("Initializing session...") # This is the last thing we will see.
24+
await session.initialize()
25+
print("Session initialized successfully.") # If it's broken we won't see this.
26+
27+
# List available prompts
28+
prompts = await session.list_prompts()
29+
30+
# Get a prompt
31+
prompt = await session.get_prompt(
32+
"example-prompt", arguments={"arg1": "value"}
33+
)
34+
35+
# List available resources
36+
resources = await session.list_resources()
37+
38+
# List available tools
39+
tools = await session.list_tools()
40+
41+
# Read a resource
42+
content, mime_type = await session.read_resource("file://some/path")
43+
44+
# Call a tool
45+
result = await session.call_tool("tool-name", arguments={"arg1": "value"})
46+
47+
48+
def main():
49+
print('Ultra Basic MCP Client')
50+
print(f'{sys.executable=}')
51+
print(f'Python version {sys.version}')
52+
53+
asyncio.run(run())
54+
55+
56+
if __name__ == "__main__":
57+
main()

src/mcp_echo_server.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# This is used to test the mcp server
2+
# from https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#echo-server
3+
from mcp.server.fastmcp import FastMCP
4+
5+
mcp = FastMCP("Echo")
6+
7+
8+
@mcp.resource("echo://{message}")
9+
def echo_resource(message: str) -> str:
10+
"""Echo a message as a resource"""
11+
return f"Resource echo: {message}"
12+
13+
14+
@mcp.tool()
15+
def echo_tool(message: str) -> str:
16+
"""Echo a message as a tool"""
17+
return f"Tool echo: {message}"
18+
19+
20+
@mcp.prompt()
21+
def echo_prompt(message: str) -> str:
22+
"""Create an echo prompt"""
23+
return f"Please process this message: {message}"

0 commit comments

Comments
 (0)