Skip to content

Commit 6cae439

Browse files
committed
Added action_feedback through ctx.report_progress. Tested and working in Cursor, not showing in ChatGPT.
1 parent bf2dd8b commit 6cae439

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

server.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import argparse
2+
import asyncio
23
import io
34
import json
45
import os
56
import time
67
import uuid
78
from typing import Any, Dict, List, Optional, Union
89

9-
from fastmcp import FastMCP
10+
from fastmcp import Context, FastMCP
1011
from fastmcp.utilities.types import Image
1112
from PIL import Image as PILImage
1213

@@ -2463,7 +2464,9 @@ def inspect_all_actions() -> dict:
24632464
"send_action_goal('/turtle1/rotate_absolute', 'turtlesim/action/RotateAbsolute', {'theta': 1.57})"
24642465
)
24652466
)
2466-
def send_action_goal(action_name: str, action_type: str, goal: dict, timeout: float = None) -> dict:
2467+
async def send_action_goal(
2468+
action_name: str, action_type: str, goal: dict, timeout: float = None, ctx: Context = None
2469+
) -> dict:
24672470
"""
24682471
Send a goal to a ROS action server. Works only with ROS 2.
24692472
@@ -2515,16 +2518,29 @@ def send_action_goal(action_name: str, action_type: str, goal: dict, timeout: fl
25152518
actual_timeout = timeout if timeout is not None else 10.0 # Default 10 seconds
25162519
start_time = time.time()
25172520
last_feedback = None # Store the last feedback message
2521+
feedback_count = 0 # Count feedback messages received
25182522

25192523
while time.time() - start_time < actual_timeout:
2520-
response = ws_manager.receive(timeout=actual_timeout - (time.time() - start_time))
2524+
elapsed_time = time.time() - start_time
2525+
2526+
response = ws_manager.receive(timeout=actual_timeout - elapsed_time)
25212527

25222528
if response:
25232529
try:
25242530
msg_data = json.loads(response)
25252531

25262532
# Handle action_result messages (final completion)
25272533
if msg_data.get("op") == "action_result":
2534+
# Report completion
2535+
if ctx:
2536+
try:
2537+
completion_msg = f"Action completed successfully (received {feedback_count} feedback messages)"
2538+
await ctx.report_progress(
2539+
progress=feedback_count, total=None, message=completion_msg
2540+
)
2541+
except Exception:
2542+
pass
2543+
25282544
return {
25292545
"action": action_name,
25302546
"action_type": action_type,
@@ -2534,16 +2550,41 @@ def send_action_goal(action_name: str, action_type: str, goal: dict, timeout: fl
25342550
"result": msg_data.get("values", {}),
25352551
}
25362552

2537-
# Store action_feedback messages for timeout case
2553+
# Store action_feedback messages and report progress
25382554
if msg_data.get("op") == "action_feedback":
2555+
feedback_count += 1
25392556
last_feedback = msg_data
25402557

2558+
# Report feedback progress
2559+
if ctx:
2560+
try:
2561+
feedback_values = msg_data.get("values", {})
2562+
feedback_msg = f"Action feedback #{feedback_count}: {str(feedback_values)[:100]}..."
2563+
await ctx.report_progress(
2564+
progress=feedback_count, total=None, message=feedback_msg
2565+
)
2566+
except Exception:
2567+
pass
2568+
25412569
except json.JSONDecodeError:
25422570
continue
2571+
else:
2572+
# No response received, continue waiting
2573+
pass
25432574

2544-
time.sleep(0.1)
2575+
await asyncio.sleep(0.1)
25452576

25462577
# Timeout - return last feedback if available
2578+
if ctx and feedback_count > 0:
2579+
try:
2580+
await ctx.report_progress(
2581+
progress=feedback_count,
2582+
total=None,
2583+
message=f"Action timed out after {actual_timeout} seconds (received {feedback_count} feedback messages)",
2584+
)
2585+
except Exception:
2586+
pass
2587+
25472588
result = {
25482589
"action": action_name,
25492590
"action_type": action_type,

0 commit comments

Comments
 (0)