Skip to main content

local-dev

Run, test, and debug the photofield server locally. Use when building, running, or testing the server, making API calls, calling MCP tools, or inspecting runtime state. Covers server lifecycle via `./tools/agent.sh server`, generic HTTP calls via `./tools/agent.sh api`, MCP tool calls, database inspection, error debugging, and common fixes.

Source facts

Repository
SmilyOrg/photofield
Last source activity
August 5, 2026 at 21:21
Detected SKILL.md language
English
Stars
608
Forks
16

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
local-dev
description
Run, test, and debug the photofield server locally. Use when building, running, or testing the server, making API calls, calling MCP tools, or inspecting runtime state. Covers server lifecycle via `./tools/agent.sh server`, generic HTTP calls via `./tools/agent.sh api`, MCP tool calls, database inspection, error debugging, and common fixes.
# Local Development — Running and Testing the Server This skill covers building, running, testing, and debugging the photofield server on your local machine. All tool invocation, server management, and API calls go through `./tools/agent.sh` — a unified harness that handles the server lifecycle, generic HTTP calls, and MCP tool invocation with session management, SSE parsing, and named-arg parsing. ## Verbose Flag The harness accepts `--verbose`, `-v`, and `-V`. Any of these can be placed directly after `./tools/agent.sh`: ```bash ./tools/agent.sh --verbose mcp call get_photo --file_id 1 ./tools/agent.sh -v mcp call get_photo --file_id 1 ./tools/agent.sh -V mcp call get_photo --file_id 1 ``` Or avoid the flag entirely via environment variable: ```bash AGT_VERBOSE=1 ./tools/agent.sh mcp call get_photo --file_id 1 ``` ## 1. Build ```bash go build -o photofield . ``` Kill any old instance before rebuilding: ```bash ./tools/agent.sh server kill ``` ## 2. Configuration The server reads `data/configuration.yaml`. Without it, collections point to empty directories. **Minimal setup:** ```bash mkdir -p data cat > data/configuration.yaml <<EOF collections: - name: test dirs: - docs/assets EOF ``` ## 3. Server Lifecycle Use `./tools/agent.sh server <command>` to manage the server process: ```bash # Start (auto-detects if already running) ./tools/agent.sh server start # Stop gracefully (uses PID file) ./tools/agent.sh server stop # Restart ./tools/agent.sh server restart # Check status (shows PID and port listeners) ./tools/agent.sh server status # Aggressive kill (PID file + all port listeners including exiftool) ./tools/agent.sh server kill ``` **How it works:** `server start` launches the binary with `nohup` and writes a PID file to `data/agent.pid`. It then polls the server endpoint until ready (up to 30s). `server stop` reads the PID file and sends SIGTERM. `server kill` sends SIGKILL to the PID and anything else listening on the port. **Important:** The server does **not** auto-scan. After starting, run a scan: ```bash ./photofield -scan test # or from another directory: AGT_BIN=/path/to/photofield ./tools/agent.sh server start && ./photofield -scan test ``` The server listens on port `8080` by default (override with `AGT_PORT`). **Note:** With `AGT_START=true` (the default), `mcp call`, `mcp quick`, and `mcp shell` will auto-start the server if it is not already running. The `server start`, `server stop`, `server restart`, `server status`, and `server kill` commands manage the process regardless of `AGT_START`. ### Stale PID cleanup If the server crashes without a clean shutdown, the PID file may become stale. The harness auto-detects this: `server start` will clean up a dead PID file and launch a new instance. `server status` also removes stale entries. ## 4. MCP Tool Calls Use `./tools/agent.sh mcp` to call MCP tools. The harness handles the session handshake (initialize + initialized notification), session ID extraction from response headers, SSE response parsing, and named-arg to JSON conversion. ### Tool commands ```bash # Call a tool with JSON args ./tools/agent.sh mcp call list_collections '{}' # Call with named args (auto-detects --key val pairs) ./tools/agent.sh mcp call search_photos --query 'beach' --collection_id 'test' --limit 3 # Verbose mode — shows full raw JSON response ./tools/agent.sh --verbose mcp call get_photo --file_id 1 --w 200 # Smoke test (calls list_collections by default) ./tools/agent.sh mcp quick # Smoke test with a specific tool ./tools/agent.sh mcp quick get_photo --file_id 1 # Interactive REPL ./tools/agent.sh mcp shell ``` ### Argument modes | Mode | Syntax | |------|--------| | JSON | `./tools/agent.sh mcp call <tool> '<json>'` | | Named | `./tools/agent.sh mcp call <tool> --key val` | Named args are auto-converted to JSON: numbers stay numeric, `true`/`false` become booleans, `null` stays null, everything else is quoted as strings. `agent.sh` auto-detects the named-arg mode when the first token starts with `--`, so no explicit `-- --` boundary is ever needed. ### Output Non-verbose mode shows a clean summary: ``` ✓ list_collections — 22 items ✓ events — 19 events ✓ get_photo ``` Errors show with a red ✗ and the error message. Set `--verbose` (see Verbose Flag above) for full raw JSON on every call. **Output streams:** The `log_*` helpers (`ℹ`, `▶`) go to stderr. Tool result summaries (`✓`, `✗`) and raw JSON output go to stdout. This lets you pipe tool results: `./tools/agent.sh mcp call list_collections '{}' | jq '.collections'`. ### From another directory ```bash AGT_BIN=/path/to/photofield ./tools/agent.sh mcp call list_collections '{}' AGT_URL=http://remote-host:9000/mcp ./tools/agent.sh mcp call list_collections '{}' ``` ## 5. Generic API Calls Use `./tools/agent.sh api` for arbitrary HTTP calls to any server endpoint. This is useful for testing non-MCP routes, debugging, or calling endpoints that don't have a dedicated tool. ```bash # GET request (health check) ./tools/agent.sh api GET http://localhost:8080/health # POST with JSON body ./tools/agent.sh api POST http://localhost:8080/api/collections \ '{"name":"my-collection","dirs":["/path/to/photos"]}' # POST with named args (auto-constructs JSON body) ./tools/agent.sh api POST http://localhost:8080/api/collections \ --name my-collection --dirs /path/to/photos # PUT / DELETE ./tools/agent.sh api DELETE http://localhost:8080/api/collections/test ``` The output shows the HTTP status code, pretty-printed JSON when possible, and the response body (truncated if over 500 chars). Note: `AGT_VERBOSE=1` does not currently change the truncation behavior for API calls. ### Health Check The server exposes a health check endpoint at `/health`: ```bash ./tools/agent.sh api GET http://localhost:8080/health ``` Returns `{"status": "ok"}` when healthy. ## 6. Test the Server ### Tool tests ```bash # Basic call ./tools/agent.sh mcp call get_photo --file_id 1 # Metadata-only call ./tools/agent.sh mcp call get_photo_metadata --file_id 1 # Error handling ./tools/agent.sh mcp call get_photo --file_id 999999 # Verbose debugging ./tools/agent.sh --verbose mcp call search_photos --query 'test' --collection_id 'test' ``` ### API tests ```bash # Check health ./tools/agent.sh api GET http://localhost:8080/health # List collections via API (alternative to mcp call) ./tools/agent.sh api GET http://localhost:8080/api/collections ``` ## 7. Inspect Errors and Crashes The harness captures the server's **entire stdout and stderr** to `data/agent.log` via `nohup`. Panics and errors appear in this log: ```bash tail -100 data/agent.log ``` ### Session warnings If the server does not return a `Mcp-Session-Id` header, the harness continues without one (some MCP servers don't require it). You will see a benign info message: `No session ID (server may not require one)`. | Symptom | Cause | Fix | |---------|-------|-----| | `cannot create context from nil parent` | Nil context passed to `WithTimeout` | Add `if ctx == nil { ctx = context.Background() }` in handler | | `file not found: N` | Photo ID doesn't exist | Scan collection or check DB | | Empty response data | Rendering panic | Check server log | | Schema says all fields required | SDK infers from Go struct pointers | Use explicit `InputSchema` in tool registration | | Server not responding | Old binary running | `./tools/agent.sh server kill` then rebuild | | No photos found | Config points to empty dirs | Create `data/configuration.yaml` | ## 8. Inspect Runtime State ### Database ```bash sqlite3 data/photofield.cache.db "SELECT id, width, height FROM infos ORDER BY id;" sqlite3 data/photofield.cache.db ".tables" ``` ### Via the harness ```bash # List collections ./tools/agent.sh mcp call list_collections '{}' # Check events for a collection ./tools/agent.sh mcp call events --collection_id 'test' # Search photos ./tools/agent.sh mcp call search_photos --query 'faces' --collection_id 'test' --limit 5 ``` ## Environment Variables | Variable | Default | Purpose | |----------|---------|---------| | `AGT_PORT` | `8080` | Server port | | `AGT_BIN` | `./photofield` | Path to binary | | `AGT_DATA_DIR` | `./data` | Data directory | | `AGT_START` | `true` | Auto-start server if not running | | `AGT_URL` | (derived) | Full MCP endpoint URL | | `AGT_API_BASE` | `http://localhost:$PORT` | Base URL for API calls | | `AGT_VERBOSE` | `0` | Verbose output | ## Quick Reference | Command | Purpose | |---------|---------| | `go build -o photofield .` | Build the server | | `./photofield -scan <name>` | Scan a collection | | `./tools/agent.sh server start` | Start the server | | `./tools/agent.sh server stop` | Stop the server | | `./tools/agent.sh server restart` | Restart the server | | `./tools/agent.sh server status` | Show PID/port status | | `./tools/agent.sh server kill` | Kill server processes | | `./tools/agent.sh mcp call <tool> <args>` | Call an MCP tool | | `./tools/agent.sh mcp quick [tool]` | Smoke test | | `./tools/agent.sh mcp shell` | Interactive REPL | | `./tools/agent.sh api <method> <url> [body]` | Generic HTTP call | | `./tools/agent.sh --verbose <cmd>` | Verbose output (see Verbose Flag above for `-v`/`-V`/env var) | | `sqlite3 data/photofield.cache.db ...` | Inspect the database |
View on GitHub