Spaces:
Running
Running
Jeremiah Lowin commited on
Use a simple overwrite instead of a merge for meta (#1296)
Browse files
src/fastmcp/server/proxy.py
CHANGED
|
@@ -256,7 +256,7 @@ class ProxyTool(Tool, MirroredComponent):
|
|
| 256 |
annotations=mcp_tool.annotations,
|
| 257 |
output_schema=mcp_tool.outputSchema,
|
| 258 |
meta=mcp_tool.meta,
|
| 259 |
-
tags=(mcp_tool.meta or {}).get("tags", []),
|
| 260 |
_mirrored=True,
|
| 261 |
)
|
| 262 |
|
|
@@ -305,6 +305,7 @@ class ProxyResource(Resource, MirroredComponent):
|
|
| 305 |
mcp_resource: mcp.types.Resource,
|
| 306 |
) -> ProxyResource:
|
| 307 |
"""Factory method to create a ProxyResource from a raw MCP resource schema."""
|
|
|
|
| 308 |
return cls(
|
| 309 |
client=client,
|
| 310 |
uri=mcp_resource.uri,
|
|
@@ -312,7 +313,7 @@ class ProxyResource(Resource, MirroredComponent):
|
|
| 312 |
description=mcp_resource.description,
|
| 313 |
mime_type=mcp_resource.mimeType or "text/plain",
|
| 314 |
meta=mcp_resource.meta,
|
| 315 |
-
tags=(mcp_resource.meta or {}).get("tags", []),
|
| 316 |
_mirrored=True,
|
| 317 |
)
|
| 318 |
|
|
@@ -353,7 +354,7 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
|
|
| 353 |
mime_type=mcp_template.mimeType or "text/plain",
|
| 354 |
parameters={}, # Remote templates don't have local parameters
|
| 355 |
meta=mcp_template.meta,
|
| 356 |
-
tags=(mcp_template.meta or {}).get("tags", []),
|
| 357 |
_mirrored=True,
|
| 358 |
)
|
| 359 |
|
|
@@ -387,7 +388,7 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
|
|
| 387 |
description=self.description,
|
| 388 |
mime_type=result[0].mimeType,
|
| 389 |
meta=self.meta,
|
| 390 |
-
tags=(self.meta or {}).get("tags", []),
|
| 391 |
_value=value,
|
| 392 |
)
|
| 393 |
|
|
@@ -422,7 +423,7 @@ class ProxyPrompt(Prompt, MirroredComponent):
|
|
| 422 |
description=mcp_prompt.description,
|
| 423 |
arguments=arguments,
|
| 424 |
meta=mcp_prompt.meta,
|
| 425 |
-
tags=(mcp_prompt.meta or {}).get("tags", []),
|
| 426 |
_mirrored=True,
|
| 427 |
)
|
| 428 |
|
|
|
|
| 256 |
annotations=mcp_tool.annotations,
|
| 257 |
output_schema=mcp_tool.outputSchema,
|
| 258 |
meta=mcp_tool.meta,
|
| 259 |
+
tags=(mcp_tool.meta or {}).get("_fastmcp", {}).get("tags", []),
|
| 260 |
_mirrored=True,
|
| 261 |
)
|
| 262 |
|
|
|
|
| 305 |
mcp_resource: mcp.types.Resource,
|
| 306 |
) -> ProxyResource:
|
| 307 |
"""Factory method to create a ProxyResource from a raw MCP resource schema."""
|
| 308 |
+
|
| 309 |
return cls(
|
| 310 |
client=client,
|
| 311 |
uri=mcp_resource.uri,
|
|
|
|
| 313 |
description=mcp_resource.description,
|
| 314 |
mime_type=mcp_resource.mimeType or "text/plain",
|
| 315 |
meta=mcp_resource.meta,
|
| 316 |
+
tags=(mcp_resource.meta or {}).get("_fastmcp", {}).get("tags", []),
|
| 317 |
_mirrored=True,
|
| 318 |
)
|
| 319 |
|
|
|
|
| 354 |
mime_type=mcp_template.mimeType or "text/plain",
|
| 355 |
parameters={}, # Remote templates don't have local parameters
|
| 356 |
meta=mcp_template.meta,
|
| 357 |
+
tags=(mcp_template.meta or {}).get("_fastmcp", {}).get("tags", []),
|
| 358 |
_mirrored=True,
|
| 359 |
)
|
| 360 |
|
|
|
|
| 388 |
description=self.description,
|
| 389 |
mime_type=result[0].mimeType,
|
| 390 |
meta=self.meta,
|
| 391 |
+
tags=(self.meta or {}).get("_fastmcp", {}).get("tags", []),
|
| 392 |
_value=value,
|
| 393 |
)
|
| 394 |
|
|
|
|
| 423 |
description=mcp_prompt.description,
|
| 424 |
arguments=arguments,
|
| 425 |
meta=mcp_prompt.meta,
|
| 426 |
+
tags=(mcp_prompt.meta or {}).get("_fastmcp", {}).get("tags", []),
|
| 427 |
_mirrored=True,
|
| 428 |
)
|
| 429 |
|
src/fastmcp/utilities/components.py
CHANGED
|
@@ -16,12 +16,6 @@ class FastMCPMeta(TypedDict, total=False):
|
|
| 16 |
tags: list[str]
|
| 17 |
|
| 18 |
|
| 19 |
-
def _merge_meta(left: FastMCPMeta, right: FastMCPMeta) -> FastMCPMeta:
|
| 20 |
-
return FastMCPMeta(
|
| 21 |
-
tags=sorted(set(left.get("tags", [])) | set(right.get("tags", [])))
|
| 22 |
-
)
|
| 23 |
-
|
| 24 |
-
|
| 25 |
def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:
|
| 26 |
"""Convert a sequence to a set, defaulting to an empty set if None."""
|
| 27 |
if maybe_set is None:
|
|
@@ -90,8 +84,9 @@ class FastMCPComponent(FastMCPBaseModel):
|
|
| 90 |
|
| 91 |
if include_fastmcp_meta:
|
| 92 |
fastmcp_meta = FastMCPMeta(tags=sorted(self.tags))
|
|
|
|
| 93 |
if upstream_meta := meta.get("_fastmcp"):
|
| 94 |
-
fastmcp_meta =
|
| 95 |
meta["_fastmcp"] = fastmcp_meta
|
| 96 |
|
| 97 |
return meta or None
|
|
|
|
| 16 |
tags: list[str]
|
| 17 |
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:
|
| 20 |
"""Convert a sequence to a set, defaulting to an empty set if None."""
|
| 21 |
if maybe_set is None:
|
|
|
|
| 84 |
|
| 85 |
if include_fastmcp_meta:
|
| 86 |
fastmcp_meta = FastMCPMeta(tags=sorted(self.tags))
|
| 87 |
+
# overwrite any existing _fastmcp meta with keys from the new one
|
| 88 |
if upstream_meta := meta.get("_fastmcp"):
|
| 89 |
+
fastmcp_meta = upstream_meta | fastmcp_meta
|
| 90 |
meta["_fastmcp"] = fastmcp_meta
|
| 91 |
|
| 92 |
return meta or None
|