Skip to content

feat: API endpoint is served under the /v1 prefix#4403

Open
Lang-Akshay wants to merge 14 commits intomainfrom
API_v1
Open

feat: API endpoint is served under the /v1 prefix#4403
Lang-Akshay wants to merge 14 commits intomainfrom
API_v1

Conversation

@Lang-Akshay
Copy link
Copy Markdown
Collaborator

@Lang-Akshay Lang-Akshay commented Apr 22, 2026

Summary

This PR introduces API versioning for ContextForge by serving all resource management and business-logic endpoints under a /v1 URL prefix. A new mcpgateway/api/v1/__init__.py module centralizes router assembly through a build_v1_router() factory, keeping main.py clean and making future version additions (/v2, etc.) straightforward.

Protocol-level routes (MCP transports, OAuth, well-known URIs, health probes) intentionally remain unversioned at the root — these follow external standards or must stay stable for infrastructure compatibility.

Changes

  • mcpgateway/api/v1/__init__.py — new build_v1_router() factory that assembles all versioned routers under /v1; feature-flagged routers are conditionally included here
  • mcpgateway/api/__init__.py — new namespace package
  • mcpgateway/main.py — router registration refactored; versioned routers delegated to build_v1_router(); unversioned routers mounted directly on app
  • mcpgateway/admin.py — admin redirect paths updated to /v1/admin/*
  • mcpgateway/middleware/ — path references updated (path_filter.py, rbac.py, token_scoping.py)
  • Tests — all e2e, integration, fuzz, and load tests updated to use /v1 prefixed paths
  • scripts/update_test_paths.py — utility script for migrating test path references

Endpoint Classification

Versioned — served under /v1

Endpoint Group Path (new) Feature Flag
MCP Protocol /v1/protocol/** always-on
Tools /v1/tools/** always-on
Resources /v1/resources/** always-on
Prompts /v1/prompts/** always-on
Gateways /v1/gateways/** always-on
Roots /v1/roots/** always-on
Servers /v1/servers/** always-on
Metrics /v1/metrics/** always-on
Tags /v1/tags/** always-on
Export / Import /v1/export, /v1/import always-on
Tool Plugin Bindings /v1/tools/plugin_bindings/** always-on
Admin UI & API /v1/admin/** MCPGATEWAY_ADMIN_API_ENABLED
Runtime Admin /v1/admin/runtime/** MCPGATEWAY_ADMIN_API_ENABLED
LLM Admin /v1/admin/llm/** MCPGATEWAY_LLMCHAT_ENABLED
A2A /v1/a2a/** MCPGATEWAY_A2A_ENABLED
Observability /v1/observability/** OBSERVABILITY_ENABLED
Reverse Proxy /v1/reverse-proxy/** MCPGATEWAY_REVERSE_PROXY_ENABLED
Tool Cancellation /v1/cancellation/** MCPGATEWAY_TOOL_CANCELLATION_ENABLED
ToolOps /v1/toolops/** TOOLOPS_ENABLED
Authentication /v1/auth/** EMAIL_AUTH_ENABLED
Email Authentication /v1/auth/email/** EMAIL_AUTH_ENABLED
SSO Authentication /v1/auth/sso/** EMAIL_AUTH_ENABLED + SSO_ENABLED
Teams /v1/teams/** EMAIL_AUTH_ENABLED
JWT Token Catalog /v1/tokens/** EMAIL_AUTH_ENABLED
RBAC /v1/rbac/** EMAIL_AUTH_ENABLED
LLM Chat /v1/llmchat/** MCPGATEWAY_LLMCHAT_ENABLED
LLM Config /v1/llm/** MCPGATEWAY_LLMCHAT_ENABLED

Not versioned — mounted at root

Endpoint Group Path Reason
Health probes /health, /ready, /health/security Infrastructure / liveness; must remain stable
MCP Streamable HTTP transport /mcp MCP protocol spec — path is fixed by the spec
Internal MCP transport bridge /_internal/mcp/transport Internal trusted bridge; not a public API
OAuth 2.0 /oauth/** Standard protocol location (RFC 6749)
Well-known URIs /.well-known/** RFC 8615 / RFC 9116 / RFC 9728 — path is standardized
Per-server well-known /servers/{id}/.well-known/** RFC standard path, must not be prefixed
Version / Diagnostics /version Diagnostic utility, not a resource API
Static assets /static/** UI asset serving
Root redirect / Entry point / UI redirect
Favicon /favicon.ico Browser convention
Log Search /api/logs/** Internal structured-logging query interface
LLM Proxy {llm_api_prefix} (default /v1) Prefix is runtime-configurable via LLM_API_PREFIX; cannot be nested inside the gateway's own /v1

Breaking Change

All previously unversioned API paths (/tools, /resources, /prompts, /gateways, /servers, /roots, /metrics, /tags, /a2a, /admin, /auth, /teams, /tokens, /rbac, /observability, /cancellation, /toolops, /reverse-proxy, /export, /import) are now served exclusively under /v1. Clients must update base URLs accordingly.

The MCP transports (/mcp), OAuth endpoints (/oauth), health probes, and well-known URIs are unchanged.

@Lang-Akshay Lang-Akshay marked this pull request as draft April 22, 2026 22:41
@Lang-Akshay Lang-Akshay force-pushed the API_v1 branch 6 times, most recently from c8e7d17 to 77af9dd Compare April 26, 2026 15:55
@Lang-Akshay Lang-Akshay marked this pull request as ready for review April 26, 2026 22:16
@Lang-Akshay Lang-Akshay marked this pull request as draft April 26, 2026 22:16
@Lang-Akshay Lang-Akshay marked this pull request as ready for review April 26, 2026 22:19
@msureshkumar88 msureshkumar88 self-requested a review April 27, 2026 08:10
@Lang-Akshay Lang-Akshay force-pushed the API_v1 branch 2 times, most recently from cfeb057 to d190e69 Compare April 27, 2026 09:30
Copy link
Copy Markdown
Collaborator

@msureshkumar88 msureshkumar88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request Changes - PR #4403

Summary

This PR implements API versioning under /v1 prefix with excellent architecture and comprehensive test coverage. However, there are 1 CRITICAL and 2 MEDIUM priority issues that must be addressed before merging.


🚨 CRITICAL Issues (Must Fix)

1. Breaking Change Without Backward Compatibility

Location: mcpgateway/main.py:11544

Problem: This PR introduces an immediate breaking change for all external API consumers. Any client using unversioned endpoints (e.g., /tools, /servers, /gateways) will break immediately upon deployment.

Required Action: Implement a backward compatibility layer with deprecation warnings:

# In main.py after line 11544
# Mount v1_router at both /v1 (new) and root (deprecated)
app.include_router(v1_router)  # /v1/* (new canonical path)

# Temporary compatibility layer - remove in v2.0.0
app.include_router(v1_router, prefix="")  # /* (deprecated, for backward compatibility)

# Add deprecation warning middleware for unversioned paths
# Log warnings when clients use deprecated unversioned endpoints

Additional Requirements:

  • Add MIGRATION.md documenting the breaking change and migration path
  • Update CHANGELOG.md with breaking change notice
  • Add deprecation timeline (e.g., "unversioned endpoints deprecated, will be removed in v2.0.0")
  • Ensure all security middleware applies to both /v1/* and /* paths

⚠️ MEDIUM Issues (Should Fix)

2. Duplicated Path Normalization Logic

Location: mcpgateway/middleware/token_scoping.py:243-250 and 345-352

Problem: Path normalization logic for stripping /v1 prefix is duplicated in two functions (_normalize_llm_api_prefix() and _normalize_path_for_matching()), creating maintenance burden and potential inconsistencies.

Required Action: Consolidate into a single shared utility function:

def _normalize_api_path(path: str) -> str:
    """Strip /v1 prefix for consistent pattern matching across middleware."""
    if path.startswith("/v1/"):
        return path[3:]
    if path == "/v1":
        return "/"
    return path

# Then update both functions to use this shared utility

3. Missing API Version Discovery Endpoint

Location: mcpgateway/api/v1/__init__.py:273

Problem: No endpoint exists for clients to programmatically discover the API version, making it difficult for clients to adapt to versioning changes.

Required Action: Add version discovery endpoint:

# In build_v1_router() after creating v1_router (line 73)
@v1_router.get("/version", tags=["Version"])
async def get_api_version():
    """Return current API version information."""
    return {
        "version": "v1",
        "deprecated": False,
        "deprecation_date": None,
        "sunset_date": None
    }

📋 Additional Recommendations (Optional)

Test Coverage Gap

Add explicit test verifying unversioned routes remain unversioned:

def test_unversioned_routes_remain_unversioned():
    """Verify RFC well-known, OAuth, health remain at root."""
    assert client.get("/.well-known/openid-configuration").status_code != 404
    assert client.get("/oauth/authorize").status_code != 404
    assert client.get("/health").status_code == 200

Documentation

  • Update OpenAPI schema to reflect /v1 prefix in all endpoint paths
  • Add API versioning policy to project documentation

✅ What's Working Well

  • Excellent centralized router architecture
  • Comprehensive test coverage (194 files updated)
  • Proper security middleware updates
  • Clean separation of versioned vs unversioned routes
  • No security regressions identified

🎯 Merge Criteria

Cannot merge until:

  1. ✅ Backward compatibility layer implemented
  2. ✅ Migration documentation added (MIGRATION.md, CHANGELOG.md)
  3. ✅ Path normalization logic consolidated
  4. ✅ Version discovery endpoint added

Estimated effort: 2-4 hours to address all issues


Review Status: 🔴 REQUEST CHANGES
Risk Level: 🟡 MEDIUM (Technical: LOW, Business: MEDIUM due to breaking change)

Copy link
Copy Markdown
Collaborator

@msureshkumar88 msureshkumar88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the comments

…pace package

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
- Updated test cases in  to change API paths from  and  to  and .
- Modified pagination tests in  to reflect new API paths with versioning.
- Adjusted proxy authentication tests in  to use  and .
- Changed credential verification tests in  to redirect to .

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
- Updated all instances of /v1/servers/{id}/mcp to /servers/{id}/mcp in test cases.
- Ensured consistency across tests for authentication and authorization checks.
- Adjusted related test assertions to reflect the new endpoint structure.

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
- Updated various service and router files to remove the /v1 prefix from API paths.
- Adjusted tests to reflect the new endpoint structure without versioning.
- Ensured that all references to admin routes are updated to include the new path format.
- Modified the metrics endpoint to return data without the version prefix.
- Cleaned up related tests to ensure they align with the new routing structure.

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…baseline

refactor: reorder logging import in alembic env.py
fix: add comment for first-party import in audit_trail_service.py
cleanup: remove merge conflict markers in resource_service.py
refactor: add first-party comment in context.py
refactor: add blank line after import in streamablehttp_transport.py
docs: enhance API endpoint organization documentation in plan.md
chmod: update permissions for update_test_paths.py script

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…API paths to include versioning in tests

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…rage

- Implement tests for legacy /admin/* paths to ensure they trigger admin auth checks.
- Ensure /admin/login remains exempt from authentication.
- Add tests for browser and HTMX request redirects when unauthenticated admin is enabled.
- Introduce tests for token scoping and cancellation router functionalities.
- Enhance audit trail service tests to handle identity extraction failures gracefully.
- Add email auth service tests for forgot and reset password URL constructions.
- Introduce comprehensive tests for the v1 API router, covering various feature flags and import errors.
- Remove obsolete cancellation router tests to streamline the codebase.

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…aseline; add noqa comment for import in main.py

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…ioning

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…fix in tests

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
- Changed all admin-related fetch and form action URLs in observability templates to include the new versioning scheme (v1).
- Updated paths in performance, prompts, resources, tools, and user management templates to reflect the new API structure.
- Adjusted Playwright tests to align with the updated URL structure for admin routes.

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
…ion in logout tests

Signed-off-by: Lang-Akshay <akshay.shinde26@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants