"""MCP Resources for exposing standards documentation.
Resources are read-only data sources that provide context to agents.
These resources expose the Darwin platform standards as MCP resources.
"""
import aiofiles
from fastmcp import FastMCP
from fastmcp.exceptions import NotFoundError
from ..config import get_config
from ..observability import get_tracer
router = FastMCP("standards-resources")
tracer = get_tracer(__name__)
config = get_config()
# =============================================================================
# Static Resources - Standards Documents
# =============================================================================
@router.resource("standards://agents/design")
async def agent_design_standards() -> str:
"""Agent design principles and 5-layer architecture.
This document defines the core design principles for building
AI agents in the Darwin platform.
Topics covered:
- 5-layer agent architecture
- Agent lifecycle
- Error handling patterns
- Testing requirements
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_design_standards"):
return await _load_standard("agents/agent-design.md")
@router.resource("standards://agents/communication")
async def agent_communication_standards() -> str:
"""Agent-to-Agent (A2A) protocol standards.
Defines how agents communicate with each other using
the A2A protocol based on Google's specification.
Topics covered:
- A2A protocol overview
- Agent Cards
- Task lifecycle
- Message formats
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_communication_standards"):
return await _load_standard("agents/agent-communication.md")
@router.resource("standards://agents/tools")
async def agent_tools_standards() -> str:
"""MCP tool integration standards for agents.
Defines how agents should integrate with and use MCP tools.
Topics covered:
- Tool design principles
- Context usage
- Error handling
- Testing patterns
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_tools_standards"):
return await _load_standard("agents/agent-tools.md")
@router.resource("standards://agents/memory")
async def agent_memory_standards() -> str:
"""Agent memory architecture using Neo4j.
Defines the graph-based memory system for agents.
Topics covered:
- Memory types (episodic, semantic, procedural)
- Neo4j schema
- Memory operations
- Retention policies
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_memory_standards"):
return await _load_standard("agents/agent-memory.md")
@router.resource("standards://agents/observability")
async def agent_observability_standards() -> str:
"""Agent observability standards with OpenTelemetry.
Defines observability requirements for agents using
OpenTelemetry as the instrumentation foundation.
Topics covered:
- OpenTelemetry SDK setup
- Trace propagation
- LLM-specific metrics
- Langfuse integration
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_observability_standards"):
return await _load_standard("agents/agent-observability.md")
@router.resource("standards://agents/security")
async def agent_security_standards() -> str:
"""Agent security requirements.
Defines security requirements for agent authentication,
authorization, and secrets management.
Topics covered:
- Authentication methods
- Role-based access control
- Secrets management
- Audit logging
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.agent_security_standards"):
return await _load_standard("agents/agent-security.md")
@router.resource("standards://mcp/server-design")
async def mcp_server_design_standards() -> str:
"""MCP server architecture standards.
Defines how to build MCP servers for the Darwin platform.
Topics covered:
- Server architecture
- Transport configuration
- Capability advertisement
- Health checks
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.mcp_server_design_standards"):
return await _load_standard("mcp/mcp-server-design.md")
@router.resource("standards://mcp/tool-design")
async def mcp_tool_design_standards() -> str:
"""MCP tool definition standards.
Defines how to design and implement MCP tools.
Topics covered:
- Tool design principles
- Input/output schemas
- Tool categories
- Documentation requirements
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.mcp_tool_design_standards"):
return await _load_standard("mcp/mcp-tool-design.md")
@router.resource("standards://mcp/resource-design")
async def mcp_resource_design_standards() -> str:
"""MCP resource exposure standards.
Defines how to design and implement MCP resources.
Topics covered:
- Resource types
- URI schemes
- Caching strategies
- Subscriptions
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.mcp_resource_design_standards"):
return await _load_standard("mcp/mcp-resource-design.md")
@router.resource("standards://mcp/security")
async def mcp_security_standards() -> str:
"""MCP authentication and authorization standards.
Defines security requirements for MCP servers.
Topics covered:
- Transport security
- Authentication methods
- Authorization patterns
- Audit logging
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.mcp_security_standards"):
return await _load_standard("mcp/mcp-security.md")
@router.resource("standards://mcp/error-handling")
async def mcp_error_handling_standards() -> str:
"""MCP error handling patterns.
Defines error handling standards for MCP servers.
Topics covered:
- Error categories
- Error response structure
- Retry logic
- Error logging
Cache: Long-lived (24 hours)
"""
with tracer.start_as_current_span("resource.mcp_error_handling_standards"):
return await _load_standard("mcp/mcp-error-handling.md")
# =============================================================================
# Dynamic Resources - Parameterized access
# =============================================================================
@router.resource("standards://{category}/{document}")
async def get_standard_by_path(category: str, document: str) -> str:
"""Get any standards document by category and name.
Args:
category: Standards category (agents, mcp, infrastructure, etc.)
document: Document name without .md extension
Returns:
Markdown content of the standards document.
Raises:
ResourceNotFoundError: If document doesn't exist.
"""
with tracer.start_as_current_span("resource.get_standard_by_path") as span:
span.set_attribute("standards.category", category)
span.set_attribute("standards.document", document)
path = f"{category}/{document}.md"
return await _load_standard(path)
# =============================================================================
# Helper Functions
# =============================================================================
async def _load_standard(relative_path: str) -> str:
"""Load a standards document from disk.
Args:
relative_path: Path relative to standards directory.
Returns:
Markdown content.
Raises:
ResourceNotFoundError: If file doesn't exist.
"""
standards_root = config.get_standards_root()
file_path = standards_root / relative_path
if not file_path.exists():
raise NotFoundError(
f"Standards document not found: {relative_path}"
)
async with aiofiles.open(file_path, mode='r', encoding='utf-8') as f:
return await f.read()