Skip to content

issue with integrating createUIResource with python sdk #103

@Riyaksharma

Description

@Riyaksharma

I am trying to leverage mcp-ui with my python sdk

import { createUIResource } from '@mcp-ui/server';

const input = process.argv[2]; // Expect a JSON string as the first argument
const params = JSON.parse(input);

const uiResource = createUIResource(params);
console.log(JSON.stringify(uiResource));
import subprocess
import json

def create_ui_resource_py(params):
    import os
    # Get absolute path to create_ui_resource.js in the same directory
    node_script = os.path.join(os.path.dirname(__file__), 'create_ui_resource.mjs')
    args = [json.dumps(params)]
    result = subprocess.run(
        ['node', node_script] + args,
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise RuntimeError(f"Node.js error: {result.stderr}")
    return json.loads(result.stdout)
@register_as_tool
   @with_header_auth(ApplicationAnalyzeApi)
   async def get_all_traces(
       self,
       payload: Optional[Union[Dict[str, Any], str]] = None,
       api_client=None,
       ctx=None,
   ) -> Dict[str, Any]:
       """
       Get all traces in the monitoring.
       This tool endpoint retrieves the metrics for traces.

       Sample payload:
       {
       "includeInternal": false,
       "includeSynthetic": false,
       "pagination": { "retrievalSize": 1 },
       "tagFilterExpression": {
           "type": "EXPRESSION",
           "logicalOperator": "AND",
           "elements": [
           {
               "type": "TAG_FILTER",
               "name": "endpoint.name",
               "operator": "EQUALS",
               "entity": "DESTINATION",
               "value": "GET /"
           },
           {
               "type": "TAG_FILTER",
               "name": "service.name",
               "operator": "EQUALS",
               "entity": "DESTINATION",
               "value": "groundskeeper"
           }
           ]
       },
       "order": { "by": "traceLabel", "direction": "DESC" }
       }

       Returns:
           Union[Dict[str, Any]]: Structured traces data with summary statistics and analysis.
       """
       try:
           # Parse the payload if it's a string
           if isinstance(payload, str):
               logger.debug("Payload is a string, attempting to parse")
               try:
                   try:
                       parsed_payload = json.loads(payload)
                       logger.debug("Successfully parsed payload as JSON")
                       request_body = parsed_payload
                   except json.JSONDecodeError as e:
                       logger.debug(f"JSON parsing failed: {e}, trying with quotes replaced")

                       # Try replacing single quotes with double quotes
                       fixed_payload = payload.replace("'", "\"")
                       try:
                           parsed_payload = json.loads(fixed_payload)
                           logger.debug("Successfully parsed fixed JSON")
                           request_body = parsed_payload
                       except json.JSONDecodeError:
                           # Try as Python literal
                           try:
                               parsed_payload = ast.literal_eval(payload)
                               logger.debug("Successfully parsed payload as Python literal")
                               request_body = parsed_payload
                           except (SyntaxError, ValueError) as e2:
                               logger.debug(f"Failed to parse payload string: {e2}")
                               return {"error": f"Invalid payload format: {e2}", "payload": payload}
               except Exception as e:
                   logger.debug(f"Error parsing payload string: {e}")
                   return {"error": f"Failed to parse payload: {e}", "payload": payload}
           else:
               # If payload is already a dictionary, use it directly
               logger.debug("Using provided payload dictionary")
               request_body = payload

           # GetTraces is already imported at the top of the file
           logger.debug("Using GetTraces from top-level import")

           # Create an GetTraces object from the request body
           try:
               query_params = {}
               if request_body and "tag_filter_expression" in request_body:
                   query_params["tag_filter_expression"] = request_body["tag_filter_expression"]
               logger.debug(f"Creating get_traces with params: {query_params}")
               config_object = GetTraces(**query_params)
               logger.debug("Successfully got traces")
           except Exception as e:
               logger.debug(f"Error creating get_traces: {e}")
               return {"error": f"Failed to get traces: {e!s}"}

           # Call the get_traces method from the SDK
           logger.debug("Calling get_traces with config object")
           result = api_client.get_traces(get_traces=config_object)
           result_dict = result.to_dict() if hasattr(result, "to_dict") else (result or {})
           
           # Build UI resource with trace data
           trace_items = result_dict.get('items', [])
           html_content = (
               '<h2>Instana Traces Dashboard</h2>'
               f'<p>Total traces: {len(trace_items)}</p>'
               f'<pre>{json.dumps(trace_items, indent=2)}</pre>'
           )
           
           # Use rawHtml content type as it's the most direct approach
           content = {
               "type": "rawHtml",
               "htmlString": html_content
           }
           
           params = {
               "uri": "ui://instana-traces",
               "content": content,
               "encoding": "text",
               "mimeType": "text/html",
               "name": "Instana Traces Dashboard",
               "description": "Real-time traces from Instana monitoring platform",
               "uiMetadata": {
                   "mcpui.dev/ui-title": "Instana Traces Dashboard",
                   "mcpui.dev/ui-icon": "📊",
                   "mcpui.dev/ui-category": "monitoring",
                   "mcpui.dev/ui-renderMode": "inline"
               },
               "metadata": {
                   "source": "instana",
                   "type": "dashboard",
                   "refreshable": True
               }
           }
           
           ui_resource = create_ui_resource_py(params)
           
           return {"content": [ui_resource]}

       except Exception as e:
           logger.error(f"Error in get_all_traces: {e}")
           return {"error": f"Failed to get traces: {e!s}"}

but I see no UI being rendered.
{"content":[{"type":"resource","resource":{"uri":"ui://instana-traces","mimeType":"text/html","text":"<h2>Instana Traces Dashboard</h2><p>Total traces: 200</p><pre>[\n {\n \"cursor\": {\n \"service\": {\n \"entityType\": \"SERVICE\",\n }\n }\n]</pre>","_meta":{"mcpui.dev/ui-mcpui.dev/ui-title":"Instana Traces Dashboard","mcpui.dev/ui-mcpui.dev/ui-icon":"📊","mcpui.dev/ui-mcpui.dev/ui-category":"monitoring","mcpui.dev/ui-mcpui.dev/ui-renderMode":"inline","source":"instana","type":"dashboard","refreshable":true}}}]}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions