ไคลเอนต์คือแอปพลิเคชันหรือสคริปต์ที่สร้างขึ้นเองซึ่งสื่อสารโดยตรงกับ MCP Server เพื่อขอทรัพยากร เครื่องมือ และพรอมต์ ต่างจากการใช้เครื่องมือ inspector ซึ่งให้ส่วนติดต่อกราฟิกสำหรับการโต้ตอบกับเซิร์ฟเวอร์ การเขียนไคลเอนต์ของคุณเองช่วยให้สามารถโต้ตอบแบบเป็นโปรแกรมและอัตโนมัติได้ ซึ่งช่วยให้นักพัฒนาสามารถผนวกความสามารถของ MCP เข้ากับเวิร์กโฟลว์ของตนเอง อัตโนมัติภารกิจ และสร้างโซลูชันที่ออกแบบเฉพาะสำหรับความต้องการต่าง ๆ
บทเรียนนี้จะแนะนำแนวคิดของไคลเอนต์ในระบบนิเวศ Model Context Protocol (MCP) คุณจะได้เรียนรู้วิธีเขียนไคลเอนต์ของคุณเองและทำให้เชื่อมต่อกับ MCP Server ได้
เมื่อจบบทเรียนนี้ คุณจะสามารถ:
- เข้าใจว่าคลไอเอนต์สามารถทำอะไรได้บ้าง
- เขียนไคลเอนต์ของคุณเอง
- เชื่อมต่อและทดสอบไคลเอนต์กับเซิร์ฟเวอร์ MCP เพื่อให้แน่ใจว่าเซิร์ฟเวอร์ทำงานได้ตามที่คาดไว้
ในการเขียนไคลเอนต์ คุณจำเป็นต้องทำดังนี้:
- นำเข้าห้องสมุดที่ถูกต้อง คุณจะใช้ห้องสมุดเดียวกับที่ใช้อยู่ก่อนหน้านี้ เพียงแต่ใช้โครงสร้างต่างกัน
- สร้างอินสแตนซ์ไคลเอนต์ ซึ่งจะเกี่ยวข้องกับการสร้างอินสแตนซ์ไคลเอนต์และเชื่อมต่อกับวิธีการขนส่งที่เลือก
- ตัดสินใจว่าจะรายการทรัพยากรใดบ้าง เซิร์ฟเวอร์ MCP ของคุณมาพร้อมกับทรัพยากร เครื่องมือ และพรอมต์ คุณต้องตัดสินใจว่าจะรายการอันใดบ้าง
- ผนวกไคลเอนต์กับแอปโฮสต์ เมื่อคุณทราบความสามารถของเซิร์ฟเวอร์แล้ว คุณจำเป็นต้องผนวกสิ่งนี้กับแอปโฮสต์ของคุณ เพื่อให้เมื่อผู้ใช้พิมพ์พรอมต์หรือคำสั่งอื่น ๆ ฟีเจอร์ของเซิร์ฟเวอร์ที่เกี่ยวข้องถูกเรียกใช้งาน
เมื่อเราเข้าใจภาพรวมแล้วว่ากำลังจะทำอะไร ต่อไปมาดูตัวอย่างกัน
ลองดูตัวอย่างไคลเอนต์นี้:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "node",
args: ["server.js"]
});
const client = new Client(
{
name: "example-client",
version: "1.0.0"
}
);
await client.connect(transport);
// รายการคำสั่ง
const prompts = await client.listPrompts();
// รับคำสั่ง
const prompt = await client.getPrompt({
name: "example-prompt",
arguments: {
arg1: "value"
}
});
// รายการทรัพยากร
const resources = await client.listResources();
// อ่านทรัพยากร
const resource = await client.readResource({
uri: "file:///example.txt"
});
// เรียกใช้งานเครื่องมือ
const result = await client.callTool({
name: "example-tool",
arguments: {
arg1: "value"
}
});ในโค้ดด้านบนเราได้:
- นำเข้าห้องสมุด
- สร้างอินสแตนซ์ของไคลเอนต์และเชื่อมต่อโดยใช้ stdio เป็นการขนส่ง
- รายการพรอมต์ ทรัพยากร และเครื่องมือ และเรียกใช้งานทั้งหมด
เท่านี้คุณก็มีไคลเอนต์ที่สามารถพูดคุยกับ MCP Server ได้แล้ว
ตอนต่อไปเราจะใช้เวลาอธิบายแต่ละส่วนของโค้ดอย่างละเอียด
ดังที่ได้กล่าวไว้ข้างต้น มาใช้เวลาอธิบายโค้ดกัน และแน่นอนว่าเขียนโค้ดตามไปด้วยได้
นำเข้าห้องสมุดที่ต้องใช้ เราจะต้องอ้างอิงถึงไคลเอนต์และโปรโตคอลการขนส่งที่เราเลือก คือ stdio ซึ่งเป็นโปรโตคอลสำหรับสิ่งที่รันบนเครื่องของคุณเอง SSE เป็นโปรโตคอลอีกตัวที่จะแสดงในบทถัดไป แต่นี่คือทางเลือกอื่นของคุณ ตอนนี้เราจะเริ่มกับ stdio
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_clientusing Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Client;สำหรับ Java คุณจะสร้างไคลเอนต์ที่เชื่อมต่อกับ MCP server จากแบบฝึกหัดก่อนหน้า โดยใช้โครงสร้างโปรเจค Java Spring Boot เดียวกันจาก Getting Started with MCP Server สร้างคลาสใหม่ชื่อ SDKClient ในโฟลเดอร์ src/main/java/com/microsoft/mcp/sample/client/ และเพิ่มการนำเข้าดังนี้:
import java.util.Map;
import org.springframework.web.reactive.function.client.WebClient;
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.transport.WebFluxSseClientTransport;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema.CallToolRequest;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
import io.modelcontextprotocol.spec.McpSchema.ListToolsResult;คุณจะต้องเพิ่ม dependencies ต่อไปนี้ในไฟล์ Cargo.toml ของคุณ
[package]
name = "calculator-client"
version = "0.1.0"
edition = "2024"
[dependencies]
rmcp = { version = "0.5.0", features = ["client", "transport-child-process"] }
serde_json = "1.0.141"
tokio = { version = "1.46.1", features = ["rt-multi-thread"] }จากนั้นคุณสามารถนำเข้าห้องสมุดที่จำเป็นในโค้ดไคลเอนต์ของคุณได้
use rmcp::{
RmcpError,
model::CallToolRequestParam,
service::ServiceExt,
transport::{ConfigureCommandExt, TokioChildProcess},
};
use tokio::process::Command;ต่อไปเป็นการสร้างอินสแตนซ์
เราจะต้องสร้างอินสแตนซ์ของการขนส่งและไคลเอนต์:
const transport = new StdioClientTransport({
command: "node",
args: ["server.js"]
});
const client = new Client(
{
name: "example-client",
version: "1.0.0"
}
);
await client.connect(transport);ในโค้ดด้านบนเราได้:
-
สร้างอินสแตนซ์ stdio transport สังเกตว่าได้ระบุคำสั่งและอาร์กิวเมนต์สำหรับการค้นหาและเริ่มเซิร์ฟเวอร์ เพราะนั่นคือสิ่งที่เราต้องทำในตอนสร้างไคลเอนต์
const transport = new StdioClientTransport({ command: "node", args: ["server.js"] });
-
สร้างอินสแตนซ์ไคลเอนต์โดยกำหนดชื่อและเวอร์ชัน
const client = new Client( { name: "example-client", version: "1.0.0" });
-
เชื่อมต่อไคลเอนต์กับการขนส่งที่เลือก
await client.connect(transport);
from mcp import ClientSession, StdioServerParameters, types
from mcp.client.stdio import stdio_client
# สร้างพารามิเตอร์เซิร์ฟเวอร์สำหรับการเชื่อมต่อ stdio
server_params = StdioServerParameters(
command="mcp", # ไฟล์ที่สามารถรันได้
args=["run", "server.py"], # อาร์กิวเมนต์บรรทัดคำสั่งที่เป็นทางเลือก
env=None, # ตัวแปรสิ่งแวดล้อมที่เป็นทางเลือก
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(
read, write
) as session:
# เริ่มต้นการเชื่อมต่อ
await session.initialize()
if __name__ == "__main__":
import asyncio
asyncio.run(run())ในโค้ดด้านบนเราได้:
- นำเข้าห้องสมุดที่จำเป็น
- สร้างอ็อบเจ็กต์ server parameters เพื่อใช้รันเซิร์ฟเวอร์ เพื่อให้เชื่อมต่อกับไคลเอนต์ได้
- นิยามเมธอด
runซึ่งเรียกstdio_clientเพื่อเริ่มเซสชันไคลเอนต์ - สร้างจุดเริ่มต้นโดยให้
runmethod กับasyncio.run
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Client;
var builder = Host.CreateApplicationBuilder(args);
builder.Configuration
.AddEnvironmentVariables()
.AddUserSecrets<Program>();
var clientTransport = new StdioClientTransport(new()
{
Name = "Demo Server",
Command = "dotnet",
Arguments = ["run", "--project", "path/to/file.csproj"],
});
await using var mcpClient = await McpClient.CreateAsync(clientTransport);
ในโค้ดด้านบนเราได้:
- นำเข้าห้องสมุดที่จำเป็น
- สร้าง stdio transport และสร้างไคลเอนต์
mcpClientซึ่งเป็นสิ่งที่จะใช้ในการรายการและเรียกใช้งานฟีเจอร์บน MCP Server
โปรดทราบว่าใน "Arguments" คุณสามารถชี้ไปที่ไฟล์ .csproj หรือไฟล์ executable ก็ได้
public class SDKClient {
public static void main(String[] args) {
var transport = new WebFluxSseClientTransport(WebClient.builder().baseUrl("http://localhost:8080"));
new SDKClient(transport).run();
}
private final McpClientTransport transport;
public SDKClient(McpClientTransport transport) {
this.transport = transport;
}
public void run() {
var client = McpClient.sync(this.transport).build();
client.initialize();
// ตรรกะของไคลเอนต์ของคุณจะอยู่ที่นี่
}
}ในโค้ดด้านบนเราได้:
- สร้างเมธอด main ที่ตั้งค่า SSE transport ชี้ไปที่
http://localhost:8080ซึ่งจะเป็นที่เซิร์ฟเวอร์ MCP ของเราจะรัน - สร้างคลาสไคลเอนต์ที่รับ transport เป็นพารามิเตอร์ใน constructor
- ในเมธอด
runเราสร้าง MCP client แบบ synchronous โดยใช้ transport และเริ่มการเชื่อมต่อ - ใช้ SSE (Server-Sent Events) transport ซึ่งเหมาะสำหรับการสื่อสารแบบ HTTP กับ Java Spring Boot MCP servers
โค้ดไคลเอนต์ Rust นี้สมมุติว่าเซิร์ฟเวอร์เป็นโปรเจกต์พี่น้องชื่อ "calculator-server" ในไดเรกทอรีเดียวกัน โค้ดด้านล่างนี้จะเริ่มเซิร์ฟเวอร์และเชื่อมต่อกับมัน
async fn main() -> Result<(), RmcpError> {
// สมมติว่าเซิร์ฟเวอร์เป็นโปรเจกต์พี่น้องชื่อ "calculator-server" ในไดเรกทอรีเดียวกัน
let server_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("failed to locate workspace root")
.join("calculator-server");
let client = ()
.serve(
TokioChildProcess::new(Command::new("cargo").configure(|cmd| {
cmd.arg("run").current_dir(server_dir);
}))
.map_err(RmcpError::transport_creation::<TokioChildProcess>)?,
)
.await?;
// งานที่จะทำ: เริ่มต้น
// งานที่จะทำ: แสดงรายการเครื่องมือ
// งานที่จะทำ: เรียกใช้เครื่องมือเพิ่มด้วยอาร์กิวเมนต์ = {"a": 3, "b": 2}
client.cancel().await?;
Ok(())
}ตอนนี้เรามีไคลเอนต์ที่สามารถเชื่อมต่อได้เมื่อตอนรันโปรแกรมแล้ว แต่ยังไม่ได้รายการฟีเจอร์ของเซิร์ฟเวอร์ ดังนั้นมาทำตรงนี้ต่อกัน:
// รายการพร้อมท์
const prompts = await client.listPrompts();
// รายการทรัพยากร
const resources = await client.listResources();
// รายการเครื่องมือ
const tools = await client.listTools();# แสดงรายการทรัพยากรที่มีอยู่
resources = await session.list_resources()
print("LISTING RESOURCES")
for resource in resources:
print("Resource: ", resource)
# แสดงรายการเครื่องมือที่มีอยู่
tools = await session.list_tools()
print("LISTING TOOLS")
for tool in tools.tools:
print("Tool: ", tool.name)ที่นี่เรารายการทรัพยากรที่มี list_resources() และเครื่องมือ list_tools และพิมพ์ออกมา
foreach (var tool in await client.ListToolsAsync())
{
Console.WriteLine($"{tool.Name} ({tool.Description})");
}
ข้างบนเป็นตัวอย่างวิธีรายการเครื่องมือบนเซิร์ฟเวอร์ สำหรับแต่ละเครื่องมือ เราจะพิมพ์ชื่อของมันออกมา
// แสดงรายการและสาธิตเครื่องมือ
ListToolsResult toolsList = client.listTools();
System.out.println("Available Tools = " + toolsList);
// คุณสามารถ ping เซิร์ฟเวอร์เพื่อตรวจสอบการเชื่อมต่อได้ด้วย
client.ping();ในโค้ดนี้เราได้:
- เรียก
listTools()เพื่อรับเครื่องมือทั้งหมดที่มีอยู่บน MCP server - ใช้
ping()เพื่อตรวจสอบว่าเชื่อมต่อกับเซิร์ฟเวอร์ได้ ListToolsResultมีข้อมูลเกี่ยวกับเครื่องมือทั้งหมดรวมถึงชื่อ คำอธิบาย และสกีมาอินพุต
เยี่ยมมาก ตอนนี้เราได้เก็บข้อมูลฟีเจอร์ทั้งหมดแล้ว คำถามคือเมื่อไหร่เราจะใช้? ไคลเอนต์นี้ค่อนข้างเรียบง่าย ต้องเรียกใช้ฟีเจอร์เหล่านั้นอย่างชัดเจนเมื่อเราต้องการ ในบทถัดไป เราจะสร้างไคลเอนต์ขั้นสูงที่เข้าถึงโมเดลภาษาใหญ่ของตัวเอง (LLM) ได้ แต่ตอนนี้มาดูวิธีเรียกใช้ฟีเจอร์บนเซิร์ฟเวอร์กันก่อน:
ในฟังก์ชัน main หลังจากเริ่มไคลเอนต์แล้ว เราสามารถเริ่มเซิร์ฟเวอร์และรายการฟีเจอร์บางอย่างของมันได้
// เริ่มต้น
let server_info = client.peer_info();
println!("Server info: {:?}", server_info);
// รายการเครื่องมือ
let tools = client.list_tools(Default::default()).await?;
println!("Available tools: {:?}", tools);เพื่อเรียกใช้ฟีเจอร์ เราต้องแน่ใจว่าได้ระบุอาร์กิวเมนต์ที่ถูกต้องและในบางกรณีชื่อของสิ่งที่ต้องการเรียกใช้งาน
// อ่านทรัพยากร
const resource = await client.readResource({
uri: "file:///example.txt"
});
// เรียกใช้เครื่องมือ
const result = await client.callTool({
name: "example-tool",
arguments: {
arg1: "value"
}
});
// เรียกคำสั่ง prompt
const promptResult = await client.getPrompt({
name: "review-code",
arguments: {
code: "console.log(\"Hello world\")"
}
})ในโค้ดด้านบนเราได้:
-
อ่านทรัพยากรโดยเรียกใช้
readResource()โดยระบุuriนี่คือตัวอย่างว่าฝั่งเซิร์ฟเวอร์เป็นอย่างไร:server.resource( "readFile", new ResourceTemplate("file://{name}", { list: undefined }), async (uri, { name }) => ({ contents: [{ uri: uri.href, text: `Hello, ${name}!` }] }) );
ค่า
uriของเราfile://example.txtตรงกับfile://{name}บนเซิร์ฟเวอร์ โดยexample.txtจะถูกแมปเป็นname -
เรียกใช้เครื่องมือโดยระบุ
nameและargumentsดังนี้:const result = await client.callTool({ name: "example-tool", arguments: { arg1: "value" } });
-
รับพรอมต์ โดยเรียก
getPrompt()พร้อมกับnameและargumentsโค้ดบนเซิร์ฟเวอร์หน้าตาดังนี้:server.prompt( "review-code", { code: z.string() }, ({ code }) => ({ messages: [{ role: "user", content: { type: "text", text: `Please review this code:\n\n${code}` } }] }) );
และโค้ดไคลเอนต์ที่ได้จึงต้องเขียนให้ตรงกับที่ประกาศในเซิร์ฟเวอร์:
const promptResult = await client.getPrompt({ name: "review-code", arguments: { code: "console.log(\"Hello world\")" } })
# อ่านทรัพยากร
print("READING RESOURCE")
content, mime_type = await session.read_resource("greeting://hello")
# เรียกใช้เครื่องมือ
print("CALL TOOL")
result = await session.call_tool("add", arguments={"a": 1, "b": 7})
print(result.content)ในโค้ดนี้เราได้:
- เรียกทรัพยากรชื่อ
greetingโดยใช้read_resource - เรียกใช้เครื่องมือชื่อ
addโดยใช้call_tool
- เพิ่มโค้ดสำหรับเรียกใช้เครื่องมือ:
var result = await mcpClient.CallToolAsync(
"Add",
new Dictionary<string, object?>() { ["a"] = 1, ["b"] = 3 },
cancellationToken:CancellationToken.None);- สำหรับการพิมพ์ผลลัพธ์ นี่คือตัวอย่างโค้ดที่จัดการกับผลลัพธ์:
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);
// Sum 4// เรียกใช้เครื่องมือเครื่องคิดเลขต่างๆ
CallToolResult resultAdd = client.callTool(new CallToolRequest("add", Map.of("a", 5.0, "b", 3.0)));
System.out.println("Add Result = " + resultAdd);
CallToolResult resultSubtract = client.callTool(new CallToolRequest("subtract", Map.of("a", 10.0, "b", 4.0)));
System.out.println("Subtract Result = " + resultSubtract);
CallToolResult resultMultiply = client.callTool(new CallToolRequest("multiply", Map.of("a", 6.0, "b", 7.0)));
System.out.println("Multiply Result = " + resultMultiply);
CallToolResult resultDivide = client.callTool(new CallToolRequest("divide", Map.of("a", 20.0, "b", 4.0)));
System.out.println("Divide Result = " + resultDivide);
CallToolResult resultHelp = client.callTool(new CallToolRequest("help", Map.of()));
System.out.println("Help = " + resultHelp);ในโค้ดนี้เราได้:
- เรียกใช้เครื่องมือคำนวณหลายรายการ โดยใช้เมธอด
callTool()กับอ็อบเจ็กต์CallToolRequest - การเรียกแต่ละเครื่องมือจะระบุชื่อเครื่องมือและ
Mapของอาร์กิวเมนต์ที่เครื่องมือต้องการ - เครื่องมือบนเซิร์ฟเวอร์คาดหวังชื่อพารามิเตอร์เฉพาะ (เช่น "a", "b" สำหรับการคำนวณ)
- ผลลัพธ์จะถูกส่งกลับมาในอ็อบเจ็กต์
CallToolResultซึ่งมีการตอบกลับจากเซิร์ฟเวอร์
// เรียกใช้เครื่องมือเพิ่มด้วยอาร์กิวเมนต์ = {"a": 3, "b": 2}
let a = 3;
let b = 2;
let tool_result = client
.call_tool(CallToolRequestParam {
name: "add".into(),
arguments: serde_json::json!({ "a": a, "b": b }).as_object().cloned(),
})
.await?;
println!("Result of {:?} + {:?}: {:?}", a, b, tool_result);เพื่อรันไคลเอนต์ ให้พิมพ์คำสั่งนี้ในเทอร์มินัล:
เพิ่มรายการนี้ในส่วน "scripts" ของ package.json:
"client": "tsc && node build/client.js"npm run clientเรียกไคลเอนต์โดยใช้คำสั่งดังนี้:
python client.pydotnet runก่อนอื่น ให้แน่ใจว่า MCP server ของคุณกำลังรันที่ http://localhost:8080 แล้วจึงรันไคลเอนต์:
# สร้างโปรเจกต์ของคุณ
./mvnw clean compile
# รันไคลเอนต์
./mvnw exec:java -Dexec.mainClass="com.microsoft.mcp.sample.client.SDKClient"หรือคุณสามารถรันโปรเจคไคลเอนต์ครบชุดในโฟลเดอร์ solution 03-GettingStarted\02-client\solution\java:
# ไปยังไดเรกทอรีโซลูชัน
cd 03-GettingStarted/02-client/solution/java
# สร้างและรันไฟล์ JAR
./mvnw clean package
java -jar target/calculator-client-0.0.1-SNAPSHOT.jarcargo fmt
cargo runในการบ้านนี้ คุณจะใช้สิ่งที่เรียนรู้ในการสร้างไคลเอนต์ แต่ให้สร้างไคลเอนต์ของคุณเอง
นี่คือเซิร์ฟเวอร์ที่คุณสามารถใช้และเรียกผ่านโค้ดไคลเอนต์ของคุณ ลองเพิ่มฟีเจอร์เพิ่มเติมในเซิร์ฟเวอร์เพื่อทำให้มันน่าสนใจขึ้น
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// สร้างเซิร์ฟเวอร์ MCP
const server = new McpServer({
name: "Demo",
version: "1.0.0"
});
// เพิ่มเครื่องมือบวก
server.tool("add",
{ a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }]
})
);
// เพิ่มแหล่งทรัพยากรทักทายแบบไดนามิก
server.resource(
"greeting",
new ResourceTemplate("greeting://{name}", { list: undefined }),
async (uri, { name }) => ({
contents: [{
uri: uri.href,
text: `Hello, ${name}!`
}]
})
);
// เริ่มรับข้อความจาก stdin และส่งข้อความไปยัง stdout
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCPServer started on stdin/stdout");
}
main().catch((error) => {
console.error("Fatal error: ", error);
process.exit(1);
});# server.py
from mcp.server.fastmcp import FastMCP
# สร้างเซิร์ฟเวอร์ MCP
mcp = FastMCP("Demo")
# เพิ่มเครื่องมือบวก
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
# เพิ่มทรัพยากรทักทายแบบไดนามิก
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting"""
return f"Hello, {name}!"using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(consoleLogOptions =>
{
// Configure all logs to go to stderr
consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();
[McpServerToolType]
public static class CalculatorTool
{
[McpServerTool, Description("Adds two numbers")]
public static string Add(int a, int b) => $"Sum {a + b}";
}ดูโปรเจคนี้เพื่อดูวิธี เพิ่มพรอมต์และทรัพยากร
นอกจากนี้ดูลิงก์นี้เพื่อเรียนรู้วิธีเรียกใช้ พรอมต์และทรัพยากร
ใน ส่วนก่อนหน้า คุณได้เรียนรู้วิธีสร้าง MCP server แบบง่ายด้วย Rust คุณสามารถสร้างต่อจากนั้นได้ หรือดูลิงก์นี้สำหรับตัวอย่าง MCP server ที่ใช้ Rust เพิ่มเติม: MCP Server Examples
โฟลเดอร์โซลูชัน ประกอบด้วยตัวอย่างไคลเอนต์ที่สมบูรณ์พร้อมรัน ซึ่งแสดงแนวคิดทั้งหมดที่สอนในบทเรียนนี้ โซลูชันแต่ละชุดประกอบด้วยโค้ดไคลเอนต์และเซิร์ฟเวอร์ที่จัดในโครงการแยกอิสระ
ไดเรกทอรีโซลูชันจัดเรียงตามภาษาโปรแกรม:
solution/
├── typescript/ # TypeScript client with npm/Node.js setup
│ ├── package.json # Dependencies and scripts
│ ├── tsconfig.json # TypeScript configuration
│ └── src/ # Source code
├── java/ # Java Spring Boot client project
│ ├── pom.xml # Maven configuration
│ ├── src/ # Java source files
│ └── mvnw # Maven wrapper
├── python/ # Python client implementation
│ ├── client.py # Main client code
│ ├── server.py # Compatible server
│ └── README.md # Python-specific instructions
├── dotnet/ # .NET client project
│ ├── dotnet.csproj # Project configuration
│ ├── Program.cs # Main client code
│ └── dotnet.sln # Solution file
├── rust/ # Rust client implementation
| ├── Cargo.lock # Cargo lock file
| ├── Cargo.toml # Project configuration and dependencies
| ├── src # Source code
| │ └── main.rs # Main client code
└── server/ # Additional .NET server implementation
├── Program.cs # Server code
└── server.csproj # Server project file
โซลูชันสำหรับแต่ละภาษาจะประกอบด้วย:
- ไคลเอนต์ที่สมบูรณ์ ที่มีฟีเจอร์ทั้งหมดจากบทเรียน
- โครงสร้างโปรเจคที่ใช้งานได้จริง พร้อม dependencies และการกำหนดค่าที่เหมาะสม
- สคริปต์การสร้างและรัน เพื่อการตั้งค่าและใช้งานง่าย
- README รายละเอียด พร้อมคำแนะนำเฉพาะสำหรับแต่ละภาษา
- ตัวอย่างการจัดการข้อผิดพลาด และการประมวลผลผลลัพธ์
-
ไปที่โฟลเดอร์ภาษาที่คุณต้องการ:
cd solution/typescript/ # สำหรับ TypeScript cd solution/java/ # สำหรับ Java cd solution/python/ # สำหรับ Python cd solution/dotnet/ # สำหรับ .NET
-
ปฏิบัติตามคำแนะนำใน README ของแต่ละโฟลเดอร์ สำหรับ:
- การติดตั้ง dependencies
- การสร้างโปรเจค
- การรันไคลเอนต์
-
ตัวอย่างเอาต์พุตที่คุณควรเห็น:
Prompt: Please review this code: console.log("hello"); Resource template: file Tool result: { content: [ { type: 'text', text: '9' } ] }
สำหรับเอกสารฉบับสมบูรณ์และคำแนะนำแบบทีละขั้นตอน โปรดดูที่: 📖 เอกสารโซลูชัน
เราได้จัดเตรียมตัวอย่างไคลเอนต์ที่สมบูรณ์และใช้งานได้สำหรับทุกภาษาที่สอนในบทเรียนนี้ ตัวอย่างเหล่านี้แสดงฟังก์ชันการทำงานเต็มรูปแบบที่อธิบายไว้ข้างต้น และสามารถใช้เป็นตัวอย่างหรือจุดเริ่มต้นสำหรับโปรเจคของคุณเอง
| ภาษา | ไฟล์ | รายละเอียด |
|---|---|---|
| Java | client_example_java.java |
ไคลเอนต์ Java สมบูรณ์โดยใช้ SSE transport พร้อมการจัดการข้อผิดพลาดครบถ้วน |
| C# | client_example_csharp.cs |
ไคลเอนต์ C# สมบูรณ์โดยใช้ stdio transport ที่เริ่มเซิร์ฟเวอร์โดยอัตโนมัติ |
| TypeScript | client_example_typescript.ts |
ไคลเอนต์ TypeScript สมบูรณ์ที่รองรับโปรโตคอล MCP เต็มรูปแบบ |
| Python | client_example_python.py |
ไคลเอนต์ Python สมบูรณ์ที่ใช้รูปแบบ async/await |
| Rust | client_example_rust.rs |
ไคลเอนต์ Rust สมบูรณ์ที่ใช้ Tokio สำหรับงานแบบ async |
ตัวอย่างสมบูรณ์แต่ละชิ้นประกอบด้วย:
- ✅ การสร้างการเชื่อมต่อ และการจัดการข้อผิดพลาด
- ✅ การค้นหาเซิร์ฟเวอร์ (เครื่องมือ, แหล่งข้อมูล, คำสั่งแนะนำถ้ามี)
- ✅ การดำเนินการเครื่องคิดเลข (บวก, ลบ, คูณ, หาร, ช่วยเหลือ)
- ✅ การประมวลผลผลลัพธ์ และการแสดงผลแบบฟอร์แมต
- ✅ การจัดการข้อผิดพลาดอย่างครอบคลุม
- ✅ โค้ดสะอาดและมีเอกสารประกอบ พร้อมคอมเมนต์ทีละขั้นตอน
- เลือกภาษาที่คุณต้องการ จากตารางด้านบน
- ตรวจสอบไฟล์ตัวอย่างครบถ้วน เพื่อทำความเข้าใจการใช้งานทั้งหมด
- รันตัวอย่าง ตามคำแนะนำใน
complete_examples.md - แก้ไขและขยาย ตัวอย่างให้เหมาะกับกรณีใช้งานของคุณ
สำหรับเอกสารรายละเอียดเกี่ยวกับการรันและการปรับแต่งตัวอย่างเหล่านี้ ดูได้ที่: 📖 เอกสารตัวอย่างครบถ้วน
| โฟลเดอร์โซลูชัน | ตัวอย่างครบถ้วน |
|---|---|
| โครงสร้างโปรเจกต์เต็มพร้อมไฟล์บิวด์ | การใช้งานแบบไฟล์เดี่ยว |
| พร้อมใช้งานพร้อม dependencies | ตัวอย่างโค้ดเฉพาะส่วน |
| การตั้งค่าแบบโปรดักชัน | อ้างอิงเพื่อการศึกษา |
| เครื่องมือเฉพาะภาษา | การเปรียบเทียบหลายภาษา |
ทั้งสองแบบมีคุณค่า - ใช้ โฟลเดอร์โซลูชัน สำหรับโปรเจกต์ครบถ้วน และ ตัวอย่างครบถ้วน สำหรับการเรียนรู้และอ้างอิง
ประเด็นสำคัญของบทนี้เกี่ยวกับไคลเอนต์คือ:
- สามารถใช้ทั้งค้นหาและเรียกใช้ฟีเจอร์บนเซิร์ฟเวอร์ได้
- สามารถเริ่มเซิร์ฟเวอร์ในขณะที่ตัวเองเริ่มทำงาน (เหมือนในบทนี้) แต่ไคลเอนต์ยังสามารถเชื่อมต่อกับเซิร์ฟเวอร์ที่กำลังรันได้ด้วย
- เป็นวิธีที่ดีในการทดสอบความสามารถของเซิร์ฟเวอร์เคียงข้างทางเลือกอื่น เช่น Inspector ตามที่อธิบายในบทก่อนหน้า
- Java Calculator
- .Net Calculator
- JavaScript Calculator
- TypeScript Calculator
- Python Calculator
- Rust Calculator
- ถัดไป: สร้างไคลเอนต์กับ LLM
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษาด้วยปัญญาประดิษฐ์ Co-op Translator แม้เราจะพยายามให้ความถูกต้องสูงสุด โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่แม่นยำ เอกสารต้นฉบับในภาษาต้นทางถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลโดยนักแปลมืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดใด ๆ ที่เกิดขึ้นจากการใช้การแปลนี้