get_app_variables
Retrieve and filter application variables in Qlik Sense, separating script and UI sources, with pagination and wildcard search for precise results.
Instructions
Return variables split by source (script/ui) with pagination and wildcard search.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | Yes | Application GUID | |
| case_sensitive | No | Case sensitive matching for search_string | |
| created_in_script | No | Return only variables created in script (true/false). If omitted, return both | |
| limit | No | Max variables to return (default: 10, max: 100) | |
| offset | No | Offset for pagination (default: 0) | |
| search_number | No | Wildcard search among numeric variable values (* and % supported) | |
| search_string | No | Wildcard search by variable name or text value (* and % supported), case-insensitive by default |
Implementation Reference
- qlik_sense_mcp_server/server.py:345-360 (registration)Tool registration in list_tools() handler including name, description, and detailed input schema with pagination, filtering by script/UI source, wildcard search optionsname="get_app_variables", description="Return variables split by source (script/ui) with pagination and wildcard search.", inputSchema={ "type": "object", "properties": { "app_id": {"type": "string", "description": "Application GUID"}, "limit": {"type": "integer", "description": "Max variables to return (default: 10, max: 100)", "default": 10}, "offset": {"type": "integer", "description": "Offset for pagination (default: 0)", "default": 0}, "created_in_script": {"type": "string", "description": "Return only variables created in script (true/false). If omitted, return both"}, "search_string": {"type": "string", "description": "Wildcard search by variable name or text value (* and % supported), case-insensitive by default"}, "search_number": {"type": "string", "description": "Wildcard search among numeric variable values (* and % supported)"}, "case_sensitive": {"type": "boolean", "description": "Case sensitive matching for search_string", "default": False} }, "required": ["app_id"], } ),
- qlik_sense_mcp_server/server.py:761-855 (handler)Main handler in call_tool() for executing get_app_variables: validates inputs, connects to Qlik Engine, opens app, fetches variables via helper, applies search/filter/pagination by script/UI source, formats response as dict with variables_from_script and variables_from_uielif name == "get_app_variables": app_id = arguments["app_id"] limit = arguments.get("limit", 10) offset = arguments.get("offset", 0) created_in_script_arg = arguments.get("created_in_script", None) search_string = arguments.get("search_string") search_number = arguments.get("search_number") case_sensitive = arguments.get("case_sensitive", False) if limit is None or limit < 1: limit = 10 if limit > 100: limit = 100 if offset is None or offset < 0: offset = 0 def _to_bool(value: Any, default: Optional[bool] = None) -> Optional[bool]: if value is None: return default if isinstance(value, bool): return value if isinstance(value, int): return value != 0 if isinstance(value, str): v = value.strip().lower() if v in ("true", "1", "yes", "y"): return True if v in ("false", "0", "no", "n"): return False return default created_in_script = _to_bool(created_in_script_arg, None) def _wildcard_to_regex(pattern: str, case_sensitive_flag: bool): import re escaped = re.escape(pattern).replace("\\*", ".*").replace("%", ".*") regex = f"^{escaped}$" return re.compile(regex, 0 if case_sensitive_flag else re.IGNORECASE) def _get_variables(): try: self.engine_api.connect() app_result = self.engine_api.open_doc_safe(app_id, no_data=False) app_handle = app_result.get("qReturn", {}).get("qHandle", -1) if app_handle == -1: return {"error": "Failed to open app"} # Use the alternative method for getting variables var_list = self.engine_api._get_user_variables(app_handle) or [] prepared = [] for v in var_list: name = v.get("name", "") text_val = v.get("text_value", "") is_script = v.get("is_script_created", False) prepared.append({ "name": name, "text_value": text_val if text_val is not None else "", "is_script": is_script }) if created_in_script is True: prepared = [x for x in prepared if x["is_script"]] elif created_in_script is False: prepared = [x for x in prepared if not x["is_script"]] else: # По умолчанию показываем только переменные из UI prepared = [x for x in prepared if not x["is_script"]] if search_string: rx = _wildcard_to_regex(search_string, case_sensitive) prepared = [x for x in prepared if rx.match(x["name"]) or rx.match(x.get("text_value", ""))] from_script = [x for x in prepared if x["is_script"]] from_ui = [x for x in prepared if not x["is_script"]] def _slice_and_map(items): sliced = items[offset:offset + limit] result_map = {} for it in sliced: val = it.get("text_value", "") result_map[it["name"]] = val return result_map res_script = _slice_and_map(from_script) res_ui = _slice_and_map(from_ui) return { "variables_from_script": res_script if res_script else "", "variables_from_ui": res_ui if res_ui else "" } except Exception as e: return {"error": str(e)} finally: self.engine_api.disconnect() result = await asyncio.to_thread(_get_variables) return [TextContent(type="text", text=json.dumps(result, indent=2, ensure_ascii=False))]
- Core helper _get_user_variables: creates VariableList session object via Engine API (excluding system/config vars), extracts user variables with name, text_value, is_script_created flag for script/UI distinction used by main handlerdef _get_user_variables(self, app_handle: int) -> List[Dict[str, Any]]: """Get only user-created variables (exclude system).""" try: # Create VariableList object variable_list_def = { "qInfo": {"qType": "VariableList"}, "qVariableListDef": { "qType": "variable", "qShowReserved": False, # Exclude system variables "qShowConfig": False, "qData": {"tags": "/tags"} } } variable_list_response = self.send_request("CreateSessionObject", [variable_list_def], handle=app_handle) if "qReturn" not in variable_list_response: return [] variable_list_handle = variable_list_response["qReturn"]["qHandle"] layout_response = self.send_request("GetLayout", [], handle=variable_list_handle) variables = layout_response.get("qLayout", {}).get("qVariableList", {}).get("qItems", []) user_variables = [] for variable in variables: # Additional filter for user variables only if not variable.get("qIsReserved", False) and not variable.get("qIsConfig", False): definition = variable.get("qDefinition", "") user_variables.append({ "name": variable.get("qName", ""), "text_value": definition, "is_script_created": variable.get("qIsScriptCreated", False) }) return user_variables except Exception as e: return []