Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 2 additions & 18 deletions src/fastmcp/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2496,10 +2496,7 @@ async def run_stdio_async(
"""
# Display server banner
if show_banner:
log_server_banner(
server=self,
transport="stdio",
)
log_server_banner(server=self)

with temporary_log_level(log_level):
async with self._lifespan_manager():
Expand Down Expand Up @@ -2562,22 +2559,9 @@ async def run_http_async(
stateless_http=stateless_http,
)

# Get the path for the server URL
server_path = (
app.state.path.lstrip("/")
if hasattr(app, "state") and hasattr(app.state, "path")
else path or ""
)

# Display server banner
if show_banner:
log_server_banner(
server=self,
transport=transport,
host=host,
port=port,
path=server_path,
)
log_server_banner(server=self)
uvicorn_config_from_user = uvicorn_config or {}

config_kwargs: dict[str, Any] = {
Expand Down
66 changes: 23 additions & 43 deletions src/fastmcp/utilities/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json
import os
from pathlib import Path
from typing import TYPE_CHECKING, Any, Literal
from typing import TYPE_CHECKING, Any

from pydantic import ValidationError
from rich.align import Align
Expand Down Expand Up @@ -197,23 +197,8 @@ def load_and_merge_config(
)


def log_server_banner(
server: FastMCP[Any],
transport: Literal["stdio", "http", "sse", "streamable-http"],
*,
host: str | None = None,
port: int | None = None,
path: str | None = None,
) -> None:
"""Creates and logs a formatted banner with server information and logo.

Args:
transport: The transport protocol being used
server_name: Optional server name to display
host: Host address (for HTTP transports)
port: Port number (for HTTP transports)
path: Server path (for HTTP transports)
"""
def log_server_banner(server: FastMCP[Any]) -> None:
"""Creates and logs a formatted banner with server information and logo."""

# Create the logo text
# Use Text with no_wrap and markup disabled to preserve ANSI escape codes
Expand All @@ -228,39 +213,34 @@ def log_server_banner(
info_table.add_column(style="cyan", justify="left") # Label column
info_table.add_column(style="dim", justify="left") # Value column

match transport:
case "http" | "streamable-http":
display_transport = "HTTP"
case "sse":
display_transport = "SSE"
case "stdio":
display_transport = "STDIO"

info_table.add_row("🖥", "Server name:", Text(server.name + "\n", style="bold blue"))
info_table.add_row("📦", "Transport:", display_transport)

# Show connection info based on transport
if transport in ("http", "streamable-http", "sse") and host and port:
server_url = f"http://{host}:{port}"
if path:
server_url += f"/{path.lstrip('/')}"
info_table.add_row("🔗", "Server URL:", server_url)

# Add documentation link
info_table.add_row("", "", "")
info_table.add_row("📚", "Docs:", "https://gofastmcp.com")
info_table.add_row("🚀", "Hosting:", "https://fastmcp.cloud")
info_table.add_row("🖥", "Server:", Text(server.name, style="dim"))
info_table.add_row("🚀", "Deploy free:", "https://fastmcp.cloud")

# Create panel with logo, title, and information using Group
docs_url = Text("https://gofastmcp.com", style="dim")
panel_content = Group(
"",
Align.center(logo_text),
"",
Align.center(title_text),
"",
Align.center(title_text),
Align.center(docs_url),
"",
Align.center(info_table),
)

# v3 notice banner (shown below main panel)
v3_line1 = Text("✨ FastMCP 3.0 is coming!", style="bold")
v3_line2 = Text(
"Pin fastmcp<3 in production, then upgrade when you're ready.", style="dim"
)
v3_notice = Panel(
Group(Align.center(v3_line1), Align.center(v3_line2)),
border_style="blue",
padding=(0, 2),
width=80,
)

panel = Panel(
panel_content,
border_style="dim",
Expand All @@ -270,5 +250,5 @@ def log_server_banner(
)

console = Console(stderr=True)
# Center the panel itself
console.print(Group("\n", Align.center(panel), "\n"))
# Center both panels
console.print(Group("\n", Align.center(panel), Align.center(v3_notice), "\n"))