rhinomcp 0.1.2.2__py3-none-any.whl → 0.1.3.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.
rhinomcp/__init__.py CHANGED
@@ -3,7 +3,7 @@
3
3
  __version__ = "0.1.0"
4
4
 
5
5
  # Expose key classes and functions for easier imports
6
- from .server import RhinoConnection, get_rhino_connection, mcp, logger
6
+ from .server import RhinoConnection, get_rhino_connection, mcp, logger, rhinoscriptsyntax_json
7
7
 
8
8
  from .prompts.assert_general_strategy import asset_general_strategy
9
9
 
@@ -16,6 +16,9 @@ from .tools.get_selected_objects_info import get_selected_objects_info
16
16
  from .tools.modify_object import modify_object
17
17
  from .tools.modify_objects import modify_objects
18
18
  from .tools.execute_rhinoscript_python_code import execute_rhinoscript_python_code
19
+ from .tools.get_rhinoscript_python_function_names import get_rhinoscript_python_function_names
20
+ from .tools.get_rhinoscript_python_code_guide import get_rhinoscript_python_code_guide
19
21
  from .tools.select_objects import select_objects
20
-
21
- from .resources.rhinoscriptsyntax_resource import get_rhinoscriptsyntax_resource
22
+ from .tools.create_layer import create_layer
23
+ from .tools.get_or_set_current_layer import get_or_set_current_layer
24
+ from .tools.delete_layer import delete_layer
rhinomcp/server.py CHANGED
@@ -12,6 +12,15 @@ from pathlib import Path
12
12
  import base64
13
13
  from urllib.parse import urlparse
14
14
 
15
+ # load rhino_script_syntax.json
16
+ from pathlib import Path
17
+
18
+ # Define path to static folder
19
+ JSONFILE = Path("./static/rhinoscriptsyntax.json")
20
+
21
+ with open(JSONFILE, 'r') as f:
22
+ rhinoscriptsyntax_json = json.loads(f.read())
23
+
15
24
 
16
25
  # Configure logging
