ADR-006: MCP Tools API Design and Interface Specification
Status
Accepted
Context
DocuMCP must expose its functionality through a carefully designed set of MCP tools that provide comprehensive coverage of the documentation deployment workflow while maintaining clear separation of concerns, appropriate granularity, and excellent developer experience for MCP-enabled clients.
The MCP Tools API serves as the primary interface between DocuMCP's intelligence and client applications like GitHub Copilot, Claude Desktop, and other MCP-enabled development environments. This API must balance several competing concerns:
Functional Requirements:
- Comprehensive repository analysis capabilities
- Intelligent SSG recommendation with detailed justifications
- Automated configuration generation for multiple SSGs
- Diataxis-compliant documentation structure creation
- GitHub Pages deployment workflow generation
- Git integration for seamless deployment
Usability Requirements:
- Intuitive tool names and parameter structures
- Comprehensive input validation with clear error messages
- Consistent response formats across all tools
- Rich metadata for client presentation and user guidance
- Progressive disclosure of complexity (simple to advanced use cases)
Technical Requirements:
- Full MCP specification compliance
- Robust error handling and recovery
- Efficient parameter validation and sanitization
- Scalable architecture supporting complex multi-step workflows
- Extensible design for future functionality additions
Decision
We will implement a comprehensive MCP Tools API consisting of six core tools that cover the complete documentation deployment workflow, with additional utility tools for advanced scenarios and troubleshooting.
Core MCP Tools Architecture:
1. Repository Analysis Tool (analyzeRepository
)
Purpose: Comprehensive repository analysis and project characterization Scope: Deep analysis of project structure, language ecosystems, existing documentation, and complexity assessment
2. SSG Recommendation Tool (recommendSSG
)
Purpose: Intelligent static site generator recommendation with detailed justifications Scope: Multi-criteria decision analysis with confidence scoring and alternative options
3. Configuration Generation Tool (generateConfiguration
)
Purpose: Create customized SSG configuration files and directory structures Scope: Template-based generation with project-specific customizations and validation
4. Diataxis Structure Tool (createDiataxisStructure
)
Purpose: Generate comprehensive Diataxis-compliant documentation frameworks Scope: Information architecture generation with content planning and navigation design
5. Deployment Workflow Tool (generateWorkflow
)
Purpose: Create optimized GitHub Actions workflows for automated deployment Scope: SSG-specific workflow generation with security best practices and performance optimization
6. Git Integration Tool (generateGitCommands
)
Purpose: Provide ready-to-execute Git commands for deployment and maintenance Scope: Context-aware command generation with branch management and deployment verification
Supporting Tools:
validateConfiguration
: Validate generated configurations and identify issuestroubleshootDeployment
: Analyze deployment failures and provide remediation guidanceoptimizePerformance
: Analyze and optimize existing documentation site performancemigrateDocumentation
: Assist with migration between different SSGs or frameworks
Alternatives Considered
Monolithic Single Tool Approach
- Pros: Simpler API surface, single entry point, easier client integration
- Cons: Complex parameter structures, poor separation of concerns, difficult error handling
- Decision: Rejected due to poor usability and maintainability
Micro-Tool Architecture (15+ Small Tools)
- Pros: Maximum granularity, precise control, composable workflows
- Cons: Complex orchestration, cognitive overhead, fragmented user experience
- Decision: Rejected due to complexity and poor user experience
Stateful Session-Based API
- Pros: Could maintain context across tool calls, simplified parameter passing
- Cons: Session management complexity, state synchronization issues, harder client integration
- Decision: Rejected to maintain MCP stateless principles
External API Integration (REST/GraphQL)
- Pros: Standard web technologies, extensive tooling ecosystem
- Cons: Not MCP-compliant, additional infrastructure requirements, authentication complexity
- Decision: Rejected due to MCP specification requirements
Consequences
Positive
- Clear Separation of Concerns: Each tool has well-defined responsibility and scope
- Progressive Complexity: Users can start simple and add sophistication as needed
- Excellent Error Handling: Tool-specific validation and error reporting
- Client-Friendly: Rich metadata and consistent response formats enhance client UX
- Extensible Architecture: Easy to add new tools without breaking existing functionality
Negative
- API Surface Complexity: Six core tools plus supporting tools require comprehensive documentation
- Inter-Tool Coordination: Some workflows require multiple tool calls with parameter passing
- Validation Overhead: Each tool requires comprehensive input validation and error handling
Risks and Mitigations
- API Complexity: Provide comprehensive documentation and usage examples
- Parameter Evolution: Use versioned schemas with backward compatibility
- Client Integration: Offer reference implementations and integration guides
Implementation Details
Tool Parameter Schemas
// Core tool parameter interfaces
interface AnalyzeRepositoryParams {
repositoryPath: string;
analysisDepth?: "basic" | "comprehensive" | "deep";
focusAreas?: ("structure" | "languages" | "documentation" | "complexity")[];
excludePatterns?: string[];
}
interface RecommendSSGParams {
projectAnalysis: ProjectAnalysis;
teamCapabilities?: TeamCapabilities;
performanceRequirements?: PerformanceRequirements;
customizationNeeds?: CustomizationNeeds;
existingConstraints?: ProjectConstraints;
}
interface GenerateConfigurationParams {
selectedSSG: SSGType;
projectAnalysis: ProjectAnalysis;
customizations?: SSGCustomizations;
deploymentTarget?: DeploymentTarget;
advancedOptions?: AdvancedConfigOptions;
}
interface CreateDiataxisStructureParams {
selectedSSG: SSGType;
projectType: ProjectType;
existingContent?: ExistingContentAnalysis;
contentComplexity?: "minimal" | "standard" | "comprehensive";
navigationPreferences?: NavigationPreferences;
}
interface GenerateWorkflowParams {
ssgType: SSGType;
deploymentStrategy: "github-actions" | "branch-based" | "hybrid";
securityRequirements?: SecurityRequirements;
performanceOptimizations?: PerformanceOptions;
environmentConfiguration?: EnvironmentConfig;
}
interface GenerateGitCommandsParams {
deploymentStrategy: DeploymentStrategy;
repositoryState: RepositoryState;
branchConfiguration: BranchConfiguration;
commitPreferences?: CommitPreferences;
}
Response Format Standardization
// Standardized response structure for all tools
interface MCPToolResponse<T> {
success: boolean;
data?: T;
error?: ErrorDetails;
metadata: ResponseMetadata;
recommendations?: Recommendation[];
nextSteps?: NextStep[];
}
interface ResponseMetadata {
toolVersion: string;
executionTime: number;
confidenceScore?: number;
analysisDepth: string;
timestamp: string;
correlationId: string;
}
interface ErrorDetails {
code: string;
message: string;
details: string;
resolution?: string;
documentation?: string;
}
interface Recommendation {
type: "optimization" | "alternative" | "enhancement";
priority: "low" | "medium" | "high";
description: string;
implementation?: string;
resources?: string[];
}
interface NextStep {
action: string;
description: string;
toolRequired?: string;
parameters?: Record<string, any>;
estimated_time?: string;
}
analyzeRepository Tool Implementation
const analyzeRepositoryTool: MCPTool = {
name: "analyzeRepository",
description: "Comprehensive repository analysis for documentation planning",
inputSchema: {
type: "object",
properties: {
repositoryPath: {
type: "string",
description: "Path to the repository to analyze",
},
analysisDepth: {
type: "string",
enum: ["basic", "comprehensive", "deep"],
default: "comprehensive",
description: "Depth of analysis to perform",
},
focusAreas: {
type: "array",
items: {
type: "string",
enum: ["structure", "languages", "documentation", "complexity"],
},
description: "Specific areas to focus analysis on",
},
excludePatterns: {
type: "array",
items: { type: "string" },
description: "File patterns to exclude from analysis",
},
},
required: ["repositoryPath"],
},
};
async function handleAnalyzeRepository(
params: AnalyzeRepositoryParams,
): Promise<MCPToolResponse<RepositoryAnalysis>> {
try {
const analysis = await repositoryAnalyzer.analyze(params);
return {
success: true,
data: analysis,
metadata: {
toolVersion: "1.0.0",
executionTime: analysis.executionTime,
analysisDepth: params.analysisDepth || "comprehensive",
timestamp: new Date().toISOString(),
correlationId: generateCorrelationId(),
},
recommendations: generateAnalysisRecommendations(analysis),
nextSteps: [
{
action: "Get SSG Recommendation",
description:
"Use analysis results to get intelligent SSG recommendations",
toolRequired: "recommendSSG",
parameters: { projectAnalysis: analysis },
estimated_time: "< 1 minute",
},
],
};
} catch (error) {
return {
success: false,
error: {
code: "ANALYSIS_FAILED",
message: "Repository analysis failed",
details: error.message,
resolution: "Verify repository path and permissions",
documentation: "https://documcp.dev/troubleshooting#analysis-errors",
},
metadata: {
toolVersion: "1.0.0",
executionTime: 0,
analysisDepth: params.analysisDepth || "comprehensive",
timestamp: new Date().toISOString(),
correlationId: generateCorrelationId(),
},
};
}
}
recommendSSG Tool Implementation
const recommendSSGTool: MCPTool = {
name: "recommendSSG",
description:
"Intelligent static site generator recommendation with detailed justifications",
inputSchema: {
type: "object",
properties: {
projectAnalysis: {
type: "object",
description: "Repository analysis results from analyzeRepository tool",
},
teamCapabilities: {
type: "object",
properties: {
technicalSkills: { type: "array", items: { type: "string" } },
maintenanceCapacity: {
type: "string",
enum: ["minimal", "moderate", "extensive"],
},
learningAppetite: { type: "string", enum: ["low", "medium", "high"] },
},
},
performanceRequirements: {
type: "object",
properties: {
buildTimeImportance: {
type: "string",
enum: ["low", "medium", "high"],
},
siteSpeedPriority: {
type: "string",
enum: ["standard", "fast", "ultra-fast"],
},
scalabilityNeeds: {
type: "string",
enum: ["small", "medium", "large", "enterprise"],
},
},
},
},
required: ["projectAnalysis"],
},
};
async function handleRecommendSSG(
params: RecommendSSGParams,
): Promise<MCPToolResponse<SSGRecommendation>> {
const recommendation = await ssgRecommendationEngine.analyze(params);
return {
success: true,
data: recommendation,
metadata: {
toolVersion: "1.0.0",
executionTime: recommendation.analysisTime,
confidenceScore: recommendation.confidence,
analysisDepth: "comprehensive",
timestamp: new Date().toISOString(),
correlationId: generateCorrelationId(),
},
recommendations: [
{
type: "optimization",
priority: "medium",
description: "Consider performance optimization strategies",
implementation: "Review build caching and incremental build options",
},
],
nextSteps: [
{
action: "Generate Configuration",
description: "Create customized configuration for recommended SSG",
toolRequired: "generateConfiguration",
parameters: {
selectedSSG: recommendation.primaryRecommendation.ssg,
projectAnalysis: params.projectAnalysis,
},
estimated_time: "2-3 minutes",
},
],
};
}
Input Validation System
interface ValidationRule {
field: string;
validator: (value: any) => ValidationResult;
required: boolean;
errorMessage: string;
}
class MCPToolValidator {
validateParameters<T>(params: T, schema: JSONSchema): ValidationResult {
const results = this.runSchemaValidation(params, schema);
const semanticResults = this.runSemanticValidation(params);
return this.combineValidationResults(results, semanticResults);
}
private runSemanticValidation(params: any): ValidationResult {
const issues: ValidationIssue[] = [];
// Repository path validation
if (
params.repositoryPath &&
!this.isValidRepositoryPath(params.repositoryPath)
) {
issues.push({
field: "repositoryPath",
message: "Repository path does not exist or is not accessible",
severity: "error",
resolution: "Verify the path exists and you have read permissions",
});
}
// Cross-parameter validation
if (params.analysisDepth === "deep" && params.focusAreas?.length > 2) {
issues.push({
field: "analysisDepth",
message: "Deep analysis with multiple focus areas may be slow",
severity: "warning",
resolution:
"Consider using comprehensive analysis or fewer focus areas",
});
}
return { valid: issues.length === 0, issues };
}
}
Tool Orchestration Patterns
Sequential Workflow Pattern
// Common workflow: Analysis → Recommendation → Configuration → Deployment
class DocumentationWorkflow {
async executeCompleteWorkflow(
repositoryPath: string,
): Promise<WorkflowResult> {
try {
// Step 1: Analyze repository
const analysisResult = await this.callTool("analyzeRepository", {
repositoryPath,
});
if (!analysisResult.success) {
throw new Error(`Analysis failed: ${analysisResult.error?.message}`);
}
// Step 2: Get SSG recommendation
const recommendationResult = await this.callTool("recommendSSG", {
projectAnalysis: analysisResult.data,
});
if (!recommendationResult.success) {
throw new Error(
`Recommendation failed: ${recommendationResult.error?.message}`,
);
}
// Step 3: Generate configuration
const configResult = await this.callTool("generateConfiguration", {
selectedSSG: recommendationResult.data.primaryRecommendation.ssg,
projectAnalysis: analysisResult.data,
});
if (!configResult.success) {
throw new Error(
`Configuration generation failed: ${configResult.error?.message}`,
);
}
// Step 4: Create Diataxis structure
const structureResult = await this.callTool("createDiataxisStructure", {
selectedSSG: recommendationResult.data.primaryRecommendation.ssg,
projectType: analysisResult.data.projectType,
});
if (!structureResult.success) {
console.warn(
`Diataxis structure creation failed: ${structureResult.error?.message}`,
);
}
// Step 5: Generate deployment workflow
const workflowResult = await this.callTool("generateWorkflow", {
ssgType: recommendationResult.data.primaryRecommendation.ssg,
deploymentStrategy: "github-actions",
});
if (!workflowResult.success) {
console.warn(
`Workflow generation failed: ${workflowResult.error?.message}`,
);
}
return this.combineResults([
analysisResult,
recommendationResult,
configResult,
structureResult,
workflowResult,
]);
} catch (error) {
throw new Error(`Complete workflow failed: ${error.message}`);
}
}
}
Error Handling and Recovery
Comprehensive Error Classification
enum ErrorCategory {
VALIDATION = "validation",
FILESYSTEM = "filesystem",
ANALYSIS = "analysis",
GENERATION = "generation",
CONFIGURATION = "configuration",
DEPLOYMENT = "deployment",
NETWORK = "network",
PERMISSION = "permission",
}
interface ErrorContext {
tool: string;
operation: string;
parameters: Record<string, any>;
environment: EnvironmentInfo;
}
class MCPErrorHandler {
handleError(error: Error, context: ErrorContext): MCPToolResponse<null> {
const classification = this.classifyError(error);
const resolution = this.generateResolution(classification, context);
return {
success: false,
error: {
code: this.generateErrorCode(classification),
message: this.formatUserMessage(error, classification),
details: error.message,
resolution: resolution.guidance,
documentation: resolution.documentationUrl,
},
metadata: this.generateErrorMetadata(context),
nextSteps: resolution.suggestedActions,
};
}
private generateResolution(
classification: ErrorClassification,
context: ErrorContext,
): ErrorResolution {
switch (classification.category) {
case ErrorCategory.FILESYSTEM:
return {
guidance: "Verify file paths and permissions",
documentationUrl:
"https://documcp.dev/troubleshooting#filesystem-errors",
suggestedActions: [
{
action: "Check file exists",
description: `Verify ${context.parameters.repositoryPath} exists`,
},
{
action: "Check permissions",
description: "Ensure read access to repository directory",
},
],
};
// ... other error categories
}
}
}
Performance Optimization
Response Caching Strategy
interface CacheConfiguration {
analyzeRepository: {
ttl: 300;
keyFields: ["repositoryPath", "analysisDepth"];
};
recommendSSG: { ttl: 3600; keyFields: ["projectAnalysis.signature"] };
generateConfiguration: {
ttl: 1800;
keyFields: ["selectedSSG", "projectAnalysis.signature"];
};
}
class MCPToolCache {
async getCachedResponse<T>(
toolName: string,
parameters: any,
): Promise<MCPToolResponse<T> | null> {
const cacheKey = this.generateCacheKey(toolName, parameters);
const cached = await this.cache.get(cacheKey);
if (cached && !this.isExpired(cached)) {
return {
...cached,
metadata: {
...cached.metadata,
fromCache: true,
cacheAge: Date.now() - cached.metadata.timestamp,
},
};
}
return null;
}
}
Testing Strategy
Tool Testing Framework
describe("MCP Tools API", () => {
describe("analyzeRepository", () => {
it("should analyze JavaScript project correctly");
it("should handle missing repository gracefully");
it("should respect analysis depth parameters");
it("should exclude specified patterns");
});
describe("recommendSSG", () => {
it("should recommend Hugo for large documentation sites");
it("should recommend Jekyll for GitHub Pages simple sites");
it("should provide confidence scores for all recommendations");
it("should handle incomplete project analysis");
});
describe("Tool Integration", () => {
it("should support complete workflow from analysis to deployment");
it("should maintain parameter consistency across tool calls");
it("should provide appropriate next steps guidance");
});
});
Integration Testing
class MCPToolIntegrationTests {
async testCompleteWorkflow(): Promise<void> {
const testRepo = await this.createTestRepository();
// Test full workflow
const analysis = await this.callTool("analyzeRepository", {
repositoryPath: testRepo,
});
expect(analysis.success).toBe(true);
const recommendation = await this.callTool("recommendSSG", {
projectAnalysis: analysis.data,
});
expect(recommendation.success).toBe(true);
expect(recommendation.data.primaryRecommendation).toBeDefined();
const config = await this.callTool("generateConfiguration", {
selectedSSG: recommendation.data.primaryRecommendation.ssg,
projectAnalysis: analysis.data,
});
expect(config.success).toBe(true);
// Validate generated configuration
await this.validateGeneratedFiles(config.data.files);
}
}
Documentation and Examples
Tool Usage Examples
// Example: Complete documentation setup workflow
const examples = {
basicSetup: {
description: "Basic documentation setup for a JavaScript project",
steps: [
{
tool: "analyzeRepository",
parameters: { repositoryPath: "./my-project" },
expectedResult: "Project analysis with language ecosystem detection",
},
{
tool: "recommendSSG",
parameters: { projectAnalysis: "${analysis_result}" },
expectedResult: "SSG recommendation with justification",
},
],
},
advancedSetup: {
description: "Advanced setup with custom requirements",
steps: [
// ... detailed workflow steps
],
},
};
Future Enhancements
Planned Tool Additions
analyzeExistingDocs
: Deep analysis of existing documentation quality and structuregenerateMigrationPlan
: Create migration plans between different documentation systemsoptimizeContent
: AI-powered content optimization and gap analysisvalidateAccessibility
: Comprehensive accessibility testing and recommendations
API Evolution Strategy
- Versioned tool schemas with backward compatibility
- Deprecation notices and migration guidance
- Feature flags for experimental functionality
- Community feedback integration for API improvements