Files
gh-raw-labs-claude-code-mar…/skills/mxcp-expert/references/debugging-guide.md
2025-11-30 08:49:50 +08:00

577 lines
12 KiB
Markdown

# MXCP Debugging Guide
**Systematic approach to debugging MXCP servers when things don't work.**
## Debug Mode
### Enable Debug Logging
```bash
# Option 1: Environment variable
export MXCP_DEBUG=1
mxcp serve
# Option 2: CLI flag
mxcp serve --debug
# Option 3: For specific commands
mxcp validate --debug
mxcp test --debug
mxcp run tool my_tool --param key=value --debug
```
**Debug mode shows**:
- SQL queries being executed
- Parameter values
- Type conversions
- Error stack traces
- Internal MXCP operations
## Debugging Workflow
### Step 1: Identify the Layer
When something fails, determine which layer has the problem:
```
User Request
MXCP Validation (YAML structure)
Parameter Binding (Type conversion)
Python Code Execution (if language: python)
SQL Execution (if SQL source)
Type Validation (Return type check)
Response to LLM
```
**Run these commands in order**:
```bash
# 1. Structure validation
mxcp validate
# If fails → YAML structure issue (go to "YAML Errors" section)
# 2. Test with known inputs
mxcp test
# If fails → Logic or SQL issue (go to "Test Failures" section)
# 3. Manual execution
mxcp run tool my_tool --param key=value
# If fails → Runtime issue (go to "Runtime Errors" section)
# 4. Debug mode
mxcp run tool my_tool --param key=value --debug
# See detailed execution logs
```
## Common Issues and Solutions
### YAML Validation Errors
#### Error: "Invalid YAML syntax"
```bash
# Check YAML syntax
mxcp validate --debug
# Common causes:
# 1. Mixed tabs and spaces (use spaces only)
# 2. Incorrect indentation
# 3. Missing quotes around special characters
# 4. Unclosed quotes or brackets
```
**Solution**:
```bash
# Use yamllint to check
pip install yamllint
yamllint tools/my_tool.yml
# Or use online validator
# https://www.yamllint.com/
```
#### Error: "Missing required field: description"
```yaml
# ❌ WRONG
tool:
name: my_tool
parameters: []
source:
code: SELECT * FROM table
# ✅ CORRECT
tool:
name: my_tool
description: "What this tool does" # ← Added
parameters: []
source:
code: SELECT * FROM table
```
#### Error: "Invalid type specification"
```yaml
# ❌ WRONG
return:
type: "object" # Quoted string
properties:
id: "integer" # Quoted string
# ✅ CORRECT
return:
type: object # Unquoted
properties:
id: { type: integer } # Proper structure
```
### Test Failures
#### Error: "Expected X, got Y" in test
```yaml
# Test says: Expected 5 items, got 3
# Debug steps:
# 1. Run SQL directly
mxcp query "SELECT * FROM table WHERE condition"
# 2. Check test data exists
mxcp query "SELECT COUNT(*) FROM table WHERE condition"
# 3. Verify filter logic
mxcp run tool my_tool --param key=test_value --debug
```
**Common causes**:
- Test data not loaded (`dbt seed` not run)
- Wrong filter condition in SQL
- Test expects wrong values
#### Error: "Type mismatch"
```yaml
# Test fails: Expected integer, got string
# Check SQL output types
mxcp query "DESCRIBE table"
# Fix: Cast in SQL
SELECT
CAST(column AS INTEGER) as column # Explicit cast
FROM table
```
### SQL Errors
#### Error: "Table 'xyz' does not exist"
```bash
# List all tables
mxcp query "SHOW TABLES"
# Check if dbt models/seeds loaded
dbt seed
dbt run
# Verify table name (case-sensitive)
mxcp query "SELECT * FROM xyz LIMIT 1"
```
#### Error: "Column 'abc' not found"
```bash
# Show table schema
mxcp query "DESCRIBE table_name"
# Check column names (case-sensitive)
mxcp query "SELECT * FROM table_name LIMIT 1"
# Common issue: typo or wrong case
SELECT customer_id # ← Check exact spelling
```
#### Error: "Syntax error near..."
```bash
# Test SQL directly with debug
mxcp query "YOUR SQL HERE" --debug
# Common SQL syntax errors:
# 1. Missing quotes around strings
# 2. Wrong parameter binding syntax (use $param not :param)
# 3. DuckDB-specific syntax issues
```
### Parameter Binding Errors
#### Error: "Unbound parameter: $param1"
```yaml
# ❌ WRONG: Parameter used but not defined
tool:
name: my_tool
parameters:
- name: other_param
type: string
source:
code: SELECT * FROM table WHERE col = $param1 # ← Not defined!
# ✅ CORRECT: Define all parameters
tool:
name: my_tool
parameters:
- name: param1 # ← Added
type: string
- name: other_param
type: string
source:
code: SELECT * FROM table WHERE col = $param1
```
#### Error: "Type mismatch for parameter"
```yaml
# MXCP tries to convert "abc" to integer → fails
# ✅ Solution: Validate types match usage
parameters:
- name: age
type: integer # ← Must be integer for numeric comparison
source:
code: SELECT * FROM users WHERE age > $age # Numeric comparison
```
### Python Errors
#### Error: "ModuleNotFoundError: No module named 'xyz'"
```bash
# Check requirements.txt exists
cat requirements.txt
# Install dependencies
pip install -r requirements.txt
# Or install specific module
pip install xyz
```
#### Error: "ImportError: cannot import name 'db'"
```python
# ❌ WRONG import path
from mxcp import db
# ✅ CORRECT import path
from mxcp.runtime import db
```
#### Error: "Function 'xyz' not found in module"
```yaml
# tools/my_tool.yml
source:
file: ../python/my_module.py # ← Check file path
# Common issues:
# 1. Wrong file path (use ../ to go up from tools/)
# 2. Function name typo
# 3. Function not exported (not at module level)
```
**Check function exists**:
```bash
# Read Python file
cat python/my_module.py | grep "^def\|^async def"
# Should see your function listed
```
#### Error: "Async function called incorrectly"
```python
# ❌ WRONG: Calling async function without await
def my_tool():
result = async_function() # ← Missing await!
return result
# ✅ CORRECT: Properly handle async
async def my_tool():
result = await async_function() # ← Added await
return result
```
### Return Type Validation Errors
#### Error: "Expected array, got object"
```yaml
# SQL returns multiple rows (array) but type says object
# ❌ WRONG
return:
type: object # ← Wrong! SQL returns array
source:
code: SELECT * FROM table # Returns multiple rows
# ✅ CORRECT
return:
type: array # ← Matches SQL output
items:
type: object
source:
code: SELECT * FROM table
```
#### Error: "Missing required field 'xyz'"
```yaml
# Return type expects field that SQL doesn't return
# ❌ WRONG
return:
type: object
properties:
id: { type: integer }
missing_field: { type: string } # ← SQL doesn't return this!
source:
code: SELECT id FROM table # Only returns 'id'
# ✅ CORRECT: Match return type to actual SQL output
return:
type: object
properties:
id: { type: integer } # Only what SQL returns
source:
code: SELECT id FROM table
```
## Debugging Techniques
### 1. Test SQL Directly
```bash
# Instead of testing whole tool, test SQL first
mxcp query "SELECT * FROM table WHERE condition LIMIT 5"
# Test with parameters manually
mxcp query "SELECT * FROM table WHERE id = 123"
# Check aggregations
mxcp query "SELECT COUNT(*), SUM(amount) FROM table"
```
### 2. Add Debug Prints to Python
```python
# python/my_module.py
import sys
def my_function(param: str) -> dict:
# Debug output (goes to stderr, won't affect result)
print(f"DEBUG: param={param}", file=sys.stderr)
result = process(param)
print(f"DEBUG: result={result}", file=sys.stderr)
return result
```
**View debug output**:
```bash
mxcp serve --debug 2>&1 | grep DEBUG
```
### 3. Isolate the Problem
```python
# Break complex function into steps
# ❌ Hard to debug
def complex_function(data):
return process(transform(validate(data)))
# ✅ Easy to debug
def complex_function(data):
print("Step 1: Validate", file=sys.stderr)
validated = validate(data)
print("Step 2: Transform", file=sys.stderr)
transformed = transform(validated)
print("Step 3: Process", file=sys.stderr)
processed = process(transformed)
return processed
```
### 4. Test with Minimal Input
```bash
# Start with simplest possible input
mxcp run tool my_tool --param id=1
# Gradually add complexity
mxcp run tool my_tool --param id=1 --param status=active
# Test edge cases
mxcp run tool my_tool --param id=999999 # Non-existent
mxcp run tool my_tool # Missing required param
```
### 5. Check Logs
```bash
# Server logs (if running)
mxcp serve --debug 2>&1 | tee mxcp.log
# View recent errors
grep -i error mxcp.log
# View SQL queries
grep -i select mxcp.log
```
### 6. Verify Data
```bash
# Check seed data loaded
dbt seed --select my_data
mxcp query "SELECT COUNT(*) FROM my_data"
# Check dbt models built
dbt run --select my_model
mxcp query "SELECT COUNT(*) FROM my_model"
# Verify test fixtures
mxcp query "SELECT * FROM test_fixtures LIMIT 5"
```
## Common Debugging Scenarios
### Scenario 1: Tool Returns Empty Results
```bash
# 1. Check if data exists
mxcp query "SELECT COUNT(*) FROM table"
# → If 0, data not loaded (run dbt seed)
# 2. Check filter condition
mxcp query "SELECT * FROM table WHERE condition"
# → Test condition manually
# 3. Check parameter value
mxcp run tool my_tool --param key=value --debug
# → See actual SQL with parameter values
```
### Scenario 2: Tool Crashes/Returns Error
```bash
# 1. Validate structure
mxcp validate
# → Fix any YAML errors first
# 2. Test in isolation
mxcp test tool my_tool
# → See specific error
# 3. Run with debug
mxcp run tool my_tool --param key=value --debug
# → See full stack trace
```
### Scenario 3: Wrong Data Returned
```bash
# 1. Test SQL directly
mxcp query "SELECT * FROM table LIMIT 5"
# → Verify columns and values
# 2. Check test assertions
# In YAML, verify test expected results match actual
# 3. Verify type conversions
mxcp query "SELECT typeof(column) as type FROM table LIMIT 1"
# → Check DuckDB types
```
### Scenario 4: Performance Issues
```bash
# 1. Check query execution time
time mxcp query "SELECT * FROM large_table"
# 2. Analyze query plan
mxcp query "EXPLAIN SELECT * FROM table WHERE condition"
# 3. Check for missing indexes
mxcp query "PRAGMA show_tables_expanded"
# 4. Limit results during development
SELECT * FROM table LIMIT 100 # Add LIMIT for testing
```
## Debugging Checklist
When something doesn't work:
- [ ] Run `mxcp validate` to check YAML structure
- [ ] Run `mxcp test` to check logic
- [ ] Run `mxcp run tool <name> --debug` to see details
- [ ] Test SQL directly with `mxcp query`
- [ ] Check data loaded with `dbt seed` or `dbt run`
- [ ] Verify Python imports work (`from mxcp.runtime import db`)
- [ ] Check requirements.txt and install dependencies
- [ ] Add debug prints to Python code
- [ ] Test with minimal/simple inputs first
- [ ] Check return types match actual data
- [ ] Review logs for errors
## Getting Help
### Information to Provide
When asking for help or reporting issues:
1. **Error message** (full text)
2. **Command that failed** (exact command)
3. **Tool YAML** (relevant parts)
4. **Debug output** (`--debug` flag)
5. **Environment** (`mxcp --version`, `python --version`)
### Self-Help Steps
Before asking for help:
1. Read the error message carefully
2. Check this debugging guide
3. Search error message in documentation
4. Test components in isolation
5. Create minimal reproduction case
## Summary
**Debugging workflow**:
1. `mxcp validate` → Fix YAML errors
2. `mxcp test` → Fix logic errors
3. `mxcp run --debug` → See detailed execution
4. `mxcp query` → Test SQL directly
5. Add debug prints → Trace Python execution
6. Test in isolation → Identify exact failure point
**Remember**:
- Start simple, add complexity gradually
- Test each layer independently
- Use debug mode liberally
- Check data loaded before testing queries
- Verify types match at every step