17
26
  logging.basicConfig(level=logging.INFO,
@@ -0,0 +1,47 @@
1
+ from mcp.server.fastmcp import Context
2
+ import json
3
+ from rhinomcp.server import get_rhino_connection, mcp, logger
4
+ from typing import Any, List, Dict
5
+
6
+ @mcp.tool()
7
+ def create_layer(
8
+ ctx: Context,
9
+ name: str = None,
10
+ color: List[int]= None,
11
+ parent: str = None,
12
+ ) -> str:
13
+ """
14
+ Create a new layer in the Rhino document.
15
+
16
+ Parameters:
17
+ - name: The name of the new layer. If omitted, Rhino automatically generates the layer name.
18
+ - color: Optional [r, g, b] color values (0-255) for the layer
19
+ - parent: Optional name of the new layer's parent layer. If omitted, the new layer will not have a parent layer.
20
+
21
+ Returns:
22
+ A message indicating the created layer name.
23
+
24
+ Examples of params:
25
+ - name: "Layer 1"
26
+ - color: [255, 0, 0]
27
+ - parent: "Default"
28
+ """
29
+ try:
30
+ # Get the global connection
31
+ rhino = get_rhino_connection()
32
+
33
+ command_params = {
34
+ "name": name
35
+ }
36
+
37
+ if color is not None: command_params["color"] = color
38
+ if parent is not None: command_params["parent"] = parent
39
+
40
+ # Create the layer
41
+ result = rhino.send_command("create_layer", command_params)
42
+
43
+ return f"Created layer: {result['name']}"
44
+ except Exception as e:
45
+ logger.error(f"Error creating layer: {str(e)}")
46
+ return f"Error creating layer: {str(e)}"
47
+
@@ -0,0 +1,47 @@
1
+ from mcp.server.fastmcp import Context
2
+ import json
3
+ from rhinomcp.server import get_rhino_connection, mcp, logger
4
+ from typing import Any, List, Dict
5
+
6
+ @mcp.tool()
7
+ def delete_layer(
8
+ ctx: Context,
9
+ guid: str = None,
10
+ name: str = None
11
+ ) -> str:
12
+ """
13
+ Delete a layer in the Rhino document.
14
+ If name is provided, it will try to delete the layer with the given name.
15
+ If guid is provided, it will try to delete the layer with the given guid.
16
+ If neither is provided, it will return an error.
17
+
18
+ Parameters:
19
+ - name: The name of the layer to delete.
20
+ - guid: The guid of the layer to delete.
21
+
22
+ Returns:
23
+ A message indicating the layer was deleted.
24
+
25
+ Examples of params:
26
+ - name: "Layer 1"
27
+ - guid: "00000000-0000-0000-0000-000000000000"
28
+ """
29
+ try:
30
+ # Get the global connection
31
+ rhino = get_rhino_connection()
32
+
33
+ command_params = {}
34
+
35
+ if name is not None:
36
+ command_params["name"] = name
37
+ if guid is not None:
38
+ command_params["guid"] = guid
39
+
40
+ # Create the layer
41
+ result = rhino.send_command("delete_layer", command_params)
42
+
43
+ return result["message"]
44
+ except Exception as e:
45
+ logger.error(f"Error deleting layer: {str(e)}")
46
+ return f"Error deleting layer: {str(e)}"
47
+
@@ -5,50 +5,37 @@ from typing import Any, List, Dict
5
5
 
6
6
 
7
7
  @mcp.tool()
8
- def execute_rhinoscript_python_code(ctx: Context, code: str) -> str:
8
+ def execute_rhinoscript_python_code(ctx: Context, code: str) -> Dict[str, Any]:
9
9
  """
10
10
  Execute arbitrary RhinoScript code in Rhino.
11
11
 
12
12
  Parameters:
13
13
  - code: The RhinoScript code to execute
14
14
 
15
- References:
15
+ GUIDE:
16
+
17
+ 1. To get any output from the script, you should use the python `print` function.
18
+ 2. You can get a list of all possible functions names that can be used by using the get_rhinoscript_python_function_names tool.
19
+ 3. You can get the details of a specific function by using the get_rhinoscript_python_code_guide tool.
16
20
 
17
- AddBox(corners)
18
- Adds a box shaped polysurface to the document
19
- Parameters:
20
- corners ([point, point, point ,point, point, point ,point,point]) 8 points that define the corners of the box. Points need to
21
- be in counter-clockwise order starting with the bottom rectangle of the box
22
- Returns:
23
- guid: identifier of the new object on success
24
21
  Example:
25
- import rhinoscriptsyntax as rs
26
- box = rs.GetBox()
27
- if box: rs.AddBox(box)
28
-
29
- AddSphere(center_or_plane, radius)
30
- Add a spherical surface to the document
31
- Parameters:
32
- center_or_plane (point|plane): center point of the sphere. If a plane is input,
33
- the origin of the plane will be the center of the sphere
34
- radius (number): radius of the sphere in the current model units
35
- Returns:
36
- guid: identifier of the new object on success
37
- None: on error
38
- Example:
39
- import rhinoscriptsyntax as rs
40
- radius = 2
41
- center = rs.GetPoint("Center of sphere")
42
- if center: rs.AddSphere(center, radius)
22
+ - Your task is: "Create a loft surface between two curves."
23
+ - get_rhinoscript_python_function_names(["surface", "curve"])
24
+ - This will return the function names that are necessary for creating the code.
25
+ - get_rhinoscript_python_code_guide("AddLoftSrf")
26
+ - This will return the syntax of the code that are necessary for creating the code.
43
27
 
28
+ Any changes made to the document will be undone if the script returns failure.
44
29
 
30
+ DO NOT HALLUCINATE, ONLY USE THE SYNTAX THAT IS SUPPORTED BY RHINO.GEOMETRY OR RHINOSCRIPT.
31
+
45
32
  """
46
33
  try:
47
34
  # Get the global connection
48
35
  rhino = get_rhino_connection()
49
36
 
50
- result = rhino.send_command("execute_rhinoscript_python_code", {"code": code})
51
- return f"Code executed successfully: {result.get('result', '')}"
37
+ return rhino.send_command("execute_rhinoscript_python_code", {"code": code})
38
+
52
39
  except Exception as e:
53
40
  logger.error(f"Error executing code: {str(e)}")
54
- return f"Error executing code: {str(e)}"
41
+ return {"success": False, "message": str(e)}
@@ -0,0 +1,47 @@
1
+ from mcp.server.fastmcp import Context
2
+ import json
3
+ from rhinomcp.server import get_rhino_connection, mcp, logger
4
+ from typing import Any, List, Dict
5
+
6
+ @mcp.tool()
7
+ def get_or_set_current_layer(
8
+ ctx: Context,
9
+ guid: str = None,
10
+ name: str = None
11
+ ) -> str:
12
+ """
13
+ Get or set the current layer in the Rhino document.
14
+ If name is provided, it will try to set the current layer to the layer with the given name.
15
+ If guid is provided, it will try to set the current layer to the layer with the given guid.
16
+ If neither is provided, it will return the current layer.
17
+
18
+ Parameters:
19
+ - name: The name of the layer to set the current layer to.
20
+ - guid: The guid of the layer to set the current layer to.
21
+
22
+ Returns:
23
+ A message indicating the current layer.
24
+
25
+ Examples of params:
26
+ - name: "Layer 1"
27
+ - guid: "00000000-0000-0000-0000-000000000000"
28
+ """
29
+ try:
30
+ # Get the global connection
31
+ rhino = get_rhino_connection()
32
+
33
+ command_params = {}
34
+
35
+ if name is not None:
36
+ command_params["name"] = name
37
+ if guid is not None:
38
+ command_params["guid"] = guid
39
+
40
+ # Create the layer
41
+ result = rhino.send_command("get_or_set_current_layer", command_params)
42
+
43
+ return f"Current layer: {result['name']}"
44
+ except Exception as e:
45
+ logger.error(f"Error getting or setting current layer: {str(e)}")
46
+ return f"Error getting or setting current layer: {str(e)}"
47
+
@@ -0,0 +1,27 @@
1
+ from mcp.server.fastmcp import Context
2
+ from rhinomcp.server import get_rhino_connection, mcp, logger, rhinoscriptsyntax_json
3
+ from typing import Any, List, Dict
4
+
5
+
6
+
7
+ @mcp.tool()
8
+ def get_rhinoscript_python_code_guide(ctx: Context, function_name: str) -> Dict[str, Any]:
9
+ """
10
+ Return the RhinoScriptsyntax Details for a specific function.
11
+
12
+ Parameters:
13
+ - function_name: The name of the function to get the details for.
14
+
15
+ You should get the function names first by using the get_rhinoscript_python_function_names tool.
16
+ """
17
+ try:
18
+ for module in rhinoscriptsyntax_json:
19
+ for function in module["functions"]:
20
+ if function["Name"] == function_name:
21
+ return function
22
+
23
+ return {"success": False, "message": "Function not found"}
24
+
25
+ except Exception as e:
26
+ logger.error(f"Error executing code: {str(e)}")
27
+ return {"success": False, "message": str(e)}
@@ -0,0 +1,56 @@
1
+ from mcp.server.fastmcp import Context
2
+ from rhinomcp.server import get_rhino_connection, mcp, logger, rhinoscriptsyntax_json
3
+ from typing import Any, List, Dict
4
+
5
+
6
+ @mcp.tool()
7
+ def get_rhinoscript_python_function_names(ctx: Context, categories: List[str]) -> List[str]:
8
+ """
9
+ Return the RhinoScriptsyntax Function Names for specified categories.
10
+
11
+ Parameters:
12
+ - categories: A list of categories of the RhinoScriptsyntax to get.
13
+
14
+ Returns:
15
+ - A list of function names that are available in the specified categories.
16
+
17
+ The following categories are available:
18
+ - application
19
+ - block
20
+ - compat
21
+ - curve
22
+ - dimension
23
+ - document
24
+ - geometry
25
+ - grips
26
+ - group
27
+ - hatch
28
+ - layer
29
+ - light
30
+ - line
31
+ - linetype
32
+ - material
33
+ - mesh
34
+ - object
35
+ - plane
36
+ - pointvector
37
+ - selection
38
+ - surface
39
+ - toolbar
40
+ - transformation
41
+ - userdata
42
+ - userinterface
43
+ - utility
44
+ - view
45
+ """
46
+ try:
47
+ function_names: List[str] = []
48
+ for i in rhinoscriptsyntax_json:
49
+ if i["ModuleName"] in categories:
50
+ function_names.extend([func["Name"] for func in i["functions"]])
51
+
52
+ # return the related functions
53
+ return function_names
54
+ except Exception as e:
55
+ logger.error(f"Error executing code: {str(e)}")
56
+ return []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rhinomcp
3
- Version: 0.1.2.2
3
+ Version: 0.1.3.0
4
4
  Summary: Rhino integration through the Model Context Protocol
5
5
  Author-email: Jingcheng Chen <mail@jchen.ch>
6
6
  License: MIT
@@ -0,0 +1,23 @@
1
+ rhinomcp/__init__.py,sha256=_Fm4lCkvO4cPfOvUXDSvTv8bUEK3yU9S5iam-fKnEmA,1191
2
+ rhinomcp/server.py,sha256=fxCpHXYvAQJ3uKVXWHne2vx7VlEebCnx1zeIkTkm5lo,9722
3
+ rhinomcp/prompts/assert_general_strategy.py,sha256=Aovach0WYClUw191iX_Mwyh2KlxdVp0gB2Wt4eiQDvM,1250
4
+ rhinomcp/tools/create_layer.py,sha256=Pz6xgKsiNZGRcUwc4nQrvSWwRNc9Uv5Vs4g-lKQz82c,1377
5
+ rhinomcp/tools/create_object.py,sha256=uO5EhuM7SO9eq9senvskdiblZsWmveHHQxce9pMW7-g,3333
6
+ rhinomcp/tools/create_objects.py,sha256=974VI3C_iLjz9nJ6ya0fwxbsI0u0rlyb_cM98W6T86U,2616
7
+ rhinomcp/tools/delete_layer.py,sha256=MjvN2-AKHD1dbMIMqfrb3Bevjj63ooWGzqlFpOopju8,1315
8
+ rhinomcp/tools/delete_object.py,sha256=-Vz1AZlw0-hPQZ9wNVTpa5sRDJ2qLiDnfjSYKp2wafc,987
9
+ rhinomcp/tools/execute_rhinoscript_python_code.py,sha256=iHaXptYxGc0YY_oxBn_qwYr3l14ycjirRW96Q78eEPY,1585
10
+ rhinomcp/tools/get_document_info.py,sha256=poPyqfO0KeV5Au3jks9Q3o6tTZVDfEuCm9BZWCLfpqY,613
11
+ rhinomcp/tools/get_object_info.py,sha256=mqsnkVzYHMnv9CPA7DX1dyj5z538WEsIVWu9yI6DChM,967
12
+ rhinomcp/tools/get_or_set_current_layer.py,sha256=xIvwvrmWXjnxC0WDLEMFxLAUOUjL8LD-8sQ2OYPO-nw,1493
13
+ rhinomcp/tools/get_rhinoscript_python_code_guide.py,sha256=yJ80t-Ub78xPHCpKf8QgUwVILDr4k0OGnrtD3810YcA,935
14
+ rhinomcp/tools/get_rhinoscript_python_function_names.py,sha256=CBUEaRotw5lIeloDk6jbNLN1hmuD6FvGlBR8Vc9OoYA,1367
15
+ rhinomcp/tools/get_selected_objects_info.py,sha256=73u2Y9l9O8rwboFwBcfGQFYuFBZBp1UkChNJkK2Rbjo,573
16
+ rhinomcp/tools/modify_object.py,sha256=OVQa75PAmuVx-YslxSC2ITdFbp6cCELVaacI77sJ7Zg,1912
17
+ rhinomcp/tools/modify_objects.py,sha256=52okeGwV5IQiuBSBH9HcyDCxWbCNF4eA7LoLuhLlgp4,1498
18
+ rhinomcp/tools/select_objects.py,sha256=J9QjfnD9gdepTCqalBDqOi9nJEX9D3sLPJKImTcJciI,1935
19
+ rhinomcp-0.1.3.0.dist-info/METADATA,sha256=NaTycnEYEDEUc8tT4755q71SVjG1fJmoaPxvAftoFCs,920
20
+ rhinomcp-0.1.3.0.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
21
+ rhinomcp-0.1.3.0.dist-info/entry_points.txt,sha256=OserOidtKWCl-_h3O1c2e9La6wYmJ9rE5F_T5wRLX9w,50
22
+ rhinomcp-0.1.3.0.dist-info/top_level.txt,sha256=sw73qoWC7GQp5upujkME6pRWc8OxBydEeDwQqu-qv4U,9
23
+ rhinomcp-0.1.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,59 +0,0 @@
1
- import mcp.types as types
2
- from rhinomcp.server import mcp
3
- from pydantic import FileUrl
4
-
5
-
6
- import os
7
- from pathlib import Path
8
-
9
- # Define path to static folder
10
- STATIC_FOLDER = Path("./static")
11
-
12
-
13
- @mcp.tool()
14
- def get_rhinoscriptsyntax_resource(category: str) -> str:
15
- """
16
- Return the RhinoScriptsyntax for a specific category.
17
-
18
- Parameters:
19
- - category: The category of the RhinoScriptsyntax to get.
20
-
21
- The following categories are available:
22
- - application
23
- - block
24
- - compat
25
- - curve
26
- - dimension
27
- - document
28
- - geometry
29
- - grips
30
- - group
31
- - hatch
32
- - layer
33
- - light
34
- - line
35
- - linetype
36
- - material
37
- - mesh
38
- - object
39
- - plane
40
- - pointvector
41
- - selection
42
- - surface
43
- - toolbar
44
- - transformation
45
- - userdata
46
- - userinterface
47
- - utility
48
- - view
49
- """
50
-
51
- for file_path in STATIC_FOLDER.glob("*.py"):
52
- if file_path.name == f"{category}.py":
53
- try:
54
- with open(file_path, "r", encoding="utf-8") as f:
55
- return f.read()
56
- except Exception as e:
57
- print(f"Error reading {file_path}: {e}")
58
-
59
-
@@ -1,19 +0,0 @@
1
- rhinomcp/__init__.py,sha256=FiyVi0Ee7Vc0HVEfcUyEwHeHfBVP8siY-eCC5e7xLE0,909
2
- rhinomcp/server.py,sha256=G4ESexAfPZOCzIVYCbg51aMnJa-Zw6aOtZm1w2_6Ogc,9499
3
- rhinomcp/prompts/assert_general_strategy.py,sha256=Aovach0WYClUw191iX_Mwyh2KlxdVp0gB2Wt4eiQDvM,1250
4
- rhinomcp/resources/rhinoscriptsyntax_resource.py,sha256=3XtpQVlKd5jJL_YrX0tw4ZT3qUR6bO1rLdsoVZ1BXv8,1166
5
- rhinomcp/tools/create_object.py,sha256=uO5EhuM7SO9eq9senvskdiblZsWmveHHQxce9pMW7-g,3333
6
- rhinomcp/tools/create_objects.py,sha256=974VI3C_iLjz9nJ6ya0fwxbsI0u0rlyb_cM98W6T86U,2616
7
- rhinomcp/tools/delete_object.py,sha256=-Vz1AZlw0-hPQZ9wNVTpa5sRDJ2qLiDnfjSYKp2wafc,987
8
- rhinomcp/tools/execute_rhinoscript_python_code.py,sha256=7bveKWTxTJ8_9Gcelied4dEQjyd2WeNV-4iTL1i-prs,1837
9
- rhinomcp/tools/get_document_info.py,sha256=poPyqfO0KeV5Au3jks9Q3o6tTZVDfEuCm9BZWCLfpqY,613
10
- rhinomcp/tools/get_object_info.py,sha256=mqsnkVzYHMnv9CPA7DX1dyj5z538WEsIVWu9yI6DChM,967
11
- rhinomcp/tools/get_selected_objects_info.py,sha256=73u2Y9l9O8rwboFwBcfGQFYuFBZBp1UkChNJkK2Rbjo,573
12
- rhinomcp/tools/modify_object.py,sha256=OVQa75PAmuVx-YslxSC2ITdFbp6cCELVaacI77sJ7Zg,1912
13
- rhinomcp/tools/modify_objects.py,sha256=52okeGwV5IQiuBSBH9HcyDCxWbCNF4eA7LoLuhLlgp4,1498
14
- rhinomcp/tools/select_objects.py,sha256=J9QjfnD9gdepTCqalBDqOi9nJEX9D3sLPJKImTcJciI,1935
15
- rhinomcp-0.1.2.2.dist-info/METADATA,sha256=CX4Bjmt-IuwR8ZH9WMJeVfgmbFNMR6UAsLA8KiYrrAA,920
16
- rhinomcp-0.1.2.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
17
- rhinomcp-0.1.2.2.dist-info/entry_points.txt,sha256=OserOidtKWCl-_h3O1c2e9La6wYmJ9rE5F_T5wRLX9w,50
18
- rhinomcp-0.1.2.2.dist-info/top_level.txt,sha256=sw73qoWC7GQp5upujkME6pRWc8OxBydEeDwQqu-qv4U,9
19
- rhinomcp-0.1.2.2.dist-info/RECORD,,