MCP server exposing django-silk profiling data as AI assistant tools
Strong tool definitions with comprehensive descriptions (avg 180 chars, well above 34-char baseline) and clear parameter documentation. All 12 tools have explicit schemas with typed inputs. Tool names follow verb_noun pattern (get_*, explain_*). Key strengths: excellent contextual descriptions explaining WHEN to use each tool and dependencies between them (e.g., 'Pass request_id from get_slow_requests'). Weaknesses: output schemas not visible in source (only input schemas documented); no enum constraints on string parameters; error handling guidance minimal; some parameter descriptions could be more prescriptive about valid ranges.
Show the last N *distinct* requests to request_path with timing and query counts. Use this after applying an optimization to confirm it actually improved performance. Near-simultaneous requests (within 2 seconds of each other) are deduplicated: only the slowest one per burst is kept. This filters out cache-warmed follow-up hits that fire milliseconds after the real request and would otherwise look like a speedup.
Run EXPLAIN (ANALYZE, BUFFERS) on queries slower than threshold_ms for request_path. Reveals missing indexes, sequential scans, and bad join strategies. Only runs on SELECT queries to avoid side effects. Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Parse cProfile data stored on the latest request and rank Python functions by cumulative time (cumtime). Requires SILKY_PYTHON_PROFILER=True in settings. Args: request_path: The endpoint path to analyze. request_id: Pin analysis to a specific request ID (from get_slow_requests/compare_requests) instead of the most recent one matching request_path. top_n: Number of top functions to return (default 20). project_only: Strip site-packages / stdlib frames and show only project code (default True). Set False to see the full call tree.
Detect N+1 patterns for the latest request to request_path. Groups structurally identical queries (same template, different params). Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Output schemas not documented in source code. Only input schemas visible; return types and field structures not specified. LLMs cannot plan downstream tool calls or extract required fields without knowing output structure.
String parameters (request_path, table_filter) lack enum constraints or format specifications. LLMs may pass invalid paths or filter values without validation guidance.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 68 | 2026-07-28+ | v2 |
Rank all recorded endpoints by average DB time. Use this first to decide which endpoint to investigate.
Compare columns fetched by SQL against fields exposed by the serializer. Identifies candidates for .only() to avoid loading unused columns. WARNING: Adding .only() can cause extra queries if anything outside the serializer accesses a deferred field (signals, permissions, __str__, etc.). Always verify first. Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Show @silk_profile decorated function timings for the latest request. Requires endpoints or functions to be decorated with @silk_profile. Each block shows total time, DB time, pure-Python time, and query count — making it easy to spot Python-bound bottlenecks that SQL optimization won't fix. Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Show which project code lines triggered each SQL query for the latest request. Strips Django/library internals — shows only your code's stack frames. Use this to know exactly which line to add select_related/prefetch_related. Args: request_path: The endpoint path to analyze. request_id: Pin analysis to a specific request ID (from get_slow_requests/compare_requests) instead of the most recent one matching request_path. table_filter: Optional table name substring to filter queries (e.g. "auth_user"). When provided, only queries whose SQL contains this string are shown.
Return all SQL queries fired during the latest request to request_path. Use summary_only=True to get just timing and a truncated SQL preview per query, avoiding large responses when there are many or complex queries. Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Break down the latest request to request_path into DB time vs Python time. Determines whether query optimization will have high impact before diving deeper. Pass request_id (from get_slow_requests/compare_requests) to pin analysis to a specific request instead of the most recent one matching request_path.
Return the slowest individual SQL queries across all recorded requests.
Return HTTP requests with total time above threshold_ms, worst first.
Numeric parameters (threshold_ms, limit, top_n) lack explicit min/max bounds in schema. Descriptions mention constraints (e.g., 'limit' capped at 500 in helpers.py) but not visible in tool definitions. LLMs may pass out-of-range values.
Error handling guidance minimal. Tools validate inputs (helpers.py: _check_limit, _check_threshold_ms, _check_request_id) but error messages not documented in tool descriptions. LLMs lack recovery guidance when calls fail.
Mandatory resource read (silk://guide) enforced via instructions but not as a tool dependency. LLMs may skip the guide if they believe they have sufficient context, violating the 'NO EXCEPTIONS' requirement.