minitap-mcp 0.4.3__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,9 @@
1
- """Agent to extract Figma asset URLs from design context code."""
1
+ """Agent to extract Figma asset URLs from design context code using regex."""
2
2
 
3
3
  import re
4
- import uuid
5
- from pathlib import Path
6
4
 
7
- from jinja2 import Template
8
- from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage
9
5
  from pydantic import BaseModel, Field
10
6
 
11
- from minitap.mcp.core.llm import get_minitap_llm
12
-
13
7
 
14
8
  class FigmaAsset(BaseModel):
15
9
  """Represents a single Figma asset."""
@@ -27,70 +21,49 @@ class ExtractedAssets(BaseModel):
27
21
  description="List of all extracted assets from the Figma design context",
28
22
  )
29
23
  code_implementation: str = Field(
30
- description=(
31
- "The React/TypeScript code\n"
32
- "with the local url declarations turned into const declarations"
33
- )
24
+ description="The React/TypeScript code with imports instead of const declarations"
34
25
  )
35
26
 
36
27
 
37
- def sanitize_unicode_for_llm(text: str) -> str:
38
- """Remove or replace problematic Unicode characters that increase token consumption.
39
-
40
- Characters outside the Basic Multilingual Plane (BMP) like emoji and special symbols
41
- get escaped as \\U sequences when sent to LLMs, dramatically increasing token count
42
- and processing time.
28
+ def extract_figma_assets(design_context_code: str) -> ExtractedAssets:
29
+ """Extract asset URLs from Figma design context code using regex.
43
30
 
44
31
  Args:
45
- text: The text to sanitize
32
+ design_context_code: The React/TypeScript code from get_design_context
46
33
 
47
34
  Returns:
48
- Text with problematic Unicode characters replaced with placeholders
35
+ ExtractedAssets with list of assets and transformed code
49
36
  """
37
+ # Regex captures: (1) variable name, (2) full URL, (4) extension
38
+ # Supports http/https, any domain, query strings, optional semicolon
39
+ pattern = r'const\s+(\w+)\s*=\s*["\']((https?://[^"\']+?)\.(\w+)(?:\?[^"\']*)?)["\'];?'
40
+ matches = re.finditer(pattern, design_context_code)
41
+
42
+ assets = []
43
+ asset_lines = []
44
+
45
+ for match in matches:
46
+ var_name = match.group(1)
47
+ url = match.group(2)
48
+ extension = match.group(4)
49
+
50
+ assets.append(FigmaAsset(variable_name=var_name, url=url, extension=extension))
51
+ asset_lines.append(match.group(0))
52
+
53
+ import_statements = []
54
+ for asset in assets:
55
+ import_statements.append(
56
+ f"import {asset.variable_name} from './{asset.variable_name}.{asset.extension}';"
57
+ )
50
58
 
51
- # Replace characters outside BMP (U+10000 and above) with a placeholder
52
- # These are typically emoji, special symbols, or rare characters
53
- def replace_high_unicode(match):
54
- char = match.group(0)
55
- codepoint = ord(char)
56
- # Return a descriptive placeholder
57
- return f"[U+{codepoint:X}]"
58
-
59
- # Pattern matches characters with codepoints >= U+10000
60
- pattern = re.compile(r"[\U00010000-\U0010FFFF]")
61
- sanitized = pattern.sub(replace_high_unicode, text)
62
-
63
- return sanitized
64
-
59
+ transformed_code = design_context_code
60
+ for line in asset_lines:
61
+ transformed_code = transformed_code.replace(line, "")
65
62
 
66
- async def extract_figma_assets(design_context_code: str) -> ExtractedAssets:
67
- """Extract asset URLs from Figma design context code.
63
+ lines = transformed_code.split("\n")
64
+ while lines and not lines[0].strip():
65
+ lines.pop(0)
68
66
 
69
- Args:
70
- design_context_code: The React/TypeScript code from get_design_context
67
+ final_code = "\n".join(import_statements) + "\n\n" + "\n".join(lines)
71
68
 
