diff --git a/src/mcltspice/prompts.py b/src/mcltspice/prompts.py new file mode 100644 index 0000000..b95dd1f --- /dev/null +++ b/src/mcltspice/prompts.py @@ -0,0 +1,309 @@ +"""Guided-workflow prompts. Each returns a Message list and registers on the +shared mcp instance. Pure narrative -- no tool calls. +""" + +from fastmcp.prompts import Message + +from ._app import mcp + + +@mcp.prompt() +def design_filter( + filter_type: str = "lowpass", + topology: str = "rc", + cutoff_freq: str = "1kHz", +) -> list: + """Guide through designing and simulating a filter circuit. + + Args: + filter_type: lowpass, highpass, bandpass, or notch + topology: rc (1st order), rlc (2nd order), or sallen-key (active) + cutoff_freq: Target cutoff frequency with units + """ + return [Message(role="user", content=f"""Design a {filter_type} filter with these requirements: +- Topology: {topology} +- Cutoff frequency: {cutoff_freq} + +Workflow: +1. Use create_netlist to build the circuit +2. Add .ac analysis directive for frequency sweep +3. Add .meas directive for -3dB bandwidth +4. Simulate with simulate_netlist +5. Use measure_bandwidth to verify cutoff frequency +6. Use get_waveform to inspect the frequency response +7. Adjust component values with create_netlist if needed + +Tips: +- For RC lowpass: f_c = 1/(2*pi*R*C) +- For 2nd order: Q controls peaking, Butterworth Q=0.707 +- Use search_spice_models to find op-amp models for active filters +""")] + + +@mcp.prompt() +def analyze_power_supply(schematic_path: str = "") -> list: + """Guide through analyzing a power supply circuit. + + Args: + schematic_path: Path to the power supply schematic + """ + path_instruction = ( + f"The schematic is at: {schematic_path}" + if schematic_path + else "First, identify or create the power supply schematic." + ) + + return [Message(role="user", content=f"""Analyze a power supply circuit for key performance metrics. + +{path_instruction} + +Workflow: +1. Use read_schematic to understand the circuit topology +2. Use run_drc to check for design issues +3. Simulate with .tran analysis (include load step if applicable) +4. Use analyze_waveform with these analyses: + - "peak_to_peak" on output for ripple measurement + - "settling_time" for transient response + - "fft" on output to identify noise frequencies +5. If AC analysis available, use measure_bandwidth for loop gain + +Key metrics to extract: +- Output voltage regulation (DC accuracy) +- Ripple voltage (peak-to-peak on output) +- Load transient response (settling time after step) +- Efficiency (input power vs output power) +""")] + + +@mcp.prompt() +def debug_circuit(schematic_path: str = "") -> list: + """Guide through debugging a circuit that isn't working. + + Args: + schematic_path: Path to the problematic schematic + """ + path_instruction = ( + f"The schematic is at: {schematic_path}" + if schematic_path + else "First, identify the schematic file." + ) + + return [Message(role="user", content=f"""Systematic approach to debugging a circuit. + +{path_instruction} + +Step 1 - Validate the schematic: +- Use run_drc to catch obvious issues (missing ground, floating nodes) +- Use read_schematic to review component values and connections + +Step 2 - Check simulation setup: +- Verify simulation directives are correct +- Check that models/subcircuits are available (search_spice_models) + +Step 3 - Run and analyze: +- Simulate the circuit +- Use get_waveform to inspect key node voltages +- Compare expected vs actual values at each stage + +Step 4 - Isolate the problem: +- Use edit_component to simplify (replace active devices with ideal) +- Use diff_schematics to track what changes fixed the issue +- Re-simulate after each change + +Common issues: +- Wrong node connections (check wire endpoints) +- Missing bias voltages or ground +- Component values off by orders of magnitude +- Wrong model (check with search_spice_models) +""")] + + +@mcp.prompt() +def optimize_design( + circuit_type: str = "filter", + target_spec: str = "1kHz bandwidth", +) -> list: + """Guide through optimizing a circuit to meet target specifications. + + Args: + circuit_type: Type of circuit (filter, amplifier, regulator, oscillator) + target_spec: Target specification to achieve + """ + return [Message(role="user", content=f"""Optimize a {circuit_type} circuit to achieve: {target_spec} + +Workflow: +1. Start with a template: use list_templates to see available circuits +2. Create the initial circuit with create_from_template +3. Simulate and measure the current performance +4. Use optimize_circuit to automatically tune component values: + - Define target metrics (bandwidth, gain, settling time, etc.) + - Specify component ranges with preferred E-series values + - Let the optimizer iterate (typically 10-20 simulations) +5. Verify the optimized design with a full simulation +6. Run Monte Carlo (monte_carlo tool) to check yield with tolerances + +Tips: +- Start with reasonable initial values from the template +- Use E24 or E96 series for resistors/capacitors +- For filters: target bandwidth_hz metric +- For amplifiers: target gain_db and phase_margin_deg +- For regulators: target settling_time and peak_to_peak (ripple) +""")] + + +@mcp.prompt() +def monte_carlo_analysis( + circuit_description: str = "RC filter", + n_runs: str = "100", +) -> list: + """Guide through Monte Carlo tolerance analysis. + + Args: + circuit_description: What circuit to analyze + n_runs: Number of Monte Carlo iterations + """ + return [Message(role="user", content=f"""Run Monte Carlo tolerance analysis on: {circuit_description} +Number of runs: {n_runs} + +Workflow: +1. Create or identify the netlist for your circuit +2. Use monte_carlo tool with component tolerances: + - Resistors: typically 1% (0.01) or 5% (0.05) + - Capacitors: typically 10% (0.1) or 20% (0.2) + - Inductors: typically 10% (0.1) +3. For each completed run, extract key metrics: + - Use get_waveform on each raw file + - Use analyze_waveform for RMS, peak-to-peak, etc. + - Use measure_bandwidth for filter circuits +4. Compute statistics across all runs: + - Mean and standard deviation of each metric + - Min/max (worst case) + - Yield: what percentage meet spec? + +Tips: +- Use list_simulation_runs to understand stepped data +- For stepped simulations, use get_waveform with run parameter +- Start with fewer runs (10-20) to verify setup, then scale up +- Set seed for reproducible results during development +- Typical component tolerances: + - Metal film resistors: 1% + - Ceramic capacitors: 10-20% + - Electrolytic capacitors: 20% + - Inductors: 10-20% +""")] + + +@mcp.prompt() +def circuit_from_scratch( + description: str = "audio amplifier", +) -> list: + """Guide through creating a complete circuit from scratch. + + Args: + description: What circuit to build + """ + return [Message(role="user", content=f"""Build a complete circuit from scratch: {description} + +Approach 1 - Use a template (recommended for common circuits): +1. Use list_templates to see available circuit templates +2. Use create_from_template with custom parameters +3. Simulate with simulate_netlist +4. Analyze results with get_waveform and analyze_waveform + +Approach 2 - Build from components: +1. Use create_netlist to define components and connections +2. Use search_spice_models to find transistor/diode models +3. Use search_spice_subcircuits to find op-amp/IC models +4. Add simulation directives (.tran, .ac, .dc, .op, .tf) +5. Simulate and analyze + +Approach 3 - Graphical schematic (.asc file): +1. Use generate_schematic for any of 10 topologies: rc_lowpass, + voltage_divider, inverting_amp, non_inverting_amp, common_emitter_amp, + colpitts_oscillator, differential_amp, buck_converter, ldo_regulator, + h_bridge +2. The .asc file can be opened in LTspice GUI for editing +3. Simulate with the simulate tool + +Verification workflow: +1. Run run_drc to check for design issues before simulating +2. Start with .op analysis to verify DC bias point +3. Run .tf analysis for gain and impedance +4. Run .ac analysis for frequency response +5. Run .tran analysis for time-domain behavior +6. Use diff_schematics to compare design iterations +""")] + + +@mcp.prompt() +def troubleshoot_simulation( + error_description: str = "", + schematic_path: str = "", +) -> list: + """Systematic checklist for diagnosing simulation failures. + + Args: + error_description: What went wrong (error message, unexpected results, etc.) + schematic_path: Path to the problematic schematic or netlist + """ + path_note = ( + f"Schematic/netlist: {schematic_path}" + if schematic_path + else "First, identify the schematic or netlist file." + ) + error_note = ( + f"Reported issue: {error_description}" + if error_description + else "No specific error described -- run full diagnostic." + ) + + return [Message(role="user", content=f"""Troubleshoot a simulation that isn't working correctly. + +{path_note} +{error_note} + +Diagnostic checklist (work through in order): + +1. **Design Rule Check** + - Run run_drc on the schematic + - Fix any: missing ground, floating nodes, duplicate names, missing sim directive + +2. **Installation & Setup** + - Run check_installation to verify Wine + LTspice + - Check that required .lib files exist + +3. **Model Availability** + - Use search_spice_models to verify all transistor/diode models exist + - Use search_spice_subcircuits to verify op-amp models + - Common issue: model name in schematic doesn't match library + +4. **Simulation Directive** + - Use read_schematic to check the directive + - Verify analysis type matches what you want (.tran, .ac, .dc, .op, .tf) + - For .tran: is the stop time long enough? + - For .ac: are start/stop frequencies reasonable? + +5. **Node Connections** + - Use read_schematic to list all components and nets + - Check for disconnected nodes (components not wired) + - Verify ground connections on all return paths + +6. **Run & Inspect** + - Simulate the circuit + - Check the log file for convergence warnings + - Use get_waveform to inspect node voltages + - Compare expected vs actual at each circuit stage + +7. **Simplify & Isolate** + - Use edit_component to replace active devices with ideal ones + - Remove non-essential subcircuits + - Test each stage independently + - Add .ic directives if oscillators won't start + +Common failure modes: +- Convergence failure: reduce timestep, add initial conditions +- All zeros: check ground connections and source polarity +- Unexpected clipping: check supply voltages and headroom +- Oscillation in DC circuit: add small capacitors on feedback +- Model not found: verify .lib/.include paths +""")] diff --git a/src/mcltspice/server.py b/src/mcltspice/server.py index a57c96b..7ca8893 100644 --- a/src/mcltspice/server.py +++ b/src/mcltspice/server.py @@ -16,11 +16,10 @@ import tempfile from pathlib import Path import numpy as np -from fastmcp.prompts import Message # Domain modules register their tools/resources/prompts on the shared mcp # instance at import time. Imported for that side effect only. -from . import library_tools, resources, spicebook_tools # noqa: F401,E402 +from . import library_tools, prompts, resources, spicebook_tools # noqa: F401,E402 from ._app import mcp from .batch import ( run_monte_carlo, @@ -1555,313 +1554,6 @@ def list_templates() -> dict: } -# ============================================================================ -# PROMPTS -# ============================================================================ - - -@mcp.prompt() -def design_filter( - filter_type: str = "lowpass", - topology: str = "rc", - cutoff_freq: str = "1kHz", -) -> list: - """Guide through designing and simulating a filter circuit. - - Args: - filter_type: lowpass, highpass, bandpass, or notch - topology: rc (1st order), rlc (2nd order), or sallen-key (active) - cutoff_freq: Target cutoff frequency with units - """ - return [Message(role="user", content=f"""Design a {filter_type} filter with these requirements: -- Topology: {topology} -- Cutoff frequency: {cutoff_freq} - -Workflow: -1. Use create_netlist to build the circuit -2. Add .ac analysis directive for frequency sweep -3. Add .meas directive for -3dB bandwidth -4. Simulate with simulate_netlist -5. Use measure_bandwidth to verify cutoff frequency -6. Use get_waveform to inspect the frequency response -7. Adjust component values with create_netlist if needed - -Tips: -- For RC lowpass: f_c = 1/(2*pi*R*C) -- For 2nd order: Q controls peaking, Butterworth Q=0.707 -- Use search_spice_models to find op-amp models for active filters -""")] - - -@mcp.prompt() -def analyze_power_supply(schematic_path: str = "") -> list: - """Guide through analyzing a power supply circuit. - - Args: - schematic_path: Path to the power supply schematic - """ - path_instruction = ( - f"The schematic is at: {schematic_path}" - if schematic_path - else "First, identify or create the power supply schematic." - ) - - return [Message(role="user", content=f"""Analyze a power supply circuit for key performance metrics. - -{path_instruction} - -Workflow: -1. Use read_schematic to understand the circuit topology -2. Use run_drc to check for design issues -3. Simulate with .tran analysis (include load step if applicable) -4. Use analyze_waveform with these analyses: - - "peak_to_peak" on output for ripple measurement - - "settling_time" for transient response - - "fft" on output to identify noise frequencies -5. If AC analysis available, use measure_bandwidth for loop gain - -Key metrics to extract: -- Output voltage regulation (DC accuracy) -- Ripple voltage (peak-to-peak on output) -- Load transient response (settling time after step) -- Efficiency (input power vs output power) -""")] - - -@mcp.prompt() -def debug_circuit(schematic_path: str = "") -> list: - """Guide through debugging a circuit that isn't working. - - Args: - schematic_path: Path to the problematic schematic - """ - path_instruction = ( - f"The schematic is at: {schematic_path}" - if schematic_path - else "First, identify the schematic file." - ) - - return [Message(role="user", content=f"""Systematic approach to debugging a circuit. - -{path_instruction} - -Step 1 - Validate the schematic: -- Use run_drc to catch obvious issues (missing ground, floating nodes) -- Use read_schematic to review component values and connections - -Step 2 - Check simulation setup: -- Verify simulation directives are correct -- Check that models/subcircuits are available (search_spice_models) - -Step 3 - Run and analyze: -- Simulate the circuit -- Use get_waveform to inspect key node voltages -- Compare expected vs actual values at each stage - -Step 4 - Isolate the problem: -- Use edit_component to simplify (replace active devices with ideal) -- Use diff_schematics to track what changes fixed the issue -- Re-simulate after each change - -Common issues: -- Wrong node connections (check wire endpoints) -- Missing bias voltages or ground -- Component values off by orders of magnitude -- Wrong model (check with search_spice_models) -""")] - - -@mcp.prompt() -def optimize_design( - circuit_type: str = "filter", - target_spec: str = "1kHz bandwidth", -) -> list: - """Guide through optimizing a circuit to meet target specifications. - - Args: - circuit_type: Type of circuit (filter, amplifier, regulator, oscillator) - target_spec: Target specification to achieve - """ - return [Message(role="user", content=f"""Optimize a {circuit_type} circuit to achieve: {target_spec} - -Workflow: -1. Start with a template: use list_templates to see available circuits -2. Create the initial circuit with create_from_template -3. Simulate and measure the current performance -4. Use optimize_circuit to automatically tune component values: - - Define target metrics (bandwidth, gain, settling time, etc.) - - Specify component ranges with preferred E-series values - - Let the optimizer iterate (typically 10-20 simulations) -5. Verify the optimized design with a full simulation -6. Run Monte Carlo (monte_carlo tool) to check yield with tolerances - -Tips: -- Start with reasonable initial values from the template -- Use E24 or E96 series for resistors/capacitors -- For filters: target bandwidth_hz metric -- For amplifiers: target gain_db and phase_margin_deg -- For regulators: target settling_time and peak_to_peak (ripple) -""")] - - -@mcp.prompt() -def monte_carlo_analysis( - circuit_description: str = "RC filter", - n_runs: str = "100", -) -> list: - """Guide through Monte Carlo tolerance analysis. - - Args: - circuit_description: What circuit to analyze - n_runs: Number of Monte Carlo iterations - """ - return [Message(role="user", content=f"""Run Monte Carlo tolerance analysis on: {circuit_description} -Number of runs: {n_runs} - -Workflow: -1. Create or identify the netlist for your circuit -2. Use monte_carlo tool with component tolerances: - - Resistors: typically 1% (0.01) or 5% (0.05) - - Capacitors: typically 10% (0.1) or 20% (0.2) - - Inductors: typically 10% (0.1) -3. For each completed run, extract key metrics: - - Use get_waveform on each raw file - - Use analyze_waveform for RMS, peak-to-peak, etc. - - Use measure_bandwidth for filter circuits -4. Compute statistics across all runs: - - Mean and standard deviation of each metric - - Min/max (worst case) - - Yield: what percentage meet spec? - -Tips: -- Use list_simulation_runs to understand stepped data -- For stepped simulations, use get_waveform with run parameter -- Start with fewer runs (10-20) to verify setup, then scale up -- Set seed for reproducible results during development -- Typical component tolerances: - - Metal film resistors: 1% - - Ceramic capacitors: 10-20% - - Electrolytic capacitors: 20% - - Inductors: 10-20% -""")] - - -@mcp.prompt() -def circuit_from_scratch( - description: str = "audio amplifier", -) -> list: - """Guide through creating a complete circuit from scratch. - - Args: - description: What circuit to build - """ - return [Message(role="user", content=f"""Build a complete circuit from scratch: {description} - -Approach 1 - Use a template (recommended for common circuits): -1. Use list_templates to see available circuit templates -2. Use create_from_template with custom parameters -3. Simulate with simulate_netlist -4. Analyze results with get_waveform and analyze_waveform - -Approach 2 - Build from components: -1. Use create_netlist to define components and connections -2. Use search_spice_models to find transistor/diode models -3. Use search_spice_subcircuits to find op-amp/IC models -4. Add simulation directives (.tran, .ac, .dc, .op, .tf) -5. Simulate and analyze - -Approach 3 - Graphical schematic (.asc file): -1. Use generate_schematic for any of 10 topologies: rc_lowpass, - voltage_divider, inverting_amp, non_inverting_amp, common_emitter_amp, - colpitts_oscillator, differential_amp, buck_converter, ldo_regulator, - h_bridge -2. The .asc file can be opened in LTspice GUI for editing -3. Simulate with the simulate tool - -Verification workflow: -1. Run run_drc to check for design issues before simulating -2. Start with .op analysis to verify DC bias point -3. Run .tf analysis for gain and impedance -4. Run .ac analysis for frequency response -5. Run .tran analysis for time-domain behavior -6. Use diff_schematics to compare design iterations -""")] - - -@mcp.prompt() -def troubleshoot_simulation( - error_description: str = "", - schematic_path: str = "", -) -> list: - """Systematic checklist for diagnosing simulation failures. - - Args: - error_description: What went wrong (error message, unexpected results, etc.) - schematic_path: Path to the problematic schematic or netlist - """ - path_note = ( - f"Schematic/netlist: {schematic_path}" - if schematic_path - else "First, identify the schematic or netlist file." - ) - error_note = ( - f"Reported issue: {error_description}" - if error_description - else "No specific error described -- run full diagnostic." - ) - - return [Message(role="user", content=f"""Troubleshoot a simulation that isn't working correctly. - -{path_note} -{error_note} - -Diagnostic checklist (work through in order): - -1. **Design Rule Check** - - Run run_drc on the schematic - - Fix any: missing ground, floating nodes, duplicate names, missing sim directive - -2. **Installation & Setup** - - Run check_installation to verify Wine + LTspice - - Check that required .lib files exist - -3. **Model Availability** - - Use search_spice_models to verify all transistor/diode models exist - - Use search_spice_subcircuits to verify op-amp models - - Common issue: model name in schematic doesn't match library - -4. **Simulation Directive** - - Use read_schematic to check the directive - - Verify analysis type matches what you want (.tran, .ac, .dc, .op, .tf) - - For .tran: is the stop time long enough? - - For .ac: are start/stop frequencies reasonable? - -5. **Node Connections** - - Use read_schematic to list all components and nets - - Check for disconnected nodes (components not wired) - - Verify ground connections on all return paths - -6. **Run & Inspect** - - Simulate the circuit - - Check the log file for convergence warnings - - Use get_waveform to inspect node voltages - - Compare expected vs actual at each circuit stage - -7. **Simplify & Isolate** - - Use edit_component to replace active devices with ideal ones - - Remove non-essential subcircuits - - Test each stage independently - - Add .ic directives if oscillators won't start - -Common failure modes: -- Convergence failure: reduce timestep, add initial conditions -- All zeros: check ground connections and source polarity -- Unexpected clipping: check supply voltages and headroom -- Oscillation in DC circuit: add small capacitors on feedback -- Model not found: verify .lib/.include paths -""")] - - # ============================================================================ # ENTRY POINT # ============================================================================