mcp hosted on a server and client app

In this post, we are going to host our mcp tool on a remote server and let it called by a client. 

First ensure we have initialize the directory and added the right packages here 


uv add fastmcp uvicorn

Then we will have our server.py where we will use uvicorn to host it and then expose /sse endpoint for client to call.

server.py

# server.py
import os
from fastmcp import FastMCP
       
# 1. Initialize FastMCP
mcp = FastMCP("Remote Centralized Tooling")

# 2. Define your tool(s)
@mcp.tool()
def calculate_server_metrics(cpu_load: float, memory_load: float) -> str:
    """Performs complex analysis on system performance metrics."""
    # Since this lives entirely on your remote server, you can update this logic
    # at any time, and local clients will get the updated behavior instantly.
    score = (cpu_load * 0.7) + (memory_load * 0.3)
    if score > 80:
        return f"Warning: Server health score is critical ({score:.1f}%). Optimize immediately."
    return f"Server health score is stable ({score:.1f}%)."

# 3. Expose the underlying ASGI app for Uvicorn
#app = mcp.streamable_http_app()
#app  = mcp.http_app()
app = mcp.http_app(transport="sse")

# If run directly via `python server.py`, it boots via uvicorn
if __name__ == "__main__":
    import uvicorn
    # In production, change host to "0.0.0.0" and protect it behind a proxy/VPN
    uvicorn.run("server.py:app", host="0.0.0.0", port=8000, reload=True)


And then here, client.py


import asyncio
from mcp import ClientSession
# Use the standard SSE client, no streamable dependencies
from mcp.client.sse import sse_client

async def run_remote_tool_locally():
    # FastMCP's http_app() defaults to exposing the SSE stream at the /sse path
    remote_url = "http://127.0.0.1:8000/sse"
   
    print(f"Connecting to standard SSE server at {remote_url}...")
   
    # sse_client yields a tuple of (read_stream, write_stream)
    async with sse_client(remote_url) as (read_stream, write_stream):
        # Initialize the session using the standard streams
        async with ClientSession(read_stream, write_stream) as session:
            # 1. Complete the handshake
            await session.initialize()
            print("Connection established!\n")
           
            # 2. Dynamically fetch available tools over the network
            tools_response = await session.list_tools()
            print("--- Available Remote Tools ---")
            for tool in tools_response.tools:
                print(f"Tool Name: {tool.name} | Description: {tool.description}")
           
            # 3. Call the tool execution remotely
            print("\nExecuting remote tool...")
            result = await session.call_tool(
                name="calculate_server_metrics",
                arguments={"cpu_load": 85.5, "memory_load": 72.0}
            )
           
            print(f"Result from remote server:\n{result.content[0].text}")

if __name__ == "__main__":
    asyncio.run(run_remote_tool_locally())

To start the server run the following 

uvicorn main:app --host 0.0.0.0 --port 8000

And then we initiate a client request by running 

python client.py



Comments

Popular posts from this blog

mongosh install properly

gemini cli getting file not defined error

vllm : Failed to infer device type