Agent ๅ่ฎฎ๏ผMCP ไธ A2A ๐ โ
"ๆ ๅๅๅ่ฎฎๆฏ AI ็ๆ็ณป็ปไบ่ไบ้็ๅบ็ก่ฎพๆฝใ"
้็ AI Agent ็ๆ็ๅฟซ้ๅๅฑ๏ผไธคไธช้่ฆ็ๅผๆพๅ่ฎฎๆญฃๅจๆไธบ่กไธๆ ๅ๏ผModel Context Protocol (MCP) ็จไบ AI ๆจกๅไธๅทฅๅ ท/ๆฐๆฎๆบ็้ๆ๏ผAgent2Agent (A2A) ็จไบ AI Agent ไน้ด็้ไฟกๅไฝใ็่งฃ่ฟไธคไธชๅ่ฎฎๅฏนไบๆๅปบ็ฐไปฃ AI ๅบ็จ่ณๅ ณ้่ฆใ
1. ๅ่ฎฎๅ จๆฏๅพ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AI Agent ๅ่ฎฎ็ๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Agent2Agent (A2A) โ โ
โ โ Agent โโ Agent ้ไฟกไธๅไฝ โ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ โ
โ โ โ Agent A โ โโโ Agent B โ โโโ Agent C โ โ โ
โ โ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ Model Context Protocol (MCP) โ โ
โ โ โ Model โโ Tools/Data ้ๆ โ โ
โ โ โผ โผ โผ โ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ โ
โ โ โ MCP โ โ MCP โ โ MCP โ โ โ
โ โ โ Server โ โ Server โ โ Server โ โ โ
โ โ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โ โ
โ โ โ โ โ โ โ
โ โ โผ โผ โผ โ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ โ
โ โ โDatabase โ โ API โ โ Files โ โ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ1.1 ๅ่ฎฎๅฎไฝๅฏนๆฏ โ
| ็ปดๅบฆ | MCP (Model Context Protocol) | A2A (Agent2Agent) |
|---|---|---|
| ๅ่ตทๆน | Anthropic (2024.11) | Google Cloud (2025.04) |
| ๆ ธๅฟ็ฎๆ | AI ๆจกๅไธๅทฅๅ ท/ๆฐๆฎๆบ็ๆ ๅๅ้ๆ | AI Agent ไน้ด็ไบๆไฝๆงไธๅไฝ |
| ้ไฟกๅฏน่ฑก | Model โ Server (Tools/Resources) | Agent โ Agent |
| ไธป่ฆๅบๆฏ | ่ฏปๅๆไปถใ่ฐ็จ APIใๆง่กๆไฝ | ไปปๅกๅงๆดพใไฟกๆฏไบคๆขใๅไฝๅทฅไฝๆต |
| ๅ่ฎฎๅบ็ก | JSON-RPC 2.0 | HTTP, SSE, JSON-RPC |
| ้็จๆน | OpenAI, Google DeepMind, Cursor | 50+ ๅไฝไผไผด๏ผSalesforce, SAP ็ญ๏ผ |
1.2 ไบ่กฅๅ ณ็ณป โ
ๅบๆฏ็คบไพ๏ผไผไธๆบ่ฝๅทฅไฝๆต
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ็จๆท่ฏทๆฑ๏ผ"ๅๆๆ่ฟ็้ๅฎๆฐๆฎ๏ผ็ๆๆฅๅๅนถๅ้็ปๅข้" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๅ่ฐ Agent (Orchestrator) โ
โ ไฝฟ็จ A2A ๅ่ฎฎๅงๆดพไปปๅก็ปไธไธ Agent โ
โโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโ
โ A2A โ A2A โ A2A
โผ โผ โผ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ ๆฐๆฎๅๆ โ โ ๆฅๅ็ๆ โ โ ้ฎไปถๅ้ โ
โ Agent โ โ Agent โ โ Agent โ
โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ
โ MCP โ MCP โ MCP
โผ โผ โผ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Database โ โ Doc API โ โ Email API โ
โ MCP Server โ โ MCP Server โ โ MCP Server โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ2. Model Context Protocol (MCP) โ
2.1 ๆ ธๅฟๆฆๅฟต โ
MCP ๅฎไนไบ AI ๆจกๅไธๅค้จ็ณป็ปไบคไบ็ๆ ๅๅๆนๅผ๏ผๆ ธๅฟๆถๆๅ ๅซไธไธช่ง่ฒ๏ผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MCP ๆถๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ MCP Host โ โ MCP Client โ โ MCP Server โ โ
โ โ (ๅฆ Cursor) โ โโโโโโโโ โ (ๅ่ฎฎๅฑ) โ โโโโโโโโ โ (ๅทฅๅ
ทๆไพๆน) โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ ็จๆท็้ข โ โ ๆถๆฏ่ทฏ็ฑ โ โ ๅ
ทไฝๅฎ็ฐ โ โ
โ โ ๆ้็ฎก็ โ โ ๅ่ฎฎ่ฝฌๆข โ โ ๅทฅๅ
ท/่ตๆบ โ โ
โ โ ไผ่ฏ็ฎก็ โ โ ่ฟๆฅ็ฎก็ โ โ ๆ็คบๆจกๆฟ โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโไธไธช่ง่ฒ๏ผ
| ่ง่ฒ | ่่ดฃ | ็คบไพ |
|---|---|---|
| Host | ๅฎน็บณ AI ๅบ็จ็ๅฎฟไธป็ฏๅข | Cursor IDE, Claude Desktop |
| Client | ไธ Server ๅปบ็ซ่ฟๆฅ็ๅ่ฎฎๅฑ | MCP SDK ๅฎขๆท็ซฏๅฎ็ฐ |
| Server | ๆไพๅทฅๅ ทใ่ตๆบๅๆ็คบ็ๆๅก็ซฏ | ๆไปถ็ณป็ป Server, GitHub Server |
2.2 ไธๅคงๆ ธๅฟ่ฝๅ โ
MCP Server ๅฏไปฅๆไพไธ็ง็ฑปๅ็่ฝๅ๏ผ
// 1. Resources - ่ตๆบ๏ผ็ฑปไผผ REST ่ตๆบ๏ผ
// ๆไพๆฐๆฎ่ฏปๅ่ฝๅ๏ผ็ฑ Server ๆด้ฒ๏ผ็ฑ Client ่ฏปๅ
interface Resource {
uri: string; // ่ตๆบๅฏไธๆ ่ฏ๏ผๅฆ "file:///path/to/file.txt"
name: string; // ไบบ็ฑปๅฏ่ฏปๅ็งฐ
description?: string; // ่ตๆบๆ่ฟฐ
mimeType?: string; // MIME ็ฑปๅ
}
// 2. Tools - ๅทฅๅ
ท๏ผๆจกๅๅฏ่ฐ็จ็ๅฝๆฐ๏ผ
// ๅ
่ฎธ AI ๆง่กๆไฝ๏ผ้่ฆๆจกๅไธปๅจ่ฐ็จ
interface Tool {
name: string;
description: string;
inputSchema: JSONSchema; // JSON Schema ๅฎไนๅๆฐ
}
// 3. Prompts - ๆ็คบๆจกๆฟ๏ผๅฏๅค็จ็ๆ็คบ๏ผ
// ้ขๅฎไน็ๆ็คบๆจกๆฟ๏ผๆฏๆๅๆฐๅ
interface Prompt {
name: string;
description?: string;
arguments?: PromptArgument[];
}2.3 ้ไฟกๅ่ฎฎ โ
MCP ๅบไบ JSON-RPC 2.0๏ผๆฏๆๅค็งไผ ่พๅฑ๏ผ
// ่ฏทๆฑๆ ผๅผ
interface JSONRPCRequest {
jsonrpc: "2.0";
id: string | number;
method: string;
params?: object;
}
// ๅๅบๆ ผๅผ
interface JSONRPCResponse {
jsonrpc: "2.0";
id: string | number;
result?: any;
error?: {
code: number;
message: string;
data?: any;
};
}
// ้็ฅๆ ผๅผ๏ผๆ ้ๅๅบ๏ผ
interface JSONRPCNotification {
jsonrpc: "2.0";
method: string;
params?: object;
}ๆฏๆ็ไผ ่พๅฑ๏ผ
| ไผ ่พๆนๅผ | ้็จๅบๆฏ | ็น็น |
|---|---|---|
| stdio | ๆฌๅฐ่ฟ็จ้ไฟก | ็ฎๅๅฏ้ ๏ผ้ๅๆฌๅฐ Server |
| HTTP + SSE | ่ฟ็จๆๅก | ๆฏๆ Web ้จ็ฝฒ๏ผ้ๅไบๆๅก |
| WebSocket | ๅฎๆถๅๅ้ไฟก | ไฝๅปถ่ฟ๏ผ้ๅ้ซ้ขไบคไบ |
2.4 ๅฎ็ฐ MCP Server โ
ๅบ็ก Server ๅฎ็ฐ (TypeScript) โ
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// ๅๅปบ Server ๅฎไพ
const server = new Server(
{
name: "my-mcp-server",
version: "1.0.0",
},
{
capabilities: {
tools: {}, // ๅฃฐๆๆฏๆๅทฅๅ
ท
resources: {}, // ๅฃฐๆๆฏๆ่ตๆบ
},
}
);
// ๅฎไนๅทฅๅ
ทๅ่กจ
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "search_codebase",
description: "ๅจไปฃ็ ๅบไธญ่ฏญไนๆ็ดข",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "ๆ็ดขๆฅ่ฏข"
},
maxResults: {
type: "number",
description: "ๆๅคง็ปๆๆฐ",
default: 10
}
},
required: ["query"]
}
},
{
name: "read_file",
description: "่ฏปๅๆไปถๅ
ๅฎน",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "ๆไปถ่ทฏๅพ" }
},
required: ["path"]
}
}
]
}));
// ๅฎ็ฐๅทฅๅ
ท่ฐ็จ
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "search_codebase": {
const results = await performSearch(args.query, args.maxResults);
return {
content: [
{
type: "text",
text: JSON.stringify(results, null, 2)
}
]
};
}
case "read_file": {
const content = await fs.readFile(args.path, "utf-8");
return {
content: [
{
type: "text",
text: content
}
]
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
});
// ๅฎไน่ตๆบๅ่กจ
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: "config://app-settings",
name: "ๅบ็จ้
็ฝฎ",
description: "ๅบ็จ็จๅบ็้
็ฝฎไฟกๆฏ",
mimeType: "application/json"
}
]
}));
// ๅฎ็ฐ่ตๆบ่ฏปๅ
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
if (uri === "config://app-settings") {
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify(appConfig, null, 2)
}
]
};
}
throw new Error(`Unknown resource: ${uri}`);
});
// ๅฏๅจ Server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server running on stdio");
}
main().catch(console.error);Python ๅฎ็ฐ โ
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent, Resource
# ๅๅปบ Server
server = Server("my-python-server")
# ๅฎไนๅทฅๅ
ท
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="execute_python",
description="ๆง่ก Python ไปฃ็ ๅนถ่ฟๅ็ปๆ",
inputSchema={
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "่ฆๆง่ก็ Python ไปฃ็ "
}
},
"required": ["code"]
}
)
]
# ๅฎ็ฐๅทฅๅ
ท่ฐ็จ
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "execute_python":
try:
# ๅฎๅ
จ่่๏ผๅฎ้
ๅบ็จไธญ้่ฆๆฒ็ฎฑๆง่ก
result = eval(arguments["code"])
return [TextContent(type="text", text=str(result))]
except Exception as e:
return [TextContent(type="text", text=f"Error: {e}")]
raise ValueError(f"Unknown tool: {name}")
# ๅฏๅจ Server
async def main():
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream)
if __name__ == "__main__":
import asyncio
asyncio.run(main())2.5 ๅฎ็ฐ MCP Client โ
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { spawn } from "child_process";
async function createClient() {
// ๅฏๅจ Server ่ฟ็จ
const serverProcess = spawn("node", ["./my-server.js"]);
// ๅๅปบไผ ่พๅฑ
const transport = new StdioClientTransport({
command: "node",
args: ["./my-server.js"]
});
// ๅๅปบ Client
const client = new Client(
{ name: "my-client", version: "1.0.0" },
{ capabilities: {} }
);
// ่ฟๆฅๅฐ Server
await client.connect(transport);
return client;
}
async function main() {
const client = await createClient();
// ๅๅบๅฏ็จๅทฅๅ
ท
const { tools } = await client.listTools();
console.log("Available tools:", tools.map(t => t.name));
// ่ฐ็จๅทฅๅ
ท
const result = await client.callTool({
name: "search_codebase",
arguments: { query: "authentication", maxResults: 5 }
});
console.log("Search results:", result.content);
// ๅๅบ่ตๆบ
const { resources } = await client.listResources();
console.log("Available resources:", resources.map(r => r.name));
// ่ฏปๅ่ตๆบ
const resource = await client.readResource({
uri: "config://app-settings"
});
console.log("Config:", resource.contents);
}2.6 ้ ็ฝฎไธ้ๆ โ
Cursor/Claude Desktop ้ ็ฝฎ โ
// ~/.cursor/mcp.json ๆ claude_desktop_config.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"],
"env": {}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "your-github-token"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgresql://user:pass@localhost/db"
}
},
"custom-server": {
"command": "node",
"args": ["/path/to/my-custom-server.js"],
"cwd": "/path/to/working/dir"
}
}
}2.7 ๅฎๅ จๆไฝณๅฎ่ทต โ
// 1. ๆ้ๆงๅถ
const ALLOWED_PATHS = [
process.env.HOME,
'/tmp',
process.cwd()
];
function validatePath(path: string): boolean {
const resolved = path.resolve(path);
return ALLOWED_PATHS.some(allowed =>
resolved.startsWith(allowed)
);
}
// 2. ่พๅ
ฅ้ช่ฏ
import { z } from 'zod';
const SearchArgsSchema = z.object({
query: z.string().min(1).max(1000),
maxResults: z.number().int().positive().max(100).default(10)
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const args = SearchArgsSchema.parse(request.params.arguments);
// ไฝฟ็จ้ช่ฏๅ็ args
});
// 3. ้็้ๅถ
import { RateLimiter } from 'rate-limiter';
const limiter = new RateLimiter({
tokensPerInterval: 100,
interval: "minute"
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (!limiter.tryRemoveTokens(1)) {
throw new Error("Rate limit exceeded");
}
// ๅค็่ฏทๆฑ
});
// 4. ๅฎก่ฎกๆฅๅฟ
function logToolCall(name: string, args: any, result: any) {
const entry = {
timestamp: new Date().toISOString(),
tool: name,
arguments: args,
resultSize: JSON.stringify(result).length,
// ไธ่ฎฐๅฝๆๆๅ
ๅฎน
};
auditLogger.info(entry);
}3. Agent2Agent Protocol (A2A) โ
3.1 ๆ ธๅฟๆฆๅฟต โ
A2A ๅ่ฎฎไธๆณจไบ AI Agent ไน้ด็้ไฟกไธๅไฝ๏ผๆ ธๅฟ็ฎๆ ๆฏๅฎ็ฐ่ทจๅนณๅฐใ่ทจๆกๆถ็ Agent ไบๆไฝใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ A2A ้ไฟกๆจกๅ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Client Agent โ โ Remote Agent โ โ
โ โ (่ฏทๆฑๆน) โ โโโโโโโ A2A Protocol โโโโโโโ โ (ๆๅกๆน) โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ 1. ๅ็ฐ (Agent Card) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ 2. ๅ่ตทไปปๅก (Task) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโถ โ โ
โ โ โ โ
โ โ 3. ็ถๆๆดๆฐ (SSE Stream) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ 4. ไบคๆขๆถๆฏ (Message) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโถ โ โ
โ โ โ โ
โ โ 5. ่ฟๅ็ปๆ (Artifact) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ3.2 ่ฎพ่ฎกๅๅ โ
A2A ็ไบๅคง่ฎพ่ฎกๅๅ๏ผ
| ๅๅ | ๆ่ฟฐ |
|---|---|
| ๆฅๆฑ Agent ่ฝๅ | ๅ ่ฎธ Agent ไปฅ่ช็ถใ้็ปๆๅ็ๆนๅผๅไฝ๏ผๆ ้ๅ ฑไบซๅ ๅญๆๅทฅๅ ท |
| ๅบไบ็ฐๆๆ ๅ | ไฝฟ็จ HTTPใSSEใJSON-RPC๏ผไพฟไบไธไผไธ IT ้ๆ |
| ้ป่ฎคๅฎๅ จ | ๆฏๆไผไธ็บง่บซไปฝ้ช่ฏๅๆๆ๏ผOAuth 2.0ใW3C DID๏ผ |
| ๆฏๆ้ฟไปปๅก | ็ตๆดปๅค็ไป็ง็บงๅฐๆฐๅคฉ็ไปปๅก๏ผๆไพๅฎๆถ็ถๆๆดๆฐ |
| ๆจกๆๆ ๅ ณ | ๆฏๆๆๆฌใ้ณ้ขใ่ง้ขใ่กจๅใiframe ็ญๅค็งไบคไบๅฝขๅผ |
3.3 ๆ ธๅฟๅฎไฝ โ
Agent Card - Agent ่บซไปฝๅก โ
Agent Card ๆฏ Agent ็"ๅ็"๏ผๆ่ฟฐๅ ถ่ฝๅๅ่ฎฟ้ฎๆนๅผ๏ผ
interface AgentCard {
// ๅบๆฌไฟกๆฏ
name: string; // Agent ๅ็งฐ
description: string; // ่ฝๅๆ่ฟฐ
url: string; // A2A ็ซฏ็น URL
version: string; // ๅ่ฎฎ็ๆฌ
// ่ฝๅๅฃฐๆ
capabilities: {
streaming?: boolean; // ๆฏๅฆๆฏๆๆตๅผๅๅบ
pushNotifications?: boolean; // ๆฏๅฆๆฏๆๆจ้้็ฅ
stateTransitionHistory?: boolean; // ๆฏๅฆๆไพ็ถๆๅๅฒ
};
// ๆ่ฝๅ่กจ
skills: Skill[];
// ่ฎค่ฏๆนๅผ
authentication: {
schemes: string[]; // ๅฆ ["oauth2", "api_key"]
credentials?: string; // ๅญ่ฏ่ทๅๆนๅผ
};
// ้ป่ฎค่พๅ
ฅๆจกๆ
defaultInputModes: string[]; // ๅฆ ["text", "file"]
defaultOutputModes: string[]; // ๅฆ ["text", "file", "data"]
// ๆไพๅไฟกๆฏ
provider?: {
organization: string;
url?: string;
};
// ๅฏ้ๅ
ๆฐๆฎ
documentationUrl?: string;
supportUrl?: string;
}
interface Skill {
id: string;
name: string;
description: string;
tags?: string[];
examples?: string[]; // ็คบไพ่พๅ
ฅ
inputModes?: string[];
outputModes?: string[];
}็คบไพ Agent Card๏ผ
{
"name": "Data Analysis Agent",
"description": "ไธไธ็ๆฐๆฎๅๆๅฉๆ๏ผๆฏๆๆฐๆฎๆธ
ๆดใ็ป่ฎกๅๆๅๅฏ่งๅ",
"url": "https://api.example.com/a2a",
"version": "1.0.0",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true
},
"skills": [
{
"id": "data-cleaning",
"name": "ๆฐๆฎๆธ
ๆด",
"description": "่ชๅจๆฃๆตๅนถๅค็็ผบๅคฑๅผใๅผๅธธๅผๅ้ๅคๆฐๆฎ",
"tags": ["data", "preprocessing"],
"examples": ["ๆธ
ๆด่ฟไธช CSV ๆไปถ", "ๅค็ๆฐๆฎไธญ็็ผบๅคฑๅผ"]
},
{
"id": "statistical-analysis",
"name": "็ป่ฎกๅๆ",
"description": "ๆง่กๆ่ฟฐๆง็ป่ฎกใๅ่ฎพๆฃ้ชๅ็ธๅ
ณๆงๅๆ",
"tags": ["statistics", "analysis"],
"examples": ["ๅๆ้ๅฎๆฐๆฎ็่ถๅฟ", "ๆฃ้ชไธค็ปๆฐๆฎๆฏๅฆๆๆพ่ๅทฎๅผ"]
}
],
"authentication": {
"schemes": ["oauth2"],
"credentials": "https://auth.example.com/oauth"
},
"defaultInputModes": ["text", "file"],
"defaultOutputModes": ["text", "file", "data"],
"provider": {
"organization": "Example Corp",
"url": "https://example.com"
}
}Task - ไปปๅก โ
Task ๆฏ A2A ๅไฝ็ๆ ธๅฟๅๅ ๏ผ
interface Task {
id: string; // ๅฏไธไปปๅก ID
sessionId?: string; // ไผ่ฏ ID๏ผๅค่ฝฎๅฏน่ฏ๏ผ
status: TaskStatus; // ไปปๅก็ถๆ
// ๆถๆฏๅๅฒ
history?: Message[];
// ไปปๅกไบง็ฉ
artifacts?: Artifact[];
// ๅ
ๆฐๆฎ
metadata?: Record<string, any>;
}
type TaskStatus = {
state: TaskState;
message?: string; // ็ถๆๆ่ฟฐ
timestamp: string;
};
type TaskState =
| "submitted" // ๅทฒๆไบค
| "working" // ๅค็ไธญ
| "input-required" // ้่ฆ่พๅ
ฅ
| "completed" // ๅทฒๅฎๆ
| "failed" // ๅคฑ่ดฅ
| "canceled"; // ๅทฒๅๆถMessage - ๆถๆฏ โ
interface Message {
role: "user" | "agent";
parts: Part[];
metadata?: Record<string, any>;
}
type Part =
| TextPart
| FilePart
| DataPart
| FormPart;
interface TextPart {
type: "text";
text: string;
}
interface FilePart {
type: "file";
file: {
name: string;
mimeType: string;
// ไบ้ไธ
bytes?: string; // Base64 ็ผ็
uri?: string; // ๆไปถ URI
};
}
interface DataPart {
type: "data";
data: Record<string, any>;
}Artifact - ไปปๅกไบง็ฉ โ
interface Artifact {
name?: string;
description?: string;
parts: Part[];
index: number; // ไบง็ฉๅบๅท
append?: boolean; // ๆฏๅฆ่ฟฝๅ ๏ผๆตๅผ๏ผ
lastChunk?: boolean; // ๆฏๅฆๆๅไธๅ
metadata?: Record<string, any>;
}3.4 ้ไฟกๆต็จ โ
ๅบๆฌ่ฏทๆฑ-ๅๅบๆจกๅผ โ
// 1. ๅ้ไปปๅก
POST /a2a/tasks/send
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": "req-1",
"method": "tasks/send",
"params": {
"id": "task-123",
"message": {
"role": "user",
"parts": [
{ "type": "text", "text": "ๅๆ่ฟไธช้ๅฎๆฐๆฎๅนถ็ๆๆฅๅ" },
{ "type": "file", "file": { "name": "sales.csv", "uri": "..." } }
]
}
}
}
// ๅๅบ
{
"jsonrpc": "2.0",
"id": "req-1",
"result": {
"id": "task-123",
"status": {
"state": "working",
"message": "ๆญฃๅจๅๆๆฐๆฎ...",
"timestamp": "2025-01-15T10:30:00Z"
}
}
}ๆตๅผๆดๆฐ (SSE) โ
// ่ฎข้
ไปปๅกๆดๆฐ
GET /a2a/tasks/task-123/sendSubscribe
Accept: text/event-stream
// Server ๆจ้ไบไปถ
event: status
data: {"state": "working", "message": "ๆฐๆฎๅ ่ฝฝๅฎๆ..."}
event: artifact
data: {"index": 0, "parts": [{"type": "text", "text": "## ๅๆๆฅๅ\n\n"}], "append": false}
event: artifact
data: {"index": 0, "parts": [{"type": "text", "text": "### 1. ๆฆ่ง\n..."}], "append": true}
event: status
data: {"state": "completed", "message": "ๅๆๅฎๆ"}3.5 ๅฎ็ฐ A2A Agent โ
Server ๅฎ็ฐ (TypeScript) โ
import express from 'express';
import { v4 as uuidv4 } from 'uuid';
const app = express();
app.use(express.json());
// ๅญๅจไปปๅก็ถๆ
const tasks = new Map<string, Task>();
const subscribers = new Map<string, Set<express.Response>>();
// Agent Card ็ซฏ็น
app.get('/.well-known/agent.json', (req, res) => {
res.json({
name: "Data Analysis Agent",
description: "ๆฐๆฎๅๆไธๅฎถ",
url: "https://api.example.com/a2a",
version: "1.0.0",
capabilities: {
streaming: true,
pushNotifications: false
},
skills: [
{
id: "analyze-data",
name: "ๆฐๆฎๅๆ",
description: "ๅๆๆฐๆฎๅนถ็ๆๆฅๅ"
}
],
authentication: {
schemes: ["bearer"]
},
defaultInputModes: ["text", "file"],
defaultOutputModes: ["text", "file"]
});
});
// ๅ้ไปปๅก
app.post('/a2a', async (req, res) => {
const { method, params, id } = req.body;
switch (method) {
case 'tasks/send': {
const task = await handleTaskSend(params);
res.json({
jsonrpc: "2.0",
id,
result: task
});
break;
}
case 'tasks/get': {
const task = tasks.get(params.id);
res.json({
jsonrpc: "2.0",
id,
result: task || null
});
break;
}
case 'tasks/cancel': {
const task = await handleTaskCancel(params.id);
res.json({
jsonrpc: "2.0",
id,
result: task
});
break;
}
}
});
// SSE ่ฎข้
็ซฏ็น
app.get('/a2a/tasks/:taskId/subscribe', (req, res) => {
const { taskId } = req.params;
// ่ฎพ็ฝฎ SSE headers
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// ๆทปๅ ่ฎข้
่
if (!subscribers.has(taskId)) {
subscribers.set(taskId, new Set());
}
subscribers.get(taskId)!.add(res);
// ๆธ
็
req.on('close', () => {
subscribers.get(taskId)?.delete(res);
});
});
// ๅค็ไปปๅก
async function handleTaskSend(params: any): Promise<Task> {
const taskId = params.id || uuidv4();
const task: Task = {
id: taskId,
status: {
state: "submitted",
timestamp: new Date().toISOString()
},
history: [params.message]
};
tasks.set(taskId, task);
// ๅผๆญฅๅค็ไปปๅก
processTaskAsync(taskId, params.message);
return task;
}
async function processTaskAsync(taskId: string, message: Message) {
const task = tasks.get(taskId)!;
// ๆดๆฐ็ถๆไธบๅค็ไธญ
updateTaskStatus(taskId, "working", "ๆญฃๅจๅๆๆฐๆฎ...");
try {
// ๆจกๆๅค็
await new Promise(resolve => setTimeout(resolve, 2000));
// ๅ้้จๅ็ปๆ
emitArtifact(taskId, {
index: 0,
parts: [{ type: "text", text: "# ๅๆๆฅๅ\n\nๆฐๆฎๅๆๅฎๆใ" }],
lastChunk: true
});
// ๅฎๆ
updateTaskStatus(taskId, "completed", "ๅๆๅฎๆ");
} catch (error) {
updateTaskStatus(taskId, "failed", error.message);
}
}
function updateTaskStatus(taskId: string, state: TaskState, message: string) {
const task = tasks.get(taskId);
if (!task) return;
task.status = {
state,
message,
timestamp: new Date().toISOString()
};
// ้็ฅ่ฎข้
่
const subs = subscribers.get(taskId);
if (subs) {
const event = `event: status\ndata: ${JSON.stringify(task.status)}\n\n`;
subs.forEach(res => res.write(event));
}
}
function emitArtifact(taskId: string, artifact: Artifact) {
const task = tasks.get(taskId);
if (!task) return;
task.artifacts = task.artifacts || [];
task.artifacts.push(artifact);
const subs = subscribers.get(taskId);
if (subs) {
const event = `event: artifact\ndata: ${JSON.stringify(artifact)}\n\n`;
subs.forEach(res => res.write(event));
}
}
app.listen(3000, () => {
console.log('A2A Agent running on port 3000');
});Client ๅฎ็ฐ โ
class A2AClient {
private baseUrl: string;
private authToken: string;
constructor(baseUrl: string, authToken: string) {
this.baseUrl = baseUrl;
this.authToken = authToken;
}
// ่ทๅ Agent Card
async getAgentCard(): Promise<AgentCard> {
const response = await fetch(`${this.baseUrl}/.well-known/agent.json`);
return response.json();
}
// ๅ้ไปปๅก
async sendTask(message: Message, taskId?: string): Promise<Task> {
const response = await fetch(`${this.baseUrl}/a2a`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.authToken}`
},
body: JSON.stringify({
jsonrpc: "2.0",
id: crypto.randomUUID(),
method: "tasks/send",
params: {
id: taskId || crypto.randomUUID(),
message
}
})
});
const data = await response.json();
return data.result;
}
// ่ฎข้
ไปปๅกๆดๆฐ
subscribeToTask(
taskId: string,
callbacks: {
onStatus?: (status: TaskStatus) => void;
onArtifact?: (artifact: Artifact) => void;
onError?: (error: Error) => void;
}
): () => void {
const eventSource = new EventSource(
`${this.baseUrl}/a2a/tasks/${taskId}/subscribe`,
{
// ่ชๅฎไน headers ้่ฆไฝฟ็จ fetch ๆฟไปฃ
}
);
eventSource.addEventListener('status', (e) => {
const status = JSON.parse(e.data);
callbacks.onStatus?.(status);
});
eventSource.addEventListener('artifact', (e) => {
const artifact = JSON.parse(e.data);
callbacks.onArtifact?.(artifact);
});
eventSource.onerror = (e) => {
callbacks.onError?.(new Error('SSE connection error'));
};
// ่ฟๅๅๆถๅฝๆฐ
return () => eventSource.close();
}
// ่ทๅไปปๅก็ถๆ
async getTask(taskId: string): Promise<Task | null> {
const response = await fetch(`${this.baseUrl}/a2a`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.authToken}`
},
body: JSON.stringify({
jsonrpc: "2.0",
id: crypto.randomUUID(),
method: "tasks/get",
params: { id: taskId }
})
});
const data = await response.json();
return data.result;
}
// ๅๆถไปปๅก
async cancelTask(taskId: string): Promise<Task> {
const response = await fetch(`${this.baseUrl}/a2a`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.authToken}`
},
body: JSON.stringify({
jsonrpc: "2.0",
id: crypto.randomUUID(),
method: "tasks/cancel",
params: { id: taskId }
})
});
const data = await response.json();
return data.result;
}
}
// ไฝฟ็จ็คบไพ
async function main() {
const client = new A2AClient('https://api.example.com', 'your-token');
// ่ทๅ Agent ่ฝๅ
const agentCard = await client.getAgentCard();
console.log('Agent skills:', agentCard.skills);
// ๅ้ไปปๅก
const task = await client.sendTask({
role: 'user',
parts: [
{ type: 'text', text: 'ๅๆ่ฟไธชๆฐๆฎ้' }
]
});
console.log('Task created:', task.id);
// ่ฎข้
ๆดๆฐ
const unsubscribe = client.subscribeToTask(task.id, {
onStatus: (status) => {
console.log('Status:', status.state, status.message);
},
onArtifact: (artifact) => {
console.log('Artifact:', artifact.parts);
}
});
// ็จๅๅๆถ่ฎข้
// unsubscribe();
}3.6 ๅค Agent ๅไฝๆจกๅผ โ
ไปปๅกๅงๆดพๆจกๅผ โ
// ๅ่ฐ Agent ๅฐไปปๅกๅงๆดพ็ปไธไธ Agent
class OrchestratorAgent {
private agents: Map<string, A2AClient> = new Map();
constructor(agentConfigs: AgentConfig[]) {
for (const config of agentConfigs) {
this.agents.set(config.skillType, new A2AClient(config.url, config.token));
}
}
async processRequest(request: string): Promise<any> {
// 1. ๅๆ่ฏทๆฑ๏ผ็กฎๅฎ้่ฆๅชไบ Agent
const plan = await this.createPlan(request);
// 2. ๆ่ฎกๅๆง่ก
const results = [];
for (const step of plan.steps) {
const agent = this.agents.get(step.agentType);
if (!agent) {
throw new Error(`No agent found for: ${step.agentType}`);
}
// ๅงๆดพไปปๅก
const task = await agent.sendTask({
role: 'user',
parts: [
{ type: 'text', text: step.instruction },
// ๅ
ๅซๅๅบๆญฅ้ชค็็ปๆ
...this.formatPreviousResults(results)
]
});
// ็ญๅพ
ๅฎๆ
const result = await this.waitForCompletion(agent, task.id);
results.push({ step: step.name, result });
}
// 3. ๆฑๆป็ปๆ
return this.summarizeResults(results);
}
private async waitForCompletion(client: A2AClient, taskId: string): Promise<any> {
return new Promise((resolve, reject) => {
const unsubscribe = client.subscribeToTask(taskId, {
onStatus: (status) => {
if (status.state === 'completed') {
unsubscribe();
client.getTask(taskId).then(task => resolve(task?.artifacts));
} else if (status.state === 'failed') {
unsubscribe();
reject(new Error(status.message));
}
}
});
});
}
}ๅไฝๅทฅไฝๆต็คบไพ โ
// ๅฎ็ฐไธไธชๅค Agent ๆฐๆฎๅค็ๅทฅไฝๆต
async function dataProcessingWorkflow(dataUrl: string) {
const orchestrator = new OrchestratorAgent([
{ skillType: 'data-cleaning', url: 'https://cleaner.example.com', token: '...' },
{ skillType: 'analysis', url: 'https://analyst.example.com', token: '...' },
{ skillType: 'visualization', url: 'https://viz.example.com', token: '...' },
{ skillType: 'report-generation', url: 'https://reporter.example.com', token: '...' }
]);
const result = await orchestrator.processRequest(`
ๅค็ไปฅไธๆฐๆฎ๏ผ${dataUrl}
1. ๆธ
ๆดๆฐๆฎ๏ผๅค็็ผบๅคฑๅผๅๅผๅธธๅผ
2. ่ฟ่ก็ป่ฎกๅๆ๏ผๆพๅบๅ
ณ้ฎ่ถๅฟ
3. ็ๆๅฏ่งๅๅพ่กจ
4. ๆฐๅๅๆๆฅๅ
`);
return result;
}4. ๅ่ฎฎๅฏนๆฏไธ้ๆฉ โ
4.1 ๅ่ฝๅฏนๆฏ โ
| ๅ่ฝ | MCP | A2A |
|---|---|---|
| ๅทฅๅ ท่ฐ็จ | โ ๆ ธๅฟๅ่ฝ | โ ไธ็ดๆฅๆฏๆ |
| ่ตๆบ่ฎฟ้ฎ | โ Resources | โ ้่ฟ Message ้ดๆฅ |
| Agent ๅ็ฐ | โ ๆ | โ Agent Card |
| ไปปๅก็ฎก็ | โ ๆ | โ Task ็ๅฝๅจๆ |
| ๆตๅผๅๅบ | โ ๆ้ๆฏๆ | โ SSE ๅ็ๆฏๆ |
| ๅคๆจกๆ | โ ๆฏๆ | โ ๆฏๆ |
| ้ฟไปปๅก | โ ่ฎพ่ฎกไธบๅๆญฅ | โ ๅผๆญฅใๆจ้้็ฅ |
| ่บซไปฝ่ฎค่ฏ | ๅบ็ก | โ OAuth 2.0, W3C DID |
4.2 ้ๆฉๆๅ โ
้ๆฉ MCP ๅฝ:
โโโ ้่ฆ่ฎฉ AI ่ฎฟ้ฎๅทฅๅ
ทๅๆฐๆฎๆบ
โโโ ๆๅปบๅ Agent ๅบ็จ
โโโ ้่ฆ่ฏปๅๆไปถใ่ฐ็จ API
โโโ ้่ฆๅฟซ้้ๆๅทฒๆๆๅก
้ๆฉ A2A ๅฝ:
โโโ ้่ฆๅคไธช Agent ๅไฝ
โโโ Agent ๆฅ่ชไธๅไพๅบๅ/ๆกๆถ
โโโ ้่ฆๅค็้ฟๆถ้ด่ฟ่ก็ไปปๅก
โโโ ้่ฆไผไธ็บงๅฎๅ
จๅๅฎก่ฎก
ไธค่
็ปๅๅฝ:
โโโ ๆๅปบๅคๆ็ๅค Agent ็ณป็ป
โโโ Agent ๆข้่ฆๅทฅๅ
ทไน้่ฆๅไฝ
โโโ ไผไธ็บง AI ๅทฅไฝๆต4.3 ้ๆๆถๆ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ไผไธ AI ็ณป็ปๆถๆ็คบไพ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ API Gateway โ โ
โ โ (่ฎค่ฏใ้ๆตใๆฅๅฟ) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Orchestrator Agent โ โ
โ โ (ไปปๅก่งๅใAgent ่ฐๅบฆใ็ปๆๆฑๆป) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโ โ
โ โ A2A โ A2A โ A2A โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ Specialist โ โ Specialist โ โ Specialist โ โ
โ โ Agent A โ โ Agent B โ โ Agent C โ โ
โ โ (ๆฐๆฎๅๆ) โ โ (ๆๆกฃ็ๆ) โ โ (้ฎไปถๅ้) โ โ
โ โโโโโโโโโโฌโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โ
โ โ MCP โ MCP โ MCP โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ MCP Servers โ โ MCP Servers โ โ MCP Servers โ โ
โ โ - Database โ โ - Google Docs โ โ - SMTP โ โ
โ โ - Analytics API โ โ - Templates โ โ - Calendar โ โ
โ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ5. ๅฎๅ จ่้ โ
5.1 MCP ๅฎๅ จ โ
// 1. Server ่ฝๅ้ๅถ
const server = new Server({
name: "secure-server",
version: "1.0.0"
}, {
capabilities: {
// ๅชๅผๆพๅฟ
่ฆ็่ฝๅ
tools: {},
// resources: {}, // ไธๆด้ฒ่ตๆบ
// prompts: {}, // ไธๆด้ฒๆ็คบ
}
});
// 2. ่ทฏๅพ็ฝๅๅ
const ALLOWED_PATHS = [
'/safe/directory',
'/another/safe/path'
];
function isPathAllowed(path: string): boolean {
const resolved = path.resolve(path);
return ALLOWED_PATHS.some(allowed =>
resolved.startsWith(path.resolve(allowed))
);
}
// 3. ๆๆๆฐๆฎ่ฟๆปค
function sanitizeOutput(data: any): any {
const sensitiveKeys = ['password', 'token', 'secret', 'apiKey'];
if (typeof data === 'object') {
for (const key of Object.keys(data)) {
if (sensitiveKeys.some(s => key.toLowerCase().includes(s))) {
data[key] = '[REDACTED]';
} else if (typeof data[key] === 'object') {
data[key] = sanitizeOutput(data[key]);
}
}
}
return data;
}5.2 A2A ๅฎๅ จ โ
// 1. OAuth 2.0 ่ฎค่ฏ
app.use('/a2a', async (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Missing authentication' });
}
const token = authHeader.slice(7);
try {
const payload = await verifyToken(token);
req.user = payload;
next();
} catch {
return res.status(401).json({ error: 'Invalid token' });
}
});
// 2. ไปปๅกๆ้ๆฃๆฅ
function canAccessTask(user: User, taskId: string): boolean {
const task = tasks.get(taskId);
// ๆฃๆฅ็จๆทๆฏๅฆๆๆ้่ฎฟ้ฎๆญคไปปๅก
return task?.metadata?.ownerId === user.id ||
user.roles.includes('admin');
}
// 3. ่ฏทๆฑ้ช่ฏ
import { z } from 'zod';
const TaskSendSchema = z.object({
id: z.string().uuid().optional(),
message: z.object({
role: z.enum(['user', 'agent']),
parts: z.array(z.union([
z.object({ type: z.literal('text'), text: z.string().max(100000) }),
z.object({ type: z.literal('file'), file: z.object({
name: z.string(),
mimeType: z.string(),
uri: z.string().url().optional(),
bytes: z.string().optional()
})})
]))
})
});
// 4. ๅฎก่ฎกๆฅๅฟ
function auditLog(action: string, details: any) {
const entry = {
timestamp: new Date().toISOString(),
action,
userId: details.userId,
taskId: details.taskId,
ip: details.ip,
// ไธ่ฎฐๅฝๆๆๅ
ๅฎน
};
auditLogger.info(entry);
}6. ็ๆ็ณป็ป โ
6.1 MCP ็ๆ โ
ๅฎๆน Servers๏ผ
| Server | ๅ่ฝ | ๅฎ่ฃ |
|---|---|---|
@modelcontextprotocol/server-filesystem | ๆไปถ็ณป็ป่ฎฟ้ฎ | npx -y @modelcontextprotocol/server-filesystem /path |
@modelcontextprotocol/server-github | GitHub API | npx -y @modelcontextprotocol/server-github |
@modelcontextprotocol/server-postgres | PostgreSQL ๆฐๆฎๅบ | npx -y @modelcontextprotocol/server-postgres |
@modelcontextprotocol/server-sqlite | SQLite ๆฐๆฎๅบ | npx -y @modelcontextprotocol/server-sqlite |
@modelcontextprotocol/server-puppeteer | ๆต่งๅจ่ชๅจๅ | npx -y @modelcontextprotocol/server-puppeteer |
็คพๅบ Servers๏ผ
- Notion, Slack, Discord ้ๆ
- AWS, GCP, Azure ไบๆๅก
- Jira, Linear ้กน็ฎ็ฎก็
- Figma ่ฎพ่ฎกๅทฅๅ ท
6.2 A2A ็ๆ โ
ๆฏๆ็ๆกๆถ๏ผ
- LangChain / LangGraph
- CrewAI
- Google ADK (Agent Development Kit)
- Microsoft AutoGen
ไผไธๅไฝไผไผด๏ผ
- Salesforce, SAP, ServiceNow
- Atlassian, Box, MongoDB
- Accenture, Deloitte, PwC
7. ๅ ณ้ฎ่ฆ็น โ
MCP ่ฆ็น โ
- ไธๅคง่ฝๅ: Resources๏ผ่ตๆบ๏ผใTools๏ผๅทฅๅ ท๏ผใPrompts๏ผๆ็คบ๏ผ
- Client-Server ๆถๆ: Host ๆ็ฎกๅบ็จ๏ผClient ๅค็ๅ่ฎฎ๏ผServer ๆไพ่ฝๅ
- JSON-RPC 2.0: ๆ ๅๅ็่ฏทๆฑ-ๅๅบๆ ผๅผ
- ๅฎๅ จ็ฌฌไธ: ่ทฏๅพ้ช่ฏใๆ้ๆงๅถใๅฎก่ฎกๆฅๅฟ
A2A ่ฆ็น โ
- Agent Card: Agent ็่ฝๅๅ็๏ผๆฏๆๅ็ฐไธๅฏนๆฅ
- Task ็ๅฝๅจๆ: submitted โ working โ completed/failed
- SSE ๆตๅผๆดๆฐ: ๅฎๆถ็ถๆๆจ้ๅ้จๅ็ปๆ
- ไผไธ็บงๅฎๅ จ: OAuth 2.0ใW3C DID ่บซไปฝ่ฎค่ฏ
้ๆฉๅปบ่ฎฎ โ
| ๅบๆฏ | ๆจ่ๅ่ฎฎ |
|---|---|
| AI ่ฎฟ้ฎๆไปถ/ๆฐๆฎๅบ | MCP |
| AI ่ฐ็จๅค้จ API | MCP |
| ๅค Agent ๅไฝ | A2A |
| ่ทจ็ป็ป Agent ไบๆไฝ | A2A |
| ๅฎๆดไผไธ AI ็ณป็ป | MCP + A2A |