Copilot commented on code in PR #11621:
URL: https://github.com/apache/gravitino/pull/11621#discussion_r3401204010


##########
mcp-server/mcp_server/client/plain/plain_rest_client_topic_operation.py:
##########
@@ -46,3 +49,46 @@ async def load_topic(
             f"/topics/{encode_path_segment(topic_name)}"
         )
         return response.json().get("topic", {})
+

Review Comment:
   `load_topic` returns `response.json().get(...)` directly, which bypasses 
`_handle_gravitino_exception` (authorization/REST errors can be silently 
ignored) and also returns a dict while the method is declared `-> str`. Use 
`extract_content_from_response` to both surface Gravitino errors and return a 
JSON-formatted string consistently.



##########
mcp-server/mcp_server/client/plain/plain_rest_client_fileset_operation.py:
##########
@@ -62,3 +65,54 @@ async def list_files_in_fileset(
             params={"sub_path": sub_path, "location_name": location_name},
         )
         return response.json().get("files", [])

Review Comment:
   `list_files_in_fileset` returns `response.json().get(...)` directly, which 
bypasses `_handle_gravitino_exception` (errors/authz denials can be silently 
turned into an empty list) and returns a Python list while the method is 
declared `-> str`. Use `extract_content_from_response` for consistent 
JSON-string output and proper error handling.



##########
mcp-server/mcp_server/tools/fileset.py:
##########
@@ -143,3 +143,97 @@ async def list_files_in_fileset(
         return await client.as_fileset_operation().list_files_in_fileset(
             catalog_name, schema_name, fileset_name, location_name, sub_path
         )
+
+    # pylint:disable=too-many-positional-arguments

Review Comment:
   The pylint disable directive is malformed (`# pylint:disable=...`); pylint 
expects `# pylint: disable=...` with a space after the colon. As written, the 
rule suppression may not take effect and CI linting can fail.



##########
mcp-server/mcp_server/tools/model.py:
##########
@@ -230,3 +230,120 @@ async def load_model_version_by_alias(
         return await client.as_model_operation().load_model_version_by_alias(
             catalog_name, schema_name, model_name, alias
         )
+
+    @mcp.tool(tags={"model"})
+    async def register_model(
+        ctx: Context,
+        catalog_name: str,
+        schema_name: str,
+        name: str,
+        comment: str,
+        properties: dict,
+    ) -> str:
+        """
+        Register a new model within a schema.
+
+        Authorization is enforced by Gravitino: a principal without the
+        required grant receives an authorization denial.
+
+        Args:
+            ctx (Context): The request context object.
+            catalog_name (str): Name of the catalog.
+            schema_name (str): Name of the schema.
+            name (str): Name of the model to register.
+            comment (str): Human-readable description.
+            properties (dict): Model configuration properties.
+
+        Returns:
+            str: JSON-formatted string containing the registered model.
+        """
+        client = ctx.request_context.lifespan_context.rest_client()
+        return await client.as_model_operation().register_model(
+            catalog_name, schema_name, name, comment, properties
+        )
+
+    @mcp.tool(tags={"model"})
+    async def delete_model(
+        ctx: Context, catalog_name: str, schema_name: str, model_name: str
+    ) -> str:
+        """
+        Delete a model by its name.
+
+        Args:
+            ctx (Context): The request context object.
+            catalog_name (str): Name of the catalog.
+            schema_name (str): Name of the schema.
+            model_name (str): Name of the model to delete.
+
+        Returns:
+            str: JSON-formatted string indicating whether the model was 
deleted.
+        """
+        client = ctx.request_context.lifespan_context.rest_client()
+        return await client.as_model_operation().delete_model(
+            catalog_name, schema_name, model_name
+        )
+
+    # pylint:disable=too-many-positional-arguments

Review Comment:
   The pylint disable directive is malformed (`# pylint:disable=...`); pylint 
expects `# pylint: disable=...` with a space after the colon. As written, the 
suppression may not apply and linting can fail.



##########
mcp-server/mcp_server/client/plain/plain_rest_client_model_operation.py:
##########
@@ -81,3 +84,66 @@ async def load_model_version_by_alias(
             f"/aliases/{encode_path_segment(alias)}"
         )
         return response.json().get("modelVersion", {})

Review Comment:
   `load_model_version_by_alias` returns `response.json().get(...)` directly, 
bypassing `_handle_gravitino_exception` and returning a dict while the method 
is declared `-> str`. Use `extract_content_from_response` so Gravitino error 
payloads (including authz denials) are handled consistently and the return type 
matches the interface.



##########
mcp-server/mcp_server/client/plain/plain_rest_client_model_operation.py:
##########
@@ -16,7 +16,10 @@
 # under the License.
 
 from mcp_server.client import ModelOperation
-from mcp_server.client.plain.utils import encode_path_segment
+from mcp_server.client.plain.utils import (
+    encode_path_segment,
+    extract_content_from_response,
+)

Review Comment:
   `list_of_models` returns `response.json().get(...)` directly, which bypasses 
`_handle_gravitino_exception` and can silently convert authz/REST errors into 
an empty list. It also returns a Python list while the method is declared `-> 
str`. Use `extract_content_from_response` to keep error handling and output 
format consistent with the new write operations.



##########
mcp-server/mcp_server/tools/tag.py:
##########
@@ -364,8 +364,3 @@ async def list_metadata_by_tag(ctx: Context, tag_name: str) 
-> str:
         """
         client = ctx.request_context.lifespan_context.rest_client()
         return await client.as_tag_operation().list_metadata_by_tag(tag_name)

Review Comment:
   Since tag write tools are now enabled (the `mcp.disable(...)` block is 
removed), the earlier inline comments in this module that say alter/delete are 
"disabled by default" become inaccurate/misleading. Please update or remove 
those comments so the documentation matches the actual behavior (tools are 
exposed and authorization is enforced by Gravitino).



##########
mcp-server/mcp_server/client/plain/plain_rest_client_fileset_operation.py:
##########
@@ -16,7 +16,10 @@
 # under the License.
 
 from mcp_server.client.fileset_operation import FilesetOperation
-from mcp_server.client.plain.utils import encode_path_segment
+from mcp_server.client.plain.utils import (
+    encode_path_segment,
+    extract_content_from_response,
+)

Review Comment:
   `list_of_filesets` returns `response.json().get(...)` directly, which 
bypasses `_handle_gravitino_exception` and can silently turn authz/REST errors 
into an empty list. It also returns a Python list while the method is declared 
`-> str`. Use `extract_content_from_response` for consistent JSON-string output 
and proper error handling.



##########
mcp-server/mcp_server/client/model_operation.py:
##########
@@ -106,3 +106,39 @@ async def load_model_version_by_alias(
             str: JSON-formatted string containing full model version metadata
         """
         pass
+
+    @abstractmethod
+    async def register_model(
+        self,
+        catalog_name: str,
+        schema_name: str,
+        name: str,
+        comment: str,
+        properties: dict,
+    ) -> str:
+        pass
+
+    @abstractmethod
+    async def delete_model(
+        self, catalog_name: str, schema_name: str, model_name: str
+    ) -> str:
+        pass
+
+    @abstractmethod
+    async def link_model_version(
+        self,
+        catalog_name: str,
+        schema_name: str,
+        model_name: str,
+        uri: str,
+        aliases: list,
+        comment: str,
+        properties: dict,
+    ) -> str:
+        pass

Review Comment:
   The PR description/issue scope mentions a write operation to update model 
version aliases, but this interface (and corresponding tools/client 
implementation) only adds register/delete model and link/delete version. If 
alias updates are intended to be part of this PR, a dedicated operation/tool 
should be added (e.g., `update_model_version_aliases`) and wired through the 
REST client and mocks/tests.



##########
mcp-server/mcp_server/client/plain/plain_rest_client_topic_operation.py:
##########
@@ -15,7 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from mcp_server.client.plain.utils import encode_path_segment
+from mcp_server.client.plain.utils import (
+    encode_path_segment,
+    extract_content_from_response,
+)

Review Comment:
   `list_of_topics` currently returns `response.json().get(...)` directly, 
which bypasses `_handle_gravitino_exception` and can silently convert 
authz/REST errors into an empty list. It also returns a Python list while the 
method is declared `-> str`. Use `extract_content_from_response` for consistent 
JSON-string output and proper error handling (same pattern as the new write 
methods).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to