comment_contract
Add cross-reference comments to validated producer/consumer pairs to document contract relationships in both source files.
Instructions
Add cross-reference comments to validated producer/consumer pairs. Documents the contract relationship in both files.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| producerDir | Yes | Path to MCP server source directory | |
| consumerDir | Yes | Path to consumer source directory | |
| toolName | Yes | Name of the validated tool | |
| dryRun | No | Preview comments without writing to files (default: true) | |
| style | No | Comment style |
Implementation Reference
- src/index.ts:478-551 (handler)Primary handler for the 'comment_contract' MCP tool. Parses input, extracts schemas from producer and consumer directories, validates the tool exists in both, prepares options, and dispatches to previewContractComments (dryRun) or addContractComments.case 'comment_contract': { const input = CommentContractInput.parse(args); log(`Commenting contract for tool: ${input.toolName}`); // Get both producer and consumer const producers = await extractProducerSchemas({ rootDir: input.producerDir }); const consumers = await traceConsumerUsage({ rootDir: input.consumerDir }); const producer = producers.find(p => p.toolName === input.toolName); const consumer = consumers.find(c => c.toolName === input.toolName); if (!producer) { throw new Error(`Tool "${input.toolName}" not found in producer at ${input.producerDir}`); } if (!consumer) { throw new Error(`Tool "${input.toolName}" not found in consumer at ${input.consumerDir}`); } const match = { toolName: input.toolName, producerLocation: producer.location, consumerLocation: consumer.callSite, }; const commentOptions = { match, producer, consumer, style: input.style || 'block' as const, includeTimestamp: true, }; if (input.dryRun !== false) { // Preview mode (default) const preview = previewContractComments(commentOptions); return { content: [ { type: 'text', text: JSON.stringify({ success: true, mode: 'preview', toolName: input.toolName, producerPreview: preview.producerPreview, consumerPreview: preview.consumerPreview, note: 'Set dryRun: false to actually add these comments to files', }, null, 2), }, ], }; } else { // Actually add comments const result = await addContractComments(commentOptions); return { content: [ { type: 'text', text: JSON.stringify({ success: result.success, mode: 'applied', toolName: input.toolName, producerFile: result.producerFile, consumerFile: result.consumerFile, producerComment: result.producerComment, consumerComment: result.consumerComment, error: result.error, }, null, 2), }, ], }; } }
- src/index.ts:87-93 (schema)Zod schema defining the input parameters for the comment_contract tool.const CommentContractInput = z.object({ producerDir: z.string().describe('Path to MCP server source directory'), consumerDir: z.string().describe('Path to consumer source directory'), toolName: z.string().describe('Name of the validated tool'), dryRun: z.boolean().optional().describe('Preview comments without writing to files (default: true)'), style: z.enum(['jsdoc', 'inline', 'block']).optional().describe('Comment style (default: block)'), });
- src/index.ts:221-235 (registration)Registration of the comment_contract tool in the ListToolsRequest handler, providing name, description, and input schema.{ name: 'comment_contract', description: 'Add cross-reference comments to validated producer/consumer pairs. Documents the contract relationship in both files.', inputSchema: { type: 'object', properties: { producerDir: { type: 'string', description: 'Path to MCP server source directory' }, consumerDir: { type: 'string', description: 'Path to consumer source directory' }, toolName: { type: 'string', description: 'Name of the validated tool' }, dryRun: { type: 'boolean', description: 'Preview comments without writing to files (default: true)' }, style: { type: 'string', enum: ['jsdoc', 'inline', 'block'], description: 'Comment style' }, }, required: ['producerDir', 'consumerDir', 'toolName'], }, },
- src/tools/contract-comments.ts:94-141 (handler)Core implementation for adding contract comments to source files using ts-morph. Loads files, inserts comments before relevant nodes (tool definition and callTool), and saves changes.export async function addContractComments(options: ContractCommentOptions): Promise<CommentResult> { const { match, producer, consumer } = options; const { producerComment, consumerComment } = generateContractComments(options); const project = new Project({ skipAddingFilesFromTsConfig: true, }); try { // Add comment to producer file const producerFile = project.addSourceFileAtPath(producer.location.file); const producerNode = findNodeAtLine(producerFile, producer.location.line); if (producerNode) { // Add comment before the tool definition producerNode.replaceWithText(`${producerComment}\n${producerNode.getText()}`); } // Add comment to consumer file const consumerFile = project.addSourceFileAtPath(consumer.callSite.file); const consumerNode = findNodeAtLine(consumerFile, consumer.callSite.line); if (consumerNode) { // Add comment before the callTool invocation consumerNode.replaceWithText(`${consumerComment}\n${consumerNode.getText()}`); } // Save changes await project.save(); return { success: true, producerFile: producer.location.file, consumerFile: consumer.callSite.file, producerComment, consumerComment, }; } catch (error) { return { success: false, producerFile: producer.location.file, consumerFile: consumer.callSite.file, producerComment, consumerComment, error: error instanceof Error ? error.message : String(error), }; } }
- src/tools/contract-comments.ts:37-71 (helper)Generates the actual comment strings for producer and consumer, formatting details like file locations, args/props used, and validation timestamp.export function generateContractComments(options: ContractCommentOptions): { producerComment: string; consumerComment: string; } { const { match, producer, consumer, style = 'block', includeTimestamp = true, prefix = '@trace-contract' } = options; const timestamp = includeTimestamp ? ` | Validated: ${new Date().toISOString().split('T')[0]}` : ''; // Producer comment points to consumer const producerComment = formatComment({ style, lines: [ `${prefix} PRODUCER`, `Tool: ${match.toolName}`, `Consumer: ${consumer.callSite.file}:${consumer.callSite.line}`, `Args: ${Object.keys(consumer.argumentsProvided).join(', ')}`, `Expected Props: ${consumer.expectedProperties.slice(0, 5).join(', ')}${consumer.expectedProperties.length > 5 ? '...' : ''}`, timestamp ? `Validated: ${timestamp}` : '', ].filter(Boolean), }); // Consumer comment points to producer const consumerComment = formatComment({ style, lines: [ `${prefix} CONSUMER`, `Tool: ${match.toolName}`, `Producer: ${producer.location.file}:${producer.location.line}`, `Required Args: ${producer.inputSchema.required?.join(', ') || 'none'}`, `Schema Props: ${Object.keys(producer.inputSchema.properties || {}).join(', ')}`, timestamp ? `Validated: ${timestamp}` : '', ].filter(Boolean), }); return { producerComment, consumerComment }; }