This is an automated email from the ASF dual-hosted git repository.

yzheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new c2cd15f  [MCP] (feat): Standardized mcp tools (#89)
c2cd15f is described below

commit c2cd15f554a772ab2df294e0699f858c38d042ef
Author: Yong Zheng <[email protected]>
AuthorDate: Sun Dec 14 09:38:44 2025 -0600

    [MCP] (feat): Standardized mcp tools (#89)
    
    * Standardized mcp tools
---
 mcp-server/README.md                           |  14 +--
 mcp-server/polaris_mcp/tools/catalog.py        |  73 +++++++++------
 mcp-server/polaris_mcp/tools/catalog_role.py   | 125 +++++++++++++++++--------
 mcp-server/polaris_mcp/tools/namespace.py      |   8 +-
 mcp-server/polaris_mcp/tools/policy.py         |   6 +-
 mcp-server/polaris_mcp/tools/principal.py      |  11 +--
 mcp-server/polaris_mcp/tools/principal_role.py | 101 +++++++++++++-------
 mcp-server/polaris_mcp/tools/table.py          |   7 +-
 8 files changed, 216 insertions(+), 129 deletions(-)

diff --git a/mcp-server/README.md b/mcp-server/README.md
index 1382f0c..9b90ccf 100644
--- a/mcp-server/README.md
+++ b/mcp-server/README.md
@@ -179,12 +179,12 @@ Realm-specific variables (e.g., 
`POLARIS_REALM_${realm}_CLIENT_ID`) override the
 
 The server exposes the following MCP tools:
 
-* `polaris-iceberg-table` — Table operations (`list`, `get`, `create`, 
`update`, `delete`).
-* `polaris-namespace-request` — Namespace lifecycle management.
-* `polaris-policy` — Policy lifecycle management and mappings.
-* `polaris-catalog-request` — Catalog lifecycle management.
-* `polaris-principal-request` — Principal lifecycle helpers.
-* `polaris-principal-role-request` — Principal role lifecycle and catalog-role 
assignments.
-* `polaris-catalog-role-request` — Catalog role and grant management.
+* `polaris-iceberg-table-request` — Perform table operations (`list`, `get`, 
`create`, `update`, `delete`).
+* `polaris-namespace-request` — Perform namespace operations (`list`, `get`, 
`create`, `exists`, `get-properties`, `delete`).
+* `polaris-policy-request` — Perform policy operations (`list`, `get`, 
`create`, `update`, `delete`, `attach`, `detach`, `applicable`).
+* `polaris-catalog-request` — Perform catalog operations (`list`, `get`, 
`create`, `update`, `delete`).
+* `polaris-principal-request` — Perform principal operations (`list`, `get`, 
`create`, `update`, `delete`, `rotate`, `reset`, `list-roles`, `assign-role`, 
`revoke-role`).
+* `polaris-principal-role-request` — Perform principal role operations 
(`list`, `get`, `create`, `update`, `delete`, `list-assignees`, 
`list-catalog-roles`, `assign-catalog-role`, `revoke-catalog-role`).
+* `polaris-catalog-role-request` — Perform catalog role operations (`list`, 
`get`, `create`, `update`, `delete`, `list-principal-roles`, `list-grants`, 
`add-grant`, `revoke-grant`).
 
 Each tool returns both a human-readable transcript of the HTTP exchange and 
structured metadata under `result.meta`.
diff --git a/mcp-server/polaris_mcp/tools/catalog.py 
b/mcp-server/polaris_mcp/tools/catalog.py
index 5c0dc8f..b8825a9 100644
--- a/mcp-server/polaris_mcp/tools/catalog.py
+++ b/mcp-server/polaris_mcp/tools/catalog.py
@@ -37,12 +37,10 @@ class PolarisCatalogTool(McpTool):
     """Interact with the Polaris management API for catalog lifecycle 
operations."""
 
     TOOL_NAME = "polaris-catalog-request"
-    TOOL_DESCRIPTION = (
-        "Interact with the Polaris management API for catalog lifecycle 
operations."
-    )
+    TOOL_DESCRIPTION = "Perform catalog operations (list, get, create, update, 
delete)."
 
-    LIST_ALIASES: Set[str] = {"list"}
-    GET_ALIASES: Set[str] = {"get"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
+    GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
     UPDATE_ALIASES: Set[str] = {"update"}
     DELETE_ALIASES: Set[str] = {"delete", "drop", "remove"}
@@ -111,41 +109,56 @@ class PolarisCatalogTool(McpTool):
             delegate_args["realm"] = realm
 
         if normalized == "list":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = "catalogs"
+            self._handle_list(delegate_args)
         elif normalized == "get":
-            catalog_name = encode_path_segment(require_text(arguments, 
"catalog"))
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = f"catalogs/{catalog_name}"
+            self._handle_get(arguments, delegate_args)
         elif normalized == "create":
-            body = arguments.get("body")
-            if not isinstance(body, dict):
-                raise ValueError(
-                    "Create operations require a body matching 
CreateCatalogRequest."
-                )
-            delegate_args["method"] = "POST"
-            delegate_args["path"] = "catalogs"
-            delegate_args["body"] = copy.deepcopy(body)
+            self._handle_create(arguments, delegate_args)
         elif normalized == "update":
-            catalog_name = encode_path_segment(require_text(arguments, 
"catalog"))
-            body = arguments.get("body")
-            if not isinstance(body, dict):
-                raise ValueError(
-                    "Update operations require a body matching 
UpdateCatalogRequest."
-                )
-            delegate_args["method"] = "PUT"
-            delegate_args["path"] = f"catalogs/{catalog_name}"
-            delegate_args["body"] = copy.deepcopy(body)
+            self._handle_update(arguments, delegate_args)
         elif normalized == "delete":
-            catalog_name = encode_path_segment(require_text(arguments, 
"catalog"))
-            delegate_args["method"] = "DELETE"
-            delegate_args["path"] = f"catalogs/{catalog_name}"
+            self._handle_delete(arguments, delegate_args)
         else:  # pragma: no cover
             raise ValueError(f"Unsupported operation: {operation}")
 
         raw = self._rest_client.call(delegate_args)
         return self._maybe_augment_error(raw, normalized)
 
+    def _handle_list(self, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = "catalogs"
+
+    def _handle_get(self, arguments: dict, delegate_args: JSONDict) -> None:
+        catalog_name = encode_path_segment(require_text(arguments, "catalog"))
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = f"catalogs/{catalog_name}"
+
+    def _handle_create(self, arguments: dict, delegate_args: JSONDict) -> None:
+        body = arguments.get("body")
+        if not isinstance(body, dict):
+            raise ValueError(
+                "Create operations require a body matching 
CreateCatalogRequest."
+            )
+        delegate_args["method"] = "POST"
+        delegate_args["path"] = "catalogs"
+        delegate_args["body"] = copy.deepcopy(body)
+
+    def _handle_update(self, arguments: dict, delegate_args: JSONDict) -> None:
+        catalog_name = encode_path_segment(require_text(arguments, "catalog"))
+        body = arguments.get("body")
+        if not isinstance(body, dict):
+            raise ValueError(
+                "Update operations require a body matching 
UpdateCatalogRequest."
+            )
+        delegate_args["method"] = "PUT"
+        delegate_args["path"] = f"catalogs/{catalog_name}"
+        delegate_args["body"] = copy.deepcopy(body)
+
+    def _handle_delete(self, arguments: dict, delegate_args: JSONDict) -> None:
+        catalog_name = encode_path_segment(require_text(arguments, "catalog"))
+        delegate_args["method"] = "DELETE"
+        delegate_args["path"] = f"catalogs/{catalog_name}"
+
     def _maybe_augment_error(
         self, result: ToolExecutionResult, operation: str
     ) -> ToolExecutionResult:
diff --git a/mcp-server/polaris_mcp/tools/catalog_role.py 
b/mcp-server/polaris_mcp/tools/catalog_role.py
index 8d13ec2..323535b 100644
--- a/mcp-server/polaris_mcp/tools/catalog_role.py
+++ b/mcp-server/polaris_mcp/tools/catalog_role.py
@@ -38,13 +38,13 @@ class PolarisCatalogRoleTool(McpTool):
     """Manage catalog roles and grants via the Polaris management API."""
 
     TOOL_NAME = "polaris-catalog-role-request"
-    TOOL_DESCRIPTION = "Manage catalog roles and grants via the Polaris 
management API."
+    TOOL_DESCRIPTION = "Perform catalog role operations (list, get, create, 
update, delete, list-principal-roles, list-grants, add-grant, revoke-grant)."
 
-    LIST_ALIASES: Set[str] = {"list"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
+    GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
-    GET_ALIASES: Set[str] = {"get"}
     UPDATE_ALIASES: Set[str] = {"update"}
-    DELETE_ALIASES: Set[str] = {"delete", "remove"}
+    DELETE_ALIASES: Set[str] = {"delete", "drop", "remove"}
     LIST_PRINCIPAL_ROLES_ALIASES: Set[str] = {
         "list-principal-roles",
         "list-assigned-principal-roles",
@@ -134,57 +134,100 @@ class PolarisCatalogRoleTool(McpTool):
         base_path = f"catalogs/{catalog}/catalog-roles"
 
         if normalized == "list":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = base_path
+            self._handle_list(delegate_args, base_path)
         elif normalized == "create":
-            delegate_args["method"] = "POST"
-            delegate_args["path"] = base_path
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "CreateCatalogRoleRequest"
-            )
+            self._handle_create(arguments, delegate_args, base_path)
         elif normalized == "get":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = self._catalog_role_path(base_path, 
arguments)
+            self._handle_get(arguments, delegate_args, base_path)
         elif normalized == "update":
-            delegate_args["method"] = "PUT"
-            delegate_args["path"] = self._catalog_role_path(base_path, 
arguments)
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "UpdateCatalogRoleRequest"
-            )
+            self._handle_update(arguments, delegate_args, base_path)
         elif normalized == "delete":
-            delegate_args["method"] = "DELETE"
-            delegate_args["path"] = self._catalog_role_path(base_path, 
arguments)
+            self._handle_delete(arguments, delegate_args, base_path)
         elif normalized == "list-principal-roles":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = (
-                f"{self._catalog_role_path(base_path, 
arguments)}/principal-roles"
-            )
+            self._handle_list_principal_roles(arguments, delegate_args, 
base_path)
         elif normalized == "list-grants":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = (
-                f"{self._catalog_role_path(base_path, arguments)}/grants"
-            )
+            self._handle_list_grants(arguments, delegate_args, base_path)
         elif normalized == "add-grant":
