Orchestrata Ultimate / Specs / 071-mcp-resource-tools
071-mcp-resource-tools: MCP Resource Tools - Model Context Protocol Integration
A production-ready tool suite for managing Model Context Protocol (MCP) server connections, resource listing, resource reading, and authentication handling with comprehensive security, caching, and governance.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/071-mcp-resource-tools/ |
| Status line in the spec | Complete |
| Requirement IDs defined | 48 |
With a @traces citation in src/ |
16 (33.3%) |
With a @traces citation in tests/ |
0 (0.0%) |
| Tracked files | 3 |
| RTM page | 071-mcp-resource-tools |
Reading this spec
This spec defines a tool suite for working with Model Context Protocol (MCP) servers: connecting to them, listing their resources, reading resource content and handling authentication, with security, caching and governance. The aims are letting agents discover and read MCP server resources, managing MCP credentials, supporting versioning and caching for performance, and enforcing access control through PAM++ governance. The design names the mcp Python SDK, a server registry with connection pooling, vault-backed credential storage, TTL-based caching with invalidation and Prolog-based access control predicates.
Three tools carry the scope: ListMcpResourcesTool, ReadMcpResourceTool and McpAuthTool. Five user stories cover an agent discovering resources, reading a specific resource, an administrator configuring authentication, an agent meeting a protected resource and the system managing its cache. The 48 requirement IDs (REQ-071-NNN) run in that order: listing (all resources from a registered server with URI, name and type), reading (by full URI, with version retrieval, range reads and checksum validation), caching (check before fetch, honour TTL, report cached status and bypass), and authentication (API key, OAuth2, certificate and bearer token; format validation; connection testing; removal and refresh).
The requirements record where the current build is narrower than the spec. Many items carry inline notes that the build has no server registry (one server per call), no caching layer, no versioning layer and no authentication layer, and that McpAuthTool is out of scope for now. Those notes explain most of the untraced requirements.
The code is in the MCP resource tools module. The requirements traceability matrix lists each ID. The spec's own status line reads Complete and it tracks 3 files. Measured coverage is 16 of 48 requirements cited by at least one @traces in src/ (33.3%), spread over 1 module; the module citing the most of them is orchestrata_ultimate/tools/mcp_resource_tools (16 requirements). In tests/, 0 requirements are cited by a test-side @traces. 32 requirements have no citing symbol.
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-071-001 |
yes | System SHALL return all resources from a registered MCP server | 2 |
REQ-071-002 |
no | System SHALL aggregate resources from multiple servers (no server registry — MVP is one server per call) | none |
REQ-071-003 |
no | System SHALL support filtering by server name or ID (no registry to look servers up in) | none |
REQ-071-004 |
yes | System SHALL support filtering by resource type (MVP: MIME-type prefix match, not a ResourceType enum) |
2 |
REQ-071-005 |
no | System SHALL return resources sorted by modified_at descending (base MCP resources/list has no modified_at field) |
none |
REQ-071-006 |
yes | System SHALL support pagination via limit and offset | 3 |
REQ-071-007 |
yes | System SHALL include resource URI, name, type for each resource | 2 |
REQ-071-008 |
yes | System SHALL include size and MIME type when available | 2 |
REQ-071-009 |
no | System SHALL include created_at and modified_at timestamps (not part of the base protocol) | none |
REQ-071-010 |
no | System SHALL indicate whether resource is protected (no protection metadata available without auth layer) | none |
REQ-071-011 |
no | System SHALL include version information if available (no versioning layer) | none |
REQ-071-012 |
yes | System SHALL return connection status for each server (the one server contacted this call) | 2 |
REQ-071-013 |
no | System SHALL indicate whether server is authenticated (no auth layer — McpAuthTool out of scope) | none |
REQ-071-014 |
yes | System SHALL include resource count per server | 2 |
REQ-071-015 |
yes | System SHALL include last_used timestamp per server | 2 |
REQ-071-016 |
no | System SHALL indicate how many results were from cache (no cache layer) | none |
REQ-071-017 |
no | System SHALL include cache age information (no cache layer) | none |
REQ-071-018 |
no | System SHALL support cache bypass via parameter (no cache layer) | none |
REQ-071-019 |
yes | System SHALL retrieve resource content by full URI | 1 |
REQ-071-020 |
yes | System SHALL support streaming reads via offset and limit (client-side slicing of fetched content) | 1 |
REQ-071-021 |
yes | System SHALL return content as string or bytes based on MIME type | 2 |
REQ-071-022 |
yes | System SHALL include MIME type in response | 2 |
REQ-071-023 |
yes | System SHALL include content size in response | 2 |
REQ-071-024 |
no | System SHALL support retrieving specific versions by version ID (no versioning layer) | none |
REQ-071-025 |
no | System SHALL include version metadata in response (etag, created_at, checksum) (no versioning layer) | none |
REQ-071-026 |
no | System SHALL return latest version if version not specified (no versioning layer) | none |
REQ-071-027 |
no | System SHALL validate checksum when requested (no versioning layer) | none |
REQ-071-028 |
no | System SHALL check cache before fetching from server (no cache layer) | none |
REQ-071-029 |
no | System SHALL cache successful responses (no cache layer) | none |
REQ-071-030 |
no | System SHALL respect cache TTL from configuration (no cache layer) | none |
REQ-071-031 |
no | System SHALL support cache bypass parameter (no cache layer) | none |
REQ-071-032 |
no | System SHALL indicate whether response was cached (no cache layer) | none |
REQ-071-033 |
yes | System SHALL support offset parameter for partial reads | 4 |
REQ-071-034 |
yes | System SHALL support limit parameter for bounded reads | 4 |
REQ-071-035 |
no | System SHALL return accurate Content-Range headers (ToolResult has no header concept; size/offset are reported in the JSON payload instead) | none |
REQ-071-036 |
yes | System SHALL handle range requests correctly (offset/limit clamped and sliced correctly) | 2 |
REQ-071-037 |
no | System SHALL support API key authentication | none |
REQ-071-038 |
no | System SHALL support OAuth2 authentication | none |
REQ-071-039 |
no | System SHALL support certificate-based authentication | none |
REQ-071-040 |
no | System SHALL support bearer token authentication | none |
REQ-071-041 |
no | System SHALL validate credential format before storage | none |
REQ-071-042 |
no | System SHALL encrypt credentials at rest | none |
REQ-071-043 |
no | System SHALL test connection after credential configuration | none |
REQ-071-044 |
no | System SHALL return detailed error on connection failure | none |
REQ-071-045 |
no | System SHALL support testing existing configurations | none |
REQ-071-046 |
no | System SHALL support removing credentials | none |
REQ-071-047 |
no | System SHALL support refreshing expired credentials | none |
REQ-071-048 |
no | System SHALL handle credential expiration gracefully | none |
Code that traces this spec
| Module | Symbols | Requirements |
|---|---|---|
orchestrata_ultimate/tools/mcp_resource_tools |
10 | 16 |
Checklists
checklists/requirements.md
The requirement list above comes from this file; 16 of 48 checkbox items are ticked.
Other tracked files
specs/071-mcp-resource-tools/compliance-audit.md
Full spec text
Verbatim from specs/071-mcp-resource-tools/spec.md; headings are pushed down two levels.
SPEC-071: MCP Resource Tools - Model Context Protocol Integration
Metadata
- Spec ID: 071-mcp-resource-tools
- Title: MCP Resource Tools - ListMcpResourcesTool, ReadMcpResourceTool
- Author: Mohamed
- Status: Complete
- Created: 2026-04-08
- Last Updated: 2026-04-09
- Priority: P3
- Version: 1.0.0
Overview
What
A production-ready tool suite for managing Model Context Protocol (MCP) server connections, resource listing, resource reading, and authentication handling with comprehensive security, caching, and governance.
Why
- Enable AI agents to discover and access MCP server resources
- Provide secure credential management for MCP connections
- Support resource versioning and caching for performance
- Enforce access control through PAM++ governance
How
- MCP SDK integration via
mcpPython package - Server registry with connection pooling
- Encrypted credential storage using vault integration
- TTL-based resource caching with invalidation
- Prolog-based access control predicates
Terminology
| Term | Definition |
|---|---|
| MCP | Model Context Protocol - A protocol for AI agents to interact with external resources |
| MCP Server | External server that exposes resources via the MCP protocol |
| MCP Resource | Any data or service exposed by an MCP server (file, database, API, secret) |
| URI | Uniform Resource Identifier following mcp://server/path format |
| Resource Type | Classification of MCP resource (file, db, api, secret, custom) |
| Connection Pool | Pool of maintained connections to MCP servers for efficient reuse |
| TTL | Time To Live - cache expiration duration |
| LRU | Least Recently Used - cache eviction policy |
| ETag | Entity Tag - identifier for a specific version of a resource |
| Vault | Secure storage system for encrypted credentials |
| PAM++ | Policy Administration Machine with Prolog-based governance rules |
| Protected Resource | Resource requiring authentication for access |
User Scenarios
US-001: Agent Discovers Available MCP Resources
Actor: AI Agent
Scenario:
- Agent invokes
ListMcpResourcesToolwithout filters - System connects to registered MCP servers
- System returns aggregated list of all available resources across servers
- Agent displays resources with metadata (name, type, size, modified date)
- Agent can filter by server or resource type
Expected Outcome: Agent receives comprehensive list of MCP resources with metadata, sorted by last modified date.
US-002: Agent Reads Specific Resource Content
Actor: AI Agent
Scenario:
- Agent invokes
ReadMcpResourceToolwith resource URI - System validates resource URI format and accessibility
- System checks agent permissions for resource access
- System retrieves resource (from cache if valid and not expired)
- System returns resource content with metadata
Expected Outcome: Agent receives resource content with versioning metadata; cache hit returns instantly.
US-003: Administrator Configures MCP Authentication
Actor: System Administrator
Scenario:
- Administrator invokes
McpAuthTool.configure()with server name and credentials - System validates credential format (API key, OAuth token, or certificate)
- System encrypts and stores credentials in vault
- System tests connection to MCP server
- System registers server in server registry
Expected Outcome: Server connected and authenticated; credentials stored securely; connection test successful.
US-004: Agent Handles Protected Resource Access
Actor: AI Agent
Scenario:
- Agent attempts to read protected resource
- System validates resource requires authentication
- System checks if agent has permission for resource
- If authorized, system retrieves credentials from vault
- System includes credentials in MCP request
- System returns resource content or access denied error
Expected Outcome: Protected resources accessible only to authorized agents; unauthorized access returns clear error.
US-005: System Manages Resource Cache
Actor: System
Scenario:
- Resource read request arrives
- System checks cache for resource with matching URI and version
- If cache hit and not expired, return cached content
- If cache miss or expired, fetch from MCP server
- Store response in cache with TTL
- Invalidate cache on resource update detection
Expected Outcome: Cache reduces latency for repeated reads; invalidation ensures freshness.
Data Models
ListMcpResourcesTool
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
from enum import Enum
class ResourceType(Enum):
"""MCP resource types."""
FILE = "file"
DATABASE = "db"
API = "api"
SECRET = "secret"
CUSTOM = "custom"
class ConnectionStatus(Enum):
"""MCP server connection status."""
CONNECTED = "connected"
DISCONNECTED = "disconnected"
AUTHENTICATING = "authenticating"
ERROR = "error"
@dataclass
class MCPResource:
"""MCP resource representation."""
uri: str
name: str
resource_type: ResourceType
size: Optional[int] = None
mime_type: Optional[str] = None
created_at: Optional[datetime] = None
modified_at: Optional[datetime] = None
version: Optional[str] = None
is_protected: bool = False
metadata: dict = field(default_factory=dict)
@dataclass
class MCPConnection:
"""MCP server connection."""
server_id: str
server_name: str
endpoint: str
status: ConnectionStatus
authenticated: bool = False
resource_count: int = 0
last_used: Optional[datetime] = None
last_error: Optional[str] = None
@dataclass
class ListResourcesResult:
"""Result of listing MCP resources."""
success: bool
resources: list[MCPResource] = field(default_factory=list)
servers: list[MCPConnection] = field(default_factory=list)
total_count: int = 0
cached_count: int = 0
error_message: Optional[str] = None
class ListMcpResourcesTool(BaseTool):
"""List MCP server resources."""
name = "ListMcpResourcesTool"
description = "List available MCP resources from registered servers"
async def execute(
self,
server: Optional[str] = None,
filter_type: Optional[str] = None,
include_metadata: bool = True,
limit: Optional[int] = None,
offset: int = 0
) -> ListResourcesResult:
"""List MCP resources with optional filtering.
Args:
server: Filter by server name or ID (optional)
filter_type: Filter by resource type (file, db, api, secret, custom)
include_metadata: Include full metadata in response
limit: Maximum number of resources to return
offset: Number of resources to skip for pagination
Returns:
ListResourcesResult with resources and server information
"""
ReadMcpResourceTool
@dataclass
class ResourceVersion:
"""Resource version information."""
version: str
etag: str
created_at: datetime
size: int
checksum: str
@dataclass
class ReadResourceResult:
"""Result of reading MCP resource."""
success: bool
uri: str
content: Optional[str] = None
bytes_content: Optional[bytes] = None
mime_type: Optional[str] = None
size: int = 0
version: Optional[ResourceVersion] = None
cached: bool = False
cached_at: Optional[datetime] = None
error_message: Optional[str] = None
class ReadMcpResourceTool(BaseTool):
"""Read MCP resource content."""
name = "ReadMcpResourceTool"
description = "Read content from MCP resource by URI"
async def execute(
self,
resource_uri: str,
offset: int = 0,
limit: Optional[int] = None,
version: Optional[str] = None,
use_cache: bool = True,
validate_checksum: bool = True
) -> ReadResourceResult:
"""Read resource content by URI.
Args:
resource_uri: Full URI of the resource (mcp://server/path)
offset: Byte offset for streaming reads
limit: Maximum bytes to read
version: Specific version to retrieve (for versioning)
use_cache: Whether to use cached content if available
validate_checksum: Verify content integrity
Returns:
ReadResourceResult with content and metadata
"""
McpAuthTool
class AuthType(Enum):
"""MCP authentication types."""
API_KEY = "api_key"
OAUTH2 = "oauth2"
CERTIFICATE = "certificate"
BEARER_TOKEN = «redacted»
@dataclass
class AuthCredentials:
"""MCP authentication credentials."""
auth_type: AuthType
credentials: dict
server_id: str
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
expires_at: Optional[datetime] = None
@dataclass
class AuthResult:
"""Result of authentication operation."""
success: bool
server_id: Optional[str] = None
connection_status: Optional[ConnectionStatus] = None
error_message: Optional[str] = None
error_code: Optional[str] = None
class McpAuthTool(BaseTool):
"""Handle MCP authentication."""
name = "McpAuthTool"
description = "Configure and manage MCP server authentication"
async def configure(
self,
server: str,
auth_type: str,
credentials: dict,
test_connection: bool = True
) -> AuthResult:
"""Configure MCP authentication credentials.
Args:
server: Server name or ID
auth_type: Type of authentication (api_key, oauth2, certificate, bearer_token)
credentials: Authentication credentials (encrypted at rest)
test_connection: Whether to test connection after configuration
Returns:
AuthResult with success status and connection details
"""
async def test(
self,
server: str
) -> AuthResult:
"""Test MCP server connection and authentication.
Args:
server: Server name or ID
Returns:
AuthResult with connection test results
"""
async def remove(
self,
server: str,
force: bool = False
) -> AuthResult:
"""Remove MCP server credentials.
Args:
server: Server name or ID
force: Force removal even if resource access is active
Returns:
AuthResult with removal status
"""
async def refresh(
self,
server: str
) -> AuthResult:
"""Refresh expired credentials.
Args:
server: Server name or ID
Returns:
AuthResult with refresh status
"""
Functional Requirements
ListMcpResourcesTool Requirements
FR-001: Resource Listing (P1)
- System SHALL return all resources from registered MCP servers
- System SHALL aggregate resources from multiple servers
- System SHALL support filtering by server name or ID
- System SHALL support filtering by resource type
- System SHALL return resources sorted by modified_at descending
- System SHALL support pagination via limit and offset
FR-002: Metadata Inclusion (P1)
- System SHALL include resource URI, name, type for each resource
- System SHALL include size and MIME type when available
- System SHALL include created_at and modified_at timestamps
- System SHALL indicate whether resource is protected
- System SHALL include version information if available
FR-003: Server Status (P2)
- System SHALL return connection status for each server
- System SHALL indicate whether server is authenticated
- System SHALL include resource count per server
- System SHALL include last_used timestamp per server
FR-004: Cached Results (P2)
- System SHALL indicate how many results were from cache
- System SHALL include cache age information
- System SHALL support cache bypass via parameter
ReadMcpResourceTool Requirements
FR-005: Resource Reading (P1)
- System SHALL retrieve resource content by full URI
- System SHALL support streaming reads via offset and limit
- System SHALL return content as string or bytes based on MIME type
- System SHALL include MIME type in response
- System SHALL include content size in response
FR-006: Version Support (P1)
- System SHALL support retrieving specific versions by version ID
- System SHALL include version metadata in response (etag, created_at, checksum)
- System SHALL return latest version if version not specified
- System SHALL validate checksum when requested
FR-007: Cache Integration (P1)
- System SHALL check cache before fetching from server
- System SHALL cache successful responses
- System SHALL respect cache TTL from configuration
- System SHALL support cache bypass parameter
- System SHALL indicate whether response was cached
FR-008: Partial Reads (P1)
- System SHALL support offset parameter for partial reads
- System SHALL support limit parameter for bounded reads
- System SHALL return accurate Content-Range headers
- System SHALL handle range requests correctly
McpAuthTool Requirements
FR-009: Credential Configuration (P1)
- System SHALL support API key authentication
- System SHALL support OAuth2 authentication
- System SHALL support certificate-based authentication
- System SHALL support bearer token authentication
- System SHALL validate credential format before storage
- System SHALL encrypt credentials at rest
FR-010: Connection Testing (P1)
- System SHALL test connection after credential configuration
- System SHALL return detailed error on connection failure
- System SHALL support testing existing configurations
FR-011: Credential Management (P1)
- System SHALL support removing credentials
- System SHALL support refreshing expired credentials
- System SHALL handle credential expiration gracefully
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | INVALID_URI - Resource URI format is invalid | Return validation error with URI format guide |
| ERR-002 | RESOURCE_NOT_FOUND - Resource does not exist on server | Return 404 with available resources suggestion |
| ERR-003 | SERVER_UNREACHABLE - MCP server is not accessible | Return error with server status, suggest retry |
| ERR-004 | AUTHENTICATION_REQUIRED - Resource requires authentication | Return 401, prompt for credential configuration |
| ERR-005 | AUTHENTICATION_FAILED - Credentials are invalid | Return 403 with auth configuration guidance |
| ERR-006 | CREDENTIALS_EXPIRED - Authentication credentials have expired | Return error with refresh option |
| ERR-007 | PERMISSION_DENIED - Agent lacks permission for resource | Return 403 with governance error details |
| ERR-008 | RESOURCE_TOO_LARGE - Resource exceeds size limit | Return error with size info, suggest partial read |
| ERR-009 | READ_TIMEOUT - Resource read timed out | Return error with timeout details, suggest retry |
| ERR-010 | CACHE_ERROR - Cache retrieval or storage failed | Fall back to server fetch, log error |
| ERR-011 | INVALID_VERSION - Requested version does not exist | Return available versions list |
| ERR-012 | SERVER_ERROR - MCP server returned an error | Return server error message, suggest retry |
| ERR-013 | ENCODING_ERROR - Content encoding is invalid | Return error with encoding details |
| ERR-014 | CONCURRENT_ACCESS - Resource is locked for writing | Return error with retry-after suggestion |
| ERR-015 | SERVER_NOT_REGISTERED - Server is not in registry | Return error with registration guidance |
| ERR-016 | INVALID_CREDENTIALS_FORMAT - Credentials format is invalid | Return error with format requirements |
| ERR-017 | CACHE_INVALIDATION_FAILED - Failed to invalidate cache | Return error, trigger manual cache purge |
API Contracts
ListMcpResourcesTool API
Request:
{
"server": "production-mcp",
"filter_type": "file",
"include_metadata": true,
"limit": 50,
"offset": 0
}
Response (Success):
{
"success": true,
"resources": [
{
"uri": "mcp://production-mcp/files/config.yaml",
"name": "Configuration File",
"resource_type": "file",
"size": 2048,
"mime_type": "application/x-yaml",
"created_at": "2026-04-01T10:00:00Z",
"modified_at": "2026-04-08T12:00:00Z",
"version": "v3",
"is_protected": false,
"metadata": {
"extension": "yaml",
"encoding": "utf-8"
}
},
{
"uri": "mcp://production-mcp/db/users",
"name": "Users Database",
"resource_type": "db",
"size": 15728640,
"mime_type": "application/sql",
"created_at": "2026-03-15T08:00:00Z",
"modified_at": "2026-04-08T14:30:00Z",
"version": "v2",
"is_protected": true,
"metadata": {
"table_count": 12,
"row_count": 5432
}
}
],
"servers": [
{
"server_id": "prod-mcp-001",
"server_name": "production-mcp",
"endpoint": "https://mcp.example.com",
"status": "connected",
"authenticated": true,
"resource_count": 42,
"last_used": "2026-04-08T14:30:00Z",
"last_error": null
}
],
"total_count": 42,
"cached_count": 15
}
Response (Error):
{
"success": false,
"error_code": "E003",
"error_message": "Server 'production-mcp' is unreachable",
"resources": [],
"servers": [],
"total_count": 0
}
ReadMcpResourceTool API
Request:
{
"resource_uri": "mcp://production-mcp/files/config.yaml",
"offset": 0,
"limit": 4096,
"version": "v3",
"use_cache": true,
"validate_checksum": true
}
Response (Success):
{
"success": true,
"uri": "mcp://production-mcp/files/config.yaml",
"content": "# Configuration\ndatabase:\n host: localhost\n port: 5432\n",
"mime_type": "application/x-yaml",
"size": 2048,
"version": {
"version": "v3",
"etag": "abc123def456",
"created_at": "2026-04-08T12:00:00Z",
"size": 2048,
"checksum": "sha256:abc123..."
},
"cached": false,
"cached_at": null
}
Response (Cached):
{
"success": true,
"uri": "mcp://production-mcp/files/config.yaml",
"content": "# Configuration\ndatabase:\n host: localhost\n port: 5432\n",
"mime_type": "application/x-yaml",
"size": 2048,
"version": {
"version": "v3",
"etag": "abc123def456",
"created_at": "2026-04-08T12:00:00Z",
"size": 2048,
"checksum": "sha256:abc123..."
},
"cached": true,
"cached_at": "2026-04-08T14:00:00Z"
}
Response (Error):
{
"success": false,
"error_code": "E002",
"error_message": "Resource 'mcp://production-mcp/files/missing.yaml' not found",
"uri": "mcp://production-mcp/files/missing.yaml"
}
McpAuthTool API
Configure Request:
{
"server": "production-mcp",
"auth_type": "api_key",
"credentials": {
"key": "sk-xxxxx"
},
"test_connection": true
}
Configure Response (Success):
{
"success": true,
"server_id": "prod-mcp-001",
"connection_status": "connected",
"error_message": null
}
Configure Response (Error):
{
"success": false,
"error_code": "E005",
"error_message": "Authentication failed: Invalid API key",
"server_id": "prod-mcp-001"
}
Test Request:
{
"server": "production-mcp"
}
Test Response:
{
"success": true,
"server_id": "prod-mcp-001",
"connection_status": "connected",
"latency_ms": 45
}
Technical Design
Architecture Overview
The MCP Resource Tools implementation follows a layered architecture:
┌─────────────────────────────────────────────────────────────┐
│ Tool Layer │
│ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────┐ │
│ │ListMcpResources │ │ReadMcpResource │ │McpAuthTool │ │
│ │Tool │ │Tool │ │ │ │
│ └──────────────────┘ └──────────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Service Layer │
│ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────┐ │
│ │ResourceService │ │CacheService │ │AuthService │ │
│ └──────────────────┘ └──────────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
│ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────┐ │
│ │MCP Client │ │Redis Cache │ │Vault │ │
│ │Connection Pool │ │ │ │ │ │
│ └──────────────────┘ └──────────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Key Components
ResourceService
- Aggregates resources from multiple MCP servers
- Handles filtering, pagination, and sorting
- Manages resource metadata caching
CacheService
- TTL-based cache expiration (default: 300 seconds)
- LRU eviction policy with configurable max size
- Cache invalidation on resource version changes
AuthService
- Credential encryption using AES-256-GCM
- Vault integration for secure storage
- OAuth2 token refresh handling
Connection Pool Management
- Maximum 10 concurrent connections per server
- Connection timeout: 30 seconds
- Automatic reconnection with exponential backoff
- Health check every 60 seconds
Data Flow
- Tool receives request with parameters
- Service validates input and checks cache
- If cache miss, MCP client fetches from server
- Response is cached with TTL
- Governance rules are applied
- Result returned to caller
Examples
MCPResource Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MCPResource",
"type": "object",
"required": ["uri", "name", "resource_type"],
"properties": {
"uri": {
"type": "string",
"pattern": "^mcp://[a-zA-Z0-9_-]+/[a-zA-Z0-9_/.-]+$",
"description": "Unique resource identifier"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"resource_type": {
"type": "string",
"enum": ["file", "db", "api", "secret", "custom"]
},
"size": {
"type": ["integer", "null"],
"minimum": 0
},
"mime_type": {
"type": ["string", "null"]
},
"created_at": {
"type": ["string", "null"],
"format": "date-time"
},
"modified_at": {
"type": ["string", "null"],
"format": "date-time"
},
"version": {
"type": ["string", "null"]
},
"is_protected": {
"type": "boolean",
"default": false
},
"metadata": {
"type": "object",
"default": {}
}
}
}
MCPConnection Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MCPConnection",
"type": "object",
"required": ["server_id", "server_name", "endpoint", "status"],
"properties": {
"server_id": {
"type": "string",
"pattern": "^[a-zA-Z0-9_-]{8,}$"
},
"server_name": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"endpoint": {
"type": "string",
"format": "uri"
},
"status": {
"type": "string",
"enum": ["connected", "disconnected", "authenticating", "error"]
},
"authenticated": {
"type": "boolean",
"default": false
},
"resource_count": {
"type": "integer",
"minimum": 0,
"default": 0
},
"last_used": {
"type": ["string", "null"],
"format": "date-time"
},
"last_error": {
"type": ["string", "null"]
}
}
}
ResourceVersion Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ResourceVersion",
"type": "object",
"required": ["version", "etag", "created_at", "size"],
"properties": {
"version": {
"type": "string"
},
"etag": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"size": {
"type": "integer",
"minimum": 0
},
"checksum": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$"
}
}
}
ListResourcesRequest Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ListResourcesRequest",
"type": "object",
"properties": {
"server": {
"type": ["string", "null"],
"minLength": 1,
"maxLength": 128
},
"filter_type": {
"type": ["string", "null"],
"enum": ["file", "db", "api", "secret", "custom", null]
},
"include_metadata": {
"type": "boolean",
"default": true
},
"limit": {
"type": ["integer", "null"],
"minimum": 1,
"maximum": 1000
},
"offset": {
"type": "integer",
"minimum": 0,
"default": 0
}
}
}
ReadResourceRequest Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ReadResourceRequest",
"type": "object",
"required": ["resource_uri"],
"properties": {
"resource_uri": {
"type": "string",
"pattern": "^mcp://[a-zA-Z0-9_-]+/[a-zA-Z0-9_/.-]+$"
},
"offset": {
"type": "integer",
"minimum": 0,
"default": 0
},
"limit": {
"type": ["integer", "null"],
"minimum": 1,
"maximum": 10485760
},
"version": {
"type": ["string", "null"]
},
"use_cache": {
"type": "boolean",
"default": true
},
"validate_checksum": {
"type": "boolean",
"default": true
}
}
}
ConfigureAuthRequest Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ConfigureAuthRequest",
"type": "object",
"required": ["server", "auth_type", "credentials"],
"properties": {
"server": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"auth_type": {
"type": "string",
"enum": ["api_key", "oauth2", "certificate", "bearer_token"]
},
"credentials": {
"type": "object"
},
"test_connection": {
"type": "boolean",
"default": true
}
}
}
Non-Functional Requirements
Performance
| Metric | Target | Measurement |
|---|---|---|
| List resources (100 items) | < 500ms | P95 latency |
| Read cached resource | < 200ms | P95 latency |
| Read uncached resource | < 2s | P95 latency |
| Concurrent requests | 100+ | Simultaneous |
| Cache hit rate | > 80% | Daily average |
Scalability
- Support 50+ registered MCP servers
- Handle 10,000+ resources per server
- Connection pool: 10 connections per server
- Cache capacity: 100MB with LRU eviction
Reliability
- Uptime: 99.9% (excluding planned maintenance)
- Cache persistence: Redis with persistence enabled
- Automatic reconnection: Exponential backoff (1s, 2s, 4s, 8s, max 30s)
- Graceful degradation: Cache-only mode when MCP server unavailable
Security
- Credential encryption: AES-256-GCM
- TLS 1.3 for all MCP communications
- Vault integration for credential storage
- Audit logging for all access attempts
Maintainability
- Modular architecture with clear layer separation
- Configuration-driven behavior (no hardcoded values)
- Comprehensive logging at DEBUG/INFO/WARN/ERROR levels
- Health check endpoints for monitoring
Security
SR-001: Resource Versioning
- System SHALL assign unique version identifiers to all resources
- System SHALL support version retrieval via etag
- System SHALL track version history with timestamps
- System SHALL detect version changes on read
- System SHALL invalidate cache on version mismatch
SR-002: Caching Strategy
- System SHALL implement TTL-based cache expiration (default: 5 minutes)
- System SHALL support cache invalidation via explicit purge
- System SHALL support cache size limits (LRU eviction)
- System SHALL cache metadata separately from content
- System SHALL include cache metadata in responses (cached, cached_at)
SR-003: Authentication for Protected Resources
- System SHALL require authentication for protected resources
- System SHALL store credentials encrypted at rest
- System SHALL support credential refresh for OAuth2
- System SHALL handle expired credentials gracefully
- System SHALL validate credentials before each protected access
SR-004: Access Control
- System SHALL enforce PAM++ governance rules for all resource access
- System SHALL log all access attempts (authorized and denied)
- System SHALL support IP-based server restrictions
- System SHALL encrypt credentials in transit
SR-005: Audit Logging
- System SHALL log all resource read operations
- System SHALL log all authentication configuration changes
- System SHALL log all access denied events
- System SHALL include agent identity in audit logs
- System SHALL support audit log export
Testing Requirements
Test Coverage Requirements
| Requirement | Target | Verification |
|---|---|---|
| Unit test coverage | > 90% | pytest-cov |
| Integration test coverage | > 80% | pytest-cov |
| All error conditions tested | 100% | Test case count |
| All user scenarios tested | 100% | Test case count |
Test Automation Requirements
- All unit tests MUST run automatically on each commit
- All integration tests MUST run in CI/CD pipeline
- End-to-end tests MUST run nightly
- Performance tests MUST run weekly
- Test reports MUST be generated in JUnit XML format
- Code coverage reports MUST be generated in Cobertura XML format
Test Environment Requirements
- Unit tests: Mock external dependencies (MCP servers, Redis, Vault)
- Integration tests: Use test containers for MCP server, Redis
- End-to-end tests: Use staging environment with real MCP servers
- Performance tests: Use isolated environment with dedicated resources
Test Data Requirements
- Test data MUST be reproducible via seed values
- Test data MUST be isolated per test (no shared state)
- Sensitive test data MUST be encrypted or masked in logs
- Test data lifecycle: create → use → cleanup
Test Execution Requirements
- Unit tests MUST complete in < 60 seconds
- Integration tests MUST complete in < 300 seconds
- End-to-end tests MUST complete in < 600 seconds
- Tests MUST be idempotent (run multiple times with same result)
- Tests MUST be independent (no execution order dependencies)
Test Quality Requirements
- All tests MUST have descriptive names describing the scenario
- All tests MUST include docstrings explaining what is being tested
- All tests MUST assert specific expected outcomes
- All tests MUST clean up resources in finally/cleanup blocks
- Flaky tests MUST be marked and tracked until fixed
Testing
Unit Tests
- TEST-UNIT-001: Test ListMcpResourcesTool returns correct resource list
- TEST-UNIT-002: Test ReadMcpResourceTool retrieves content correctly
- TEST-UNIT-003: Test McpAuthTool configures credentials securely
- TEST-UNIT-004: Test cache integration with TTL expiration
- TEST-UNIT-005: Test error handling for all error conditions
- TEST-UNIT-006: Test version retrieval and validation
- TEST-UNIT-007: Test partial reads with offset and limit
Integration Tests
- TEST-INT-001: Test MCP server connection and authentication
- TEST-INT-002: Test resource listing across multiple servers
- TEST-INT-003: Test protected resource access with valid credentials
- TEST-INT-004: Test protected resource access denial without credentials
- TEST-INT-005: Test cache invalidation on resource update
- TEST-INT-006: Test concurrent resource access
End-to-End Tests
- TEST-E2E-001: Test complete agent workflow: list → read → process
- TEST-E2E-002: Test admin workflow: configure auth → test → verify access
- TEST-E2E-003: Test error recovery: server down → retry → success
- TEST-E2E-004: Test governance enforcement: unauthorized access denied
Performance Tests
- TEST-PERF-001: Test list response time < 500ms for 100 resources
- TEST-PERF-002: Test read response time < 200ms for cached resources
- TEST-PERF-003: Test concurrent read handling (100+ simultaneous)
- TEST-PERF-004: Test cache memory usage < 100MB
Integration Points
Runtime Dependencies
| Package | Version | Purpose |
|---|---|---|
| mcp | >=1.0.0 | MCP protocol SDK |
| pydantic | >=2.0.0 | Data validation |
| aiohttp | >=3.9.0 | Async HTTP client |
| redis | >=5.0.0 | Cache backend |
| cryptography | >=41.0.0 | Credential encryption |
| httpx | >=0.27.0 | HTTP client for testing |
Development Dependencies
| Package | Version | Purpose |
|---|---|---|
| pytest | >=8.0.0 | Testing framework |
| pytest-asyncio | >=0.23.0 | Async test support |
| pytest-cov | >=4.0.0 | Coverage reporting |
| pytest-mock | >=3.12.0 | Mocking for tests |
External Services
| Service | Purpose |
|---|---|
| MCP Server | Resource provider |
| Redis | Cache backend |
| Vault | Credential storage |
Dependencies
mcp:
servers:
production-mcp:
endpoint: "https://mcp.example.com"
timeout: 30
retry_attempts: 3
retry_delay: 1
cache:
enabled: true
ttl_seconds: 300
max_size_mb: 100
eviction_policy: "lru"
security:
encrypt_credentials: true
require_auth_for_protected: true
max_resource_size_mb: 50
logging:
level: "INFO"
audit_enabled: true
audit_retention_days: 90
Configuration
% MCP resource access governance
may_access_mcp(Agent, Server, Resource) :-
has_permission(Agent, mcp_access),
authorized_server(Agent, Server),
not resource_restricted(Resource, Level),
Level >= required_access_level(Agent, Resource).
may_access_mcp(Agent, Server, Resource) :-
has_permission(Agent, mcp_access),
authorized_server(Agent, Server),
resource_restricted(Resource, Level),
Level = restricted,
has_permission(Agent, mcp_restricted_access).
may_list_resources(Agent, Server) :-
has_permission(Agent, mcp_access),
authorized_server(Agent, Server).
may_configure_mcp(Agent) :-
has_permission(Agent, admin),
has_permission(Agent, mcp_admin).
may_read_protected_resource(Agent, Resource) :-
has_permission(Agent, mcp_restricted_access),
resource_belongs_to_tenant(Agent, Resource).
% Server authorization
authorized_server(Agent, Server) :-
agent_servers(Agent, Servers),
member(Server, Servers).
authorized_server(Agent, Server) :-
has_permission(Agent, mcp_admin).
% Resource restrictions
resource_restricted(Resource, Level) :-
mcp_resource(Resource, protected, true),
Level = restricted.
required_access_level(Agent, Resource) :-
mcp_resource(Resource, required_level, Level),
!.
required_access_level(_, normal).
% Agent server assignments
agent_servers(Agent, Servers) :-
mcp_server_assignment(Agent, Servers).
agent_servers(_, []) :-
not mcp_server_assignment(_, _).
Governance
AC-001: Resource Listing
- [ ] ListMcpResourcesTool returns all resources from registered servers
- [ ] Filtering by server works correctly
- [ ] Filtering by resource type works correctly
- [ ] Pagination with limit and offset works correctly
- [ ] Response includes all required metadata
AC-002: Resource Reading
- [ ] ReadMcpResourceTool retrieves content by URI
- [ ] Streaming reads with offset and limit work correctly
- [ ] Version retrieval returns correct version
- [ ] Checksum validation detects corruption
- [ ] Cached responses are returned when valid
AC-003: Authentication
- [ ] McpAuthTool.configue() stores credentials securely
- [ ] Connection test validates credentials
- [ ] Protected resources require authentication
- [ ] Invalid credentials return clear error
AC-004: Caching
- [ ] Cache stores responses with TTL
- [ ] Cache returns cached responses for same URI
- [ ] Cache invalidation works on version change
- [ ] LRU eviction prevents memory overflow
AC-005: Security
- [ ] Credentials encrypted at rest
- [ ] PAM++ governance enforced on all access
- [ ] Audit logging captures all operations
- [ ] Protected resources inaccessible without auth
Success Criteria
SC-001: Resource Listing
- ListMcpResourcesTool returns resources within 500ms for 100 resources
- Filtering produces correct results with no false positives
- Pagination returns accurate total_count
SC-002: Resource Reading
- ReadMcpResourceTool returns content within 200ms for cached resources
- Checksum validation detects all corrupted content
- Partial reads return accurate byte ranges
SC-003: Authentication
- All protected resources require valid credentials
- Credential encryption uses AES-256-GCM
- OAuth2 refresh succeeds within 5 seconds
SC-004: Caching
- Cache hit rate >80% for repeated reads
- Cache eviction prevents memory usage >100MB
- Cache invalidation completes within 100ms
SC-005: Governance
- All access attempts are logged with agent identity
- Unauthorized access is blocked with clear error message
- PAM++ rules are evaluated <50ms
SC-006: Reliability
- System handles 100+ concurrent read requests
- Connection pool maintains 10 connections per server
- Automatic reconnection succeeds after server outage
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-04-08 | Mohamed | Initial specification |
| 1.0.1 | 2026-04-09 | Mohamed | Added Terminology, Technical Design, Examples sections; Renumbered all sections; Added ERR-001 through ERR-017 error IDs; Added Success Criteria and Revision History |
End of SPEC-071