Bug ID: CONTEXTFORGE-005 Component: ContextForge MCP Gateway Affected Version: v0.8.0, v1.0.0-BETA-1, v1.0.0-BETA-2 Severity: Low Status: Confirmed in v1.0.0-BETA-2 (still valid) Reported: 2025-11-09 Last Validated: 2026-02-06
The POST /teams endpoint ignores the user-provided slug field in team creation requests and instead auto-generates the slug from the team name. This prevents users from creating teams with custom slugs and makes the slug field effectively read-only despite being documented as an input field in the API schema.
POST /teams
When creating a team with a custom slug:
- The API should accept the
slugfield in the request body - The created team should use the provided slug value
- The slug should be validated (lowercase, alphanumeric with hyphens)
- Duplicate slugs should be rejected with an appropriate error
Example request:
{
"name": "My Team",
"slug": "custom-slug-123"
}Expected response:
{
"id": "abc123...",
"name": "My Team",
"slug": "custom-slug-123",
...
}When creating a team with a custom slug:
- The API accepts the
slugfield without error - The created team ignores the provided slug
- The slug is auto-generated from the team name
- No validation error or warning is returned
Example request:
{
"name": "test-team-1762712080059212000",
"slug": "test-team-1762712080059212000-slug"
}Actual response:
{
"id": "5f3c153ce9aa404398fc517d177cdd37",
"name": "test-team-1762712080059212000",
"slug": "test-team-1762712080059212000", // ← Ignores provided value
...
}The slug is generated from the name, completely ignoring the user-provided value.
-
Create a team with both
nameandslugfields:curl -X POST http://localhost:8000/teams/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "My Awesome Team", "slug": "custom-slug" }'
-
Observe the response - the slug will be
"my-awesome-team"(generated) instead of"custom-slug"(provided)
SDK integration tests consistently show the slug being ignored:
=== RUN TestTeamsService_BasicCRUD/create_team_with_all_optional_fields
teams_integration_test.go:71: Expected slug "test-team-1762712080059212000-slug",
got "test-team-1762712080059212000"
=== RUN TestTeamsService_Validation/create_team_with_valid_slug_pattern
teams_integration_test.go:541: Expected slug "valid-slug-123",
got "test-team-1762710811262903000"
Likely in mcpgateway/services/team_management_service.py or mcpgateway/routers/teams.py
The team creation logic likely:
- Accepts the
slugfield in the Pydantic schema (no validation error) - Ignores the provided value during team creation
- Auto-generates the slug from
team.nameusing a slugify function
Possible code pattern:
async def create_team(self, name: str, slug: Optional[str] = None, ...):
# Provided slug is ignored
generated_slug = slugify(name) # Always uses name, ignores slug parameter
new_team = EmailTeam(
name=name,
slug=generated_slug, # Uses generated value, not user input
...
)The service should check if slug is provided and validate it:
async def create_team(self, name: str, slug: Optional[str] = None, ...):
if slug:
# Validate slug format
if not is_valid_slug(slug):
raise InvalidSlugError(...)
# Check for duplicates
if await self.slug_exists(slug):
raise DuplicateSlugError(...)
team_slug = slug
else:
# Auto-generate from name
team_slug = slugify(name)
new_team = EmailTeam(
name=name,
slug=team_slug, # Uses provided or generated
...
)The OpenAPI schema documents slug as an input field in TeamCreateRequest:
{
"TeamCreateRequest": {
"type": "object",
"properties": {
"name": {"type": "string"},
"slug": {"type": "string"}, // ← Documented but ignored
"description": {"type": "string"},
...
},
"required": ["name"]
}
}This creates a misleading API contract where:
- The schema says slug can be provided
- The implementation ignores it
- No error or warning is returned
Severity: Low
- ❌ Cannot create teams with custom slugs
- ❌ API behavior doesn't match schema documentation
- ❌ No validation or error message to alert users
- ✅ Auto-generated slugs work correctly
- ✅ Workaround exists (accept auto-generated slugs)
Affected Users:
- API consumers who want consistent slug naming
- Organizations with slug naming conventions
- Systems that need predictable slug values for URLs/references
Business Impact: Low - Auto-generated slugs are functional, but custom slug support would improve user control and naming consistency.
Accept the auto-generated slug and don't rely on the slug field in creation requests:
// Instead of:
team := &contextforge.TeamCreate{
Name: "My Team",
Slug: contextforge.String("my-custom-slug"), // This will be ignored
}
// Use:
team := &contextforge.TeamCreate{
Name: "my-custom-slug", // Put desired slug as name
}
// Result: slug will be "my-custom-slug" (auto-generated from name)Alternatively, if the API later supports updates to the slug field, update it after creation.
Modify the team creation logic to use provided slugs:
async def create_team(self, name: str, slug: Optional[str] = None, ...):
if slug:
# Validate slug format (lowercase, alphanumeric, hyphens)
if not re.match(r'^[a-z0-9-]+$', slug):
raise ValueError("Invalid slug format")
# Check uniqueness
if await self._slug_exists(slug):
raise ValueError("Slug already exists")
team_slug = slug
else:
team_slug = self._generate_slug_from_name(name)
new_team = EmailTeam(name=name, slug=team_slug, ...)If auto-generation is intentional, remove slug from the input schema:
class TeamCreateRequest(BaseModel):
name: str
# slug: str ← Remove from input (make it response-only)
description: Optional[str] = None
...This makes the API contract accurate (slug is read-only, auto-generated).
If the current behavior is intentional, document it clearly:
class TeamCreateRequest(BaseModel):
name: str
slug: Optional[str] = Field(
None,
description="IGNORED: Slug is auto-generated from name. This field has no effect."
)Status: ✅ SDK implementation is correct
The SDK correctly:
- Sends the
slugfield in creation requests - Parses the response and extracts the actual slug value
- Does not assume the provided slug matches the returned slug
The test failures correctly identify the API behavior mismatch.
- May affect other resources that accept slug fields (servers, tools, etc.)
- Should verify if
PUT /teams/{id}allows slug updates (workaround possibility)
- ContextForge Source:
mcpgateway/services/team_management_service.py - API Router:
mcpgateway/routers/teams.py - SDK Integration Tests:
test/integration/teams_integration_test.go:52-84, 513-544 - OpenAPI Spec: upstream
mcp-context-forgetag schema (no local snapshot maintained in this repo)
- Verify if this is intentional design or a bug
- If intentional, update API documentation and schema
- If a bug, implement slug validation and usage
- Consider if slug updates are supported via PUT endpoint
- Update SDK tests based on final API behavior
Validated: 2026-01-13
Source code analysis confirms the root cause - the slug field is accepted by the schema but never passed to the service.
File: mcpgateway/routers/teams.py:88
async def create_team(request: TeamCreateRequest, current_user_ctx: dict = Depends(get_current_user_with_permissions)) -> TeamResponse:
try:
db = current_user_ctx["db"]
service = TeamManagementService(db)
team = await service.create_team(
name=request.name,
description=request.description,
created_by=current_user_ctx["email"],
visibility=request.visibility,
max_members=request.max_members
)
# Note: request.slug is NOT passed to create_team()File: mcpgateway/services/team_management_service.py:100
The create_team method signature has NO slug parameter:
async def create_team(self, name: str, description: str = None, created_by: str = None,
visibility: str = "private", max_members: int = None):
# No slug parameter - slug is always auto-generatedSchema accepts slug (TeamCreateRequest):
slug: Optional[str] = Field(
None,
description="(optional, auto-generated if not provided)" # Line 5121
)But implementation ignores it - the router doesn't pass request.slug to the service.
This is definitively a bug, not intentional behavior. The schema documents slug as optional (implying it can be provided), but the implementation completely ignores any provided value.
Report Generated: 2025-11-09 Tested Against: ContextForge v0.8.0 Validated Against: ContextForge v1.0.0-BETA-2 Reporter: go-contextforge SDK Team
Validated: 2026-02-06
- Still Valid? Yes. User-provided team slug is still ignored.
- Is it actually a bug? Yes. Request schema advertises
sluginput, but implementation discards it.
TeamCreateRequeststill includesslug.- Router/service flow still does not pass user
sluginto creation logic. - Created team slug continues to be auto-generated from name.