contentrain_status
Check project configuration, models, and context to monitor content structure and governance status in Contentrain MCP.
Instructions
Get full project status (read-only). Returns config, models, context. Do NOT manually edit .contentrain/ based on this output.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- packages/mcp/src/tools/context.ts:18-98 (handler)The handler function for 'contentrain_status' tool. Reads config, models, and context files, performs git branch cleanup/health checks, and returns project status.
async () => { const crDir = contentrainDir(projectRoot) const initialized = await pathExists(join(crDir, 'config.json')) if (!initialized) { const detectedStack = await detectStack(projectRoot) return { content: [{ type: 'text' as const, text: JSON.stringify({ initialized: false, detected_stack: detectedStack, suggestion: 'Run contentrain_init to set up .contentrain/ structure', next_steps: ['Run contentrain_init'], }, null, 2), }], } } const config = await readConfig(projectRoot) const models = await listModels(projectRoot) const context = await readContext(projectRoot) const vocabulary = await readVocabulary(projectRoot) const errors: string[] = [] if (!config) errors.push('.contentrain/config.json missing') const result: Record<string, unknown> = { initialized: true, config: config ? { stack: config.stack, workflow: config.workflow, locales: config.locales, domains: config.domains, repository: config.repository, } : null, models, context: context ? { lastOperation: context.lastOperation, stats: context.stats, } : null, vocabulary_size: vocabulary ? Object.keys(vocabulary.terms).length : 0, } // Branch lifecycle: lazy cleanup + health check (run BEFORE validation summary) const hasGitRepo = await pathExists(join(projectRoot, '.git')) if (hasGitRepo) { try { const cleanup = await cleanupMergedBranches(projectRoot) const health = await checkBranchHealth(projectRoot) result['branches'] = { total: health.total, merged: health.merged, unmerged: health.unmerged, cleaned_up: cleanup.deleted, } if (health.message) { result['branch_warning'] = health.message } if (health.blocked) { errors.push(health.message!) } } catch { // Branch health check is best-effort — don't fail status } } if (errors.length > 0) { result['validation'] = { errors: errors.length, warnings: 0, summary: errors } } const nextSteps: string[] = [] if (models.length === 0) nextSteps.push('Create models with contentrain_model_save') if (errors.length > 0) nextSteps.push(`Fix ${errors.length} validation error(s)`) if (nextSteps.length === 0) nextSteps.push('Use contentrain_describe to inspect a model') result['next_steps'] = nextSteps return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], } }, - packages/mcp/src/tools/context.ts:14-99 (registration)Registration of the 'contentrain_status' tool in the McpServer using server.tool().
server.tool( 'contentrain_status', 'Get full project status (read-only). Returns config, models, context. Do NOT manually edit .contentrain/ based on this output.', {}, async () => { const crDir = contentrainDir(projectRoot) const initialized = await pathExists(join(crDir, 'config.json')) if (!initialized) { const detectedStack = await detectStack(projectRoot) return { content: [{ type: 'text' as const, text: JSON.stringify({ initialized: false, detected_stack: detectedStack, suggestion: 'Run contentrain_init to set up .contentrain/ structure', next_steps: ['Run contentrain_init'], }, null, 2), }], } } const config = await readConfig(projectRoot) const models = await listModels(projectRoot) const context = await readContext(projectRoot) const vocabulary = await readVocabulary(projectRoot) const errors: string[] = [] if (!config) errors.push('.contentrain/config.json missing') const result: Record<string, unknown> = { initialized: true, config: config ? { stack: config.stack, workflow: config.workflow, locales: config.locales, domains: config.domains, repository: config.repository, } : null, models, context: context ? { lastOperation: context.lastOperation, stats: context.stats, } : null, vocabulary_size: vocabulary ? Object.keys(vocabulary.terms).length : 0, } // Branch lifecycle: lazy cleanup + health check (run BEFORE validation summary) const hasGitRepo = await pathExists(join(projectRoot, '.git')) if (hasGitRepo) { try { const cleanup = await cleanupMergedBranches(projectRoot) const health = await checkBranchHealth(projectRoot) result['branches'] = { total: health.total, merged: health.merged, unmerged: health.unmerged, cleaned_up: cleanup.deleted, } if (health.message) { result['branch_warning'] = health.message } if (health.blocked) { errors.push(health.message!) } } catch { // Branch health check is best-effort — don't fail status } } if (errors.length > 0) { result['validation'] = { errors: errors.length, warnings: 0, summary: errors } } const nextSteps: string[] = [] if (models.length === 0) nextSteps.push('Create models with contentrain_model_save') if (errors.length > 0) nextSteps.push(`Fix ${errors.length} validation error(s)`) if (nextSteps.length === 0) nextSteps.push('Use contentrain_describe to inspect a model') result['next_steps'] = nextSteps return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], } }, )