# Build an MCP Client via UCloud API


## Install Node.js

[https://nodejs.org/en](https://nodejs.org/en)



## Install Required Dependencies

```plain
pip install mcp
pip install openai
```

## Run the Code

The following code can be used as a template. Note that you must replace it with your actual ModelVerse platform API_KEY.

> We use an MCP Server that does not require an API key: [web-search](https://github.com/mzxrai/mcp-webresearch). If you are using Windows, please uncomment the following line in the code: `# command="cmd.exe", args=["/c", "npx", "-y", "@mzxrai/mcp-webresearch@latest"]`


```python
import asyncio
import json
from typing import Optional
from contextlib import AsyncExitStack

from openai import OpenAI
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


openai_client = OpenAI(
    base_url="https://api-us-ca.umodelverse.ai/v1",  # ModelVerse API endpoint (no need to modify)
    api_key="<your_api_key>",  # Create API Key from the console
)
model_name = "Qwen/QwQ-32B"  # Model name (no need to modify)


class MCPClient:
    def __init__(self):
        """Initialize the MCP client"""
        self.exit_stack = AsyncExitStack()
        self.client = openai_client
        # Initialize client
        self.session: Optional[ClientSession] = None
        self.exit_stack = AsyncExitStack()

    async def connect_to_server(self):
        # Use MCP Server without API key
        server_params = StdioServerParameters(
            # Use the following command on macOS
            command="npx",
            args=["-y", "@mzxrai/mcp-webresearch@latest"],
            # Use the following command on Windows
            # command="cmd.exe", args=["/c", "npx", "-y", "@mzxrai/mcp-webresearch@latest"],
        )

        # Start MCP server and establish communication
        stdio_transport = await self.exit_stack.enter_async_context(
            stdio_client(server_params)
        )
        self.stdio, self.write = stdio_transport
        self.session = await self.exit_stack.enter_async_context(
            ClientSession(self.stdio, self.write)
        )

        await self.session.initialize()

        # List tools on MCP server
        list_tools_resp = await self.session.list_tools()
        list_prompt_resp = await self.session.list_prompts()
        list_resource_resp = await self.session.list_resources()
        self.session.get_prompt
        tools = list_tools_resp.tools
        print(
            "\nConnected to server. Available tools:",
            [tool.name for tool in tools],
            "Available prompts:",
            [prompt.name for prompt in list_prompt_resp.prompts],
            "Available resources:",
            [resource.name for resource in list_resource_resp.resources],
        )

    async def process_prompt(self, query: str) -> str:
        """
        Use LLM to process queries and call available MCP tools (tool calling)
        """
        messages = [{"role": "user", "content": query}]

        list_tools_resp = await self.session.list_tools()
        self.session.complete

        available_tools = [
            {
                "type": "function",
                "function": {
                    "name": tool.name,
                    "description": tool.description,
                    "parameters": tool.inputSchema,
                },
            }
            for tool in list_tools_resp.tools
        ]

        resp = self.client.chat.completions.create(
            model=model_name, messages=messages, tools=available_tools
        )
        # Handle response
        content = resp.choices[0]
        if content.finish_reason == "tool_calls":
            # If tool usage is required, parse tool call
            tool_call = content.message.tool_calls[0]
            tool_name = tool_call.function.name
            tool_args = json.loads(tool_call.function.arguments)

            # Execute tool
            result = await self.session.call_tool(tool_name, tool_args)
            print(f"\n\n[Calling tool {tool_name} with args {tool_args}]\n\n")

            # Append tool call and result into messages
            messages.append(
                {
                    "role": "tool",
                    "content": result.content[0].text,
                    "tool_call_id": tool_call.id,
                }
            )

            # Send result back to LLM for final response
            resp = self.client.chat.completions.create(
                messages=messages, model=model_name, tools=available_tools
            )
            return resp.choices[0].message.content

        return content.message.content

    async def chat_loop(self):
        """Run interactive chat loop"""
        print("\n🤖 MCP Host started! Type 'exit' to quit")

        while True:
            try:
                prompt = input("\nYou: ").strip()
                if prompt.lower() == "exit":
                    break

                response = await self.process_prompt(prompt)
                print(f"\n🤖 ModelVerse QwQ-32B: {response}")

            except Exception as e:
                print(f"\n⚠️ Error occurred: {str(e)}")

    async def cleanup(self):
        """Clean up resources"""
        await self.exit_stack.aclose()


async def main():
    client = MCPClient()
    try:
        await client.connect_to_server()
        await client.chat_loop()
    finally:
        await client.cleanup()


if __name__ == "__main__":

    asyncio.run(main())
```

## Interaction Example

User request:

> Please help me read and summarize the webpage [https://XXXXXXXXXXXXXXXX)

![image](https://cdn.udelivrs.com/2026/04/0f7576984946b79be17b3a73ec462ae5_1776316925397.png)


