foundry_mcp/cli/
args.rs

1//! CLI argument structures
2
3use crate::impl_mcp_tool;
4use clap::Args;
5
6/// Arguments for create_project command
7#[derive(Args, Debug)]
8pub struct CreateProjectArgs {
9    /// Project name in kebab-case (e.g., my-awesome-project)
10    ///
11    /// Must contain only lowercase letters, numbers, and hyphens
12    /// Cannot contain spaces, underscores, or special characters
13    pub project_name: String,
14
15    /// High-level product vision content (2-4 paragraphs, 200+ characters)
16    ///
17    /// **Content Structure:**
18    /// - Problem statement and market need
19    /// - Target users and their pain points
20    /// - Unique value proposition and competitive advantages
21    /// - Key features and roadmap priorities
22    ///
23    /// **Markdown Formatting Guidelines:**
24    /// - Use ## headers for main sections (## Problem, ## Target Users, ## Value Proposition)
25    /// - Structure with bullet points and clear paragraphs
26    /// - Include specific examples and use cases
27    /// - Write in present tense, professional tone
28    /// - End with clear success metrics or goals
29    ///
30    /// Goes into vision.md
31    #[arg(long, required = true)]
32    pub vision: String,
33
34    /// Technology stack and architecture decisions (150+ characters)
35    ///
36    /// **Content Structure:**
37    /// - Core languages and frameworks with versions
38    /// - Databases, storage, and data architecture
39    /// - Deployment platforms and infrastructure
40    /// - Development tools and build systems
41    /// - Rationale for each major technology choice
42    ///
43    /// **Markdown Formatting Guidelines:**
44    /// - Use ## headers for categories (## Backend, ## Frontend, ## Database, ## Deployment)
45    /// - List technologies with bullet points and brief rationale
46    /// - Include version constraints where relevant
47    /// - Add ### subsections for complex areas
48    /// - Include links to documentation where helpful
49    ///
50    /// Goes into tech-stack.md
51    #[arg(long, required = true)]
52    pub tech_stack: String,
53
54    /// Concise summary of vision and tech stack (100+ characters)
55    ///
56    /// **Content Guidelines:**
57    /// - 2-3 sentences capturing project essence
58    /// - Combine key points from vision and tech stack
59    /// - Focus on what makes this project unique
60    /// - Written for quick LLM context loading
61    ///
62    /// **Format:**
63    /// - Clear, professional language
64    /// - Present tense, active voice
65    /// - Include primary technology and main value proposition
66    /// - No markdown formatting needed (plain text)
67    ///
68    /// Goes into summary.md
69    #[arg(long, required = true)]
70    pub summary: String,
71}
72
73// Generate MCP tool implementation for CreateProjectArgs
74impl_mcp_tool! {
75    name = "create_project",
76    description = "Create new project structure with LLM-provided content. Creates ~/.foundry/PROJECT_NAME/ with vision.md, tech-stack.md, and summary.md",
77    struct CreateProjectArgs {
78        project_name: String {
79            description = "Descriptive project name using kebab-case (e.g., 'my-awesome-app')"
80        },
81        vision: String {
82            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: High-level product vision (2-4 paragraphs, 200+ chars) that will serve as the COMPLETE implementation context for future LLMs who have NO prior knowledge of this project. Must include comprehensive problem definition, target users, unique value proposition, and key roadmap priorities. This document will be loaded as the PRIMARY reference for all future development work. Apply 'Cold Start Test': Could a skilled developer understand the project purpose using only this document? Use markdown with ## headers, bullet points, and clear structure. Include specific examples and architectural context. Goes into vision.md",
83            min_length = 200
84        },
85        tech_stack: String {
86            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: Comprehensive technology decisions (150+ chars) that will serve as the COMPLETE technical architecture guide for future LLMs with NO prior project knowledge. Must include languages, frameworks, databases, deployment platforms, and detailed rationale for each choice. This document will be the PRIMARY reference for all technical implementation decisions. Include integration patterns, dependencies, constraints, team standards, and architectural context. Future implementers must understand the complete technical landscape from this document alone. Use markdown with ## headers for categories, bullet points for technologies, and comprehensive explanations. Goes into tech-stack.md",
87            min_length = 150
88        },
89        summary: String {
90            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: Concise summary (100+ chars) of vision and tech-stack for quick context loading by future LLMs. This will be the FIRST document loaded to provide immediate project understanding for implementers with NO prior knowledge. Should capture essential project essence, main value proposition, and primary technology in 2-3 sentences using clear, professional language. Must enable rapid context acquisition for future development sessions. Goes into summary.md",
91            min_length = 100
92        }
93    }
94}
95
96/// Arguments for analyze_project command
97#[derive(Args, Debug)]
98pub struct AnalyzeProjectArgs {
99    /// Project name to create with your analyzed content
100    ///
101    /// Must be in kebab-case format (lowercase letters, numbers, hyphens only)
102    /// Cannot contain spaces, underscores, or special characters
103    pub project_name: String,
104
105    /// High-level product vision content (2-4 paragraphs, 200+ characters) based on your codebase analysis
106    ///
107    /// **Analysis Approach:**
108    /// - Use Search, Grep, and Read tools to explore the codebase first
109    /// - Examine package.json, README files, main entry points, API routes
110    /// - Look for user-facing features, business logic, and data models
111    /// - Review existing documentation and configuration files
112    ///
113    /// **Content Structure & Markdown:**
114    /// - Use ## headers (## Problem Analysis, ## Target Users, ## Product Goals)
115    /// - Base vision on actual code functionality discovered
116    /// - Include specific examples from the codebase
117    /// - Structure with bullet points and clear paragraphs
118    /// - Write in present tense, referencing actual implementation
119    ///
120    /// Goes into vision.md
121    #[arg(long, required = true)]
122    pub vision: String,
123
124    /// Technology stack and architecture decisions (150+ characters) based on your codebase exploration
125    ///
126    /// **Detection Strategy:**
127    /// - Analyze package.json, requirements.txt, Cargo.toml, etc. for dependencies
128    /// - Check build scripts, Docker files, and deployment configurations
129    /// - Examine database connections, API integrations, and external services
130    /// - Review folder structure and architectural patterns used
131    ///
132    /// **Content Structure & Markdown:**
133    /// - Use ## headers (## Languages, ## Frameworks, ## Database, ## Deployment, ## Build Tools)
134    /// - List detected technologies with versions where found
135    /// - Include rationale based on code patterns observed
136    /// - Add ### subsections for complex architectural decisions
137    /// - Reference specific files or configurations discovered
138    ///
139    /// Goes into tech-stack.md
140    #[arg(long, required = true)]
141    pub tech_stack: String,
142
143    /// Concise summary (100+ characters) combining vision and tech stack from your analysis
144    ///
145    /// Should capture key insights from your codebase exploration for quick context loading
146    /// Use this to understand the project essence before diving into implementation
147    /// Goes into summary.md
148    #[arg(long, required = true)]
149    pub summary: String,
150}
151
152// Generate MCP tool implementation for AnalyzeProjectArgs
153impl_mcp_tool! {
154    name = "analyze_project",
155    description = "Create project structure by analyzing existing codebase. You analyze codebase and provide vision, tech-stack, and summary content as arguments.",
156    struct AnalyzeProjectArgs {
157        project_name: String {
158            description = "Descriptive project name using kebab-case (e.g., 'my-analyzed-project')"
159        },
160        vision: String {
161            description = "Your analyzed product vision (200+ chars) based on codebase examination. Use Search/Grep/Read tools first. Structure with ## headers, bullet points, and specific examples from code. Cover problem solved, target users, and value proposition derived from actual functionality. Goes into vision.md",
162            min_length = 200
163        },
164        tech_stack: String {
165            description = "Your detected technology stack (150+ chars) based on codebase analysis. Examine package files, configs, and code patterns. Structure with ## headers for categories, list technologies with versions, include rationale from observed patterns. Reference specific files discovered. Goes into tech-stack.md",
166            min_length = 150
167        },
168        summary: String {
169            description = "Your created concise summary (100+ chars) of analyzed project combining vision and tech-stack insights for quick context loading. Goes into summary.md",
170            min_length = 100
171        }
172    }
173}
174
175/// Arguments for create_spec command
176#[derive(Args, Debug)]
177pub struct CreateSpecArgs {
178    /// Project name to create spec for
179    ///
180    /// Must be an existing project in ~/.foundry/
181    /// Use 'foundry list-projects' to see available projects
182    pub project_name: String,
183
184    /// Feature name in snake_case (e.g., user_authentication)
185    ///
186    /// Used to create timestamped directory: YYYYMMDD_HHMMSS_feature_name
187    /// Should be descriptive and use underscores, not spaces or hyphens
188    pub feature_name: String,
189
190    /// Detailed specification content
191    ///
192    /// **Required Sections:**
193    /// - Feature overview and purpose
194    /// - Functional requirements and acceptance criteria
195    /// - Technical implementation approach
196    /// - Testing strategy and edge cases
197    /// - Dependencies and constraints
198    ///
199    /// **Markdown Structure:**
200    /// - Use # Feature Name as main header
201    /// - Use ## for major sections (## Overview, ## Requirements, ## Implementation)
202    /// - Use ### for subsections (### API Design, ### Database Changes)
203    /// - Include code blocks with ```language for examples
204    /// - Use bullet points and numbered lists for clarity
205    /// - Add tables for complex requirements or APIs
206    ///
207    /// Goes into spec.md
208    #[arg(long, required = true)]
209    pub spec: String,
210
211    /// Implementation notes and considerations
212    ///
213    /// **Content Focus:**
214    /// - Design decisions and rationale
215    /// - Technical tradeoffs and alternatives considered
216    /// - Dependencies on other features or systems
217    /// - Implementation constraints and limitations
218    /// - Future enhancement opportunities
219    ///
220    /// **Markdown Structure:**
221    /// - Use ## headers for categories (## Design Decisions, ## Dependencies, ## Constraints)
222    /// - Use bullet points for lists of considerations
223    /// - Include code snippets for technical details
224    /// - Reference external documentation with links
225    /// - Keep it conversational but technical
226    ///
227    /// Goes into notes.md
228    #[arg(long, required = true)]
229    pub notes: String,
230
231    /// Task list content
232    ///
233    /// **Task Organization:**
234    /// - Break feature into actionable, testable tasks
235    /// - Group related tasks under logical phases or components
236    /// - Include both implementation and validation tasks
237    /// - Consider setup, development, testing, and deployment phases
238    ///
239    /// **Markdown Checklist Format:**
240    /// - Use ## headers for phases (## Phase 1: Setup, ## Phase 2: Core Implementation)
241    /// - Use `- [ ] Task description` for uncompleted tasks
242    /// - Use `- [x] Task description` for completed tasks
243    /// - Include estimated effort or complexity where helpful
244    /// - Add sub-tasks with indented checkboxes when needed
245    /// - Keep tasks specific and measurable
246    ///
247    /// Goes into task-list.md
248    #[arg(long, required = true)]
249    pub tasks: String,
250}
251
252// Generate MCP tool implementation for CreateSpecArgs
253impl_mcp_tool! {
254    name = "create_spec",
255    description = "Create timestamped specification for a feature. Creates YYYYMMDD_HHMMSS_FEATURE_NAME directory with spec.md, task-list.md, and notes.md. You provide complete specification content as arguments.",
256    struct CreateSpecArgs {
257        project_name: String {
258            description = "Name of the existing project to create spec for"
259        },
260        feature_name: String {
261            description = "Descriptive feature name using snake_case (e.g., 'user_authentication')"
262        },
263        spec: String {
264            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: Detailed feature specification (200+ chars) that will serve as the COMPLETE implementation guide for future LLMs who have NO prior knowledge of this feature. Must include comprehensive requirements, architectural context, implementation approach with component interactions, dependencies, edge cases, and everything needed for successful implementation. This document will be the PRIMARY reference for feature development. Apply 'Cold Start Test': Could a skilled developer implement this feature using only this document? Use # for feature name, ## for major sections (Overview, Requirements, Implementation, Testing). Include code blocks, bullet points, tables, and detailed technical context. Goes into spec.md",
265            min_length = 200
266        },
267        notes: String {
268            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: Additional context and design decisions (50+ chars) that will provide COMPLETE implementation context for future LLMs with NO prior feature knowledge. Must include comprehensive design rationale, architectural tradeoffs, dependency analysis, implementation constraints, and future opportunities. This document will be loaded alongside the spec to provide full context for implementation decisions. Include business context, technical constraints, and decision history that future implementers need to understand. Use ## headers for categories, bullet points for considerations. Keep technical but conversational. Goes into notes.md",
269            min_length = 50
270        },
271        tasks: String {
272            description = "**CONTEXT FOR FUTURE IMPLEMENTATION**: Markdown checklist (100+ chars) of implementation steps that will guide future LLMs through COMPLETE feature implementation with NO prior knowledge. Must include comprehensive, actionable phases covering setup, development, testing, and deployment. This task list will be the PRIMARY implementation roadmap for future development sessions. Break feature into specific, measurable tasks that provide complete implementation guidance. Use ## headers for phases, - [ ] for uncompleted tasks, - [x] for completed. Include dependencies, prerequisites, and validation steps. Goes into task-list.md",
273            min_length = 100
274        }
275    }
276}
277
278/// Arguments for load_spec command
279#[derive(Args, Debug)]
280pub struct LoadSpecArgs {
281    /// Project name to load spec from
282    ///
283    /// Must be an existing project in ~/.foundry/
284    /// Use 'foundry list-projects' to see available projects
285    pub project_name: String,
286
287    /// Specific spec name (if not provided, lists available specs)
288    ///
289    /// **Exact Match**: Use full spec name (YYYYMMDD_HHMMSS_feature_name format)
290    /// **Fuzzy Matching**: Use natural language queries like "auth" or "user management"
291    ///   - Supports feature name matching (e.g., "auth" matches "user_authentication")
292    ///   - Supports partial spec name matching with Levenshtein distance
293    ///   - Returns match confidence and details in response
294    ///
295    /// If omitted, returns list of all available specs for the project
296    /// Use 'foundry list-specs PROJECT_NAME' for lightweight spec discovery
297    pub spec_name: Option<String>,
298}
299
300// Manual MCP tool implementation for LoadSpecArgs (has optional field)
301impl crate::mcp::traits::McpToolDefinition for LoadSpecArgs {
302    fn tool_definition() -> rust_mcp_sdk::schema::Tool {
303        let mut properties = std::collections::HashMap::new();
304
305        let mut project_name_prop = serde_json::Map::new();
306        project_name_prop.insert("type".to_string(), serde_json::json!("string"));
307        project_name_prop.insert(
308            "description".to_string(),
309            serde_json::json!("Name of the project containing the spec"),
310        );
311        properties.insert("project_name".to_string(), project_name_prop);
312
313        let mut spec_name_prop = serde_json::Map::new();
314        spec_name_prop.insert("type".to_string(), serde_json::json!("string"));
315        spec_name_prop.insert("description".to_string(), serde_json::json!("Optional: specific spec to load. Supports exact spec names (YYYYMMDD_HHMMSS_feature_name format) or fuzzy matching with natural language queries like 'auth' or 'user management'. If omitted, lists available specs"));
316        properties.insert("spec_name".to_string(), spec_name_prop);
317
318        rust_mcp_sdk::schema::Tool {
319            name: "load_spec".to_string(),
320            description: Some("Load specific specification content with project context. Supports fuzzy matching on feature names (e.g., 'auth' matches 'user_authentication'). You can use this to review full specification details, task lists, and implementation notes. If spec_name is omitted, lists available specs.".to_string()),
321            title: None,
322            input_schema: rust_mcp_sdk::schema::ToolInputSchema::new(
323                vec!["project_name".to_string()], // Only project_name is required
324                Some(properties),
325            ),
326            annotations: None,
327            meta: None,
328            output_schema: None,
329        }
330    }
331
332    fn from_mcp_params(params: &serde_json::Value) -> anyhow::Result<Self> {
333        Ok(Self {
334            project_name: params["project_name"]
335                .as_str()
336                .ok_or_else(|| anyhow::anyhow!("Missing project_name parameter"))?
337                .to_string(),
338            spec_name: params["spec_name"].as_str().map(|s| s.to_string()),
339        })
340    }
341}
342
343/// Arguments for load_project command
344#[derive(Args, Debug)]
345pub struct LoadProjectArgs {
346    /// Project name to load context from (must exist in ~/.foundry/)
347    ///
348    /// Returns complete project context: vision, tech-stack, summary, and available specs
349    /// Essential for resuming work on existing projects
350    /// Use 'foundry list-projects' to see available project names
351    pub project_name: String,
352}
353
354// Generate MCP tool implementation for LoadProjectArgs
355impl_mcp_tool! {
356    name = "load_project",
357    description = "Load complete project context (vision, tech-stack, summary) for LLM sessions. Essential for resuming work on existing projects. You can use this to get full project context before creating specifications or continuing development work.",
358    struct LoadProjectArgs {
359        project_name: String {
360            description = "Name of the existing project to load (must exist in ~/.foundry/)"
361        }
362    }
363}
364
365/// Arguments for list_projects command
366#[derive(Args, Debug)]
367pub struct ListProjectsArgs;
368
369// Note: This command takes no arguments - it lists all projects in ~/.foundry/
370// Returns: project names, creation dates, spec counts, validation status
371// Use this to discover available projects before loading or creating specs
372
373/// Arguments for list_specs command
374#[derive(Args, Debug)]
375pub struct ListSpecsArgs {
376    /// Project name to list specs for
377    ///
378    /// Must be an existing project in ~/.foundry/
379    /// Typically matches repository name - try this first before listing projects
380    ///
381    /// **Efficient Workflow**: Use this for lightweight spec discovery without loading
382    /// full project context. Returns only spec metadata for focused feature work.
383    ///
384    /// **Performance**: ~90% reduction in data transfer compared to load_project
385    pub project_name: String,
386}
387
388// Generate MCP tool implementation for ListSpecsArgs
389impl_mcp_tool! {
390    name = "list_specs",
391    description = "List available specifications for a project without loading full context. Returns lightweight spec metadata including names, feature names, and creation dates for efficient spec discovery.",
392    struct ListSpecsArgs {
393        project_name: String {
394            description = "Name of the existing project to list specs for (must exist in ~/.foundry/)"
395        }
396    }
397}
398
399/// Arguments for get_foundry_help command
400#[derive(Args, Debug)]
401pub struct GetFoundryHelpArgs {
402    /// Help topic for detailed guidance
403    ///
404    /// Available topics:
405    /// - workflows: User-driven development patterns (not automated sequences)
406    /// - decision-points: Guidance for choosing appropriate tools based on user intent
407    /// - content-examples: Content templates and examples
408    /// - project-structure: File organization and structure
409    /// - parameter-guidance: Parameter requirements and best practices
410    /// - tool-capabilities: When each tool is appropriate and what user input is required
411    ///
412    /// If omitted, provides overview and available topics
413    pub topic: Option<String>,
414}
415
416// Manual MCP tool implementation for GetFoundryHelpArgs (has optional field)
417impl crate::mcp::traits::McpToolDefinition for GetFoundryHelpArgs {
418    fn tool_definition() -> rust_mcp_sdk::schema::Tool {
419        let mut properties = std::collections::HashMap::new();
420
421        let mut topic_prop = serde_json::Map::new();
422        topic_prop.insert("type".to_string(), serde_json::json!("string"));
423        topic_prop.insert("description".to_string(), serde_json::json!("Optional: specific help topic (workflows, decision-points, content-examples, project-structure, parameter-guidance, tool-capabilities). If omitted, provides general guidance"));
424        properties.insert("topic".to_string(), topic_prop);
425
426        rust_mcp_sdk::schema::Tool {
427            name: "get_foundry_help".to_string(),
428            description: Some("Get comprehensive workflow guidance, content examples, and usage patterns. You can use this to understand foundry workflows and content standards. Essential for effective tool selection and workflow optimization.".to_string()),
429            title: None,
430            input_schema: rust_mcp_sdk::schema::ToolInputSchema::new(
431                vec![], // No required fields
432                Some(properties),
433            ),
434            annotations: None,
435            meta: None,
436            output_schema: None,
437        }
438    }
439
440    fn from_mcp_params(params: &serde_json::Value) -> anyhow::Result<Self> {
441        Ok(Self {
442            topic: params["topic"].as_str().map(|s| s.to_string()),
443        })
444    }
445}
446
447/// Arguments for validate_content command
448#[derive(Args, Debug)]
449pub struct ValidateContentArgs {
450    /// Content to validate
451    ///
452    /// The actual content string to check against schema requirements
453    /// Validation includes: length, format, content quality, improvement suggestions
454    /// Returns detailed feedback for content improvement
455    #[arg(long, required = true)]
456    pub content: String,
457
458    /// Content type to validate
459    ///
460    /// Must be one of: vision, tech-stack, summary, spec, notes, tasks
461    /// Each type has specific length and quality requirements
462    /// Use this to check content before creating projects/specs
463    pub content_type: String,
464}
465
466// Generate MCP tool implementation for ValidateContentArgs
467impl_mcp_tool! {
468    name = "validate_content",
469    description = "Validate content against schema requirements with improvement suggestions. You can use this to ensure your content meets foundry standards before creating projects or specifications. Provides detailed feedback for content improvement.",
470    struct ValidateContentArgs {
471        content: String {
472            description = "Content to validate against the specified type's requirements"
473        },
474        content_type: String {
475            description = "Type of content to validate (vision, tech-stack, summary, spec, notes, tasks)"
476        }
477    }
478}
479
480/// Arguments for update_spec command
481#[derive(Args, Debug)]
482pub struct UpdateSpecArgs {
483    /// Project name containing the spec to update
484    ///
485    /// Must be an existing project in ~/.foundry/
486    /// Use 'foundry list-projects' to see available projects
487    pub project_name: String,
488
489    /// Spec name to update (YYYYMMDD_HHMMSS_feature_name format)
490    ///
491    /// Must be an existing spec within the project
492    /// Use 'foundry load-project PROJECT_NAME' to see available specs
493    pub spec_name: String,
494
495    /// Edit commands to apply (REQUIRED). Provide as JSON array via MCP.
496    #[arg(long, required = true)]
497    pub commands: String,
498}
499
500// Manual MCP tool implementation for UpdateSpecArgs (custom schema)
501impl crate::mcp::traits::McpToolDefinition for UpdateSpecArgs {
502    fn tool_definition() -> rust_mcp_sdk::schema::Tool {
503        let mut properties = std::collections::HashMap::new();
504
505        let mut project_name_prop = serde_json::Map::new();
506        project_name_prop.insert("type".to_string(), serde_json::json!("string"));
507        project_name_prop.insert(
508            "description".to_string(),
509            serde_json::json!("Name of the existing project containing the spec"),
510        );
511        properties.insert("project_name".to_string(), project_name_prop);
512
513        let mut spec_name_prop = serde_json::Map::new();
514        spec_name_prop.insert("type".to_string(), serde_json::json!("string"));
515        spec_name_prop.insert(
516            "description".to_string(),
517            serde_json::json!(
518                "Name of the existing spec to update (YYYYMMDD_HHMMSS_feature_name format)"
519            ),
520        );
521        properties.insert("spec_name".to_string(), spec_name_prop);
522
523        let mut commands_prop = serde_json::Map::new();
524        commands_prop.insert("type".to_string(), serde_json::json!("array"));
525        // Explicitly specify the item type to satisfy strict schema validators (e.g., Cursor GPT-5)
526        commands_prop.insert(
527            "items".to_string(),
528            serde_json::json!({
529                "type": "object"
530            }),
531        );
532        commands_prop.insert("description".to_string(), serde_json::json!("Array of edit commands to apply. Each command must include target (spec|tasks|notes), command (set_task_status|upsert_task|append_to_section), selector (task_text|section), and relevant fields (status|content)."));
533        properties.insert("commands".to_string(), commands_prop);
534
535        rust_mcp_sdk::schema::Tool {
536            name: "update_spec".to_string(),
537            description: Some("Edit Foundry spec files using intent-based commands; precise anchors; idempotent updates. Provide a 'commands' array of edit operations.".to_string()),
538            title: None,
539            input_schema: rust_mcp_sdk::schema::ToolInputSchema::new(
540                vec!["project_name".to_string(), "spec_name".to_string(), "commands".to_string()], // Required fields
541                Some(properties),
542            ),
543            annotations: None,
544            meta: None,
545            output_schema: None,
546        }
547    }
548
549    fn from_mcp_params(params: &serde_json::Value) -> anyhow::Result<Self> {
550        Ok(Self {
551            project_name: params["project_name"]
552                .as_str()
553                .ok_or_else(|| anyhow::anyhow!("Missing project_name parameter"))?
554                .to_string(),
555            spec_name: params["spec_name"]
556                .as_str()
557                .ok_or_else(|| anyhow::anyhow!("Missing spec_name parameter"))?
558                .to_string(),
559            commands: serde_json::to_string(
560                params["commands"]
561                    .as_array()
562                    .ok_or_else(|| anyhow::anyhow!("Missing commands array"))?,
563            )?,
564        })
565    }
566}
567
568/// Arguments for delete_spec command
569#[derive(Args, Debug)]
570pub struct DeleteSpecArgs {
571    /// Project name containing the spec to delete
572    ///
573    /// Must be an existing project in ~/.foundry/
574    /// Use 'foundry list-projects' to see available projects
575    pub project_name: String,
576
577    /// Spec name to delete (YYYYMMDD_HHMMSS_feature_name format)
578    ///
579    /// Must be an existing spec within the project
580    /// Use 'foundry load-project PROJECT_NAME' to see available specs
581    /// **Warning: This will permanently delete all spec files**
582    pub spec_name: String,
583
584    /// Confirmation flag - must be "true" to proceed
585    ///
586    /// This is a safety mechanism to prevent accidental deletions
587    /// Must explicitly set to "true": --confirm true
588    #[arg(long, required = true)]
589    pub confirm: String,
590}
591
592// Generate MCP tool implementation for DeleteSpecArgs
593impl_mcp_tool! {
594    name = "delete_spec",
595    description = "Delete an existing specification and all its files (spec.md, task-list.md, notes.md). You can use this to permanently remove specifications that are no longer needed. This action cannot be undone.",
596    struct DeleteSpecArgs {
597        project_name: String {
598            description = "Name of the existing project containing the spec"
599        },
600        spec_name: String {
601            description = "Name of the spec to delete (YYYYMMDD_HHMMSS_feature_name format). WARNING: This permanently deletes all spec files."
602        },
603        confirm: String {
604            description = "Confirmation flag - must be set to 'true' to proceed with deletion (safety mechanism)"
605        }
606    }
607}
608
609/// Arguments for serve command
610#[derive(Args, Debug)]
611pub struct ServeArgs {
612    /// Enable verbose logging
613    #[arg(long, short)]
614    pub verbose: bool,
615}
616
617/// Arguments for install command
618#[derive(Args, Debug)]
619pub struct InstallArgs {
620    /// Target environment to install for
621    ///
622    /// Supported targets:
623    /// - claude-code: Install for Claude Code CLI environment (includes subagent template)
624    /// - cursor: Install for Cursor IDE environment (includes rules template)
625    ///
626    /// Installation creates both MCP server configuration and AI assistant guidance templates.
627    pub target: String,
628
629    /// Custom path to foundry binary (optional)
630    ///
631    /// If not provided, will attempt to detect the current binary path
632    /// Useful for installations where the binary is in a custom location
633    #[arg(long)]
634    pub binary_path: Option<String>,
635
636    /// Output installation information in JSON format
637    ///
638    /// When enabled, outputs structured JSON data instead of
639    /// human-readable formatted text with colors and status indicators
640    #[arg(long)]
641    pub json: bool,
642}
643
644/// Arguments for uninstall command
645#[derive(Args, Debug)]
646pub struct UninstallArgs {
647    /// Target environment to uninstall from
648    ///
649    /// Supported targets:
650    /// - claude-code: Uninstall from Claude Code CLI environment
651    /// - cursor: Uninstall from Cursor IDE environment
652    pub target: String,
653
654    /// Also remove configuration files
655    ///
656    /// If set, will remove configuration files in addition to
657    /// unregistering the MCP server
658    #[arg(long)]
659    pub remove_config: bool,
660
661    /// Output uninstallation information in JSON format
662    ///
663    /// When enabled, outputs structured JSON data instead of
664    /// human-readable formatted text with colors and status indicators
665    #[arg(long)]
666    pub json: bool,
667}
668
669/// Arguments for status command
670#[derive(Args, Debug, Clone)]
671pub struct StatusArgs {
672    /// Show detailed configuration information
673    ///
674    /// Includes full paths, configuration file contents,
675    /// and detailed installation status
676    #[arg(long)]
677    pub detailed: bool,
678
679    /// Check only specific target environment
680    ///
681    /// If provided, only show status for the specified environment
682    /// instead of all supported environments
683    #[arg(long)]
684    pub target: Option<String>,
685
686    /// Output status information in JSON format
687    ///
688    /// When enabled, outputs structured JSON data instead of
689    /// human-readable formatted text with colors
690    #[arg(long)]
691    pub json: bool,
692}
693
694// MCP parameter conversion implementations
695// All structs now use auto-generated McpTool implementation via derive macro
696// Except ListProjectsArgs which is a unit struct and needs manual implementation
697
698impl crate::mcp::traits::McpToolDefinition for ListProjectsArgs {
699    fn tool_definition() -> rust_mcp_sdk::schema::Tool {
700        rust_mcp_sdk::schema::Tool {
701            name: "list_projects".to_string(),
702            description: Some("List all available projects with metadata including creation dates, spec counts, and validation status. You can use this to discover available projects before loading or creating specifications.".to_string()),
703            title: None,
704            input_schema: rust_mcp_sdk::schema::ToolInputSchema::new(
705                vec![],
706                Some(std::collections::HashMap::new()),
707            ),
708            annotations: None,
709            meta: None,
710            output_schema: None,
711        }
712    }
713
714    fn from_mcp_params(_params: &serde_json::Value) -> anyhow::Result<Self> {
715        Ok(Self)
716    }
717}