Bug ID: CONTEXTFORGE-002 Component: ContextForge MCP Gateway - Prompts API Affected Version: v0.8.0, v1.0.0-BETA-1, v1.0.0-BETA-2 (partial) Severity: Low Status: PARTIALLY FIXED (empty string still accepted) Reported: 2025-11-09 Validated: 2026-02-06
The POST /prompts endpoint accepts prompt creation requests without a template field, allowing prompts to be created with empty/missing templates. This violates the semantic requirement that prompts must have a template to be functional.
POST /prompts
When creating a prompt without a template field:
- The API should reject the request with a 422 Unprocessable Entity error
- The response should indicate that
templateis a required field - No prompt should be created in the database
A prompt without a template is semantically invalid since:
- The template defines what the prompt renders
- Without a template, the prompt cannot function in the MCP protocol
- The OpenAPI spec describes
templateas the core content of a prompt
When creating a prompt without a template field:
- The API accepts the request (returns 200 OK) ✓
- A prompt is created in the database with an empty template
- No validation error is returned
- Send POST request to
/promptswith request body:{ "prompt": { "name": "test-prompt-without-template" } } - Request succeeds with 200 OK
- Prompt is created with empty/null template field
Expected: 422 Unprocessable Entity with validation error Actual: 200 OK with created prompt
=== RUN TestPromptsService_InputValidation/create_prompt_without_required_template
prompts_integration_test.go:498: Expected error when creating prompt without template
prompts_integration_test.go:501: Correctly rejected prompt without template: <nil>
--- FAIL: TestPromptsService_InputValidation/create_prompt_without_required_template (0.00s)
The test expects an error but receives nil, confirming the API accepts the invalid request.
The OpenAPI spec for PromptCreate likely does not mark template as required:
# Expected (should be):
PromptCreate:
type: object
required:
- name
- template # ← Should be required
properties:
name:
type: string
template:
type: stringThe Pydantic schema in ContextForge may allow optional template:
File: mcpgateway/schemas.py (presumed)
class PromptCreate(BaseModel):
name: str
description: Optional[str] = None
template: Optional[str] = None # ← Should not be Optional
# ...The database schema may allow NULL values for the template column:
File: mcpgateway/models.py (presumed)
class DbPrompt(Base):
__tablename__ = "prompts"
template = Column(String, nullable=True) # ← Should be nullable=FalseOther resource types properly validate required fields:
- Tools: Require
namefield (returns 422 if missing) ✓ - Resources: Require
uri,name,content(returns 422 if missing) ✓ - Servers: Require
name(returns 422 if missing) ✓ - Prompts: Require
namebut NOTtemplate✗
The prompts endpoint is inconsistent with other resource validation patterns.
Severity: Low
Positive Impacts:
- Allows creating "draft" prompts that can be filled in later
- Supports multi-step creation workflows
Negative Impacts:
- Creates semantically invalid prompts that cannot function
- Violates principle of least surprise (template seems required)
- May cause issues when prompts are used in MCP protocol without templates
- Inconsistent with validation patterns of other resources
This may be intentional to support workflows like:
- Create placeholder prompt with just a name
- Update prompt later with template and arguments
- Activate prompt when complete
This may be unintentional due to:
- Missing validation constraint in Pydantic model
- Database schema allowing NULL values
- OpenAPI spec not marking field as required
-
Update Documentation:
- Clarify that template is optional for draft prompts
- Document workflow for creating incomplete prompts
- Add validation that prompts cannot be activated without template
-
Add State Field:
class PromptCreate(BaseModel): name: str template: Optional[str] = None state: str = "draft" # draft, complete, active
-
Validate on Activation:
- Prevent toggling to
isActive=trueif template is empty - Return 422 error: "Cannot activate prompt without template"
- Prevent toggling to
-
Update Pydantic Model:
class PromptCreate(BaseModel): name: str template: str # Remove Optional
-
Update Database Schema:
template = Column(String, nullable=False)
-
Update OpenAPI Spec:
required: - name - template
Status: ✅ SDK implementation is correct
Our go-contextforge SDK correctly:
- Sends the create request with or without template field
- Handles API response appropriately
- Does not add artificial client-side validation
The SDK integration test documents expected vs actual behavior, which is valuable for API contract testing.
SDK users should:
-
Always provide template field:
prompt := &contextforge.PromptCreate{ Name: "my-prompt", Template: "Hello {{name}}!", // Always include }
-
Add client-side validation:
if prompt.Template == "" { return errors.New("template is required") }
-
Check created prompts:
created, _, err := client.Prompts.Create(ctx, prompt, nil) if created.Template == "" { log.Warn("Prompt created without template") }
- CONTEXTFORGE-001: Prompts toggle returns stale state
- OpenAPI Spec: upstream
mcp-context-forgetag schema (no local snapshot maintained in this repo) - SDK Integration Test:
test/integration/prompts_integration_test.go:490-501
- Clarify with ContextForge team if this is intentional or a bug
- If intentional: Request documentation update
- If bug: Request validation constraint addition
- Update SDK tests based on team response
- Document behavior in SDK README
Validated: 2026-01-13
The bug is PARTIALLY FIXED in ContextForge v1.0.0-BETA-1.
File: mcpgateway/schemas.py:2046
template: str = Field(..., description="Prompt template text")The ... in Pydantic Field() means the field is required. However:
| Request | Status Code | Result |
|---|---|---|
Missing template field |
422 | FIXED - Rejected |
Empty template: "" |
200 | NOT FIXED - Accepted |
# Missing template - correctly rejected with 422
curl -X POST /prompts -d '{"prompt": {"name": "test"}}'
# Returns 422: "Field required"
# Empty template - incorrectly accepted!
curl -X POST /prompts -d '{"prompt": {"name": "test", "template": ""}}'
# Returns 200: Prompt created with empty templateThe Go SDK's PromptCreate struct has Template string without omitempty, which means it always sends "template": "" when Template is the zero value. This causes the API to accept the request.
Integration tests remain skipped because:
- The SDK cannot omit the template field (would require
*stringtype) - The API accepts empty template strings
- The underlying issue (prompts with empty templates are semantically invalid) persists
Report Generated: 2025-11-09 Tested Against: ContextForge v0.8.0 Fix Validated Against: ContextForge v1.0.0-BETA-2 Reporter: go-contextforge SDK Team
Validated: 2026-02-06
- Still Valid? Partially. Missing
templateis rejected, buttemplate: ""is still accepted. - Is it actually a bug? Yes. Accepting an empty prompt template contradicts expected prompt semantics.
POST /promptswithouttemplatenow returns validation error.POST /promptswithtemplate: ""still succeeds and creates an effectively empty prompt.- Current schema path:
mcpgateway/schemas.pyandmcpgateway/common/validators.py.