From efcfe7b290a3c57e869c23bf123344d5b53131f9 Mon Sep 17 00:00:00 2001 From: rholinshead <5060851+rholinshead@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:32:55 -0400 Subject: [PATCH 1/3] Support settings dict for FastMCP server --- examples/mcp_agent_server/asyncio/README.md | 5 ++++- .../asyncio/basic_agent_server.py | 20 +++++++++++++++++-- src/mcp_agent/server/app_server.py | 6 +++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/examples/mcp_agent_server/asyncio/README.md b/examples/mcp_agent_server/asyncio/README.md index 8b2e64c74..39c3cbb5a 100644 --- a/examples/mcp_agent_server/asyncio/README.md +++ b/examples/mcp_agent_server/asyncio/README.md @@ -12,7 +12,7 @@ https://github.com/user-attachments/assets/f651af86-222d-4df0-8241-616414df66e4 - Creating workflows with the `Workflow` base class - Registering workflows with an `MCPApp` -- Exposing workflows as MCP tools using `create_mcp_server_for_app` +- Exposing workflows as MCP tools using `create_mcp_server_for_app`, optionally using custom FastMCP settings - Connecting to an MCP server using `gen_client` - Running workflows remotely and monitoring their status @@ -93,6 +93,9 @@ You can also run the server and client separately: ```bash uv run basic_agent_server.py + + # Optionally, run with the example custom FastMCP settings + uv run basic_agent_server.py --custom-fastmcp-settings ``` 2. In another terminal, run the client: diff --git a/examples/mcp_agent_server/asyncio/basic_agent_server.py b/examples/mcp_agent_server/asyncio/basic_agent_server.py index 07264f5b2..ad3044c6a 100644 --- a/examples/mcp_agent_server/asyncio/basic_agent_server.py +++ b/examples/mcp_agent_server/asyncio/basic_agent_server.py @@ -7,6 +7,7 @@ 3. Declarative agent configuration using FastMCPApp decorators """ +import argparse import asyncio import os import logging @@ -169,6 +170,15 @@ async def run(self, input: str) -> WorkflowResult[str]: async def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--custom-fastmcp-settings", + type=bool, + help="Enable custom FastMCP settings for the server", + ) + args = parser.parse_args() + use_custom_fastmcp_settings = args.custom_fastmcp_settings + async with app.run() as agent_app: # Add the current directory to the filesystem server's args if needed context = agent_app.context @@ -182,8 +192,14 @@ async def main(): for workflow_id in agent_app.workflows: logger.info(f" - {workflow_id}") - # Create the MCP server that exposes both workflows and agent configurations - mcp_server = create_mcp_server_for_app(agent_app) + # Create the MCP server that exposes both workflows and agent configurations, + # optionally using custom FastMCP settings + fast_mcp_settings = ( + {"host": "localhost", "port": 8001, "debug": True, "log_level": "debug"} + if use_custom_fastmcp_settings + else None + ) + mcp_server = create_mcp_server_for_app(agent_app, fast_mcp_settings) # Add custom tool to get token usage for a workflow @mcp_server.tool( diff --git a/src/mcp_agent/server/app_server.py b/src/mcp_agent/server/app_server.py index 7d92c4c6a..0c96f0abb 100644 --- a/src/mcp_agent/server/app_server.py +++ b/src/mcp_agent/server/app_server.py @@ -81,12 +81,15 @@ def workflow_registry(self) -> WorkflowRegistry: return self.context.workflow_registry -def create_mcp_server_for_app(app: MCPApp) -> FastMCP: +def create_mcp_server_for_app( + app: MCPApp, settings: dict[str, Any] | None = None +) -> FastMCP: """ Create an MCP server for a given MCPApp instance. Args: app: The MCPApp instance to create a server for + settings: Optional FastMCP Settings dict to configure the server. Returns: A configured FastMCP server instance @@ -119,6 +122,7 @@ async def app_specific_lifespan(mcp: FastMCP) -> AsyncIterator[ServerContext]: # or use the MCPApp's description if available. instructions=f"MCP server exposing {app.name} workflows and agents. Description: {app.description}", lifespan=app_specific_lifespan, + settings=settings, ) # region Workflow Tools From 353d724f9846d75ce1242e81811aae19f390d740 Mon Sep 17 00:00:00 2001 From: rholinshead <5060851+rholinshead@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:05:04 -0400 Subject: [PATCH 2/3] Fix settings spread --- examples/mcp_agent_server/asyncio/README.md | 4 ++++ .../asyncio/basic_agent_server.py | 5 +++-- examples/mcp_agent_server/asyncio/client.py | 18 +++++++++++++++++- src/mcp_agent/server/app_server.py | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/examples/mcp_agent_server/asyncio/README.md b/examples/mcp_agent_server/asyncio/README.md index 39c3cbb5a..8b5b59965 100644 --- a/examples/mcp_agent_server/asyncio/README.md +++ b/examples/mcp_agent_server/asyncio/README.md @@ -99,8 +99,12 @@ You can also run the server and client separately: ``` 2. In another terminal, run the client: + ```bash uv run client.py + + # Optionally, run with the example custom FastMCP settings + uv run client.py --custom-fastmcp-settings ``` ## MCP Clients diff --git a/examples/mcp_agent_server/asyncio/basic_agent_server.py b/examples/mcp_agent_server/asyncio/basic_agent_server.py index ad3044c6a..e72aff046 100644 --- a/examples/mcp_agent_server/asyncio/basic_agent_server.py +++ b/examples/mcp_agent_server/asyncio/basic_agent_server.py @@ -173,7 +173,7 @@ async def main(): parser = argparse.ArgumentParser() parser.add_argument( "--custom-fastmcp-settings", - type=bool, + action="store_true", help="Enable custom FastMCP settings for the server", ) args = parser.parse_args() @@ -195,11 +195,12 @@ async def main(): # Create the MCP server that exposes both workflows and agent configurations, # optionally using custom FastMCP settings fast_mcp_settings = ( - {"host": "localhost", "port": 8001, "debug": True, "log_level": "debug"} + {"host": "localhost", "port": 8001, "debug": True, "log_level": "DEBUG"} if use_custom_fastmcp_settings else None ) mcp_server = create_mcp_server_for_app(agent_app, fast_mcp_settings) + logger.info(f"MCP Server settings: {mcp_server.settings}") # Add custom tool to get token usage for a workflow @mcp_server.tool( diff --git a/examples/mcp_agent_server/asyncio/client.py b/examples/mcp_agent_server/asyncio/client.py index 91e2b689f..27ea442ed 100644 --- a/examples/mcp_agent_server/asyncio/client.py +++ b/examples/mcp_agent_server/asyncio/client.py @@ -1,3 +1,4 @@ +import argparse import asyncio import json import time @@ -11,6 +12,15 @@ async def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--custom-fastmcp-settings", + action="store_true", + help="Enable custom FastMCP settings for the server", + ) + args = parser.parse_args() + use_custom_fastmcp_settings = args.custom_fastmcp_settings + # Create MCPApp to get the server registry app = MCPApp(name="workflow_mcp_client") async with app.run() as client_app: @@ -21,11 +31,17 @@ async def main(): logger.info("Connecting to workflow server...") # Override the server configuration to point to our local script + run_server_args = ["run", "basic_agent_server.py"] + if use_custom_fastmcp_settings: + logger.info("Using custom FastMCP settings for the server.") + run_server_args += ["--custom-fastmcp-settings"] + else: + logger.info("Using default FastMCP settings for the server.") context.server_registry.registry["basic_agent_server"] = MCPServerSettings( name="basic_agent_server", description="Local workflow server running the basic agent example", command="uv", - args=["run", "basic_agent_server.py"], + args=run_server_args, ) # Connect to the workflow server diff --git a/src/mcp_agent/server/app_server.py b/src/mcp_agent/server/app_server.py index 0c96f0abb..aba9fa665 100644 --- a/src/mcp_agent/server/app_server.py +++ b/src/mcp_agent/server/app_server.py @@ -122,7 +122,7 @@ async def app_specific_lifespan(mcp: FastMCP) -> AsyncIterator[ServerContext]: # or use the MCPApp's description if available. instructions=f"MCP server exposing {app.name} workflows and agents. Description: {app.description}", lifespan=app_specific_lifespan, - settings=settings, + **settings or {}, ) # region Workflow Tools From a67f7f07bf2750998fef6c8a4f4fc31e2b0eaf0f Mon Sep 17 00:00:00 2001 From: rholinshead <5060851+rholinshead@users.noreply.github.com> Date: Thu, 7 Aug 2025 10:10:51 -0400 Subject: [PATCH 3/3] Just use kwargs instead of settings arg --- examples/mcp_agent_server/asyncio/basic_agent_server.py | 2 +- src/mcp_agent/server/app_server.py | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/mcp_agent_server/asyncio/basic_agent_server.py b/examples/mcp_agent_server/asyncio/basic_agent_server.py index e72aff046..feacef111 100644 --- a/examples/mcp_agent_server/asyncio/basic_agent_server.py +++ b/examples/mcp_agent_server/asyncio/basic_agent_server.py @@ -199,7 +199,7 @@ async def main(): if use_custom_fastmcp_settings else None ) - mcp_server = create_mcp_server_for_app(agent_app, fast_mcp_settings) + mcp_server = create_mcp_server_for_app(agent_app, **(fast_mcp_settings or {})) logger.info(f"MCP Server settings: {mcp_server.settings}") # Add custom tool to get token usage for a workflow diff --git a/src/mcp_agent/server/app_server.py b/src/mcp_agent/server/app_server.py index aba9fa665..4a8eec3a6 100644 --- a/src/mcp_agent/server/app_server.py +++ b/src/mcp_agent/server/app_server.py @@ -81,15 +81,13 @@ def workflow_registry(self) -> WorkflowRegistry: return self.context.workflow_registry -def create_mcp_server_for_app( - app: MCPApp, settings: dict[str, Any] | None = None -) -> FastMCP: +def create_mcp_server_for_app(app: MCPApp, **kwargs: Any) -> FastMCP: """ Create an MCP server for a given MCPApp instance. Args: app: The MCPApp instance to create a server for - settings: Optional FastMCP Settings dict to configure the server. + kwargs: Optional FastMCP settings to configure the server. Returns: A configured FastMCP server instance @@ -122,7 +120,7 @@ async def app_specific_lifespan(mcp: FastMCP) -> AsyncIterator[ServerContext]: # or use the MCPApp's description if available. instructions=f"MCP server exposing {app.name} workflows and agents. Description: {app.description}", lifespan=app_specific_lifespan, - **settings or {}, + **kwargs, ) # region Workflow Tools