connect_cluster
Generate and bind a KUBECONFIG to a specified ClusterRole for accessing and managing a Kubernetes cluster, with cluster-admin as the default role.
Instructions
Generates the KUBECONFIG for the managed cluster and binds it to the specified ClusterRole (default: cluster-admin).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cluster | Yes | The target cluster where the ServiceAccount will be created for the KUBECONFIG. | |
| clusterRole | No | The ClusterRole defining permissions to access the cluster | cluster-admin |
Implementation Reference
- src/tools/clusters.ts:82-211 (handler)Async handler function that implements the connect_cluster tool: creates ManagedServiceAccount, binds ClusterRole via ManifestWork, polls for token secret, generates and returns KUBECONFIG path or error.export async function connectCluster({ cluster, clusterRole = "cluster-admin" }: { cluster: string, clusterRole?: string }): Promise<CallToolResult> { // https://open-cluster-management.io/docs/getting-started/integration/managed-serviceaccount/ const mcpServerName = "multicluster-mcp-server" const msa = { apiVersion: 'authentication.open-cluster-management.io/v1beta1', kind: 'ManagedServiceAccount', metadata: { name: mcpServerName, namespace: cluster, }, spec: { rotation: {}, }, } const mca = { apiVersion: 'addon.open-cluster-management.io/v1alpha1', kind: 'ManagedClusterAddOn', metadata: { name: "managed-serviceaccount", namespace: cluster, }, } let result = `Successfully connected to cluster ${cluster} using ServiceAccount ${mcpServerName}, with the ${clusterRole} ClusterRole assigned.`; let isErrored = false try { const [applyMsa, getMca, getClusters] = await Promise.all([ client.patch<k8s.KubernetesObject>( msa, undefined, undefined, mcpServerName, true, k8s.PatchStrategy.ServerSideApply ), client.read(mca), listClusters({}) ]); if (!applyMsa) { console.warn(`Patched ManagedServiceAccount ${msa.metadata.namespace}/${msa.metadata.name} with empty response`); } const saNamespace = (getMca as any)?.status?.namespace; if (!saNamespace) { throw new Error(`ManagedServiceAccount ${mca.metadata.namespace}/${mca.metadata.name} not found in the cluster`); } const clusterRoleBinding = { apiVersion: "rbac.authorization.k8s.io/v1", kind: "ClusterRoleBinding", metadata: { name: `${mcpServerName}-clusterrolebinding`, }, roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "ClusterRole", name: clusterRole, // default clusterRole name for kubernetes admin - "cluster-admin" }, subjects: [ { kind: "ServiceAccount", name: mcpServerName, namespace: saNamespace, }, ], }; // create manifestWork to binding the clusterRole into the serviceAccount const bindingPermissionManifestWork = { apiVersion: 'work.open-cluster-management.io/v1', kind: 'ManifestWork', metadata: { name: mcpServerName, namespace: cluster, }, spec: { workload: { manifests: [ clusterRoleBinding, ] } }, } const [tokenSecret, applyRBACManifest, appliedStatusErrMessage] = await Promise.all([ getSecretWithRetry(cluster, mcpServerName), // createKubeConfigFile(acmMCPServer, cluster), client.patch<k8s.KubernetesObject>( bindingPermissionManifestWork, undefined, undefined, mcpServerName, true, k8s.PatchStrategy.ServerSideApply), // get the status manifestWorkAppliedErrorMessage(client, mcpServerName, cluster) ]); // error token if (typeof tokenSecret == 'string') { throw new Error(tokenSecret) } // error status if (appliedStatusErrMessage != "") { throw new Error(appliedStatusErrMessage) } const kubeConfigErrMessage = generateKubeconfig(tokenSecret, clusterToServerAPIMap); if (kubeConfigErrMessage) { throw new Error(kubeConfigErrMessage) } } catch (err: any) { isErrored = true result = `Failed to generate KUBECONFIG for ${cluster}: ${err}` } // return manifestsResponse return { content: [{ type: "text", text: result }], isErrored: isErrored } }
- MCP tool handler decorated function that sets up cluster access by calling setup_cluster_access, which handles MSA creation, RBAC, secret retrieval, and kubeconfig generation.@mcp.tool(description="Generates the 'KUBECONFIG' for the managed cluster and binds it to the specified ClusterRole (default: cluster-admin).") def connect_cluster( cluster: Annotated[str, Field(description="The target cluster where the ServiceAccount will be created for the KUBECONFIG.")], cluster_role: Annotated[str, Field(description="The ClusterRole defining permissions to access the cluster.")] = "cluster-admin", ) -> Annotated[str, Field(description="A message indicating the kubeconfig file or failure of the operation.")]: return setup_cluster_access(cluster, cluster_role=cluster_role)
- src/index.ts:30-35 (registration)Registration of the 'connect_cluster' tool on the MCP server using server.tool() with description, args schema, and handler.server.tool( "connect_cluster", connectClusterDesc, connectClusterArgs, async (args, extra) => connectCluster(args) // ensure connectCluster matches (args, extra) => ... )
- src/tools/clusters.ts:75-78 (schema)Zod schema defining input arguments for connectCluster tool: cluster (string), clusterRole (string, default 'cluster-admin').export const connectClusterArgs = { cluster: z.string().describe("The target cluster where the ServiceAccount will be created for the KUBECONFIG."), clusterRole: z.string().default('cluster-admin').describe("The ClusterRole defining permissions to access the cluster") }
- python/multicluster_mcp_server/__main__.py:4-4 (registration)Import of connect_cluster tool in __main__.py, which registers it via the @mcp.tool decorator when running mcp.run().from multicluster_mcp_server.tools.connect import connect_cluster