72
- Returns:
73
- List of dictionaries containing variable_name, url, and extension
74
- """
75
- system_message = Template(
76
- Path(__file__).parent.joinpath("extract_figma_assets.md").read_text(encoding="utf-8")
77
- ).render()
78
-
79
- sanitized_code = sanitize_unicode_for_llm(design_context_code)
80
-
81
- messages: list[BaseMessage] = [
82
- SystemMessage(content=system_message),
83
- HumanMessage(
84
- content=f"Here is the code to analyze:\n\n```typescript\n{sanitized_code}\n```"
85
- ),
86
- ]
87
-
88
- llm = get_minitap_llm(
89
- model="openai/gpt-5",
90
- temperature=0,
91
- trace_id=str(uuid.uuid4()),
92
- remote_tracing=True,
93
- ).with_structured_output(ExtractedAssets)
94
- result: ExtractedAssets = await llm.ainvoke(messages) # type: ignore
95
-
96
- return result
69
+ return ExtractedAssets(assets=assets, code_implementation=final_code)
@@ -41,9 +41,9 @@ logger = get_logger(__name__)
41
41
 
42
42
  This tool:
43
43
  1. Calls get_design_context from Figma MCP to get the React/TypeScript code
44
- 2. Extracts all asset URLs and code implementation from the code
44
+ 2. Extracts asset URLs and transforms const declarations to import statements
45
45
  3. Downloads each asset to .mobile-use/figma_assets/<node-id>/ folder
46
- 4. Saves the code implementation to .mobile-use/figma_assets/<node-id>/code_implementation.ts
46
+ 4. Saves the transformed code to .mobile-use/figma_assets/<node-id>/code_implementation.ts
47
47
  5. Returns a list of downloaded files
48
48
  """,
49
49
  )
