Full chat client with LLM

Our basic client calls tools directly. But a real assistant needs an LLM deciding which tools to call based on the user's question. Let's build a full chat client with Streamlit and LiteLLM.

The key insight: the only glue code you need is a small function that converts MCP tool format to OpenAI tool format. That is it. Compare this to the ~108 lines of boilerplate per integration we wrote manually.

08-mcp-client-single.py
python
async def get_available_tools(server_url):
    """Connect to MCP server, discover tools, convert to OpenAI format."""
    async with sse_client(server_url) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools_result = await session.list_tools()
            return [
                {
                    "type": "function",
                    "function": {
                        "name": tool.name,
                        "description": tool.description,
                        "parameters": tool.inputSchema,
                    }
                }
                for tool in tools_result.tools
            ]

The entire glue code: connect, list_tools(), convert format. That is all you need.

08-mcp-client-single.py
python
async def execute_tool(server_url, tool_name, tool_args):
    """Execute a tool on the MCP server."""
    async with sse_client(server_url) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool(
                tool_name, arguments=tool_args
            )
            return result

Tool execution: connect, call_tool(), done. No dispatcher, no routing logic.

Notice we're using SSE transport here (sse_client) instead of STDIO. The chat client connects to a running server over HTTP. To switch, we just changed the server's mcp.run(transport='sse') and used sse_client on the client side. Everything else (tools, schemas, behavior) is identical.

The LLM receives the tool list (in OpenAI format) with every request. When a user asks 'search for papers about transformers,' the LLM decides to call search_articles with the right arguments. We pass the result back to the LLM, and it generates a natural language response. This is the same tool-calling loop from the Building AI Agents course, but now MCP handles all the wiring.

Validation checklist: Chat client validation

Loading practice…

Quiz: Quiz

Loading practice…

Checkpoint: MCP builder check

Loading practice…