Skip to content

Commit a36d03e

Browse files
authored
Merge branch 'modelcontextprotocol:main' into main
2 parents 2131e25 + 40acbc5 commit a36d03e

File tree

15 files changed

+598
-1146
lines changed

15 files changed

+598
-1146
lines changed

examples/clients/simple-auth-client/pyproject.toml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ classifiers = [
1414
"Programming Language :: Python :: 3",
1515
"Programming Language :: Python :: 3.10",
1616
]
17-
dependencies = [
18-
"click>=8.2.0",
19-
"mcp>=1.0.0",
20-
]
17+
dependencies = ["click>=8.2.0", "mcp"]
2118

2219
[project.scripts]
2320
mcp-simple-auth-client = "mcp_simple_auth_client.main:cli"
@@ -44,9 +41,3 @@ target-version = "py310"
4441

4542
[tool.uv]
4643
dev-dependencies = ["pyright>=1.1.379", "pytest>=8.3.3", "ruff>=0.6.9"]
47-
48-
[tool.uv.sources]
49-
mcp = { path = "../../../" }
50-
51-
[[tool.uv.index]]
52-
url = "https://pypi.org/simple"

examples/clients/simple-auth-client/uv.lock

Lines changed: 0 additions & 535 deletions
This file was deleted.

examples/clients/simple-chatbot/mcp_simple_chatbot/main.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ async def start(self) -> None:
401401
await self.cleanup_servers()
402402

403403

404-
async def main() -> None:
404+
async def run() -> None:
405405
"""Initialize and run the chat session."""
406406
config = Configuration()
407407
server_config = config.load_config("servers_config.json")
@@ -411,5 +411,9 @@ async def main() -> None:
411411
await chat_session.start()
412412

413413

414+
def main() -> None:
415+
asyncio.run(run())
416+
417+
414418
if __name__ == "__main__":
415-
asyncio.run(main())
419+
main()

