之前兩篇文章: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客户端的基本功能。對於實際的項目工程來説,這只是一個小小的開始,但是在絕大部分情況下,這種簡單的實戰演練對“更深入的理解概念和技術”會大有幫助。


代碼

本文涉及的所有代碼以及相關資源都已經共享,參見:

  • github
  • gitee

為便於找到代碼,程序文件名稱最前面的編號與本系列文章的文檔編號相同。

🪐感謝您觀看,祝好運🪐