# Testing the Skraak MCP Server

## Overview

The Skraak MCP Server provides 10 tools across three categories:
- **Read tools (2)**: `get_current_time`, `execute_sql`
- **Write tools (4)**: `create_or_update_dataset`, `create_or_update_location`, `create_or_update_cluster`, `create_or_update_pattern`
- **Import tools (2 MCP)**: `import_audio_files`, `import_ml_selections`

Plus resources (schema) and prompts (SQL workflow templates).

## Test Scripts

All scripts are in `shell_scripts/` and follow a consistent pattern.

### Read-Only Tests (No DB Modification)

```bash
cd shell_scripts

# Time tool (no database needed)
./test_time.sh

# SQL queries and security validation
./test_sql.sh

# Schema resources
./test_resources.sh

# All 6 MCP prompts
./test_prompts.sh

# Database integrity check
./test_db_state.sh
```

### Write Tests (Fresh DB Each Run)

These tests create a fresh copy of `skraak.duckdb` in `/tmp` and clean up automatically.

```bash
cd shell_scripts

# Create/update tools (dataset, location, cluster, pattern)
./test_write_tools.sh

# Import tools validation (error handling)
./test_import.sh
```

## Test Library

All tests source `test_lib.sh` for shared functionality:

```bash
source ./test_lib.sh

# Send MCP request
result=$(send_request "tools/call" '{"name":"execute_sql","arguments":{"query":"SELECT 1"}}')

# Run test with automatic tracking
run_test "Test name" "true" "$result"  # true = expect success

# Print summary
print_summary
```

### Key Functions

| Function | Description |
|----------|-------------|
| `send_request <method> <params> [db]` | Send single MCP request |
| `send_requests <db> <req1> <req2>...` | Send multiple requests in one session |
| `run_test <name> <expect_pass> <result>` | Track test pass/fail |
| `get_result <response>` | Extract result from response |
| `is_error <response>` | Check if response is error |
| `fresh_test_db` | Create fresh test DB in /tmp |
| `cleanup_test_db <path>` | Remove test DB and temp files |
| `print_summary` | Print test counts |

## Manual JSON-RPC Testing

You can test manually via stdin:

```bash
./skraak mcp --db ./db/test.duckdb
```

Then type JSON-RPC messages (one per line):

### Initialize
```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}
```

### List Tools
```json
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
```

### Execute SQL
```json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"execute_sql","arguments":{"query":"SELECT COUNT(*) FROM dataset WHERE active = true"}}}
```

### Create Dataset
```json
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"create_or_update_dataset","arguments":{"name":"Test Dataset","type":"test"}}}
```

### Get Schema Resource
```json
{"jsonrpc":"2.0","id":5,"method":"resources/read","params":{"uri":"schema://full"}}
```

### Get Prompt
```json
{"jsonrpc":"2.0","id":6,"method":"prompts/get","params":{"name":"query_active_datasets"}}
```

## SQL Query Examples

### Basic Queries

```sql
-- Active datasets
SELECT id, name, type FROM dataset WHERE active = true ORDER BY name

-- Parameterized query
SELECT id, name FROM location WHERE dataset_id = ? AND active = true

-- With limit
SELECT * FROM file WHERE active = true LIMIT 100
```

### JOINs

```sql
-- Dataset hierarchy with counts
SELECT d.name, COUNT(l.id) as locations, COUNT(f.id) as files
FROM dataset d
LEFT JOIN location l ON d.id = l.dataset_id
LEFT JOIN cluster c ON l.id = c.location_id
LEFT JOIN file f ON c.id = f.cluster_id
WHERE d.active = true
GROUP BY d.name
```

### Aggregates

```sql
-- Cluster statistics
SELECT COUNT(*) as files, SUM(duration) as total_seconds, AVG(duration) as avg_seconds
FROM file WHERE cluster_id = ? AND active = true
```

## Running Go Unit Tests

```bash
# All tests
go test ./...

# Specific package
go test ./utils/

# With coverage
go test -cover ./...

# Coverage report
go test -coverprofile=coverage.out ./utils/
go tool cover -html=coverage.out
```

**Test coverage**: 91.5% across 170+ tests

## Troubleshooting

| Issue | Solution |
|-------|----------|
| "skraak binary not found" | Run `go build` in project root |
| "Database not found" | Check path or use default |
| "Error: --db is required" | MCP command needs `--db path` |
| JSON parsing errors | Each message must be on one line |
| No response | Server outputs to stdout; check for errors in stderr |
| Test output too large | Tests print summary, not full output |

## Best Practices

1. **Run from shell_scripts directory**: Scripts use relative paths
2. **Use test.duckdb for manual testing**: Never use skraak.duckdb
3. **Write tests auto-clean**: They use /tmp and trap EXIT
4. **Check exit codes**: Tests return 0 on success, 1 on failure
5. **Run all tests before committing**: Ensures nothing is broken