examples/clients/simple-chatbot/pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ classifiers = [
1717
dependencies = [
1818
"python-dotenv>=1.0.0",
1919
"requests>=2.31.0",
20-
"mcp>=1.0.0",
21-
"uvicorn>=0.32.1"
20+
"mcp",
21+
"uvicorn>=0.32.1",
2222
]
2323

2424
[project.scripts]
25-
mcp-simple-chatbot = "mcp_simple_chatbot.client:main"
25+
mcp-simple-chatbot = "mcp_simple_chatbot.main:main"
2626

2727
[build-system]
2828
requires = ["hatchling"]

examples/clients/simple-chatbot/uv.lock

Lines changed: 0 additions & 555 deletions
This file was deleted.

pyproject.toml

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ venv = ".venv"
9898
# those private functions instead of testing the private functions directly. It makes it easier to maintain the code source
9999
# and refactor code that is not public.
100100
executionEnvironments = [
101-
{ root = "tests", reportUnusedFunction = false, reportPrivateUsage = false },
102-
{ root = "examples/servers", reportUnusedFunction = false },
101+
{ root = "tests", reportUnusedFunction = false, reportPrivateUsage = false },
102+
{ root = "examples/servers", reportUnusedFunction = false },
103103
]
104104

105105
[tool.ruff]
@@ -109,17 +109,17 @@ extend-exclude = ["README.md"]
109109

110110
[tool.ruff.lint]
111111
select = [
112-
"C4", # flake8-comprehensions
113-
"C90", # mccabe
114-
"E", # pycodestyle
115-
"F", # pyflakes
116-
"I", # isort
117-
"PERF", # Perflint
118-
"PL", # Pylint
119-
"UP", # pyupgrade
112+
"C4", # flake8-comprehensions
113+
"C90", # mccabe
114+
"E", # pycodestyle
115+
"F", # pyflakes
116+
"I", # isort
117+
"PERF", # Perflint
118+
"PL", # Pylint
119+
"UP", # pyupgrade
120120
]
121121
ignore = ["PERF203", "PLC0415", "PLR0402"]
122-
mccabe.max-complexity = 24 # Default is 10
122+
mccabe.max-complexity = 24 # Default is 10
123123

124124
[tool.ruff.lint.per-file-ignores]
125125
"__init__.py" = ["F401"]
@@ -128,13 +128,13 @@ mccabe.max-complexity = 24 # Default is 10
128128

129129
[tool.ruff.lint.pylint]
130130
allow-magic-value-types = ["bytes", "float", "int", "str"]
131-
max-args = 23 # Default is 5
132-
max-branches = 23 # Default is 12
133-
max-returns = 13 # Default is 6
134-
max-statements = 102 # Default is 50
131+
max-args = 23 # Default is 5
132+
max-branches = 23 # Default is 12
133+
max-returns = 13 # Default is 6
134+
max-statements = 102 # Default is 50
135135

136136
[tool.uv.workspace]
137-
members = ["examples/servers/*", "examples/snippets"]
137+
members = ["examples/clients/*", "examples/servers/*", "examples/snippets"]
138138

139139
[tool.uv.sources]
140140
mcp = { workspace = true }
@@ -154,16 +154,16 @@ filterwarnings = [
154154
"ignore:websockets.server.WebSocketServerProtocol is deprecated:DeprecationWarning",
155155
"ignore:Returning str or bytes.*:DeprecationWarning:mcp.server.lowlevel",
156156
# pywin32 internal deprecation warning
157-
"ignore:getargs.*The 'u' format is deprecated:DeprecationWarning"
157+
"ignore:getargs.*The 'u' format is deprecated:DeprecationWarning",
158158
]
159159

160160
[tool.markdown.lint]
161-
default=true
162-
MD004=false # ul-style - Unordered list style
163-
MD007.indent=2 # ul-indent - Unordered list indentation
164-
MD013=false # line-length - Line length
165-
MD029=false # ol-prefix - Ordered list item prefix
166-
MD033=false # no-inline-html Inline HTML
167-
MD041=false # first-line-heading/first-line-h1
168-
MD046=false # indented-code-blocks
169-
MD059=false # descriptive-link-text
161+
default = true
162+
MD004 = false # ul-style - Unordered list style
163+
MD007.indent = 2 # ul-indent - Unordered list indentation
164+
MD013 = false # line-length - Line length
165+
MD029 = false # ol-prefix - Ordered list item prefix
166+
MD033 = false # no-inline-html Inline HTML
167+
MD041 = false # first-line-heading/first-line-h1
168+
MD046 = false # indented-code-blocks
169+
MD059 = false # descriptive-link-text

src/mcp/client/session.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,16 +328,19 @@ async def call_tool(
328328
arguments: dict[str, Any] | None = None,
329329
read_timeout_seconds: timedelta | None = None,
330330
progress_callback: ProgressFnT | None = None,
331+
*,
332+
meta: dict[str, Any] | None = None,
331333
) -> types.CallToolResult:
332334
"""Send a tools/call request with optional progress callback support."""
333335

336+
_meta: types.RequestParams.Meta | None = None
337+
if meta is not None:
338+
_meta = types.RequestParams.Meta(**meta)
339+
334340
result = await self.send_request(
335341
types.ClientRequest(
336342
types.CallToolRequest(
337-
params=types.CallToolRequestParams(
338-
name=name,
339-
arguments=arguments,
340-
),
343+
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=_meta),
341344
)
342345
),
343346
types.CallToolResult,

src/mcp/server/fastmcp/server.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44

55
import inspect
66
import re
7-
from collections.abc import AsyncIterator, Awaitable, Callable, Collection, Iterable, Sequence
7+
from collections.abc import (
8+
AsyncIterator,
9+
Awaitable,
10+
Callable,
11+
Collection,
12+
Iterable,
13+
Sequence,
14+
)
815
from contextlib import AbstractAsyncContextManager, asynccontextmanager
916
from typing import Any, Generic, Literal
1017

@@ -22,10 +29,21 @@
2229
from starlette.types import Receive, Scope, Send
2330

2431
from mcp.server.auth.middleware.auth_context import AuthContextMiddleware
25-
from mcp.server.auth.middleware.bearer_auth import BearerAuthBackend, RequireAuthMiddleware
26-
from mcp.server.auth.provider import OAuthAuthorizationServerProvider, ProviderTokenVerifier, TokenVerifier
32+
from mcp.server.auth.middleware.bearer_auth import (
33+
BearerAuthBackend,
34+
RequireAuthMiddleware,
35+
)
36+
from mcp.server.auth.provider import (
37+
OAuthAuthorizationServerProvider,
38+
ProviderTokenVerifier,
39+
TokenVerifier,
40+
)
2741
from mcp.server.auth.settings import AuthSettings
28-
from mcp.server.elicitation import ElicitationResult, ElicitSchemaModelT, elicit_with_validation
42+
from mcp.server.elicitation import (
43+
ElicitationResult,
44+
ElicitSchemaModelT,
45+
elicit_with_validation,
46+
)
2947
from mcp.server.fastmcp.exceptions import ResourceError
3048
from mcp.server.fastmcp.prompts import Prompt, PromptManager
3149
from mcp.server.fastmcp.resources import FunctionResource, Resource, ResourceManager
@@ -112,7 +130,9 @@ def lifespan_wrapper(
112130
lifespan: Callable[[FastMCP[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]],
113131
) -> Callable[[MCPServer[LifespanResultT, Request]], AbstractAsyncContextManager[LifespanResultT]]:
114132
@asynccontextmanager
115-
async def wrap(_: MCPServer[LifespanResultT, Request]) -> AsyncIterator[LifespanResultT]:
133+
async def wrap(
134+
_: MCPServer[LifespanResultT, Request],
135+
) -> AsyncIterator[LifespanResultT]:
116136
async with lifespan(app) as context:
117137
yield context
118138

@@ -126,7 +146,7 @@ def __init__( # noqa: PLR0913
126146
instructions: str | None = None,
127147
website_url: str | None = None,
128148
icons: list[Icon] | None = None,
129-
auth_server_provider: OAuthAuthorizationServerProvider[Any, Any, Any] | None = None,
149+
auth_server_provider: (OAuthAuthorizationServerProvider[Any, Any, Any] | None) = None,
130150
token_verifier: TokenVerifier | None = None,
131151
event_store: EventStore | None = None,
132152
*,
@@ -145,7 +165,7 @@ def __init__( # noqa: PLR0913
145165
warn_on_duplicate_tools: bool = True,
146166
warn_on_duplicate_prompts: bool = True,
147167
dependencies: Collection[str] = (),
148-
lifespan: Callable[[FastMCP[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]] | None = None,
168+
lifespan: (Callable[[FastMCP[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]] | None) = None,
149169
auth: AuthSettings | None = None,
150170
transport_security: TransportSecuritySettings | None = None,
151171
):
@@ -290,6 +310,7 @@ async def list_tools(self) -> list[MCPTool]:
290310
outputSchema=info.output_schema,
291311
annotations=info.annotations,
292312
icons=info.icons,
313+
_meta=info.meta,
293314
)
294315
for info in tools
295316
]
@@ -365,6 +386,7 @@ def add_tool(
365386
description: str | None = None,
366387
annotations: ToolAnnotations | None = None,
367388
icons: list[Icon] | None = None,
389+
meta: dict[str, Any] | None = None,
368390
structured_output: bool | None = None,
369391
) -> None:
370392
"""Add a tool to the server.
@@ -390,6 +412,7 @@ def add_tool(
390412
description=description,
391413
annotations=annotations,
392414
icons=icons,
415+
meta=meta,
393416
structured_output=structured_output,
394417
)
395418

@@ -411,6 +434,7 @@ def tool(
411434
description: str | None = None,
412435
annotations: ToolAnnotations | None = None,
413436
icons: list[Icon] | None = None,
437+
meta: dict[str, Any] | None = None,
414438
structured_output: bool | None = None,
415439
) -> Callable[[AnyFunction], AnyFunction]:
416440
"""Decorator to register a tool.
@@ -458,6 +482,7 @@ def decorator(fn: AnyFunction) -> AnyFunction:
458482
description=description,
459483
annotations=annotations,
460484
icons=icons,
485+
meta=meta,
461486
structured_output=structured_output,
462487
)
463488
return fn
@@ -1169,7 +1194,10 @@ async def elicit(
11691194
"""
11701195

11711196
return await elicit_with_validation(
1172-
session=self.request_context.session, message=message, schema=schema, related_request_id=self.request_id
1197+
session=self.request_context.session,
1198+
message=message,
1199+
schema=schema,
1200+
related_request_id=self.request_id,
11731201
)
11741202

11751203
async def log(

src/mcp/server/fastmcp/tools/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Tool(BaseModel):
3434
context_kwarg: str | None = Field(None, description="Name of the kwarg that should receive context")
3535
annotations: ToolAnnotations | None = Field(None, description="Optional annotations for the tool")
3636
icons: list[Icon] | None = Field(default=None, description="Optional list of icons for this tool")
37+
meta: dict[str, Any] | None = Field(default=None, description="Optional metadata for this tool")
3738

3839
@cached_property
3940
def output_schema(self) -> dict[str, Any] | None:
@@ -49,6 +50,7 @@ def from_function(
4950
context_kwarg: str | None = None,
5051
annotations: ToolAnnotations | None = None,
5152
icons: list[Icon] | None = None,
53+
meta: dict[str, Any] | None = None,
5254
structured_output: bool | None = None,
5355
) -> Tool:
5456
"""Create a Tool from a function."""
@@ -81,6 +83,7 @@ def from_function(
8183
context_kwarg=context_kwarg,
8284
annotations=annotations,
8385
icons=icons,
86+
meta=meta,
8487
)
8588

8689
async def run(

src/mcp/server/fastmcp/tools/tool_manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def add_tool(
5050
description: str | None = None,
5151
annotations: ToolAnnotations | None = None,
5252
icons: list[Icon] | None = None,
53+
meta: dict[str, Any] | None = None,
5354
structured_output: bool | None = None,
5455
) -> Tool:
5556
"""Add a tool to the server."""
@@ -60,6 +61,7 @@ def add_tool(
6061
description=description,
6162
annotations=annotations,
6263
icons=icons,
64+
meta=meta,
6365
structured_output=structured_output,
6466
)
6567
existing = self._tools.get(tool.name)

0 commit comments

Comments
 (0)