# TASK_10: send_message_to_agent MCP Tool Implementation
**Created By**: ADDER_5 | **Priority**: MEDIUM | **Duration**: 4 hours
**Technique Focus**: Contracts + Defensive Programming + Testing + Message Routing
**Size Constraint**: Target <250 lines/module, Max 400 if splitting awkward
## π¦ Status & Assignment
**Status**: COMPLETE
**Assigned**: ADDER_5
**Dependencies**: TASK_4 (Agent & Session Management Core)
**Blocking**: Other MCP tool implementations
## π Required Reading (Complete before starting)
- [x] **Architecture**: `ARCHITECTURE.md` - send_message_to_agent tool specification
- [x] **Core Management**: Results from TASK_4 - Agent and Session managers
- [x] **FastMCP Integration**: Results from TASK_3 - Server foundation
- [x] **iTerm Protocol**: `development/protocols/iterm_protocol.md` - Message injection
- [x] **Claude Protocol**: `development/protocols/claude_code_protocol.md` - Message handling
- [x] **Previous Tools**: Review TASK_5 and TASK_6 implementation patterns
## π― Objective & Context
**Goal**: Implement send_message_to_agent MCP tool for targeted agent communication
**Context**: Critical coordination tool enabling Claude Desktop to send messages with ADDER+ prepending
<thinking>
send_message_to_agent Implementation Analysis:
1. Must validate agent name and message content
2. Requires locating agent across sessions
3. Needs ADDER+ prompt prepending when requested
4. Must inject message via iTerm2 text sending
5. Requires message sanitization for security
6. Must handle offline/busy agent scenarios
7. Optional response waiting with timeout
</thinking>
## β
Implementation Subtasks (Sequential completion)
### Phase 1: Input Validation & Security
- [x] **Subtask 1.1**: Implement agent name validation and location
- [x] **Subtask 1.2**: Add message content sanitization and validation
- [x] **Subtask 1.3**: Create ADDER+ prompt construction logic
- [x] **Subtask 1.4**: Implement injection attack prevention
### Phase 2: Core Implementation
- [x] **Subtask 2.1**: Integrate with OrchestrationCoordinator for agent lookup
- [x] **Subtask 2.2**: Add iTerm2 message injection via text sending
- [x] **Subtask 2.3**: Implement ADDER+ prompt prepending logic
- [x] **Subtask 2.4**: Create response waiting mechanism (optional)
### Phase 3: Error Handling & Recovery
- [x] **Subtask 3.1**: Add handling for offline/unreachable agents
- [x] **Subtask 3.2**: Implement timeout handling for response waiting
- [x] **Subtask 3.3**: Create audit logging for all messages
- [x] **Subtask 3.4**: Add message delivery confirmation
### Phase 4: Testing & Validation
- [x] **Subtask 4.1**: Property-based testing for message sanitization
- [x] **Subtask 4.2**: Integration testing with active agents
- [x] **Subtask 4.3**: Security testing for injection attacks
- [x] **Subtask 4.4**: Performance testing with large messages
## π§ Implementation Files & Specifications
**Files to Create/Modify**:
- `src/interfaces/mcp_tools.py` - Add send_message_to_agent tool (Target: <200 lines)
- `src/utils/message_sanitization.py` - Message sanitization utilities (Target: <150 lines)
- `src/utils/adder_prompt_builder.py` - ADDER+ prompt construction (Target: <150 lines)
- `tests/interfaces/test_send_message.py` - Comprehensive tool testing
- `tests/properties/test_message_sanitization.py` - Property-based security testing
**Key Requirements**:
- FastMCP tool decorator with automatic schema generation
- Complete message sanitization to prevent injection
- Integration with OrchestrationCoordinator for agent location
- ADDER+ prompt prepending with proper formatting
- Optional response waiting with configurable timeout
## ποΈ Modularity Strategy
**Size Management**:
- Separate message sanitization into security module
- Extract ADDER+ prompt building into utility
- Use composition for message routing logic
- Keep MCP tool implementation minimal and declarative
**Organization Principles**:
- Single responsibility for message routing workflow
- Clear separation between sanitization and delivery
- Minimal coupling with other MCP tools
- Maximum reusability of messaging components
## β
Success Criteria & Verification
**Completion Requirements**:
- [x] MCP tool properly registered and accessible from Claude Desktop
- [x] Comprehensive message sanitization preventing injection
- [x] Successful message delivery to target agents
- [x] ADDER+ prompt prepending working correctly
- [x] Complete error handling for unreachable agents
- [x] Audit logging for all message operations
- [x] Property-based testing for security scenarios
**Quality Gates**:
- Functionality: Messages delivered accurately to target agents
- Security: All messages sanitized against injection attacks
- Reliability: Graceful handling of offline/busy agents
- Performance: Fast message delivery with minimal latency
- Auditability: Complete logging of all messaging operations
## π Handoff Information
**Next Task Dependencies**: Enables multi-agent coordination workflows
**Integration Points**: Uses OrchestrationCoordinator for agent management
**Future Considerations**: Extensible for broadcast messaging
## π Implementation Template
```python
# src/interfaces/mcp_tools.py (addition to existing file)
@mcp.tool()
@validate_message_operation
@require_agent_access
async def send_message_to_agent(
self,
agent_name: str,
message: str,
prepend_adder: bool = True,
wait_for_response: bool = False,
timeout_seconds: int = 30,
ctx: Context = None
) -> dict:
"""
Send message to specific agent with optional ADDER+ prepending.
Implements secure message routing to target agents with comprehensive
sanitization, ADDER+ prompt integration, and delivery confirmation.
Contracts:
Preconditions:
- agent_name must be valid and agent must exist
- message must pass sanitization checks
- Caller must have permission to message agent
Postconditions:
- Message delivered to agent's iTerm2 tab
- ADDER+ prompt prepended if requested
- Audit trail created for message
- Response returned if wait_for_response=True
Invariants:
- No injection attacks possible through messages
- All messages are logged with security context
- Agent state remains consistent
Security Implementation:
- Input Sanitization: Comprehensive message cleaning
- Injection Prevention: Escape sequences and command blocking
- Access Control: Verify messaging permissions
- Audit Trail: Complete logging of all messages
Args:
agent_name: Target agent name (Agent_# format)
message: Message content to send (will be sanitized)
prepend_adder: Whether to prepend ADDER+ prompt
wait_for_response: Whether to wait for agent response
timeout_seconds: Timeout for response waiting
ctx: FastMCP context for progress reporting
Returns:
MessageResult with delivery status and optional response
Raises:
ValidationError: Invalid agent name or message
SecurityError: Message contains forbidden content
OperationError: Message delivery failed
TimeoutError: Response timeout exceeded
"""
execution_start = time.time()
try:
await ctx.info(f"Sending message to agent {agent_name}")
# Phase 1: Agent Validation
await ctx.report_progress(10, 100, "Validating agent")
agent_info = await self.agent_manager.find_agent_by_name(
agent_name=agent_name,
security_context=SecurityContext()
)
if not agent_info:
raise ValidationError(f"Agent {agent_name} not found")
if agent_info.status != AgentStatus.ACTIVE:
raise OperationError(
f"Agent {agent_name} is not active (status: {agent_info.status})"
)
# Phase 2: Message Sanitization
await ctx.report_progress(25, 100, "Sanitizing message")
sanitized_message = await self._sanitize_message(
message=message,
security_context=SecurityContext()
)
# Phase 3: ADDER+ Prompt Construction
if prepend_adder:
await ctx.report_progress(40, 100, "Building ADDER+ prompt")
final_message = self._build_adder_message(
agent_name=agent_name,
message=sanitized_message,
session_context=agent_info.session_context
)
else:
final_message = sanitized_message
# Phase 4: Message Delivery
await ctx.report_progress(60, 100, "Delivering message")
delivery_result = await self.iterm_manager.send_text(
tab_id=agent_info.iterm_tab_id,
text=final_message + "\n",
security_context=SecurityContext()
)
if not delivery_result:
raise OperationError("Message delivery failed")
# Phase 5: Response Waiting (Optional)
response = None
if wait_for_response:
await ctx.report_progress(80, 100, "Waiting for response")
response = await self._wait_for_agent_response(
agent_id=agent_info.agent_id,
timeout_seconds=timeout_seconds
)
await ctx.report_progress(100, 100, "Message sent successfully")
await ctx.info(f"Message delivered to {agent_name}")
# Calculate execution time
execution_duration = (time.time() - execution_start) * 1000
# Update performance statistics
self._update_tool_performance("send_message_to_agent", execution_duration, success=True)
# Log message operation
if self._audit_logger:
await self._audit_logger.log_event(
level=AuditLevel.INFO,
category=AuditCategory.AGENT_COMMUNICATION,
operation="message_sent",
resource_type="agent_message",
resource_id=str(agent_info.agent_id),
success=True,
metadata={
"agent_name": agent_name,
"message_length": len(message),
"prepend_adder": prepend_adder,
"wait_for_response": wait_for_response,
"execution_duration_ms": execution_duration
}
)
return {
"success": True,
"agent_name": agent_name,
"message_delivered": True,
"delivery_timestamp": datetime.utcnow().isoformat(),
"prepend_adder": prepend_adder,
"response": response if wait_for_response else None,
"execution_duration_ms": execution_duration
}
except Exception as e:
# Error handling and logging
execution_duration = (time.time() - execution_start) * 1000
self._update_tool_performance("send_message_to_agent", execution_duration, success=False)
if ctx:
await ctx.error(f"Message delivery failed: {str(e)}")
return {
"success": False,
"error": str(e),
"error_type": type(e).__name__,
"agent_name": agent_name,
"execution_duration_ms": execution_duration
}
async def _sanitize_message(self, message: str, security_context: SecurityContext) -> str:
"""Sanitize message to prevent injection attacks."""
# Remove potential command injection sequences
sanitized = message
# Remove shell metacharacters
dangerous_chars = [';', '|', '&', '$', '`', '\\', '(', ')', '<', '>', '\n', '\r']
for char in dangerous_chars:
sanitized = sanitized.replace(char, '')
# Escape quotes
sanitized = sanitized.replace('"', '\\"').replace("'", "\\'")
# Limit message length
max_length = 10000
if len(sanitized) > max_length:
sanitized = sanitized[:max_length] + "... (truncated)"
return sanitized
def _build_adder_message(
self,
agent_name: str,
message: str,
session_context: dict
) -> str:
"""Build message with ADDER+ prompt prepending."""
adder_prefix = f"""
# ADDER+ TASK ASSIGNMENT FOR {agent_name}
**From**: Orchestration Controller
**Priority**: MEDIUM
**Context**: Session {session_context.get('session_id', 'unknown')}
## Task Description
"""
return adder_prefix + message
async def _wait_for_agent_response(
self,
agent_id: AgentId,
timeout_seconds: int
) -> Optional[str]:
"""Wait for agent response with timeout."""
# This would integrate with Claude Code output monitoring
# For now, return None as placeholder
await asyncio.sleep(2) # Simulate waiting
return None
```
### **Message Sanitization Module**
```python
# src/utils/message_sanitization.py
from typing import List, Set
import re
from dataclasses import dataclass
@dataclass
class SanitizationConfig:
"""Configuration for message sanitization."""
max_length: int = 10000
forbidden_patterns: List[str] = None
escape_sequences: bool = True
class MessageSanitizer:
"""Comprehensive message sanitization for security."""
def __init__(self, config: SanitizationConfig):
self.config = config
self._compile_patterns()
def sanitize(self, message: str) -> str:
"""Sanitize message content for safe delivery."""
# Implementation with comprehensive sanitization
```
This send_message_to_agent implementation provides secure message routing with ADDER+ integration, comprehensive sanitization, and optional response waiting.