11import asyncio
22import random
33import time
4- from datetime import datetime
5- from typing import Dict , Any
4+ from typing import Any , Dict
65
7- from mcp .server .fastmcp import FastMCP , Context
6+ from mcp .server .fastmcp import Context , FastMCP
87
98mcp = FastMCP ("Long Running Operations MCP Server" )
109
@@ -14,60 +13,60 @@ async def run_blocking_operation(
1413 progress_interval_seconds : int ,
1514 enable_logs : bool ,
1615 operation_name : str ,
17- ctx : Context
16+ ctx : Context ,
1817) -> Dict [str , Any ]:
1918 """Run a blocking operation with progress notifications."""
2019 start_time = time .time ()
21-
20+
2221 try :
2322 # Send initial progress
2423 await ctx .report_progress (progress = 0 , total = total_seconds )
2524 if enable_logs :
2625 await ctx .info (f"Starting { operation_name } " )
27-
26+
2827 elapsed = 0
2928 while elapsed < total_seconds :
3029 await asyncio .sleep (min (progress_interval_seconds , total_seconds - elapsed ))
3130 elapsed = time .time () - start_time
32-
31+
3332 current_progress = min (elapsed , total_seconds )
3433 remaining_time = max (0 , total_seconds - elapsed )
35-
34+
3635 message = f"Running { operation_name } - { remaining_time :.1f} s remaining"
3736 await ctx .report_progress (progress = current_progress , total = total_seconds )
38-
37+
3938 if enable_logs :
40- await ctx .info (f"{ operation_name } : { current_progress / total_seconds * 100 :.1f} % - { message } " )
41-
39+ await ctx .info (
40+ f"{ operation_name } : { current_progress / total_seconds * 100 :.1f} % - { message } "
41+ )
42+
4243 # Final completion notification
4344 await ctx .report_progress (progress = total_seconds , total = total_seconds )
4445 if enable_logs :
4546 await ctx .info (f"Completed { operation_name } " )
46-
47+
4748 return {
4849 "status" : "completed" ,
4950 "operation_name" : operation_name ,
5051 "duration_seconds" : total_seconds ,
5152 "actual_elapsed_seconds" : elapsed ,
52- "message" : f"{ operation_name } completed successfully"
53+ "message" : f"{ operation_name } completed successfully" ,
5354 }
54-
55+
5556 except Exception as e :
5657 error_message = f"Error in { operation_name } : { str (e )} "
5758 await ctx .error (error_message )
5859 return {
5960 "status" : "error" ,
6061 "operation_name" : operation_name ,
6162 "error" : str (e ),
62- "message" : error_message
63+ "message" : error_message ,
6364 }
6465
6566
6667@mcp .tool ()
6768async def run_one_second_task (
68- ctx : Context ,
69- progress_interval_seconds : int = 1 ,
70- enable_logs : bool = False
69+ ctx : Context , progress_interval_seconds : int = 1 , enable_logs : bool = False
7170) -> Dict [str , Any ]:
7271 """Run a task that takes approximately 1 second to complete and blocks until finished.
7372
@@ -80,19 +79,17 @@ async def run_one_second_task(
8079 Dictionary containing operation completion details
8180 """
8281 operation_name = "One Second Task"
83-
82+
8483 result = await run_blocking_operation (
8584 1 , progress_interval_seconds , enable_logs , operation_name , ctx
8685 )
87-
86+
8887 return result
8988
9089
9190@mcp .tool ()
9291async def run_one_minute_task (
93- ctx : Context ,
94- progress_interval_seconds : int = 10 ,
95- enable_logs : bool = False
92+ ctx : Context , progress_interval_seconds : int = 10 , enable_logs : bool = False
9693) -> Dict [str , Any ]:
9794 """Run a task that takes approximately 1 minute to complete and blocks until finished.
9895
@@ -105,19 +102,17 @@ async def run_one_minute_task(
105102 Dictionary containing operation completion details
106103 """
107104 operation_name = "One Minute Task"
108-
105+
109106 result = await run_blocking_operation (
110107 60 , progress_interval_seconds , enable_logs , operation_name , ctx
111108 )
112-
109+
113110 return result
114111
115112
116113@mcp .tool ()
117114async def run_one_hour_task (
118- ctx : Context ,
119- progress_interval_seconds : int = 300 ,
120- enable_logs : bool = False
115+ ctx : Context , progress_interval_seconds : int = 300 , enable_logs : bool = False
121116) -> Dict [str , Any ]:
122117 """Run a task that takes approximately 1 hour to complete and blocks until finished.
123118
@@ -130,11 +125,11 @@ async def run_one_hour_task(
130125 Dictionary containing operation completion details
131126 """
132127 operation_name = "One Hour Task"
133-
128+
134129 result = await run_blocking_operation (
135130 3600 , progress_interval_seconds , enable_logs , operation_name , ctx
136131 )
137-
132+
138133 return result
139134
140135
@@ -145,7 +140,7 @@ async def run_custom_delay_task(
145140 minutes : int = 0 ,
146141 hours : int = 0 ,
147142 progress_interval_seconds : int = 30 ,
148- enable_logs : bool = False
143+ enable_logs : bool = False ,
149144) -> Dict [str , Any ]:
150145 """Run a task with custom delay duration that blocks until finished.
151146
@@ -161,26 +156,26 @@ async def run_custom_delay_task(
161156 Dictionary containing operation completion details
162157 """
163158 total_seconds = seconds + (minutes * 60 ) + (hours * 3600 )
164-
159+
165160 if total_seconds <= 0 :
166161 return {
167162 "status" : "error" ,
168- "message" : "Total delay must be greater than 0. Please specify seconds, minutes, or hours."
163+ "message" : "Total delay must be greater than 0. Please specify seconds, minutes, or hours." ,
169164 }
170-
165+
171166 operation_name = f"Custom Delay Task ({ hours } h { minutes } m { seconds } s)"
172-
167+
173168 result = await run_blocking_operation (
174169 total_seconds , progress_interval_seconds , enable_logs , operation_name , ctx
175170 )
176-
171+
177172 # Add duration breakdown to result
178173 result ["duration_breakdown" ] = {
179174 "hours" : hours ,
180175 "minutes" : minutes ,
181- "seconds" : seconds
176+ "seconds" : seconds ,
182177 }
183-
178+
184179 return result
185180
186181
@@ -189,7 +184,7 @@ async def run_random_duration_task(
189184 ctx : Context ,
190185 max_duration_seconds : int = 100 ,
191186 progress_interval_seconds : int = 10 ,
192- enable_logs : bool = False
187+ enable_logs : bool = False ,
193188) -> Dict [str , Any ]:
194189 """Run a task that takes a random amount of time between 0 and max_duration_seconds.
195190
@@ -205,24 +200,28 @@ async def run_random_duration_task(
205200 if max_duration_seconds <= 0 :
206201 return {
207202 "status" : "error" ,
208- "message" : "max_duration_seconds must be greater than 0."
203+ "message" : "max_duration_seconds must be greater than 0." ,
209204 }
210-
205+
211206 # Generate random duration between 0 and max_duration_seconds
212207 random_duration = random .uniform (0 , max_duration_seconds )
213208 operation_name = f"Random Duration Task ({ random_duration :.1f} s)"
214-
209+
215210 result = await run_blocking_operation (
216- int (random_duration ), progress_interval_seconds , enable_logs , operation_name , ctx
211+ int (random_duration ),
212+ progress_interval_seconds ,
213+ enable_logs ,
214+ operation_name ,
215+ ctx ,
217216 )
218-
217+
219218 # Add random duration info to result
220219 result ["random_duration_seconds" ] = random_duration
221220 result ["max_duration_seconds" ] = max_duration_seconds
222-
221+
223222 return result
224223
225224
226225# Run the server when the script is executed
227226if __name__ == "__main__" :
228- mcp .run ()
227+ mcp .run ()
0 commit comments