langflow-ai/langflow · error · HTTPException

Project ID is required to start MCP server

Error message

Project ID is required to start MCP server

What it means

400 from get_project_sse: it was called with a falsy project_id (None or empty), so it cannot build the project-scoped SSE transport path /api/v1/mcp/project/{id}/. In practice the id should come from the request path; reaching this with None indicates the project context variable was never set — a server-side wiring bug or a route mounted without the project parameter resolved, not a client formatting mistake.

Source

Thrown at src/backend/base/langflow/api/v1/mcp_projects.py:281

        ).first()

        if not project_access:
            raise HTTPException(status_code=404, detail="Project not found")

        return user


# Create project-specific context variable
current_project_ctx: ContextVar[UUID | None] = ContextVar("current_project_ctx", default=None)

# Mapping of project-specific SSE transports
project_sse_transports: dict[str, SseServerTransport] = {}


def get_project_sse(project_id: UUID | None) -> SseServerTransport:
    """Get or create an SSE transport for a specific project."""
    if not project_id:
        raise HTTPException(status_code=400, detail="Project ID is required to start MCP server")

    project_id_str = str(project_id)
    if project_id_str not in project_sse_transports:
        project_sse_transports[project_id_str] = SseServerTransport(f"/api/v1/mcp/project/{project_id_str}/")
    return project_sse_transports[project_id_str]


async def _build_project_tools_response(
    project_id: UUID,
    current_user: CurrentActiveMCPUser,
    *,
    mcp_enabled: bool,
) -> MCPProjectResponse:
    """Return tool metadata for a project."""
    tools: list[MCPSettings] = []
    try:
        async with session_scope() as session:
            # Fetch the project first to verify it exists and belongs to the current user

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Use the stock route path /api/v1/mcp/project/{project_id}/sse so FastAPI injects the id.
  2. If you forked/mounted routes, ensure the {project_id} path parameter name matches the endpoint signature.
  3. In tests, pass an explicit project UUID rather than relying on the context var.
  4. Check that auth dependencies that set current_project_ctx run before the SSE handler.
Defensive patterns

Strategy: validation

Validate before calling

def has_project_id(pid) -> bool:
    return pid is not None and str(pid) != ''

Try / catch

except 400 'Project ID is required': this is a routing/wiring defect — verify the endpoint path includes the project UUID; no client retry helps.

Prevention

When it happens

Trigger: An SSE connect request where the project_id dependency resolved to None (route mismatch, misconfigured path parameter, or code calling get_project_sse(current_project_ctx.get()) before the context var was set).

Common situations: Custom deployments or forks that mount the MCP project routes under a different path pattern; race where the SSE connect handler runs before _bind_project_context; tests invoking handlers directly without the path param.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/5da88cfcd9b30763. Report an issue: GitHub.