|
| 1 | +```markdown |
| 2 | +# Model Context Protocol (MCP) - AgentVault Profile |
| 3 | + |
| 4 | +## Introduction |
| 5 | + |
| 6 | +The AgentVault Agent-to-Agent (A2A) protocol defines the core mechanisms for secure communication, task management, and event streaming between agents. However, many complex agent interactions require more than just the primary message content. Agents often need additional **context** to perform their tasks effectively. This could include: |
| 7 | + |
| 8 | +* User profile information |
| 9 | +* Relevant snippets from previous interactions |
| 10 | +* Metadata about the environment |
| 11 | +* References to external files or data artifacts |
| 12 | +* Schema definitions for expected inputs/outputs |
| 13 | +* Tool descriptions and schemas |
| 14 | + |
| 15 | +The **Model Context Protocol (MCP)** is designed to be the standardized way to provide this richer context within the AgentVault ecosystem. It is *not* a separate transport protocol but rather a defined structure for embedding context *within* standard A2A messages. |
| 16 | + |
| 17 | +## Current Status |
| 18 | + |
| 19 | +**Evolving Specification:** It's important to note that the formal MCP specification is still evolving within the broader AI agent community. The implementation within AgentVault currently represents a **basic, conceptual profile** based on common needs observed during development. |
| 20 | + |
| 21 | +**Implementation:** The core `agentvault` library provides utilities (`agentvault.mcp_utils`) for formatting and validating a basic MCP structure, and the `agentvault-server-sdk` provides helpers for extracting it on the agent side. Future versions of AgentVault will align with and potentially contribute to more formalized MCP standards as they emerge. |
| 22 | + |
| 23 | +## Transport Mechanism |
| 24 | + |
| 25 | +MCP context is transported within the `metadata` field of standard A2A `Message` objects (defined in `agentvault.models`). Specifically, the formatted MCP payload is expected under the key `"mcp_context"`. |
| 26 | + |
| 27 | +```json |
| 28 | +{ |
| 29 | + "role": "user", |
| 30 | + "parts": [ |
| 31 | + { "type": "text", "content": "Refactor the attached Python script." } |
| 32 | + // Potentially other parts like FilePart referencing the script |
| 33 | + ], |
| 34 | + "metadata": { |
| 35 | + "timestamp": "...", |
| 36 | + "client_request_id": "...", |
| 37 | + // MCP context is embedded here: |
| 38 | + "mcp_context": { |
| 39 | + // ... MCP payload structure ... |
| 40 | + } |
| 41 | + } |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +## Conceptual Structure (Based on Current Implementation) |
| 46 | + |
| 47 | +The current implementation in `agentvault.mcp_utils` defines a basic structure using Pydantic models as placeholders. |
| 48 | + |
| 49 | +1. **`MCPContext` (Root Object):** |
| 50 | + * The top-level container for the context. |
| 51 | + * Currently defined with a single primary field: |
| 52 | + * `items`: A dictionary where keys are unique identifiers/names for context items, and values are `MCPItem` objects. |
| 53 | + |
| 54 | +2. **`MCPItem` (Individual Context Piece):** |
| 55 | + * Represents a single piece of contextual information. |
| 56 | + * Fields: |
| 57 | + * `id` (Optional `str`): A unique identifier for this specific item within the context payload. |
| 58 | + * `mediaType` (Optional `str`): The MIME type of the `content` if applicable (e.g., "text/plain", "application/json", "text/csv"). |
| 59 | + * `content` (Optional `Any`): The actual contextual data itself (e.g., a string, dictionary, list). Used for embedding smaller pieces of context directly. |
| 60 | + * `ref` (Optional `str`): A reference (e.g., a URL, artifact ID) pointing to external context information, often used for larger data. |
| 61 | + * `metadata` (Optional `Dict[str, Any]`): Additional key-value metadata specific to this context item. |
| 62 | + |
| 63 | +**Example `mcp_context` Payload:** |
| 64 | + |
| 65 | +```json |
| 66 | +"mcp_context": { |
| 67 | + "items": { |
| 68 | + "user_profile": { |
| 69 | + "mediaType": "application/json", |
| 70 | + "content": { |
| 71 | + "user_id": "usr_123", |
| 72 | + "preferences": {"theme": "dark"}, |
| 73 | + "permissions": ["read", "write"] |
| 74 | + }, |
| 75 | + "metadata": {"source": "internal_db"} |
| 76 | + }, |
| 77 | + "target_document": { |
| 78 | + "mediaType": "application/pdf", |
| 79 | + "ref": "s3://my-bucket/documents/report.pdf", |
| 80 | + "metadata": {"version": "1.2"} |
| 81 | + }, |
| 82 | + "system_instruction_override": { |
| 83 | + "mediaType": "text/plain", |
| 84 | + "content": "Focus specifically on the financial results section.", |
| 85 | + "id": "instr-001" |
| 86 | + } |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +## Client-Side Usage (AgentVault Library) |
| 92 | + |
| 93 | +The `agentvault.client.AgentVaultClient` provides optional parameters in its `initiate_task` and `send_message` methods to include MCP context: |
| 94 | + |
| 95 | +```python |
| 96 | +# Example using agentvault library |
| 97 | +from agentvault import AgentVaultClient, KeyManager, Message, TextPart, agent_card_utils |
| 98 | +from agentvault.models import AgentCard # Assuming AgentCard is available |
| 99 | + |
| 100 | +# Assume agent_card, key_manager are loaded/initialized |
| 101 | +client = AgentVaultClient() |
| 102 | +initial_message = Message(role="user", parts=[TextPart(content="Analyze this data.")]) |
| 103 | + |
| 104 | +# Define the context payload |
| 105 | +mcp_payload = { |
| 106 | + "items": { |
| 107 | + "data_reference": { |
| 108 | + "ref": "https://data.example.com/dataset.csv", |
| 109 | + "mediaType": "text/csv" |
| 110 | + }, |
| 111 | + "analysis_params": { |
| 112 | + "content": {"mode": "deep", "output_format": "json"}, |
| 113 | + "mediaType": "application/json" |
| 114 | + } |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +try: |
| 119 | + # Pass the payload to initiate_task |
| 120 | + task_id = await client.initiate_task( |
| 121 | + agent_card=agent_card, |
| 122 | + initial_message=initial_message, |
| 123 | + key_manager=key_manager, |
| 124 | + mcp_context=mcp_payload # Pass the context dictionary here |
| 125 | + ) |
| 126 | + print(f"Task initiated with MCP context, ID: {task_id}") |
| 127 | + |
| 128 | + # ... handle subsequent events ... |
| 129 | + |
| 130 | +except Exception as e: |
| 131 | + print(f"Error: {e}") |
| 132 | + |
| 133 | +``` |
| 134 | + |
| 135 | +The client library uses `agentvault.mcp_utils.format_mcp_context` internally to perform basic validation against the placeholder Pydantic models and embed the formatted context into `message.metadata["mcp_context"]` before sending the request. |
| 136 | + |
| 137 | +## Server-Side Usage (AgentVault Server SDK) |
| 138 | + |
| 139 | +Agents built using the `agentvault-server-sdk` can easily extract the MCP context from incoming messages using the provided utility function: |
| 140 | + |
| 141 | +```python |
| 142 | +# Example within an AgentVault SDK Agent method |
| 143 | +from agentvault_server_sdk import BaseA2AAgent |
| 144 | +from agentvault_server_sdk.mcp_utils import get_mcp_context |
| 145 | +from agentvault.models import Message # Assuming Message is available |
| 146 | + |
| 147 | +class MyAgent(BaseA2AAgent): |
| 148 | + # ... other methods ... |
| 149 | + |
| 150 | + async def handle_task_send(self, task_id: Optional[str], message: Message) -> str: |
| 151 | + # Extract MCP context |
| 152 | + mcp_data = get_mcp_context(message) |
| 153 | + |
| 154 | + if mcp_data: |
| 155 | + print(f"Received MCP context for task {task_id or 'new'}: {mcp_data}") |
| 156 | + # Access specific items |
| 157 | + user_profile = mcp_data.get("items", {}).get("user_profile") |
| 158 | + if user_profile and user_profile.get("content"): |
| 159 | + user_id = user_profile["content"].get("user_id") |
| 160 | + print(f"User ID from MCP: {user_id}") |
| 161 | + # ... process context items ... |
| 162 | + else: |
| 163 | + print(f"No valid MCP context found in message for task {task_id or 'new'}.") |
| 164 | + |
| 165 | + # ... rest of task handling logic ... |
| 166 | + new_task_id = f"task-{uuid.uuid4().hex[:6]}" |
| 167 | + # ... store task state, start background work etc ... |
| 168 | + return new_task_id |
| 169 | + |
| 170 | +``` |
| 171 | + |
| 172 | +The `get_mcp_context` function safely checks for the presence and type of `message.metadata` and the `"mcp_context"` key, returning the dictionary if found, or `None` otherwise. |
| 173 | + |
| 174 | +## Future Directions |
| 175 | + |
| 176 | +As MCP standards solidify, AgentVault plans to: |
| 177 | + |
| 178 | +* Adopt or contribute to official schema definitions. |
| 179 | +* Enhance validation logic in `mcp_utils`. |
| 180 | +* Potentially provide more structured ways to interact with specific MCP item types within the SDK. |
| 181 | + |
| 182 | +The current implementation provides a flexible placeholder mechanism for passing structured context alongside core A2A messages. |
| 183 | +``` |
0 commit comments