إنشاء عميل MCP
يُعد تطبيق ADK-Rust عميل MCP عندما يتصل بخادم، ويقرأ الكتالوج المنشور الخاص به، ويجعل الإمكانات المحددة متاحة لوكيل أو سير عمل.
التثبيت
[dependencies]
adk-tool = { version = "2.1.0", features = ["mcp"] }
بالنسبة إلى Streamable HTTP عن بُعد:
adk-tool = { version = "2.1.0", features = ["mcp", "http-transport"] }
اتصال stdio محلي
use adk_tool::{
McpToolset,
mcp::rmcp::{ServiceExt, transport::TokioChildProcess},
};
use std::sync::Arc;
use tokio::process::Command;
let command = Command::new("./target/release/company-mcp");
let client = ().serve(TokioChildProcess::new(command)?).await?;
let toolset = McpToolset::new(client)
.with_name("company_tools")
.with_tools(&["find_customer", "read_order", "request_refund"]);
let shutdown = toolset.cancellation_token().await;
let agent = LlmAgentBuilder::new("support")
.model(model)
.toolset(Arc::new(toolset))
.build()?;
// Run the agent, then close the client-owned MCP session.
shutdown.cancel();
استخدم مسارًا مطلقًا للملف التنفيذي في بيئة الإنتاج. تجنّب علامات الحزم مثل latest
في إعدادات النشر، لأنها تجعل عمليات البناء واستعادة الخدمة بعد الحوادث
غير قابلة لإعادة الإنتاج.
اكتشاف الأدوات وتصفيتها
يحوّل McpToolset كل أداة MCP منشورة إلى Tool ADK-Rust. ويُبقي
مخططات الإدخال والإخراج الخاصة بالخادم دون تغيير. ويطبّع موفّر النموذج المحدد
نسخةً من المخطط عند إنشاء طلبه.
يحتفظ المحوّل أيضًا بالتعليقات التوضيحية لأداة MCP. وتشير readOnlyHint إلى أن
الأداة ADK للقراءة فقط وآمنة للتزامن؛ وتسمح idempotentHint بإعادة التشغيل الآمن
بعد إعادة الاتصال، لكنها لا تجعل الأداة مؤهلة تلقائيًا للإرسال المتوازي.
ويؤدي غياب التلميحات إلى إبقاء كلا السلوكين معطّلًا.
مهم: التعليقات التوضيحية MCP هي تلميحات منشورة من الخادم. استخدم بيانات إعادة التشغيل والإرسال التلقائية الوصفية فقط مع الخوادم الموجودة داخل حدود الثقة الخاصة بالتطبيق.
let reviewed = McpToolset::new(client).with_filter(|name| {
matches!(name, "read_order" | "read_policy" | "request_replacement")
});
تتحكم التصفية في ظهور الأدوات للنموذج. ولا تحل محل التفويض وقت تنفيذ الأداة.
الموارد والمطالبات والإكمال
use serde_json::json;
let resources = toolset.list_resources().await?;
let templates = toolset.list_resource_templates().await?;
let policy = toolset.read_resource("company://policy/refunds").await?;
let prompts = toolset.list_prompts().await?;
let prompt = toolset
.get_prompt(
"investigate_order",
Some(serde_json::Map::from_iter([
("order_id".to_string(), json!("ORD-1042")),
])),
)
.await?;
let suggestions = toolset
.complete_prompt_argument("investigate_order", "order_id", "ORD-", None)
.await?;
يستخدم إكمال قالب المورد complete_resource_argument. ويعيد الخادم الذي لا ينفّذ عمليات
القوائم قائمةً فارغة عندما يستجيب بـ MCP MethodNotFound؛ أما حالات فشل البروتوكول
والنقل الأخرى فتبقى أخطاءً.
اشتراكات الموارد
use adk_tool::{AutoDeclineElicitationHandler, McpToolset, ResourceNotificationHandler};
use std::sync::Arc;
struct ResourceUpdates;
#[async_trait::async_trait]
impl ResourceNotificationHandler for ResourceUpdates {
async fn handle_resource_updated(
&self,
uri: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Resource changed: {uri}");
Ok(())
}
async fn handle_resource_list_changed(
&self,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("The resource catalog changed");
Ok(())
}
}
let toolset = McpToolset::with_handlers(
transport,
Arc::new(AutoDeclineElicitationHandler),
Arc::new(ResourceUpdates),
).await?;
toolset.subscribe_resource("company://inventory/sku-42").await?;
toolset.unsubscribe_resource("company://inventory/sku-42").await?;
McpToolset يستعيد الاشتراكات النشطة بعد تحديث الاتصال المحدود.
كما يحتفظ McpServerManager بالاشتراكات عبر عمليات إعادة تشغيل العملية المُدارة.
تُسجَّل أخطاء المعالج وحالات الذعر دون إنهاء اتصال MCP.
بالنسبة إلى HTTP القابل للبث، اضبط المعالج نفسه باستخدام
McpHttpClientBuilder::with_resource_notification_handler قبل استدعاء
connect_with_elicitation.
طلب المعلومات
يتيح طلب المعلومات للخادم طلب معلومات أثناء معالجة استدعاء أداة. يقرر التطبيق كيفية عرض الطلب وما إذا كان سيقبله أو يرفضه أو يلغيه.
let toolset = McpToolset::with_elicitation_handler(
transport,
Arc::new(MyElicitationHandler),
).await?;
يعلن ADK-Rust عن طلب معلومات بنموذج وURL. يتحول فشل المعالج أو حالة الذعر إلى رفض، مع الحفاظ على جلسة MCP. ومع ذلك، يجب على التطبيق التحقق من صحة القيم المقبولة وتطبيق سياسة الموافقة.
راجع examples/mcp_elicitation للاطلاع على زوج كامل من العميل والخادم.
المهام المتفاوض عليها
use adk_tool::McpTaskConfig;
use std::time::Duration;
let toolset = McpToolset::new(client).with_task_support(
McpTaskConfig::enabled()
.poll_interval(Duration::from_secs(1))
.timeout(Duration::from_secs(120))
.max_attempts(120),
);
يُحدَّد وضع المهمة استنادًا إلى حقيقتين متفاوض عليهما:
- يعلن الخادم عن
tasks.requests.tools.call؛ و - تعلن الأداة دعم المهام على أنه مطلوب أو اختياري.
يرسل ADK-Rust بيانات وصفية للمهمة مع tools/call، ويتلقى المهمة المُنشأة، ويستطلع
tasks/get، ويقرأ tasks/result، ويستدعي tasks/cancel عند
تجاوز الحدود المحلية. يُعاد input_required كخطأ ذي نوع محدد، لأن استدعاء أداة
ADK عاديًا لا يوفر بعد قناة محايدة بروتوكوليًا لإدخال استئناف المهمة.
HTTP القابل للبث عن بُعد
use adk_tool::{McpAuth, McpHttpClientBuilder};
use std::time::Duration;
let toolset = McpHttpClientBuilder::new("https://mcp.example.com/mcp")
.with_auth(McpAuth::bearer(std::env::var("MCP_TOKEN")?))
.header("X-Tenant-ID", "tenant-42")
.timeout(Duration::from_secs(30))
.reinit_on_expired_session(true)
.connect()
.await?;
يدعم المُنشئ الرموز المميزة لحاملها، ورأسًا مخصصًا بالمفتاح API، وبيانات اعتماد عميل ثابتة من الإصدار OAuth 2.0. راجع الأمان والتفويض قبل اختيار تدفق مصادقة.