-            delegate_args["method"] = "PUT"
-            delegate_args["path"] = (
-                f"{self._catalog_role_path(base_path, arguments)}/grants"
-            )
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "AddGrantRequest"
-            )
+            self._handle_add_grant(arguments, delegate_args, base_path)
         elif normalized == "revoke-grant":
-            delegate_args["method"] = "POST"
-            delegate_args["path"] = (
-                f"{self._catalog_role_path(base_path, arguments)}/grants"
-            )
-            if isinstance(arguments.get("body"), dict):
-                delegate_args["body"] = copy.deepcopy(arguments["body"])
+            self._handle_revoke_grant(arguments, delegate_args, base_path)
         else:  # pragma: no cover
             raise ValueError(f"Unsupported operation: {operation}")
 
         raw = self._rest_client.call(delegate_args)
         return self._maybe_augment_error(raw, normalized)
 
+    def _handle_list(self, delegate_args: JSONDict, base_path: str) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = base_path
+
+    def _handle_create(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "POST"
+        delegate_args["path"] = base_path
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "CreateCatalogRoleRequest"
+        )
+
+    def _handle_get(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = self._catalog_role_path(base_path, arguments)
+
+    def _handle_update(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "PUT"
+        delegate_args["path"] = self._catalog_role_path(base_path, arguments)
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "UpdateCatalogRoleRequest"
+        )
+
+    def _handle_delete(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "DELETE"
+        delegate_args["path"] = self._catalog_role_path(base_path, arguments)
+
+    def _handle_list_principal_roles(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = (
+            f"{self._catalog_role_path(base_path, arguments)}/principal-roles"
+        )
+
+    def _handle_list_grants(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = (
+            f"{self._catalog_role_path(base_path, arguments)}/grants"
+        )
+
+    def _handle_add_grant(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "PUT"
+        delegate_args["path"] = (
+            f"{self._catalog_role_path(base_path, arguments)}/grants"
+        )
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "AddGrantRequest"
+        )
+
+    def _handle_revoke_grant(
+        self, arguments: dict, delegate_args: JSONDict, base_path: str
+    ) -> None:
+        delegate_args["method"] = "POST"
+        delegate_args["path"] = (
+            f"{self._catalog_role_path(base_path, arguments)}/grants"
+        )
+        if isinstance(arguments.get("body"), dict):
+            delegate_args["body"] = copy.deepcopy(arguments["body"])
+
     def _catalog_role_path(self, base_path: str, arguments: Dict[str, Any]) -> 
str:
         role = encode_path_segment(require_text(arguments, "catalogRole"))
         return f"{base_path}/{role}"
diff --git a/mcp-server/polaris_mcp/tools/namespace.py 
b/mcp-server/polaris_mcp/tools/namespace.py
index 7d34070..b3adaf1 100644
--- a/mcp-server/polaris_mcp/tools/namespace.py
+++ b/mcp-server/polaris_mcp/tools/namespace.py
@@ -40,12 +40,12 @@ class PolarisNamespaceTool(McpTool):
     """Manage namespaces through the Polaris REST API."""
 
     TOOL_NAME = "polaris-namespace-request"
-    TOOL_DESCRIPTION = "Manage namespaces in an Iceberg catalog (list, get, 
create, update properties, delete)."
+    TOOL_DESCRIPTION = "Perform namespace operations (list, get, create, 
exists, get-properties, delete)."
 
-    LIST_ALIASES: Set[str] = {"list"}
-    GET_ALIASES: Set[str] = {"get", "load"}
-    EXISTS_ALIASES: Set[str] = {"exists", "head"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
+    GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
+    EXISTS_ALIASES: Set[str] = {"exists", "head"}
     UPDATE_PROPS_ALIASES: Set[str] = {
         "update-properties",
         "set-properties",
diff --git a/mcp-server/polaris_mcp/tools/policy.py 
b/mcp-server/polaris_mcp/tools/policy.py
index f8eee13..1961044 100644
--- a/mcp-server/polaris_mcp/tools/policy.py
+++ b/mcp-server/polaris_mcp/tools/policy.py
@@ -37,10 +37,10 @@ from polaris_mcp.rest import PolarisRestTool, 
encode_path_segment
 class PolarisPolicyTool(McpTool):
     """Expose Polaris policy endpoints via MCP."""
 
-    TOOL_NAME = "polaris-policy"
-    TOOL_DESCRIPTION = "Manage Polaris policies (list, create, update, delete, 
attach, detach, applicable)."
+    TOOL_NAME = "polaris-policy-request"
+    TOOL_DESCRIPTION = "Perform policy operations (list, get, create, update, 
delete, attach, detach, applicable)."
 
-    LIST_ALIASES: Set[str] = {"list"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
     GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
     UPDATE_ALIASES: Set[str] = {"update"}
diff --git a/mcp-server/polaris_mcp/tools/principal.py 
b/mcp-server/polaris_mcp/tools/principal.py
index 9bea911..cc396bc 100644
--- a/mcp-server/polaris_mcp/tools/principal.py
+++ b/mcp-server/polaris_mcp/tools/principal.py
@@ -38,16 +38,13 @@ class PolarisPrincipalTool(McpTool):
     """Manage principals via the Polaris management API."""
 
     TOOL_NAME = "polaris-principal-request"
-    TOOL_DESCRIPTION = (
-        "Manage principals via the Polaris management API (list, get, create, 
update, delete, "
-        "rotate/reset credentials, role assignment)."
-    )
+    TOOL_DESCRIPTION = "Perform principal operations (list, get, create, 
update, delete, rotate, reset, list-roles, assign-role, revoke-role)."
 
-    LIST_ALIASES: Set[str] = {"list"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
+    GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
-    GET_ALIASES: Set[str] = {"get"}
     UPDATE_ALIASES: Set[str] = {"update"}
-    DELETE_ALIASES: Set[str] = {"delete", "remove"}
+    DELETE_ALIASES: Set[str] = {"delete", "drop", "remove"}
     ROTATE_ALIASES: Set[str] = {"rotate-credentials", "rotate"}
     RESET_ALIASES: Set[str] = {"reset-credentials", "reset"}
     LIST_ROLES_ALIASES: Set[str] = {"list-principal-roles", "list-roles"}
diff --git a/mcp-server/polaris_mcp/tools/principal_role.py 
b/mcp-server/polaris_mcp/tools/principal_role.py
index b23cce8..ec0a15b 100644
--- a/mcp-server/polaris_mcp/tools/principal_role.py
+++ b/mcp-server/polaris_mcp/tools/principal_role.py
@@ -37,13 +37,13 @@ class PolarisPrincipalRoleTool(McpTool):
     """Manage principal roles through the Polaris management API."""
 
     TOOL_NAME = "polaris-principal-role-request"
-    TOOL_DESCRIPTION = "Manage principal roles (list, get, create, update, 
delete) and their catalog-role assignments via the Polaris management API."
+    TOOL_DESCRIPTION = "Perform principal role operations (list, get, create, 
update, delete, list-assignees, list-catalog-roles, assign-catalog-role, 
revoke-catalog-role)."
 
-    LIST_ALIASES: Set[str] = {"list"}
+    LIST_ALIASES: Set[str] = {"list", "ls"}
+    GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
-    GET_ALIASES: Set[str] = {"get"}
     UPDATE_ALIASES: Set[str] = {"update"}
-    DELETE_ALIASES: Set[str] = {"delete", "remove"}
+    DELETE_ALIASES: Set[str] = {"delete", "drop", "remove"}
     LIST_PRINCIPALS_ALIASES: Set[str] = {"list-principals", "list-assignees"}
     LIST_CATALOG_ROLES_ALIASES: Set[str] = {
         "list-catalog-roles",
@@ -140,50 +140,83 @@ class PolarisPrincipalRoleTool(McpTool):
             delegate_args["realm"] = realm
 
         if normalized == "list":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = "principal-roles"
+            self._handle_list(delegate_args)
         elif normalized == "create":
-            delegate_args["method"] = "POST"
-            delegate_args["path"] = "principal-roles"
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "CreatePrincipalRoleRequest"
-            )
+            self._handle_create(arguments, delegate_args)
         elif normalized == "get":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = self._principal_role_path(arguments)
+            self._handle_get(arguments, delegate_args)
         elif normalized == "update":
-            delegate_args["method"] = "PUT"
-            delegate_args["path"] = self._principal_role_path(arguments)
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "UpdatePrincipalRoleRequest"
-            )
+            self._handle_update(arguments, delegate_args)
         elif normalized == "delete":
-            delegate_args["method"] = "DELETE"
-            delegate_args["path"] = self._principal_role_path(arguments)
+            self._handle_delete(arguments, delegate_args)
         elif normalized == "list-principals":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = 
f"{self._principal_role_path(arguments)}/principals"
+            self._handle_list_principals(arguments, delegate_args)
         elif normalized == "list-catalog-roles":
-            delegate_args["method"] = "GET"
-            delegate_args["path"] = 
self._principal_role_catalog_path(arguments)
+            self._handle_list_catalog_roles(arguments, delegate_args)
         elif normalized == "assign-catalog-role":
-            delegate_args["method"] = "PUT"
-            delegate_args["path"] = 
self._principal_role_catalog_path(arguments)
-            delegate_args["body"] = self._require_object(
-                arguments, "body", "GrantCatalogRoleRequest"
-            )
+            self._handle_assign_catalog_role(arguments, delegate_args)
         elif normalized == "revoke-catalog-role":
-            delegate_args["method"] = "DELETE"
-            catalog_role = encode_path_segment(require_text(arguments, 
"catalogRole"))
-            delegate_args["path"] = (
-                
f"{self._principal_role_catalog_path(arguments)}/{catalog_role}"
-            )
+            self._handle_revoke_catalog_role(arguments, delegate_args)
         else:  # pragma: no cover
             raise ValueError(f"Unsupported operation: {operation}")
 
         raw = self._rest_client.call(delegate_args)
         return self._maybe_augment_error(raw, normalized)
 
