|
| 1 | +--- |
| 2 | +status: planned |
| 3 | +created: 2025-12-21 |
| 4 | +priority: medium |
| 5 | +tags: |
| 6 | +- mcp |
| 7 | +- dx |
| 8 | +- ai-agents |
| 9 | +- templates |
| 10 | +- documentation |
| 11 | +created_at: 2025-12-21T14:53:17.954876Z |
| 12 | +updated_at: 2025-12-21T14:53:17.954876Z |
| 13 | +--- |
| 14 | + |
| 15 | +# Embed Spec Template in MCP Create Tool Content Field Description |
| 16 | + |
| 17 | +> **Status**: planned · **Priority**: medium · **Created**: {date} |
| 18 | +
|
| 19 | +## Problem & Motivation |
| 20 | + |
| 21 | +The MCP `create` tool's `content` field has a minimal static description: "Full markdown content to use instead of template". |
| 22 | + |
| 23 | +**The core issue**: The actual template file (`.lean-spec/templates/spec-template.md`) exists on disk but is NOT exposed to AI agents through the MCP tool schema. AI agents have no way to see what the template looks like, so they don't know: |
| 24 | + |
| 25 | +1. **What structure** the body content should follow |
| 26 | +2. **What sections** are expected (Overview, Design, Plan, Test, Notes) |
| 27 | +3. **What format** these sections use (comments, task lists, etc.) |
| 28 | +4. **What the body looks like** without frontmatter/title (since those are auto-generated) |
| 29 | + |
| 30 | +This leads to: |
| 31 | +- AI agents guessing at spec structure |
| 32 | +- Inconsistent formatting across specs |
| 33 | +- Missing critical sections |
| 34 | +- Specs that don't follow LeanSpec conventions |
| 35 | +- Need for manual corrections and iterations |
| 36 | + |
| 37 | +**Solution**: Make the MCP server **load the template at runtime** and **embed it into the `content` field description** so AI agents can see exactly what a spec body should look like. |
| 38 | + |
| 39 | +## High-Level Approach |
| 40 | + |
| 41 | +**Load template dynamically** and embed it into the MCP tool schema description. |
| 42 | + |
| 43 | +### How It Should Work |
| 44 | + |
| 45 | +1. **At MCP server startup**: |
| 46 | + - Load `.lean-spec/templates/spec-template.md` |
| 47 | + - Extract the **body content only** (everything after frontmatter and title) |
| 48 | + - Format it for inclusion in schema description |
| 49 | + |
| 50 | +2. **In the tool schema**: |
| 51 | + - Prepend explanatory text about what `content` expects |
| 52 | + - Include the actual template body (formatted/escaped for JSON) |
| 53 | + - Make it clear that frontmatter/title are auto-generated |
| 54 | + |
| 55 | +3. **Result**: AI agents see exactly what a spec body should look like |
| 56 | + |
| 57 | +### Implementation Strategy |
| 58 | + |
| 59 | +The MCP server should: |
| 60 | +- Use existing `TemplateLoader` to load the template |
| 61 | +- Strip frontmatter and title (`# {name}`) from template |
| 62 | +- Keep only the body sections (## Overview, ## Design, etc.) |
| 63 | +- Embed the body into the `content` field description |
| 64 | +- Handle template loading errors gracefully (fallback to basic description) |
| 65 | + |
| 66 | +### Example Result |
| 67 | + |
| 68 | +After implementation, the schema would look like: |
| 69 | +```rust |
| 70 | +"content": { |
| 71 | + "type": "string", |
| 72 | + "description": "Body content only (markdown sections). DO NOT include frontmatter or title - these are auto-generated from other parameters (name, title, status, priority, tags). |
| 73 | +
|
| 74 | +TEMPLATE STRUCTURE (body sections only): |
| 75 | +
|
| 76 | +## Overview |
| 77 | +
|
| 78 | +<!-- What are we solving? Why now? --> |
| 79 | +
|
| 80 | +## Design |
| 81 | +
|
| 82 | +<!-- Technical approach, architecture decisions --> |
| 83 | +
|
| 84 | +## Plan |
| 85 | +
|
| 86 | +<!-- Break down implementation into steps --> |
| 87 | +
|
| 88 | +- [ ] Task 1 |
| 89 | +- [ ] Task 2 |
| 90 | +- [ ] Task 3 |
| 91 | +
|
| 92 | +## Test |
| 93 | +
|
| 94 | +<!-- How will we verify this works? --> |
| 95 | +
|
| 96 | +- [ ] Test criteria 1 |
| 97 | +- [ ] Test criteria 2 |
| 98 | +
|
| 99 | +## Notes |
| 100 | +
|
| 101 | +<!-- Optional: Research findings, alternatives considered, open questions --> |
| 102 | +
|
| 103 | +Keep specs <2000 tokens optimal, <3500 max. Consider sub-specs (IMPLEMENTATION.md) if >400 lines." |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +### Design Considerations |
| 108 | + |
| 109 | +**Option 1: Load Full Template, Strip Frontmatter/Title** |
| 110 | +- Load template using `TemplateLoader` |
| 111 | +- Parse and remove YAML frontmatter |
| 112 | +- Remove title line (`# {name}`) |
| 113 | +- Embed remaining body in description |
| 114 | + |
| 115 | +**Pros**: Shows exact template structure, always in sync |
| 116 | +**Cons**: Description can be long (~500 chars + template body) |
| 117 | + |
| 118 | +**Option 2: Load Template, Summarize Structure** |
| 119 | +- Load template |
| 120 | +- Extract section headings only (## Overview, ## Design, etc.) |
| 121 | +- Provide condensed structure |
| 122 | + |
| 123 | +**Pros**: Shorter description |
| 124 | +**Cons**: Loses valuable details (comments, task list format, tips) |
| 125 | + |
| 126 | +**Option 3: Static Description (Current)** |
| 127 | +- Manually write description |
| 128 | +- No template loading |
| 129 | + |
| 130 | +**Pros**: Short, controlled |
| 131 | +**Cons**: Out of sync with template, lacks real examples |
| 132 | + |
| 133 | +### Recommendation |
| 134 | + |
| 135 | +**Option 1** - Load full template body and embed it. Reasons: |
| 136 | +- AI agents see **exact** template structure |
| 137 | +- **Always synchronized** with actual template file |
| 138 | +- Shows **real examples** of comments, task lists, etc. |
| 139 | +- Template is already concise (~25 lines body), acceptable for schema |
| 140 | +- LLMs handle long descriptions well |
| 141 | +- Worth the length for accuracy |
| 142 | + |
| 143 | +## Recommendation |
| 144 | + |
| 145 | +**Option 1** - Dynamically load and embed the full template body. |
| 146 | + |
| 147 | +**Why**: |
| 148 | +- Shows **exact** template to AI agents (no guessing) |
| 149 | +- **Always synchronized** (template changes auto-reflect) |
| 150 | +- **Real examples** of formatting (comments, task lists, tips) |
| 151 | +- Template body is ~25 lines (acceptable length) |
| 152 | +- LLMs handle long descriptions well |
| 153 | +- Worth the trade-off for accuracy and zero-maintenance |
| 154 | + |
| 155 | +**Critical**: Strip frontmatter AND title heading before embedding, since those are auto-generated by the tool. |
| 156 | + |
| 157 | +## Key Decisions |
| 158 | + |
| 159 | +1. **Dynamic loading**: Load template at MCP server startup, not hardcoded |
| 160 | +2. **Template processing**: Strip frontmatter (YAML) and title line (`# {name}`), keep body only |
| 161 | +3. **Fallback handling**: If template load fails, use minimal static description |
| 162 | +4. **Cache strategy**: Load once at startup, don't reload on every tool schema request |
| 163 | +5. **Description format**: Prepend explanatory text, then embed processed template body |
| 164 | + |
| 165 | +## Acceptance Criteria |
| 166 | + |
| 167 | +- [ ] MCP server loads `.lean-spec/templates/spec-template.md` at startup |
| 168 | +- [ ] Template loading uses existing `TemplateLoader` infrastructure |
| 169 | +- [ ] Frontmatter (YAML block) is stripped from loaded template |
| 170 | +- [ ] Title line (`# {name}` or similar) is stripped from loaded template |
| 171 | +- [ ] Template body is embedded into `content` field description |
| 172 | +- [ ] Description prepends explanatory text about body-only content |
| 173 | +- [ ] If template load fails, falls back to minimal static description |
| 174 | +- [ ] Tool schema reflects actual template (test by viewing schema) |
| 175 | +- [ ] AI agents can see template structure in MCP tool descriptions |
| 176 | +- [ ] Changes to template file automatically reflect in tool schema after MCP restart |
| 177 | + |
| 178 | +## Out of Scope |
| 179 | + |
| 180 | +- Changing the template structure itself (separate spec) |
| 181 | +- Adding validation for content structure (could be follow-up) |
| 182 | +- Creating additional MCP tools for template queries |
| 183 | +- Modifying other MCP tool descriptions (unless similar issues exist) |
| 184 | + |
| 185 | +## Dependencies |
| 186 | + |
| 187 | +- Built on spec 074-content-at-creation (complete) |
| 188 | +- Relies on current spec template structure (spec-template.md) |
| 189 | +- Related to spec 073-template-engine-agents-md (template system) |
| 190 | + |
| 191 | +## Implementation Notes |
| 192 | + |
| 193 | +**Files to modify**: |
| 194 | +- `rust/leanspec-mcp/src/tools.rs` - Tool definitions and schema generation |
| 195 | + |
| 196 | +**Approach**: |
| 197 | + |
| 198 | +1. **Add template loading function**: |
| 199 | + ```rust |
| 200 | + fn load_template_body_for_description() -> String { |
| 201 | + // Load template using TemplateLoader |
| 202 | + // Strip frontmatter (YAML between --- delimiters) |
| 203 | + // Strip title line (first # heading) |
| 204 | + // Return body only with explanatory header |
| 205 | + } |
| 206 | + ``` |
| 207 | + |
| 208 | +2. **Modify tool definition** (lines 85-87): |
| 209 | + ```rust |
| 210 | + "content": { |
| 211 | + "type": "string", |
| 212 | + "description": load_template_body_for_description() // Dynamic! |
| 213 | + }, |
| 214 | + ``` |
| 215 | + |
| 216 | +3. **Error handling**: |
| 217 | + - If template load fails, use fallback static description |
| 218 | + - Log warning but don't crash MCP server |
| 219 | + |
| 220 | +**Implementation details**: |
| 221 | +- Use existing `TemplateLoader` infrastructure |
| 222 | +- Strip YAML frontmatter (everything between `---` markers) |
| 223 | +- Strip title heading (`# {name}` line and following status line) |
| 224 | +- Keep body sections (## Overview, ## Design, etc.) |
| 225 | +- Prepend: "Body content only (markdown sections). DO NOT include frontmatter or title.\n\nTEMPLATE:" |
| 226 | +- Append: "\n\nKeep <2000 tokens optimal." |
| 227 | + |
| 228 | +**Testing**: |
| 229 | +- Verify template loads at MCP startup |
| 230 | +- Check tool schema includes template body (MCP inspector/logs) |
| 231 | +- Test AI agent can create spec using description alone |
| 232 | +- Verify fallback works if template missing |
| 233 | +- Confirm template changes reflect after restart |
| 234 | + |
| 235 | +## Open Questions |
| 236 | + |
| 237 | +1. Should we cache the loaded template or reload on every schema request? |
| 238 | + - **Recommendation**: Cache at startup, reload only on server restart |
| 239 | +2. How to handle custom templates (if users override spec-template.md)? |
| 240 | + - **Recommendation**: Load default template, document that custom templates won't reflect in schema |
| 241 | +3. Should we add line number limits to prevent extremely long descriptions? |
| 242 | + - **Recommendation**: No artificial limits, templates should be reasonable (~25 lines body) |
| 243 | +4. Should CLI `--content` help text also reference the template? |
| 244 | + - **Recommendation**: Yes, add similar guidance in CLI help text (separate task) |
| 245 | + |
| 246 | +## Notes |
| 247 | + |
| 248 | +### Why Dynamic Loading |
| 249 | + |
| 250 | +**Benefits**: |
| 251 | +1. **Zero maintenance** - Template changes automatically reflect in tool schema |
| 252 | +2. **Accuracy** - AI agents see EXACTLY what the template looks like |
| 253 | +3. **Consistency** - No risk of manual description drift from actual template |
| 254 | +4. **Examples included** - Comments, task list format, tips all visible to AI |
| 255 | + |
| 256 | +**Trade-offs**: |
| 257 | +- Longer description (but LLMs handle this fine) |
| 258 | +- Requires template load at startup (negligible performance cost) |
| 259 | +- Template errors could affect MCP server (mitigated by fallback) |
| 260 | + |
| 261 | +### Template Processing Logic |
| 262 | + |
| 263 | +The loaded template looks like: |
| 264 | +```markdown |
| 265 | +--- |
| 266 | +status: planned |
| 267 | +created: '{date}' |
| 268 | +... |
| 269 | +--- |
| 270 | + |
| 271 | +# {name} |
| 272 | + |
| 273 | +> **Status**: {status} · **Priority**: {priority} |
| 274 | + |
| 275 | +## Overview |
| 276 | + |
| 277 | +<!-- What are we solving? Why now? --> |
| 278 | +... |
| 279 | +``` |
| 280 | + |
| 281 | +We need to **extract only**: |
| 282 | +```markdown |
| 283 | +## Overview |
| 284 | + |
| 285 | +<!-- What are we solving? Why now? --> |
| 286 | + |
| 287 | +## Design |
| 288 | +... |
| 289 | +``` |
| 290 | + |
| 291 | +**Algorithm**: |
| 292 | +1. Skip YAML frontmatter (lines between `---`) |
| 293 | +2. Skip title heading (`# {name}`) |
| 294 | +3. Skip status line (`> **Status**:`) |
| 295 | +4. Keep everything from first `##` onward |
| 296 | + |
| 297 | +### Future Enhancement: Multiple Templates |
| 298 | + |
| 299 | +If LeanSpec adds multiple templates (standard, detailed, minimal), we could: |
| 300 | +- Load all templates at startup |
| 301 | +- Show merged/combined structure in description |
| 302 | +- Or dynamically show template based on `template` parameter |
| 303 | + |
| 304 | +For now, **YAGNI** - just load the default `spec-template.md`. |
0 commit comments