diagram
GAgarrytan/gstack136k883 new stars in the last 7 days
Design and document new features with GitHub issue, low-level design (LLD), expert review, and testing plan. Creates structured documentation in .scratchpad/ with issue spec, technical design with diagrams and pseudo-code, multi-persona expert review, and a testing plan covering functional (curl and registry_management.py), backwards-compatibility, UX, ECS/terraform, and E2E API tests. Supports starting from a user description OR an existing GitHub issue URL. Folder naming: issue-{number}/ for existing issues, {feature-name}/ for new features.
Use this skill when the user wants to design a new feature for the MCP Gateway Registry. This skill creates comprehensive design documentation that enables entry-level developers to implement the feature.
This skill supports two input modes:
When the user invokes this skill:
https://github.com/owner/repo/issues/123), use GitHub Issue URL Mode.scratchpad/{feature-name}/ directorygithub-issue.md for issue creationlld.md with technical detailsreview.md with multi-persona feedbacktesting.md with functional, backwards-compat, UX, ECS, and E2E tests.html for each document with scripts/render-doc-html.pygh CLI.scratchpad/issue-{number}/ directory (e.g., issue-500 for GitHub issue #500)github-issue.md summarizing the existing issuelld.md with technical detailsreview.md with multi-persona feedbacktesting.md with functional, backwards-compat, UX, ECS, and E2E tests.html for each document with scripts/render-doc-html.pyWhen a user provides a GitHub issue URL, fetch the issue content using the gh CLI:
# Extract owner, repo, and issue number from URL
# URL format: https://github.com/{owner}/{repo}/issues/{number}
# Fetch issue details
gh issue view {number} --repo {owner}/{repo} --json title,body,labels,state,assignees,comments
# For more context, also fetch related PRs if any
gh issue view {number} --repo {owner}/{repo} --json linkedPullRequests
After fetching the issue, analyze it for:
Existing Requirements
Existing Design Elements
Discussion Context
Metadata
Create a summary document that captures what was found:
# GitHub Issue Analysis: #{issue_number}
*Source: {issue_url}*
*Fetched: {date}*
## Issue Overview
| Field | Value |
|-------|-------|
| Title | {title} |
| State | {state} |
| Labels | {labels} |
| Assignees | {assignees} |
## Extracted Requirements
### Problem Statement
{extracted or "Not explicitly stated - needs clarification"}
### User Stories
{extracted user stories or "None found"}
### Acceptance Criteria
{extracted criteria or "Not defined - will need to establish"}
### Scope
{inferred scope or "Not specified"}
## Existing Design Elements
### Technical Proposals
{any technical details from issue body}
### Architecture Suggestions
{any architecture mentioned}
### API Design
{any API designs proposed}
### Open Questions in Issue
{questions raised but not answered}
## Discussion Summary
### Key Decisions Made
{decisions from comments}
### Concerns Raised
{concerns from team members}
### Alternative Approaches Mentioned
{alternatives discussed}
## Gaps Identified
The following information is missing and needs clarification:
1. {gap 1}
2. {gap 2}
Based on the analysis, ask the user only about gaps not covered in the issue:
Example prompt:
I've analyzed GitHub issue #{number}: "{title}"
The issue provides:
- {what's available}
However, I need clarification on:
1. {gap question 1}
2. {gap question 2}
Also, the issue discusses two approaches for {topic}:
- Option A: {description}
- Option B: {description}
Which approach should we pursue in the design?
Before creating any files, ask the user:
Before creating any design documents, perform a quick exploration of the codebase to understand:
Project Structure - Use Glob to understand the overall directory layout
registry/, src/, etc.)Related Components - Search for existing features similar to the one being designed
Entry Points - Understand how the application is structured
This quick review should take 5-10 minutes and helps you ask better clarifying questions and avoid proposing designs that conflict with existing architecture.
IMPORTANT: Use different naming conventions based on the input mode:
| Input Mode | Folder Name | Example |
|---|---|---|
| GitHub Issue URL Mode | issue-{number}/ | issue-500/ for GitHub issue #500 |
| User Description Mode | {feature-name}/ | rate-limiting/ for a rate limiting feature |
This convention makes it easy to:
Create the folder structure:
.scratchpad/issue-{number}/ # For GitHub Issue URL Mode
# OR
.scratchpad/{feature-name}/ # For User Description Mode
├── github-issue.md # GitHub issue specification or summary
├── lld.md # Low-level design document
├── review.md # Expert review document
├── testing.md # Testing plan (functional, backwards-compat, UX, ECS, E2E)
├── diagrams/ # Optional: <key>.svg files inlined into the HTML
├── github-issue.html # Generated (see Step 9)
├── lld.html # Generated
├── review.html # Generated
└── testing.html # Generated
The four markdown files are the source of truth. The .html files are build artifacts produced in Step 9; never hand-edit them.
For User Description Mode: Create a comprehensive GitHub issue specification.
For GitHub Issue URL Mode: Create a summary document that consolidates the existing issue content with any clarifications gathered. Use the "Issue Summary from URL" template below instead.
# GitHub Issue: {Feature Title}
## Title
{concise title for the issue}
## Labels
- {appropriate labels from: enhancement, feature-request, api, frontend, backend, etc.}
## Description
### Problem Statement
{What problem does this solve? Why is it needed?}
### Proposed Solution
{High-level description of the solution}
### User Stories
- As a {user type}, I want to {action} so that {benefit}
- ...
### Acceptance Criteria
- [ ] {Criterion 1}
- [ ] {Criterion 2}
- ...
### Out of Scope
- {What is explicitly NOT included}
### Dependencies
- {Any dependent issues or external dependencies}
### Related Issues
- #{issue numbers if any}
When working from an existing GitHub issue, create a summary document:
# Issue Summary: {Issue Title}
*Source Issue: [{owner}/{repo}#{number}]({issue_url})*
*Fetched: {date}*
*Status: {open/closed}*
## Issue Metadata
| Field | Value |
|-------|-------|
| Labels | {labels} |
| Assignees | {assignees} |
| Created | {created_date} |
| Last Updated | {updated_date} |
## Original Problem Statement
{Copy or summarize the problem statement from the issue body}
## Requirements Extracted
### From Issue Body
{Requirements found in the original issue}
### From Discussion (Comments)
{Additional requirements or clarifications from comments}
### Clarified with User
{Any requirements clarified during our conversation}
## Existing Design Elements
{Any technical proposals, architecture suggestions, or design decisions already in the issue}
### Technical Approach
{If specified in the issue}
### API Design
{If specified in the issue}
### Data Models
{If specified in the issue}
## Acceptance Criteria
### From Issue
{Criteria from the original issue}
### Additional (Established)
{Any additional criteria we established}
## Scope
{Scope as defined or inferred from the issue}
## Out of Scope
{What is explicitly excluded}
## Key Decisions from Discussion
| Decision | Context | Decided By |
|----------|---------|------------|
| {decision} | {why} | {who/when} |
## Open Questions Resolved
| Question | Resolution |
|----------|------------|
| {question from issue} | {answer we determined} |
## Dependencies
{Any dependencies mentioned in the issue}
## Notes
{Any additional context or notes relevant to the design}
CRITICAL: Before writing the LLD, you MUST thoroughly understand all relevant code in the repository. This is not optional - a design that doesn't account for existing code patterns will fail during implementation.
REQUIRED: theory alignment. Read Theory of the System and check the proposed feature against its core invariants (single control plane for all asset types; the gateway is a generic reverse proxy and the registry is the control plane; registry is control-plane-not-data-path for A2A;
DEPLOYMENT_MODEvsREGISTRY_MODE; three-surface config parity; fail-closed admission vs fail-open notification; IdP-agnostic across a closed provider factory; MCP spec compliance). Use the doc's "how to change this system without breaking its theory" checklist. If the design would violate an invariant, flag it explicitly to the user in the LLD (a "Theory impact" note) and in the Expert Review. A deliberate theory change is allowed, but it must be called out and argued, never slipped in. State which invariant is affected and the justification.
Existing Models and Data Structures
registry/models/Service Layer Patterns
registry/services/Route/API Patterns
registry/routes/Storage Layer
registry/storage/Configuration and Constants
Existing Tests
tests/Use the Task tool with subagent_type=Explore for thorough investigation:
Task tool with prompt: "Thoroughly analyze the service layer patterns in registry/services/.
Read all service files and document: 1) Common patterns used, 2) Error handling approaches,
3) Logging conventions, 4) Any base classes or utilities, 5) How services interact with storage."
For each area, you should:
Create a brief section in your LLD documenting:
Create a detailed technical design document. This is the most critical document - it should contain enough detail for an entry-level developer to implement the feature.
# Low-Level Design: {Feature Name}
*Created: {date}*
*Author: Claude*
*Status: Draft*
## Table of Contents
1. [Overview](#overview)
2. [Codebase Analysis](#codebase-analysis)
3. [Architecture](#architecture)
4. [Data Models](#data-models)
5. [API Design](#api-design)
6. [Configuration Parameters](#configuration-parameters)
7. [New Dependencies](#new-dependencies)
8. [Implementation Details](#implementation-details)
9. [Observability](#observability)
10. [Scaling Considerations](#scaling-considerations)
11. [File Changes](#file-changes)
12. [Testing Strategy](#testing-strategy)
13. [Alternatives Considered](#alternatives-considered)
14. [Rollout Plan](#rollout-plan)
## Overview
### Problem Statement
{Detailed problem description}
### Goals
- {Goal 1}
- {Goal 2}
### Non-Goals
- {What this design explicitly does NOT address}
### Theory Impact
{State whether this feature upholds or changes any core invariant in
[Theory of the System](../../../docs/design/theory-of-the-system.md). Default: "No invariant
affected." If an invariant IS affected, name it, explain why the change is deliberate and
justified, and note the consequence. This is a flag for the reviewer rather than something to bury.}
## Codebase Analysis
*Summary of the deep codebase analysis performed before writing this LLD.*
### Key Files Reviewed
| File/Directory | Purpose | Relevance to This Feature |
|----------------|---------|---------------------------|
| `registry/models/{model}.py` | {Description} | {How it relates} |
| `registry/services/{service}.py` | {Description} | {How it relates} |
| `registry/routes/{route}.py` | {Description} | {How it relates} |
### Existing Patterns Identified
1. **Pattern Name**: {Description of the pattern and where it's used}
- Files: `{file1.py}`, `{file2.py}`
- How we'll follow this: {How the new feature will use this pattern}
2. **Pattern Name**: {Description}
- Files: `{files}`
- How we'll follow this: {How we'll apply it}
### Integration Points
| Component | Integration Type | Details |
|-----------|------------------|---------|
| {Existing component} | {Extends/Uses/Depends on} | {Specific integration details} |
### Constraints and Limitations Discovered
- {Constraint 1}: {How it affects the design}
- {Constraint 2}: {How it affects the design}
### Code Snippets Reference
{Include relevant code snippets from existing codebase that the new feature will integrate with or follow patterns from}
```python
# From registry/services/example_service.py:45-60
# This shows the pattern we'll follow for...
def existing_pattern_example():
pass
{ASCII diagram showing how this feature fits into the overall system}
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Component A │────▶│ New Feature │────▶│ Component B │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
{Show the flow of requests/data}
User Frontend Backend Database
│ │ │ │
│──── Request ──▶│ │ │
│ │── API Call ──▶│ │
│ │ │── Query ────▶│
│ │ │◀── Result ───│
│ │◀── Response ─│ │
│◀── Display ───│ │ │
{Show internal components and their relationships}
{Define any new Pydantic models with full field definitions}
class NewModel(BaseModel):
"""Description of the model."""
field_name: str = Field(
...,
description="What this field represents",
min_length=1,
max_length=100
)
optional_field: Optional[int] = Field(
default=None,
description="Optional field description"
)
{Changes to existing models}
{If applicable, show collection/table changes}
{For each read path the feature introduces, state how the data is fetched.
Any time you need a count or lookup over a list of items, design a single bulk
query or aggregation ($group/$sum/$in/batched fetch) rather than one
query per item. Do NOT design a for loop that awaits a repository call per
element. If a per-item read seems unavoidable, justify why and bound the item
count. Note any new repository method (e.g. a count_* aggregation) the design
needs so it does not fall back to loading and counting in Python.}
Description: {What this endpoint does}
Request:
{
"field": "value"
}
Response (200 OK):
{
"id": "123",
"status": "success"
}
Error Responses:
{Changes to existing endpoints}
IMPORTANT: Clearly document all new configuration parameters this feature requires.
| Variable Name | Type | Default | Required | Description |
|---|---|---|---|---|
FEATURE_ENABLED | bool | true | No | Enable/disable the feature |
FEATURE_INTERVAL_SECONDS | int | 30 | No | Polling interval in seconds |
Add to registry/core/config.py:
# Feature-specific settings
feature_enabled: bool = Field(
default=True,
description="Enable/disable feature X"
)
feature_interval_seconds: int = Field(
default=30,
description="Interval for feature X operations"
)
{Any validation rules for configuration values}
CRITICAL: Every new configuration parameter must be propagated to all three deployment surfaces AND documented in the unified parameter reference. Use the checklist below and fill in the file-level details for each new parameter.
The project maintains a single cross-surface mapping of every parameter at docs/unified-parameter-reference.md. This is the authoritative index for how each logical parameter is named on each surface. You must update it whenever a parameter is added, renamed, removed, or re-scoped.
| File | What to Add | Done? |
|---|---|---|
docs/unified-parameter-reference.md | Add one row per new parameter to the correct logical group table: parameter name, Docker .env var, Terraform .tfvars var, Helm values path, purpose. Mark secrets with (secret). If no existing group fits, add a new group section and explain why in the PR description. If a surface legitimately does not expose the parameter, leave the cell blank and note the reason in the PR. | [ ] |
Verification: grep the new variable name across .env.example, terraform/aws-ecs/terraform.tfvars.example, charts/, AND docs/unified-parameter-reference.md. It must appear in all surfaces that the reference file claims it does.
| File | What to Add | Done? |
|---|---|---|
.env.example | Variable with description and default value | [ ] |
.env | Variable with the actual deployment value | [ ] |
docker-compose.yml | Pass variable to the correct service(s) environment block | [ ] |
docker-compose.podman.yml | Same as above (Podman variant) | [ ] |
docker-compose.prebuilt.yml | Same as above (prebuilt-image variant) | [ ] |
| File | What to Add | Done? |
|---|---|---|
terraform/aws-ecs/variables.tf | Root variable definition with description and default | [ ] |
terraform/aws-ecs/main.tf | Pass the variable into the module call | [ ] |
terraform/aws-ecs/modules/mcp-gateway/variables.tf | Module-level variable definition | [ ] |
terraform/aws-ecs/modules/mcp-gateway/ecs-services.tf | Map variable to container environment in ECS task definition | [ ] |
terraform/aws-ecs/terraform.tfvars.example | Documented example value | [ ] |
Sensitive values (tokens, private keys) must use AWS Secrets Manager references.
| File | What to Add | Done? |
|---|---|---|
charts/registry/values.yaml (or the correct subchart) | Default value under the appropriate section | [ ] |
charts/mcp-gateway-registry-stack/values.yaml | Default value (stack-level chart) | [ ] |
charts/<subchart>/templates/secret.yaml | Add variable if sensitive (base64-encoded), plus support existingSecret / secretKeyRef | [ ] |
charts/<subchart>/templates/deployment.yaml | Map value to container env var (plain or secretKeyRef) | [ ] |
Sensitive values must support secretKeyRef for Kubernetes secrets.
New config params must appear on the System Config page in the UI. This requires backend and possibly frontend changes.
| File | What to Add | Done? |
|---|---|---|
registry/api/config_routes.py | Add field to CONFIG_GROUPS dict with (field_name, display_label, is_sensitive). Sensitive fields must have is_sensitive=True so they are masked via _mask_sensitive_value(). | [ ] |
Frontend (ConfigPanel.tsx) | Auto-renders fields from /api/config/full. Update only if the new parameters need special UI treatment (toggles, grouped display, color-coded status, etc.). | [ ] |
Verify after deployment: navigate to the System Config page and confirm the new parameter(s) appear with correct values and labels. Sensitive values should be masked. The same data is also available programmatically via GET /api/config/full (admin auth required) and can be exported via GET /api/config/export?format={env|json|tfvars|yaml}.
IMPORTANT: List all new Python packages or libraries required by this feature.
| Package | Version | Purpose | Added By |
|---|---|---|---|
package-name | latest | {Why needed} | Backend |
another-package | latest | {Why needed} | Frontend |
# Add to pyproject.toml
uv add package-name
If no new dependencies are required, explicitly state:
File: path/to/file.py
Lines: {approximate line numbers or "new file"}
# Pseudo-code or actual code
def new_function(
param1: str,
param2: int
) -> dict:
"""
Description of what this function does.
Args:
param1: Description
param2: Description
Returns:
Description of return value
"""
# Step 1: Validate input
if not param1:
raise ValueError("param1 is required")
# Step 2: Process data
result = process_data(param1, param2)
# Step 3: Return response
return {"status": "success", "data": result}
{Continue with detailed steps...}
{How errors should be handled}
{What should be logged and at what level}
{Define trace spans for this feature}
| Span Name | Attributes | Parent Span |
|---|---|---|
feature.operation_name | param1, param2 | http.request |
{Define metrics to track for this feature}
| Metric Name | Type | Labels | Description |
|---|---|---|---|
feature_requests_total | Counter | status, endpoint | Total requests |
feature_duration_seconds | Histogram | operation | Operation duration |
{Key operations that should emit logs}
| Log Level | Event | Data to Include |
|---|---|---|
| INFO | Operation started | request_id, user_id |
| ERROR | Operation failed | error_type, context |
{Expected request volume and data size}
{How this feature scales across multiple instances}
{Potential bottlenecks and mitigation strategies}
{If applicable, what can be cached and for how long}
| File Path | Description |
|---|---|
registry/routes/new_feature.py | API routes for new feature |
registry/services/new_feature_service.py | Business logic |
tests/unit/test_new_feature.py | Unit tests |
| File Path | Lines | Change Description |
|---|---|---|
registry/main.py | ~50 | Add router import and include |
registry/models/domain.py | ~100-150 | Add new model |
When new API endpoints are added or modified, the following files MUST also be updated:
| File Path | Update Required |
|---|---|
api/registry_client.py | Add Pydantic response models and client methods for new endpoints |
api/registry_management.py | Add CLI commands (argparse parsers) and handler functions |
api/openapi.json | Regenerate. Not auto-generated and not checked by CI, so a new endpoint is invisible to API consumers until someone refreshes it by hand. See below. |
Example additions for a new endpoint GET /api/feature/{path}/data:
# In api/registry_client.py:
class FeatureDataResponse(BaseModel):
"""Response model for feature data endpoint."""
path: str = Field(..., description="Feature path")
data: dict = Field(..., description="Feature data")
def get_feature_data(self, path: str) -> FeatureDataResponse:
"""Get feature data from the registry."""
response = self._make_request("GET", f"/api/feature/{path}/data")
return FeatureDataResponse(**response)
# In api/registry_management.py:
def cmd_feature_data(args: argparse.Namespace) -> None:
"""Get feature data command handler."""
client = _get_client(args)
result = client.get_feature_data(path=args.path)
# Display result...
This ensures the registry management CLI stays in sync with backend API capabilities.
api/openapi.jsonAny design that adds or changes a route must include this as an explicit task, because nothing enforces it: there is no generator script and no CI check, so the spec drifts silently. It has already shipped stale, missing endpoints from several merged PRs at once.
# The container MUST be built from the commit being documented.
curl -s http://localhost/openapi.json > /tmp/live.json
python3 - <<'PYEOF'
import json, pathlib
spec = json.load(open("/tmp/live.json"))
spec["info"]["version"] = "X.Y.Z" # the release this lands in, NOT the app's dev string
pathlib.Path("api/openapi.json").write_text(json.dumps(spec, indent=2) + "\n")
PYEOF
Do not pass ensure_ascii=False: it rewrites every non-ASCII character in every docstring and buries the real change in hundreds of lines of diff. Full procedure and the semantic-diff check in AGENTS.md.
| Category | Lines |
|---|---|
| New Python code | ~{X} |
| New test code | ~{X} |
| Modified code | ~{X} |
| Total | ~{X} |
IMPORTANT: Explicitly list all new test files and test cases required for this feature.
| Test File | Type | Description |
|---|---|---|
tests/unit/services/test_feature_service.py | Unit | Service layer unit tests |
tests/unit/repositories/test_feature_repository.py | Unit | Repository unit tests |
tests/integration/test_feature_integration.py | Integration | End-to-end integration tests |
tests/unit/api/test_feature_routes.py | Unit | API route unit tests |
List specific unit test cases:
| Test Case | File | What It Tests |
|---|---|---|
test_happy_path | test_feature_service.py | Normal operation with valid inputs |
test_error_handling | test_feature_service.py | Error cases and edge conditions |
test_validation | test_feature_service.py | Input validation logic |
Example unit test structure:
class TestNewFeature:
"""Tests for new feature."""
def test_happy_path(self):
"""Test normal operation."""
# Arrange
input_data = {...}
# Act
result = function_under_test(input_data)
# Assert
assert result["status"] == "success"
def test_error_case(self):
"""Test error handling."""
with pytest.raises(ValueError):
function_under_test(None)
List specific integration test cases:
| Test Case | File | What It Tests |
|---|---|---|
test_end_to_end_flow | test_feature_integration.py | Complete feature workflow |
test_database_persistence | test_feature_integration.py | Data is correctly persisted |
test_concurrent_operations | test_feature_integration.py | Concurrency handling |
{Steps for manual verification}
IMPORTANT: Document alternative approaches that were considered and why they were rejected.
Description: {Brief description of the alternative}
Pros:
Cons:
Why Rejected: {Clear explanation of why this wasn't chosen}
Description: {Brief description}
Pros:
Cons:
Why Rejected: {Explanation}
| Criteria | Chosen Approach | Alternative 1 | Alternative 2 |
|---|---|---|---|
| Complexity | Low | Medium | High |
| Performance | Good | Better | Best |
| Maintainability | High | Medium | Low |
| Implementation Time | 1 week | 2 weeks | 3 weeks |
## Step 7: Expert Review (review.md)
Create a review document with feedback from multiple expert personas:
```markdown
# Expert Review: {Feature Name}
*Review Date: {date}*
*LLD Version: 1.0*
## Review Panel
| Role | Reviewer | Status |
|------|----------|--------|
| Frontend Engineer | Pixel | Pending |
| Backend Engineer | Byte | Pending |
| SRE/DevOps Engineer | Circuit | Pending |
| Security Engineer | Cipher | Pending |
| SMTS (Overall) | Sage | Pending |
---
## Frontend Engineer Review
**Reviewer:** Pixel
**Focus Areas:** UI/UX, React components, state management, API integration
### Assessment
#### Strengths
- {Positive aspects of the design from frontend perspective}
#### Concerns
- {Issues or risks identified}
#### New Libraries Required
| Library | Version | Purpose | Justification |
|---------|---------|---------|---------------|
| `library-name` | `latest` | {What it does} | {Why it's needed vs alternatives} |
| None | - | - | No new frontend dependencies required |
#### Better Alternatives Considered
{Are there better frontend approaches? Discuss alternatives like different state management, component libraries, etc.}
#### Recommendations
1. {Specific recommendation}
2. {Specific recommendation}
#### Questions for Author
- {Questions that need clarification}
### Verdict: {APPROVED / APPROVED WITH CHANGES / NEEDS REVISION}
---
## Backend Engineer Review
**Reviewer:** Byte
**Focus Areas:** API design, data models, business logic, database queries, performance
### Assessment
#### Strengths
- {Positive aspects from backend perspective}
#### N+1 Access Pattern Check (MANDATORY)
Inspect every data-access path in the design. Flag any pattern that reads from
a database or data source once per item (a `count()` / `find_one()` / `get()` /
`distinct()` or repository call inside a `for`/`while`/comprehension/per-item
callback, or a service that internally queries per element). State the fix: a
single bulk query or aggregation (`$group`/`$sum`/`$in`/batched fetch) outside
the loop. `asyncio.gather` over a per-item list is still N+1 round-trips; flag
it unless the item count is small and bounded.
- **N+1 patterns:** {None found / FLAGGED: <where + the per-item read and the bulk-query fix>}
#### Concerns
- {Issues or risks identified}
#### New Libraries Required
| Library | Version | Purpose | Justification |
|---------|---------|---------|---------------|
| `library-name` | `latest` | {What it does} | {Why it's needed vs alternatives} |
| None | - | - | No new backend dependencies required |
#### Better Alternatives Considered
{Are there better backend approaches? Discuss alternatives like different algorithms, data structures, caching strategies, etc.}
#### Recommendations
1. {Specific recommendation}
2. {Specific recommendation}
#### Questions for Author
- {Questions that need clarification}
### Verdict: {APPROVED / APPROVED WITH CHANGES / NEEDS REVISION}
---
## SRE/DevOps Engineer Review
**Reviewer:** Circuit
**Focus Areas:** Deployment, monitoring, scaling, infrastructure, reliability
### Assessment
#### Strengths
- {Positive aspects from SRE perspective}
#### Concerns
- {Issues or risks identified}
#### Infrastructure Dependencies
| Resource | Type | Purpose | Cost Impact |
|----------|------|---------|-------------|
| `resource-name` | AWS Service / Tool | {What it does} | {Estimated cost} |
| None | - | - | No new infrastructure required |
#### Better Alternatives Considered
{Are there better infrastructure approaches? Discuss alternatives like different AWS services, deployment strategies, monitoring tools, etc.}
#### Recommendations
1. {Specific recommendation}
2. {Specific recommendation}
#### Operational Checklist
- [ ] Monitoring/alerting considered
- [ ] Logging sufficient for debugging
- [ ] Graceful degradation planned
- [ ] Rollback strategy defined
- [ ] Resource requirements estimated
### Verdict: {APPROVED / APPROVED WITH CHANGES / NEEDS REVISION}
---
## Security Engineer Review
**Reviewer:** Cipher
**Focus Areas:** Authentication, authorization, input validation, data protection, OWASP
> **Before writing this section, read [security-patterns.md](../pr-review/personas/security-patterns.md)**. It is the catalog of security defects that have shipped and been fixed in this project. Design the feature so it does not reintroduce any of them (SSRF on outbound fetches, broken access control / info disclosure on new endpoints, weak defaults, token-boundary confusion, missing CSRF, injection, log/secret leakage, agent execution safety). Call out in the Concerns/Recommendations below which patterns this feature touches and how the design avoids them.
### Assessment
#### Strengths
- {Positive aspects from security perspective}
#### Concerns
- {Issues or risks identified}
#### Security Checklist
See [security-patterns.md#review-checklist](../pr-review/personas/security-patterns.md#review-checklist) for the full per-pattern list. Key items:
- [ ] Outbound fetches of stored/request-supplied URLs go through the SSRF guard (pattern #1)
- [ ] New GET endpoints strip backend URLs for non-admins; mutations 404-then-403 on resolved identity (pattern #2)
- [ ] No new secret ships with a working default; new env vars added to reserved-name + weak-secret lists (pattern #3)
- [ ] Inbound auth headers stripped on egress; JWTs verified; no client-supplied session id trusted (pattern #4)
- [ ] Every mutating endpoint carries the CSRF dependency (pattern #5)
- [ ] No untrusted input interpolated into nginx/query/HTML/href without escaping (pattern #6)
- [ ] No secrets/headers/OIDC claim values logged; secret fields write-only in responses (pattern #7)
- [ ] Mutating agent tools gated behind confirmation; agent endpoints authenticate (pattern #9)
#### Recommendations
1. {Specific recommendation}
2. {Specific recommendation}
### Verdict: {APPROVED / APPROVED WITH CHANGES / NEEDS REVISION}
---
## SMTS Overall Review
**Reviewer:** Sage
**Focus Areas:** Architecture, code quality, maintainability, alignment with project goals
### Executive Summary
{2-3 sentence summary of the design and overall assessment}
### Architecture Assessment
- **Alignment with existing patterns:** {Good/Needs Work}
- **Maintainability:** {Good/Needs Work}
- **Scalability:** {Good/Needs Work}
- **Testability:** {Good/Needs Work}
### Cross-Cutting Concerns
{Issues that span multiple review areas}
### Final Recommendations
1. **Must Fix (Blockers):**
- {Critical issues that must be addressed}
2. **Should Fix (Important):**
- {Important issues to address before implementation}
3. **Consider (Nice to Have):**
- {Suggestions for improvement}
### Overall Verdict: {APPROVED / APPROVED WITH CHANGES / NEEDS REVISION}
---
## Review Summary
| Reviewer | Verdict | Blockers | Key Concerns |
|----------|---------|----------|--------------|
| Frontend | {verdict} | {count} | {summary} |
| Backend | {verdict} | {count} | {summary} |
| SRE/DevOps | {verdict} | {count} | {summary} |
| Security | {verdict} | {count} | {summary} |
| SMTS | {verdict} | {count} | {summary} |
### Next Steps
1. {Action item}
2. {Action item}
3. {Action item}
### Sign-Off
- [ ] All blockers resolved
- [ ] Design updated based on feedback
- [ ] Ready for implementation
README.md: feature documentation goes to the feature's own
docs page (create one if it lacks one) and, on release, to docs/release-notes/ plus a single
curated highlight in docs/overview/feature-release-highlights.md. The README's "What's New"
section is limited to the 3 most-recent highlights and is rotated only by the release-notes
skill; it has a CI-enforced 350-line budget. A design must not plan to add README sections or
inline feature blurbs. Call out the docs page it will add instead.User: "Design a new feature for rate limiting on tool calls"
.scratchpad/rate-limiting/github-issue.md with rate limiting requirementslld.md with:
review.md with expert feedback on:
testing.md with:
registry_management.py tests for any new CLI flagsRATE_LIMIT_REDIS_URL)User: "https://github.com/agentic-community/mcp-gateway-registry/issues/456"
gh issue view 456 --repo agentic-community/mcp-gateway-registry --json title,body,labels,state,comments.scratchpad/issue-456/ (folder named after the GitHub issue number)github-issue.md summarizing the issue with clarificationslld.md incorporating:
review.md with expert feedbacktesting.md with:
registry_management.py tests for any new sync-related CLI commandsFEDERATION_PEER_URLS, FEDERATION_SYNC_INTERVAL_SECONDS)Create a comprehensive testing plan document that captures executable, copy-pasteable tests covering every externally observable change introduced by the feature. The goal is for a reviewer or implementer to be able to walk through this document and verify the feature works end-to-end without having to invent test cases.
Include a category only when it is relevant to the feature. Mark a category "Not Applicable" with a short justification when it does not apply.
| Category | Include When |
|---|---|
| Functional Tests (curl) | Feature adds/modifies any HTTP endpoint |
| Functional Tests (registry_management.py) | Feature adds/modifies anything exposed via the management CLI |
| Backwards Compatibility Tests | Feature changes an existing endpoint, schema, CLI command, config default, or data model |
| UX Tests | Feature adds/changes any UI surface (web UI, CLI output formatting, error messages shown to users) |
| Deployment Surface Tests (Docker, ECS, Helm) | Feature adds or modifies any config parameter (env var, setting, Terraform variable, Helm value, secret) across Docker, ECS/Terraform, or Helm/EKS deployments |
| Nginx Routing / MCP Proxy Tests | Feature touches nginx config generation (nginx_service.py), auth server mcp-proxy (/mcp-proxy/), or any proxy_pass/location-block logic |
| E2E API Tests | Feature adds a new user-visible workflow that spans multiple endpoints or services |
Any change that impacts nginx routing (in registry/core/nginx_service.py, auth_server/server.py mcp-proxy, or nginx template files) MUST include an end-to-end MCP client connectivity test. This is because:
Required test for any nginx routing change:
# Verify ai-registry-tools (mcpgw) is reachable through the full proxy chain
TOKEN="<valid JWT>"
curl -X POST \
-H "X-Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}' \
"https://<registry-url>/airegistry-tools/mcp"
# Expected: 200 OK with JSON-RPC response containing serverInfo
# Failure: 502/404/405 or "Upstream MCP server error"
This test must pass on all deployment surfaces (Docker Compose, ECS, EKS) before merging. The airegistry-tools server is the canary for MCP proxy routing because it is always registered and always healthy.
Use this template verbatim (fill in the placeholders, remove sections marked "Not Applicable" except to record the justification):
# Testing Plan: {Feature Name}
*Created: {date}*
*Related LLD: `./lld.md`*
*Related Issue: `./github-issue.md`*
## Overview
### Scope of Testing
{1-2 sentences describing what is being tested and why}
### Test Environments
| Environment | Purpose | How to Reach |
|-------------|---------|--------------|
| Local (docker-compose) | Primary dev verification | `docker-compose up -d` at repo root |
| AWS ECS (terraform) | Staging/prod parity | `terraform/aws-ecs/` deployment |
### Prerequisites
- [ ] Registry and Keycloak running (`docker ps | grep -E 'registry\|keycloak'`)
- [ ] Auth tokens generated: `cd credentials-provider && ./generate_creds.sh`
- [ ] Token file exists: `ls -la .oauth-tokens/ingress.json`
- [ ] {Any feature-specific prereqs, e.g. MongoDB seeded with X}
### Shared Variables
```bash
export REGISTRY_URL="http://localhost" # or https://registry.<region>.<domain>
export TOKEN_FILE=".oauth-tokens/ingress.json"
export ACCESS_TOKEN=$(jq -r '.access_token' "$TOKEN_FILE")
For each new or modified endpoint, provide a copy-pasteable curl command, the expected response, and the assertion being verified.
Endpoint: POST /api/v1/{path}
Command:
curl -sS -X POST "$REGISTRY_URL/api/v1/{path}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"field1": "value1",
"field2": 42
}' \
| jq
Expected Status: 200 OK (or 201 Created)
Expected Response:
{
"id": "{id}",
"status": "success"
}
Assertions:
id fieldstatus == "success"Negative Case:
# Missing required field should return 400
curl -sS -X POST "$REGISTRY_URL/api/v1/{path}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}' -w "\n%{http_code}\n"
Expected: 400 with validation error body.
{Repeat the structure above for each endpoint}
For each new or modified CLI command exposed via api/registry_management.py, provide the exact invocation and expected output.
Command:
cd api
uv run python registry_management.py {subcommand} \
--token-file "../$TOKEN_FILE" \
--registry-url "$REGISTRY_URL" \
--{new-param} "{value}"
Expected Output (key fragments):
Successfully created {resource}: <id>
Assertions:
0list command shows the resourceFollow-up Verification:
uv run python registry_management.py list \
--token-file "../$TOKEN_FILE" \
--registry-url "$REGISTRY_URL"
{Repeat the structure above}
Include this section if the feature touches any existing endpoint, schema, CLI command, default value, or data model. Otherwise replace with: "Not Applicable - feature introduces only net-new surface area: {justification}".
Goal: confirm that existing clients continue to work without code changes.
Command (pre-feature request body):
curl -sS -X POST "$REGISTRY_URL/api/v1/{existing-endpoint}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"legacy_field": "value"
}' | jq
Assertions:
200 (not 400)uv run python registry_management.py {existing-command} \
--token-file "../$TOKEN_FILE" \
--registry-url "$REGISTRY_URL"
Assertions:
0Include this section if the feature changes any user-facing surface (web UI, CLI output, error messages). Otherwise replace with: "Not Applicable - feature is internal only, with no UX changes."
For each UI change, describe the manual test steps.
Steps:
$REGISTRY_URLAssertions:
uv run python registry_management.py {command} --invalid-flag bad-value
Assertions:
Include this section whenever the feature adds or modifies ANY config parameter (env var, setting, Terraform variable, Helm value, secret). Otherwise replace with: "Not Applicable - feature introduces no new config parameters. Verified by reviewing diff of registry/core/config.py."
Before any surface-specific wiring tests, confirm the cross-surface index was updated.
| Check | Verification Command |
|---|---|
New parameter row(s) added to docs/unified-parameter-reference.md | grep -n "<PARAM_NAME>" docs/unified-parameter-reference.md |
| Each cell points to a file that actually contains the variable | grep -rn "<PARAM_NAME>" .env.example terraform/aws-ecs/terraform.tfvars.example charts/ |
Assertions:
docs/unified-parameter-reference.md in the correct group (or a new group is added with justification)/api/config/full endpoint returns the new parameter (sensitive values masked)For each new config parameter, confirm it is present in all Docker deployment files.
| Config Parameter | Env Var Name | Verification Command |
|---|---|---|
feature_enabled | FEATURE_ENABLED | grep FEATURE_ENABLED .env.example docker-compose*.yml |
feature_interval_seconds | FEATURE_INTERVAL_SECONDS | grep FEATURE_INTERVAL_SECONDS .env.example docker-compose*.yml |
Assertions:
.env.example with description and default.env with deployment valuedocker-compose.yml environment block for the correct service(s)docker-compose.podman.yml environment blockdocker-compose.prebuilt.yml environment blockdocker-compose up -d starts successfully with the new variableFor each new config parameter, confirm it is plumbed through the ECS deployment.
| Config Parameter | Env Var Name | Added To | Verification Command |
|---|---|---|---|
feature_enabled | FEATURE_ENABLED | terraform/aws-ecs/variables.tf + ecs-services.tf | grep -rn FEATURE_ENABLED terraform/aws-ecs/ |
feature_interval_seconds | FEATURE_INTERVAL_SECONDS | terraform/aws-ecs/variables.tf + ecs-services.tf | grep -rn FEATURE_INTERVAL_SECONDS terraform/aws-ecs/ |
Assertions:
terraform/aws-ecs/variables.tf with description and defaultterraform/aws-ecs/main.tfterraform/aws-ecs/modules/mcp-gateway/variables.tfterraform/aws-ecs/modules/mcp-gateway/ecs-services.tfterraform/aws-ecs/terraform.tfvars.examplecd terraform/aws-ecs
terraform init
terraform validate
terraform plan -var 'feature_enabled=true' -var 'feature_interval_seconds=60'
Assertions:
terraform validate passesterraform plan shows the new variable in the ECS task definition env blockFor each new config parameter, confirm it is plumbed through the Helm charts.
| Config Parameter | Helm Value Path | Verification Command |
|---|---|---|
feature_enabled | registry.featureEnabled | grep -rn FEATURE_ENABLED charts/ |
feature_interval_seconds | registry.featureIntervalSeconds | grep -rn FEATURE_INTERVAL_SECONDS charts/ |
Assertions:
charts/registry/values.yamlcharts/mcp-gateway-registry-stack/values.yamlcharts/registry/templates/secret.yaml (base64-encoded)charts/registry/templates/deployment.yamlhelm template charts/registry renders the new env var correctlycd terraform/aws-ecs
terraform apply -var 'feature_enabled=true' -var 'feature_interval_seconds=60'
Post-Deploy Assertions:
RUNNING state200 against the deployed ALB/CloudFront URL$REGISTRY_URLterraform apply with feature_enabled=false disables the feature cleanlyInclude this section if the feature adds a user-visible workflow that spans multiple endpoints or services. Otherwise replace with: "Not Applicable - feature is a single-endpoint change, covered by Functional Tests section 1."
Goal: {business outcome being exercised, e.g. "A tenant onboards, registers a server, invokes a tool, and tears down the resources"}
Setup:
# Generate token, set env vars (see Shared Variables above)
export RUN_ID=$(date +%s)
Steps (each step is executable):
Create prerequisite resources
curl -sS -X POST "$REGISTRY_URL/api/v1/{pre-req}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{ "name": "e2e-'$RUN_ID'" }'
Exercise the new feature
curl -sS -X POST "$REGISTRY_URL/api/v1/{new-endpoint}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{ "ref": "e2e-'$RUN_ID'" }'
Verify cross-service side effect
curl -sS "$REGISTRY_URL/api/v1/{downstream-check}/e2e-$RUN_ID" | jq
Teardown
curl -sS -X DELETE "$REGISTRY_URL/api/v1/{pre-req}/e2e-$RUN_ID"
Assertions:
If api/test-management-api-e2e.sh already exercises adjacent flows, extend it rather than duplicating:
api/test-management-api-e2e.shapi/test-management-api-e2e.mdcd api
./test-management-api-e2e.sh --token-file ../$TOKEN_FILE --registry-url "$REGISTRY_URL"
Copy this checklist into the PR description when implementing the feature:
registry_management.py commands succeedtests/unit/tests/integration/uv run pytest tests/ -n 8 passes with no regressions
### Guidance for Generating testing.md
1. **Make tests copy-pasteable.** Use the exact env var conventions (`REGISTRY_URL`, `TOKEN_FILE`, `ACCESS_TOKEN`) and match the style of `api/test-management-api-e2e.sh`.
2. **Cover every new endpoint and every new CLI command.** If the LLD adds three endpoints and two CLI commands, section 1 must have at least five subsections.
3. **Anchor ECS tests on concrete files.** Reference `terraform/aws-ecs/ecs.tf`, `variables.tf`, and any module under `terraform/aws-ecs/modules/` that the parameter flows through. Do not write generic "deploy and verify" wording - name the files.
4. **Mark Not Applicable explicitly.** Do not silently omit sections - always include the heading with a short justification, so reviewers see that the category was considered.
5. **Align with backwards-compat rules.** If the LLD introduces a schema change, the backwards-compat section must test the pre-change request/response shapes.
6. **Do not invent endpoints or flags.** Every curl URL, every `registry_management.py` flag, and every Terraform variable must exist in the LLD or the current codebase.
## Step 9: Render the documents as HTML
A low-level design runs to tens of thousands of words with dozens of tables, which reads badly as raw markdown in a terminal. Render every document the design produced:
```bash
for doc in github-issue lld review testing; do
uv run python scripts/render-doc-html.py .scratchpad/issue-NNNN/$doc.md
done
Each run writes <doc>.html beside the markdown, self-contained (all CSS inline, no CDN, no JavaScript, renders from file://), using the same stylesheet as the explainer skill so every generated document looks the same. The title comes from the document's H1, the byline from the italic metadata lines beneath it, and a section nav from the H2 headings.
Useful flags:
--footer-html '...' for provenance, such as the commit the design was verified against and the command to regenerate the file.--diagrams DIR to point at the SVG directory. A diagrams/ directory beside the markdown is picked up automatically, so the flag is only needed for a different location.--code-style invert for the template's dark code blocks. The default (match) makes code blocks follow the page surface, which is what a design document full of code wants.The LLD's architecture, sequence, and component views should be SVG in the HTML, not ASCII art. Write each one to diagrams/<key>.svg and fence the markdown block as:
```svg:system-context The caption that renders under the diagram.
<the ASCII version, which is what a terminal reader sees>
```
The renderer inlines diagrams/system-context.svg in place of the fence and uses the fence text as the <figcaption>.
Rules for authoring the SVG:
.box for nodes, .flow for normal arrows, .bad plus .bad-text for a failing path, .label for annotations, .mono for code-ish text.svg a role="img" and an aria-label describing what it shows.defs block inside the same SVG and prefix the ids per diagram, since ids must not collide across one page..svg file falls back to it rather than losing the diagram. Each diagram therefore has two representations: edit both or neither.uv run python scripts/prose-scan.py --strict .scratchpad/issue-NNNN/*.md .scratchpad/issue-NNNN/*.html
The renderer already warns about unfilled placeholders, broken in-page anchors, and svg: fences with no matching file. Fix anything it reports and re-run.
Re-render after every edit to a markdown file. The markdown is the source; the HTML is a build artifact, and the two drift the moment you hand-edit the HTML. Then open the LLD for the reader rather than starting a server:
code -r .scratchpad/issue-NNNN/lld.html
Do not start a server. The HTML is self-contained, so the editor's preview or a downloaded copy is enough, and a process the user did not ask for is one they have to hunt down later. If they want HTTP, offer this and let them run it in a VS Code integrated terminal, which is what makes VS Code forward the port:
python3 -m http.server 8112 --bind 127.0.0.1 --directory /abs/path/to/.scratchpad/issue-NNNN
Then the URL is http://127.0.0.1:8112/lld.html, or drop the filename for a directory listing. Point --directory at the single document's folder, never at .scratchpad/ itself: that folder holds credential files and http.server serves everything below its root.
The renderer treats the markdown body, the byline derived from it, and any inlined SVG as untrusted, because this skill summarizes GitHub-fetched content into that markdown. Raw HTML in the markdown is disabled, the byline is escaped with an href scheme allowlist, and an SVG carrying a script, an event handler, or an external reference aborts the render. A <script> in a PR body therefore renders as visible, inert text.
--byline-html and --footer-html are the two exceptions: both are inserted verbatim. Use them only for first-party provenance text you wrote. Never pass a PR title, an issue body, an author name, or any other fetched metadata through either one.
IMPORTANT: After completing the design documents and expert review, present a clear summary to the user and ask for guidance on addressing recommendations.
Present the following information in a clear, tabular format:
## Design Summary
### Documents Created
| Document | Location | Description |
|----------|----------|-------------|
| GitHub Issue | `.scratchpad/{feature}/github-issue.md` | Issue specification |
| Low-Level Design | `.scratchpad/{feature}/lld.md` | Technical design |
| Expert Review | `.scratchpad/{feature}/review.md` | Multi-persona review |
| Testing Plan | `.scratchpad/{feature}/testing.md` | Functional, backwards-compat, UX, ECS, and E2E tests |
| Rendered HTML | `.scratchpad/{feature}/*.html` | Styled, self-contained copies of each document |
### Review Verdicts
| Reviewer | Verdict | Blockers | Key Recommendations |
|----------|---------|----------|---------------------|
| Frontend (Pixel) | {verdict} | {count} | {brief summary} |
| Backend (Byte) | {verdict} | {count} | {brief summary} |
| SRE (Circuit) | {verdict} | {count} | {brief summary} |
| Security (Cipher) | {verdict} | {count} | {brief summary} |
| SMTS (Sage) | {verdict} | {count} | {brief summary} |
### Configuration Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `PARAM_NAME` | type | value | {description} |
### New Dependencies
| Package/Resource | Type | Required By |
|------------------|------|-------------|
| `package-name` | Python | Backend |
| None | - | No new dependencies |
### New Tests Required
| Test File | Type | Coverage |
|-----------|------|----------|
| `tests/unit/test_feature.py` | Unit | Service layer |
| `tests/integration/test_feature.py` | Integration | End-to-end |
### Estimated Effort
| Category | Lines of Code |
|----------|---------------|
| New code | ~{X} |
| Tests | ~{X} |
| Modified | ~{X} |
| **Total** | **~{X}** |
After presenting the summary, explicitly ask the user for guidance:
## Action Required
### Blockers (Must Address)
The following issues were identified as **blockers** and should be addressed before implementation:
1. {Blocker description from review}
2. {Blocker description from review}
**These will be incorporated into the LLD.**
### Recommendations (Need Your Input)
The following recommendations were made by reviewers. Please indicate which ones to incorporate:
| # | Recommendation | Reviewer | Priority | Incorporate? |
|---|----------------|----------|----------|--------------|
| 1 | {recommendation} | Backend | Should Fix | ? |
| 2 | {recommendation} | SRE | Should Fix | ? |
| 3 | {recommendation} | Security | Nice to Have | ? |
### Questions for You
1. Should I update the LLD to address the blockers and your selected recommendations?
2. Are there any additional requirements or constraints I should consider?
3. Would you like me to proceed with creating the GitHub issue?
Based on user response:
lld.md file with the agreed-upon changesIf reviewers identified better alternatives, explicitly call this out:
### Alternative Approaches Identified
Reviewers suggested these alternative approaches that may be worth considering:
| Alternative | Proposed By | Trade-offs |
|-------------|-------------|------------|
| {approach} | {reviewer} | {pros/cons summary} |
Would you like me to explore any of these alternatives further?
GAgarrytan/gstack136k883 new stars in the last 7 days
NEnextlevelbuilder/ui-ux-pro-max-skill135k1,864 new stars in the last 7 days
NEnextlevelbuilder/ui-ux-pro-max-skill135k1,864 new stars in the last 7 days
NEnexu-io/open-design101k1,126 new stars in the last 7 days
NEnexu-io/open-design101k1,126 new stars in the last 7 days
THthedotmack/claude-mem100k3,024 new stars in the last 7 days