@@ -75,10 +75,8 @@ async def save_figma_assets(
75
75
  # Step 1: Get design context from Figma MCP
76
76
  design_context = await get_design_context(node_id, file_key)
77
77
 
78
- # Step 2: Extract asset URLs using LLM agent
79
- extracted_context: ExtractedAssets = await extract_figma_assets(
80
- design_context.code_implementation
81
- )
78
+ # Step 2: Extract asset URLs and transform code
79
+ extracted_context: ExtractedAssets = extract_figma_assets(design_context.code_implementation)
82
80
  if not extracted_context.assets:
83
81
  raise ToolError("No assets found in the Figma design context.")
84
82
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: minitap-mcp
3
- Version: 0.4.3
3
+ Version: 0.5.0
4
4
  Summary: Model Context Protocol server for controlling Android & iOS devices with natural language
5
5
  Author: Pierre-Louis Favreau, Jean-Pierre Lo, Clément Guiguet
6
6
  Requires-Dist: fastmcp>=2.12.4
@@ -1,8 +1,7 @@
1
1
  minitap/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  minitap/mcp/core/agents/compare_screenshots.md,sha256=Gt27HVzXzu71BxcanKPokz1dFPvq90vXbjE2HOn5X0I,3559
3
3
  minitap/mcp/core/agents/compare_screenshots.py,sha256=Yb7kR8Cv0gWzXyNf-6IS7_9l1npfqYmL-SONJJGgzM4,2060
4
- minitap/mcp/core/agents/extract_figma_assets.md,sha256=JrXuWF8-2PeQpVix-kf-p6zmu2gQVf9Z6ptTK1cedDk,2413
5
- minitap/mcp/core/agents/extract_figma_assets.py,sha256=4XwPi7JRGPPvW9P4igQFdKYG94cM5Y8qc3pWRkQ8BsU,3095
4
+ minitap/mcp/core/agents/extract_figma_assets.py,sha256=L5aAHm59mrRYaqrwMJSM24SSdZPu2yVg-wsHTF3L8vk,2310
6
5
  minitap/mcp/core/config.py,sha256=_rIH31treZlM2RVnTz5cPXhV9Bu4D-w4TmbPh5_mxxM,1026
7
6
  minitap/mcp/core/decorators.py,sha256=kMx_mlaa-2U1AgCoYkgPoLOa-iOoKUF1OjcNV7x59Ds,2940
8
7
  minitap/mcp/core/device.py,sha256=sEO3Z-8F325hDOObdH1YBhZE60f17FmIclt5UlhY_nU,7875
@@ -17,9 +16,9 @@ minitap/mcp/server/poller.py,sha256=Qakq4yO3EJ9dXmRqtE3sJjyk0ij7VBU-NuupHhTf37g,
17
16
  minitap/mcp/tools/analyze_screen.py,sha256=fjcjf3tTZDlxzmiQFHFNgw38bxPz4eisw57zuxshN2A,1984
18
17
  minitap/mcp/tools/compare_screenshot_with_figma.py,sha256=G69F6vRFI2tE2wW-oFYPjnY8oFMD9nRZH0H-yvtD4gE,4575
19
18
  minitap/mcp/tools/execute_mobile_command.py,sha256=qY3UfcDq1BtYcny1YlEF4WV9LwUJxLAmLJCm1VBzxS8,2442
20
- minitap/mcp/tools/save_figma_assets.py,sha256=T5a_7wi1aLoyCrn4FWwXEE_m8dXqUu2ZFGDKst_sKHI,9985
19
+ minitap/mcp/tools/save_figma_assets.py,sha256=6GRaaBQfU4h7H_q69Xoy8qdzkZXtBMlFUeV5kCAeBMc,9978
21
20
  minitap/mcp/tools/screen_analyzer.md,sha256=TTO80JQWusbA9cKAZn-9cqhgVHm6F_qJh5w152hG3YM,734
22
- minitap_mcp-0.4.3.dist-info/WHEEL,sha256=5w2T7AS2mz1-rW9CNagNYWRCaB0iQqBMYLwKdlgiR4Q,78
23
- minitap_mcp-0.4.3.dist-info/entry_points.txt,sha256=rYVoXm7tSQCqQTtHx4Lovgn1YsjwtEEHfddKrfEVHuY,55
24
- minitap_mcp-0.4.3.dist-info/METADATA,sha256=-3t9Ox1LrXQfWtYQRyar6Bneyp_T1FQkBV0djX1lJBY,8641
25
- minitap_mcp-0.4.3.dist-info/RECORD,,
21
+ minitap_mcp-0.5.0.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
22
+ minitap_mcp-0.5.0.dist-info/entry_points.txt,sha256=rYVoXm7tSQCqQTtHx4Lovgn1YsjwtEEHfddKrfEVHuY,55
23
+ minitap_mcp-0.5.0.dist-info/METADATA,sha256=j4TMgzWoC3WHoDBEavfB-SSzQVdpUV10E0HZW30njDg,8641
24
+ minitap_mcp-0.5.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.7
2
+ Generator: uv 0.9.8
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,64 +0,0 @@
1
- You are an expert at parsing React/TypeScript code to extract asset URLs and generate clean, documented code implementations.
2
-
3
- Your task is to:
4
-
5
- 1. Extract all asset URLs from the provided code snippet
6
- 2. Generate a clean `code_implementation` output that includes the React code with embedded comments referencing implementation and node guidelines
7
-
8
- **Instructions:**
9
-
10
- ## Part 1: Extract Asset URLs
11
-
12
- 1. Look for all constant declarations that contain URLs pointing to assets (images, SVGs, etc.)
13
- 2. These constants typically follow patterns like:
14
-
15
- - `const imgVariableName = "http://localhost:3845/assets/[hash].[extension]";`
16
- - The variable names usually start with `img` followed by a descriptive name in camelCase
17
-
18
- 3. For each asset URL found, extract:
19
- - The **variable name** (e.g., `imgSignal`, `imgBatteryThreeQuarters`)
20
- - The **full URL** (e.g., `http://localhost:3845/assets/685c5ac58caa29556e29737cf8f8c9605d9c8571.svg`)
21
- - The **file extension** from the URL (e.g., `svg`, `png`, `jpg`)
22
-
23
- ## Part 2: Generate Code Implementation
24
-
25
- The `code_implementation` field should contain:
26
-
27
- 1. The React/TypeScript code with **LOCAL asset imports** instead of HTTP URLs:
28
-
29
- - Convert `const imgSignal = "http://localhost:3845/assets/[hash].svg";`
30
- - To `import imgSignal from './assets/imgSignal.svg';` (or appropriate relative path)
31
- - Use the **exact same variable names** as in the original const declarations
32
- - **CRITICAL**: Preserve the variable naming convention
33
-
34
- 2. Preserve all `data-node-id` attributes and other metadata in the code
35
-
36
- ## Part 3: Return Format
37
-
38
- Return a JSON object with two fields:
39
-
40
- - `assets`: Array of extracted asset objects
41
- - `code_implementation`: String containing the React code with embedded guideline comments
42
-
43
- ```json
44
- {
45
- "assets": [
46
- {
47
- "variable_name": "imgSignal",
48
- "url": "http://localhost:3845/assets/685c5ac58caa29556e29737cf8f8c9605d9c8571.svg",
49
- "extension": "svg"
50
- },
51
- ...
52
- ],
53
- "code_implementation": "import ... function ..."
54
- }
55
- ```
56
-
57
- **Important:**
58
-
59
- - Only extract asset URLs
60
- - Preserve the exact variable names as they appear in the code
61
- - DO NOT MISS any assets
62
- - If no assets are found, return an empty array for `assets`
63
- - Return ONLY the JSON object with both `assets` and `code_implementation` fields
64
- - Do NOT include the const declarations of the assets in the code_implementation output - convert them to imports.