之前两篇文章:MCP简介MCP能做什么阐述了MCP的基本概念和原理。
本文将使用Visual Studio Code写一个MCP服务端MCP客户端,演示MCP的基本功能。

MCP版本迭代很快,能用把代码顺利跑起来并不是一件容易的事:)

准备运行环境

  • Windows 10
  • Visual studio code 1.104.3
  • python 3.12.3
  • mcp 1.16.0
  1. 创建 venv 虚拟环境

参见:在Visual Studio Code中配置venv

  1. 安装 mcp

激活虚拟环境(windows):

.venv\Scripts\activate

安装mcp

pip install mcp

MCP代码仓库推荐使用 uv 工具管理包。由于我之前一直用 pip 管理包,觉得再用 uv 比较麻烦,所以没有安装它。

构建MCP服务端

下面的程序使用 FastMCP 构建了一个带有 工具/tool资源/resource提示词模板/prompt 的MCP服务端。
本次的服务使用 标准输入输出/Stdio 方式对客户端提供服务,这样MCP客户端加载这个MCP服务端就能完成它们的通信,调试起来比较方便。当然,MCP服务端也可以使用HTTP(支持流式传输)的方式向远端MCP客户端提供服务。

from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo MCP Server")

# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"


# Add a prompt
@mcp.prompt()
def greet_user(name: str, style: str = "friendly") -> str:
    """Generate a greeting prompt"""
    styles = {
        "friendly": "Please write a warm, friendly greeting",
        "formal": "Please write a formal, professional greeting",
        "casual": "Please write a casual, relaxed greeting",
    }
    return f"{styles.get(style, styles['friendly'])} for someone named {name}."   

def main():
    # Initialize and run the server
    mcp.run(transport='stdio')

if __name__ == "__main__":
    main()

由于没有安装 nv 工具,所以这里我们用mcp.run(transport='stdio')明确启动mcp服务端,传输方式采用 stdio

构建MCP客户端

下面的MCP客户端将调用MCP服务端,测试 工具/tool资源/resource提示词模板/prompt

import asyncio
import os

from pydantic import AnyUrl

from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_client

# 获取当前文件所在目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
print(current_dir)
server_path = os.path.join(current_dir, "fastmcp_server.py")

# Create server parameters for stdio connection
server_params = StdioServerParameters(
    command="python",
    args=[server_path], 
    env=None,
)

async def run():
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            # Initialize the connection
            await session.initialize()

            # List available tools
            tools = await session.list_tools()
            print(f"Available tools: {[t.name for t in tools.tools]}")

            # Call a tool
            result = await session.call_tool("add", arguments={"a": 5, "b": 3})
            result_unstructured = result.content[0]
            if isinstance(result_unstructured, types.TextContent):
                print(f"Tool result: {result_unstructured.text}")
            result_structured = result.structuredContent
            print(f"Structured tool result: {result_structured}")

            # List available resources
            resources = await session.list_resources()  # it doesn't work!
            print(f"Available resources: {[r.uri for r in resources.resources]}")

            # Read a resource
            resource_content = await session.read_resource(AnyUrl("greeting://World"))
            content_block = resource_content.contents[0]
            if isinstance(content_block, types.TextResourceContents):
                print(f"Resource content: {content_block.text}")

            # List available prompts
            prompts = await session.list_prompts()
            print(f"Available prompts: {[p.name for p in prompts.prompts]}")

            # Get a prompt
            if prompts.prompts:
                prompt = await session.get_prompt("greet_user", arguments={"name": "Alice", "style": "friendly"})
                print(f"Prompt result: {prompt.messages[0].content}")

def main():
    """Entry point for the client script."""
    asyncio.run(run())

if __name__ == "__main__":
    main()

由于没有使用nv,运行MCP服务端和MCP客户端要多写一些代码,而客户端看起来更复杂一点。

请注意

  • 使用MCP服务端的准确地址:使用绝对路径是比较稳妥的方法,否则可能因为MCP客户端加载MCP服务端失败。
  • session.list_resources返回空:不知道为什么无法返回MCP服务端的资源,而直接调用服务端的资源却没问题。

运行代码

Visual Studio Code 中运行MCP客户端代码即可,客户端会在启动时加载MCP服务端。

Available tools: ['add']
Tool result: 8
Structured tool result: {'result': 8}
Available resources: []
Resource content: Hello, World!
Available prompts: ['greet_user']
Prompt result: type='text' text='Please write a warm, friendly greeting for someone named Alice.' annotations=None meta=None

总结

以上演示了MCP服务端和MCP客户端的基本功能。对于实际的项目工程来说,这只是一个小小的开始,但是在绝大部分情况下,这种简单的实战演练对“更深入的理解概念和技术”会大有帮助。


代码

本文涉及的所有代码以及相关资源都已经共享,参见:

为便于找到代码,程序文件名称最前面的编号与本系列文章的文档编号相同。

🪐感谢您观看,祝好运🪐