Skip to main content
Glama
mdz-axo

PT-MCP (Paul Test Man Context Protocol)

by mdz-axo
generate-context.ts10.7 kB
/** * generate_context tool implementation * * Generates context files in various formats with optional KG enrichment */ import { enrichContext, EnrichedContext } from './enrich-context.js'; import { analyzeCodebase } from './analyze-codebase.js'; import { writeFile, mkdir } from 'fs/promises'; import { join, dirname } from 'path'; import { existsSync } from 'fs'; interface GenerateContextArgs { path: string; format: 'cursorrules' | 'cursor_dir' | 'spec_md' | 'agents_md' | 'custom'; output_path?: string; analysis_result?: any; options?: Record<string, any>; } export async function generateContext( args: GenerateContextArgs ): Promise<{ content: Array<{ type: string; text: string }> }> { const { path, format, output_path, analysis_result, options = {} } = args; // Get or perform analysis let analysis = analysis_result; if (!analysis) { const analyzeResult = await analyzeCodebase({ path }); analysis = JSON.parse(analyzeResult.content[0].text); } // Enrich with knowledge graph if enabled (default: true) let enriched: EnrichedContext | null = null; if (options.enable_kg !== false) { enriched = await enrichContext({ path, analysis_result: analysis, enrichment_level: options.enrichment_level || 'standard', include_yago: options.include_yago !== false, include_schema: options.include_schema !== false, max_entities: options.max_entities || 10, }); } // Generate context based on format let content: string; let filename: string; switch (format) { case 'cursorrules': content = generateCursorRules(analysis, enriched); filename = '.cursorrules'; break; case 'cursor_dir': content = generateCursorDir(analysis, enriched); filename = '.cursor/context.md'; break; case 'spec_md': content = generateSpecMd(analysis, enriched); filename = 'SPEC.md'; break; case 'agents_md': content = generateAgentsMd(analysis, enriched); filename = 'AGENTS.md'; break; case 'custom': content = generateCustom(analysis, enriched, options); filename = options.filename || 'context.md'; break; default: throw new Error(`Unknown format: ${format}`); } // Write to file if output_path specified if (output_path) { const fullPath = join(output_path, filename); const dir = dirname(fullPath); if (!existsSync(dir)) { await mkdir(dir, { recursive: true }); } await writeFile(fullPath, content, 'utf-8'); } return { content: [ { type: 'text', text: JSON.stringify( { message: 'Context generated successfully', format, path, output_file: output_path ? join(output_path, filename) : null, content_preview: content.slice(0, 500) + '...', enriched: !!enriched, kg_stats: enriched?.confidence_stats, }, null, 2 ), }, ], }; } /** * Generate .cursorrules format */ function generateCursorRules(analysis: any, enriched: EnrichedContext | null): string { const lines: string[] = []; lines.push('# Project Rules for AI Assistants'); lines.push(''); // Project info if (analysis.package?.name) { lines.push(`## Project: ${analysis.package.name}`); if (analysis.package.description) { lines.push(analysis.package.description); } lines.push(''); } // Schema.org annotation if (enriched?.schema_annotation) { lines.push('## Semantic Type'); lines.push(`This is a **${enriched.schema_annotation['@type']}**`); if (enriched.schema_annotation.description) { lines.push(enriched.schema_annotation.description); } lines.push(''); } // Tech stack lines.push('## Tech Stack'); if (analysis.languages) { lines.push('**Languages:**', Object.keys(analysis.languages).join(', ')); } if (analysis.frameworks && analysis.frameworks.length > 0) { lines.push('**Frameworks:**', analysis.frameworks.join(', ')); } lines.push(''); // Knowledge graph enrichment if (enriched?.yago_entities && Object.keys(enriched.yago_entities).length > 0) { lines.push('## Knowledge Graph Context'); for (const [name, entities] of Object.entries(enriched.yago_entities)) { if (entities.length > 0) { const entity = entities[0]; lines.push(`- **${name}**: ${entity.description || entity.label}`); } } lines.push(''); } // Coding conventions lines.push('## Coding Conventions'); lines.push('- Follow existing patterns in the codebase'); lines.push('- Use TypeScript strict mode'); lines.push('- Write clear, self-documenting code'); lines.push('- Add JSDoc comments for public APIs'); lines.push(''); return lines.join('\n'); } /** * Generate .cursor/context.md format */ function generateCursorDir(analysis: any, enriched: EnrichedContext | null): string { const lines: string[] = []; lines.push('# Codebase Context'); lines.push(''); // Overview lines.push('## Overview'); if (analysis.package?.description) { lines.push(analysis.package.description); } lines.push(''); // JSON-LD structured data if (enriched?.json_ld) { lines.push('## Structured Data'); lines.push('```json'); lines.push(JSON.stringify(enriched.json_ld, null, 2)); lines.push('```'); lines.push(''); } // Architecture lines.push('## Architecture'); if (analysis.structure) { lines.push('```'); lines.push(JSON.stringify(analysis.structure, null, 2)); lines.push('```'); } lines.push(''); // Dependencies with KG context if (analysis.package?.dependencies) { lines.push('## Dependencies'); for (const [dep, version] of Object.entries(analysis.package.dependencies)) { lines.push(`- **${dep}@${version}**`); // Add KG context if available if (enriched?.yago_entities?.[dep]) { const entity = enriched.yago_entities[dep][0]; if (entity.description) { lines.push(` - ${entity.description}`); } } } lines.push(''); } return lines.join('\n'); } /** * Generate SPEC.md format */ function generateSpecMd(analysis: any, enriched: EnrichedContext | null): string { const lines: string[] = []; lines.push('# Specification'); lines.push(''); // Semantic annotation if (enriched?.schema_annotation) { lines.push('## Type'); lines.push(`**${enriched.schema_annotation['@type']}**`); lines.push(''); } // Purpose lines.push('## Purpose'); lines.push(analysis.package?.description || 'No description available'); lines.push(''); // Technical specifications lines.push('## Technical Specifications'); lines.push(''); if (enriched?.schema_annotation) { if (enriched.schema_annotation.programmingLanguage) { lines.push('**Programming Languages:**'); const langs = Array.isArray(enriched.schema_annotation.programmingLanguage) ? enriched.schema_annotation.programmingLanguage : [enriched.schema_annotation.programmingLanguage]; lines.push(langs.map((l: string) => `- ${l}`).join('\n')); lines.push(''); } if (enriched.schema_annotation.softwareRequirements) { lines.push('**Software Requirements:**'); lines.push( enriched.schema_annotation.softwareRequirements .slice(0, 10) .map((r: string) => `- ${r}`) .join('\n') ); lines.push(''); } } // API surface if (analysis.exports && analysis.exports.length > 0) { lines.push('## Public API'); for (const exp of analysis.exports.slice(0, 20)) { lines.push(`- \`${exp}\``); } lines.push(''); } return lines.join('\n'); } /** * Generate AGENTS.md format (for multi-agent systems) */ function generateAgentsMd(analysis: any, enriched: EnrichedContext | null): string { const lines: string[] = []; lines.push('# Agent Context'); lines.push(''); lines.push('This document provides context for AI agents working on this codebase.'); lines.push(''); // Semantic context if (enriched?.schema_annotation) { lines.push('## Semantic Context'); lines.push(`**Type:** ${enriched.schema_annotation['@type']}`); if (enriched.schema_annotation.name) { lines.push(`**Name:** ${enriched.schema_annotation.name}`); } if (enriched.schema_annotation.softwareVersion) { lines.push(`**Version:** ${enriched.schema_annotation.softwareVersion}`); } lines.push(''); } // Knowledge graph entities if (enriched?.yago_entities && Object.keys(enriched.yago_entities).length > 0) { lines.push('## Knowledge Graph Entities'); lines.push(''); lines.push('The following entities have been linked to world knowledge:'); lines.push(''); for (const [name, entities] of Object.entries(enriched.yago_entities)) { if (entities.length > 0) { const entity = entities[0]; lines.push(`### ${name}`); lines.push(`- **Type:** ${entity.type}`); lines.push(`- **Confidence:** ${(entity.confidence * 100).toFixed(0)}%`); if (entity.description) { lines.push(`- **Description:** ${entity.description}`); } if (entity.facts.length > 0) { lines.push(`- **Known Facts:** ${entity.facts.length}`); for (const fact of entity.facts.slice(0, 3)) { lines.push(` - ${fact.predicate}: ${fact.objectLabel || fact.object}`); } } lines.push(''); } } } // Codebase structure lines.push('## Codebase Structure'); if (analysis.structure) { lines.push('```json'); lines.push(JSON.stringify(analysis.structure, null, 2)); lines.push('```'); } lines.push(''); return lines.join('\n'); } /** * Generate custom format based on options */ function generateCustom( analysis: any, enriched: EnrichedContext | null, options: Record<string, any> ): string { const template = options.template || 'default'; if (template === 'json') { return JSON.stringify( { analysis, enriched, }, null, 2 ); } // Default custom format return `# Custom Context\n\n${JSON.stringify({ analysis, enriched }, null, 2)}`; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mdz-axo/pt-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server