+
+ New in version:
+ {version}
+
+
+
+
+
);
};
\ No newline at end of file
diff --git a/docs/style.css b/docs/style.css
index f6bb832bc..be64b3edd 100644
--- a/docs/style.css
+++ b/docs/style.css
@@ -14,16 +14,18 @@ h6 code:not(pre code) {
/* Version badge -- display a badge with the current version of the documentation */
.version-badge {
- display: inline-flex;
+ display: inline-block;
align-items: center;
gap: 0.3em;
- padding: 0.32em 1em;
- font-size: 0.92em;
- font-weight: 600;
- letter-spacing: 0.01em;
- color: #7417e5;
- background: #f3e8ff;
- border: 1.5px solid #c084fc;
+ padding: 0.2em 0.8em;
+ font-size: 1.1em;
+ font-weight: 400;
+
+ font-family: "Inter", sans-serif;
+ letter-spacing: 0.025em;
+ color: #ff5400;
+ background: #ffeee6;
+ border: 1px solid rgb(255, 84, 0, 0.5);
border-radius: 6px;
box-shadow: none;
vertical-align: middle;
@@ -31,6 +33,11 @@ h6 code:not(pre code) {
transition: box-shadow 0.2s, transform 0.15s;
}
+.version-badge-container {
+ margin: 0;
+ padding: 0;
+}
+
.version-badge:hover {
box-shadow: 0 2px 8px 0 rgba(160, 132, 252, 0.1);
transform: translateY(-1px) scale(1.03);
@@ -41,13 +48,3 @@ h6 code:not(pre code) {
background: #312e81;
border: 1.5px solid #a78bfa;
}
-
-.badge-emoji {
- font-size: 1.15em;
- line-height: 1;
- text-shadow: 0 1px 2px #fff, 0 0px 2px #c084fc;
-}
-
-.dark .badge-emoji {
- text-shadow: 0 1px 2px #312e81, 0 0px 2px #a78bfa;
-}
diff --git a/src/fastmcp/cli/cli.py b/src/fastmcp/cli/cli.py
index 379059d7e..cb4c112ab 100644
--- a/src/fastmcp/cli/cli.py
+++ b/src/fastmcp/cli/cli.py
@@ -223,6 +223,27 @@ def dev(
help="Additional packages to install",
),
] = [],
+ inspector_version: Annotated[
+ str | None,
+ typer.Option(
+ "--inspector-version",
+ help="Version of the MCP Inspector to use",
+ ),
+ ] = None,
+ ui_port: Annotated[
+ int | None,
+ typer.Option(
+ "--ui-port",
+ help="Port for the MCP Inspector UI",
+ ),
+ ] = None,
+ server_port: Annotated[
+ int | None,
+ typer.Option(
+ "--server-port",
+ help="Port for the MCP Inspector Proxy server",
+ ),
+ ] = None,
) -> None:
"""Run a MCP server with the MCP Inspector."""
file, server_object = _parse_file_path(file_spec)
@@ -234,6 +255,8 @@ def dev(
"server_object": server_object,
"with_editable": str(with_editable) if with_editable else None,
"with_packages": with_packages,
+ "ui_port": ui_port,
+ "server_port": server_port,
},
)
@@ -243,7 +266,11 @@ def dev(
if hasattr(server, "dependencies"):
with_packages = list(set(with_packages + server.dependencies))
- uv_cmd = _build_uv_command(file_spec, with_editable, with_packages)
+ env_vars = {}
+ if ui_port:
+ env_vars["CLIENT_PORT"] = str(ui_port)
+ if server_port:
+ env_vars["SERVER_PORT"] = str(server_port)
# Get the correct npx command
npx_cmd = _get_npx_command()
@@ -254,13 +281,19 @@ def dev(
)
sys.exit(1)
+ inspector_cmd = "@modelcontextprotocol/inspector"
+ if inspector_version:
+ inspector_cmd += f"@{inspector_version}"
+
+ uv_cmd = _build_uv_command(file_spec, with_editable, with_packages)
+
# Run the MCP Inspector command with shell=True on Windows
shell = sys.platform == "win32"
process = subprocess.run(
- [npx_cmd, "@modelcontextprotocol/inspector"] + uv_cmd,
+ [npx_cmd, inspector_cmd] + uv_cmd,
check=True,
shell=shell,
- env=dict(os.environ.items()), # Convert to list of tuples for env update
+ env=dict(os.environ.items()) | env_vars,
)
sys.exit(process.returncode)
except subprocess.CalledProcessError as e:
diff --git a/src/fastmcp/prompts/prompt.py b/src/fastmcp/prompts/prompt.py
index c6bcefc62..0cf37403d 100644
--- a/src/fastmcp/prompts/prompt.py
+++ b/src/fastmcp/prompts/prompt.py
@@ -1,9 +1,11 @@
"""Base classes for FastMCP prompts."""
+from __future__ import annotations as _annotations
+
import inspect
import json
from collections.abc import Awaitable, Callable, Sequence
-from typing import Annotated, Any, Literal
+from typing import TYPE_CHECKING, Annotated, Any, Literal
import pydantic_core
from mcp.types import EmbeddedResource, ImageContent, TextContent
@@ -13,6 +15,12 @@ from pydantic import BaseModel, BeforeValidator, Field, TypeAdapter, validate_ca
from fastmcp.utilities.types import _convert_set_defaults
+if TYPE_CHECKING:
+ from mcp.server.session import ServerSessionT
+ from mcp.shared.context import LifespanContextT
+
+ from fastmcp.server import Context
+
CONTENT_TYPES = TextContent | ImageContent | EmbeddedResource
@@ -72,6 +80,9 @@ class Prompt(BaseModel):
None, description="Arguments that can be passed to the prompt"
)
fn: Callable[..., PromptResult | Awaitable[PromptResult]]
+ context_kwarg: str | None = Field(
+ None, description="Name of the kwarg that should receive context"
+ )
@classmethod
def from_function(
@@ -80,7 +91,8 @@ class Prompt(BaseModel):
name: str | None = None,
description: str | None = None,
tags: set[str] | None = None,
- ) -> "Prompt":
+ context_kwarg: str | None = None,
+ ) -> Prompt:
"""Create a Prompt from a function.
The function can return:
@@ -89,11 +101,24 @@ class Prompt(BaseModel):
- A dict (converted to a message)
- A sequence of any of the above
"""
+ from fastmcp import Context
+
func_name = name or fn.__name__
if func_name == "