- Revised the API access endpoint in the agent documentation to reflect the new structure. - Expanded examples for agent hooks, database queries, and MCP tools, providing clearer guidance for users. - Updated MCP tool configuration to use 'label' instead of 'name' and refined transport types for better clarity. - Introduced input schema definitions for process transport tools, enhancing the documentation on tool mapping and error handling.
4.9 KiB
4.9 KiB
MCP Integration
Model Context Protocol (MCP) enables tool integration with external services.
Defining MCP Servers
Create mcps/tools.mcp.yao in the assistant directory:
{
"label": "Tools",
"description": "Custom tools for the assistant",
"transport": "process",
"tools": {
"search": "scripts.tools.Search",
"create": "models.data.Create"
}
}
Transport Types
Process (Yao Internal)
Map Yao Processes directly to MCP tools:
{
"transport": "process",
"tools": {
"search": "models.data.Paginate",
"create": "models.data.Create"
},
"resources": {
"detail": "models.data.Find"
}
}
STDIO (Local Server)
{
"transport": "stdio",
"command": "python",
"arguments": ["mcp_server.py"],
"env": { "API_KEY": "$ENV.API_KEY" }
}
SSE (Server-Sent Events)
{
"transport": "sse",
"url": "https://mcp.example.com/events",
"authorization_token": "$ENV.TOKEN"
}
Configuring in package.yao
All Tools
{
"mcp": {
"servers": ["tools"]
}
}
Specific Tools
{
"mcp": {
"servers": [
{ "server_id": "tools", "tools": ["search", "calculate"] }
]
}
}
With Resources
{
"mcp": {
"servers": [
{
"server_id": "data",
"tools": ["query"],
"resources": ["data://users/*"]
}
]
}
}
Dynamic Configuration in Hooks
function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
return {
messages,
mcp_servers: [
{ server_id: "tools", tools: ["search"] },
{ server_id: "data", resources: ["data://reports"] }
]
};
}
Using MCP in Hooks
List Available Tools
const tools = ctx.mcp.ListTools("server-id");
// { tools: [{ name: "search", description: "...", inputSchema: {...} }] }
Call Tool
const result = ctx.mcp.CallTool("server-id", "search", {
query: "example",
limit: 10
});
// { content: [{ type: "text", text: "..." }] }
Batch Tool Calls
// Sequential
const results = ctx.mcp.CallTools("server-id", [
{ name: "step1", arguments: { input: "a" } },
{ name: "step2", arguments: { input: "b" } }
]);
// Parallel
const results = ctx.mcp.CallToolsParallel("server-id", [
{ name: "api1", arguments: {} },
{ name: "api2", arguments: {} }
]);
Read Resources
const resources = ctx.mcp.ListResources("server-id");
const data = ctx.mcp.ReadResource("server-id", "data://users/123");
Get Prompts
const prompts = ctx.mcp.ListPrompts("server-id");
const prompt = ctx.mcp.GetPrompt("server-id", "system", { role: "helper" });
Tool Schema Mapping
Define input schemas for process transport tools:
mcps/
└── mapping/
└── <server-id>/
└── schemes/
├── search.in.yao # Input schema
└── search.out.yao # Output schema (optional)
mapping/tools/schemes/search.in.yao
{
"type": "object",
"description": "Search data",
"properties": {
"keyword": { "type": "string" },
"page": { "type": "integer" }
},
"x-process-args": [":arguments"]
}
The x-process-args maps MCP arguments to Yao Process parameters:
":arguments"- Pass entire arguments object"$args.field"- Extract specific field
Error Handling
function Next(ctx: agent.Context, payload: agent.Payload): agent.Next {
const { tools } = payload;
if (tools) {
for (const tool of tools) {
if (tool.error) {
ctx.trace.Error(`Tool ${tool.tool} failed: ${tool.error}`);
// Handle error
} else {
// Process result
console.log(tool.result);
}
}
}
return null;
}
Complete Example
mcps/calculator.mcp.yao
{
"label": "Calculator",
"description": "Math operations",
"transport": "process",
"tools": {
"add": "scripts.math.Add",
"multiply": "scripts.math.Multiply"
}
}
package.yao
{
"name": "Math Assistant",
"connector": "gpt-4o",
"mcp": {
"servers": [
{ "server_id": "calculator", "tools": ["add", "multiply"] }
]
}
}
src/index.ts
function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
// Check if calculation is needed
const query = messages[messages.length - 1]?.content || "";
if (/\d+\s*[\+\-\*\/]\s*\d+/.test(query)) {
// Enable calculator
return {
messages,
mcp_servers: [{ server_id: "calculator" }]
};
}
return { messages };
}
function Next(ctx: agent.Context, payload: agent.Payload): agent.Next {
const { tools } = payload;
if (tools?.length > 0) {
const calcResult = tools.find(t => t.server === "calculator");
if (calcResult?.result) {
return {
data: {
answer: calcResult.result,
expression: calcResult.arguments
}
};
}
}
return null;
}