+    def _handle_list(self, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = "principal-roles"
+
+    def _handle_create(self, arguments: dict, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "POST"
+        delegate_args["path"] = "principal-roles"
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "CreatePrincipalRoleRequest"
+        )
+
+    def _handle_get(self, arguments: dict, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = self._principal_role_path(arguments)
+
+    def _handle_update(self, arguments: dict, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "PUT"
+        delegate_args["path"] = self._principal_role_path(arguments)
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "UpdatePrincipalRoleRequest"
+        )
+
+    def _handle_delete(self, arguments: dict, delegate_args: JSONDict) -> None:
+        delegate_args["method"] = "DELETE"
+        delegate_args["path"] = self._principal_role_path(arguments)
+
+    def _handle_list_principals(self, arguments: dict, delegate_args: 
JSONDict) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = 
f"{self._principal_role_path(arguments)}/principals"
+
+    def _handle_list_catalog_roles(
+        self, arguments: dict, delegate_args: JSONDict
+    ) -> None:
+        delegate_args["method"] = "GET"
+        delegate_args["path"] = self._principal_role_catalog_path(arguments)
+
+    def _handle_assign_catalog_role(
+        self, arguments: dict, delegate_args: JSONDict
+    ) -> None:
+        delegate_args["method"] = "PUT"
+        delegate_args["path"] = self._principal_role_catalog_path(arguments)
+        delegate_args["body"] = self._require_object(
+            arguments, "body", "GrantCatalogRoleRequest"
+        )
+
+    def _handle_revoke_catalog_role(
+        self, arguments: dict, delegate_args: JSONDict
+    ) -> None:
+        catalog_role = encode_path_segment(require_text(arguments, 
"catalogRole"))
+        delegate_args["method"] = "DELETE"
+        delegate_args["path"] = (
+            f"{self._principal_role_catalog_path(arguments)}/{catalog_role}"
+        )
+
     def _principal_role_path(self, arguments: Dict[str, Any]) -> str:
         role = encode_path_segment(require_text(arguments, "principalRole"))
         return f"principal-roles/{role}"
diff --git a/mcp-server/polaris_mcp/tools/table.py 
b/mcp-server/polaris_mcp/tools/table.py
index d021a2f..279abcd 100644
--- a/mcp-server/polaris_mcp/tools/table.py
+++ b/mcp-server/polaris_mcp/tools/table.py
@@ -39,13 +39,14 @@ from polaris_mcp.rest import PolarisRestTool, 
encode_path_segment
 class PolarisTableTool(McpTool):
     """Expose Polaris table REST endpoints through MCP."""
 
-    TOOL_NAME = "polaris-iceberg-table"
-    TOOL_DESCRIPTION = "Perform table-centric operations (list, get, create, 
commit, delete) using the Polaris REST API."
+    TOOL_NAME = "polaris-iceberg-table-request"
+    TOOL_DESCRIPTION = "Perform table operations (list, get, create, update, 
delete)."
+
     LIST_ALIASES: Set[str] = {"list", "ls"}
     GET_ALIASES: Set[str] = {"get", "load", "fetch"}
     CREATE_ALIASES: Set[str] = {"create"}
     COMMIT_ALIASES: Set[str] = {"commit", "update"}
-    DELETE_ALIASES: Set[str] = {"delete", "drop"}
+    DELETE_ALIASES: Set[str] = {"delete", "drop", "remove"}
 
     def __init__(self, rest_client: PolarisRestTool) -> None:
         self._rest_client = rest_client

Reply via email to