@gcnv/gcnv-mcp-server 1.0.3
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.
- package/GEMINI.md +200 -0
- package/LICENSE +201 -0
- package/README.md +374 -0
- package/build/index.js +185 -0
- package/build/logger.js +19 -0
- package/build/registry/register-tools.js +101 -0
- package/build/registry/tool-registry.js +27 -0
- package/build/tools/active-directory-tools.js +124 -0
- package/build/tools/backup-policy-tools.js +140 -0
- package/build/tools/backup-tools.js +178 -0
- package/build/tools/backup-vault-tools.js +147 -0
- package/build/tools/handlers/active-directory-handler.js +321 -0
- package/build/tools/handlers/backup-handler.js +451 -0
- package/build/tools/handlers/backup-policy-handler.js +275 -0
- package/build/tools/handlers/backup-vault-handler.js +370 -0
- package/build/tools/handlers/kms-config-handler.js +327 -0
- package/build/tools/handlers/operation-handler.js +254 -0
- package/build/tools/handlers/quota-rule-handler.js +411 -0
- package/build/tools/handlers/replication-handler.js +504 -0
- package/build/tools/handlers/snapshot-handler.js +320 -0
- package/build/tools/handlers/storage-pool-handler.js +346 -0
- package/build/tools/handlers/volume-handler.js +353 -0
- package/build/tools/kms-config-tools.js +162 -0
- package/build/tools/operation-tools.js +64 -0
- package/build/tools/quota-rule-tools.js +166 -0
- package/build/tools/replication-tools.js +227 -0
- package/build/tools/snapshot-tools.js +124 -0
- package/build/tools/storage-pool-tools.js +215 -0
- package/build/tools/volume-tools.js +216 -0
- package/build/types/tool.js +1 -0
- package/build/utils/netapp-client-factory.js +53 -0
- package/gemini-extension.json +12 -0
- package/package.json +66 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// Create Storage Pool Tool
|
|
3
|
+
export const createStoragePoolTool = {
|
|
4
|
+
name: 'gcnv_storage_pool_create',
|
|
5
|
+
title: 'Create Storage Pool',
|
|
6
|
+
description: 'Creates a new storage pool in the specified project and location',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
9
|
+
location: z.string().describe('The location where the storage pool should be created'),
|
|
10
|
+
storagePoolId: z.string().describe('The ID to assign to the storage pool'),
|
|
11
|
+
capacityGib: z.number().describe('The capacity of the storage pool in GiB'),
|
|
12
|
+
serviceLevel: z
|
|
13
|
+
.enum(['STANDARD', 'PREMIUM', 'EXTREME'])
|
|
14
|
+
.describe('The service level of the storage pool'),
|
|
15
|
+
description: z.string().optional().describe('Optional description of the storage pool'),
|
|
16
|
+
labels: z
|
|
17
|
+
.record(z.string())
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Optional labels to apply to the storage pool'),
|
|
20
|
+
network: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('The VPC network to use for the storage pool (projects/{project}/global/networks/{network})'),
|
|
24
|
+
activeDirectory: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('The Active Directory policy resource to attach to SMB volumes'),
|
|
28
|
+
kmsConfig: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('The CMEK KMS config to use for pool encryption (projects/{project}/locations/{location}/kmsConfigs/{kmsConfigId})'),
|
|
32
|
+
encryptionType: z
|
|
33
|
+
.enum(['SERVICE_MANAGED', 'CLOUD_KMS'])
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Encryption type for the pool; use CLOUD_KMS with kmsConfig'),
|
|
36
|
+
ldapEnabled: z
|
|
37
|
+
.boolean()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Whether LDAP should be enabled for NFS volume access'),
|
|
40
|
+
psaRange: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('CIDR range for Private Service Access allocated to the pool'),
|
|
44
|
+
globalAccessAllowed: z
|
|
45
|
+
.boolean()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('Allow clients from other regions to access volumes in this pool'),
|
|
48
|
+
allowAutoTiering: z
|
|
49
|
+
.boolean()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Enable auto-tiering to manage capacity for the pool'),
|
|
52
|
+
},
|
|
53
|
+
outputSchema: {
|
|
54
|
+
name: z.string().describe('The name of the created storage pool'),
|
|
55
|
+
operationId: z
|
|
56
|
+
.string()
|
|
57
|
+
.describe('The ID of the long-running operation for creating the storage pool'),
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
// Delete Storage Pool Tool
|
|
61
|
+
export const deleteStoragePoolTool = {
|
|
62
|
+
name: 'gcnv_storage_pool_delete',
|
|
63
|
+
title: 'Delete Storage Pool',
|
|
64
|
+
description: 'Deletes a storage pool in the specified project and location',
|
|
65
|
+
inputSchema: {
|
|
66
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
67
|
+
location: z.string().describe('The location of the storage pool'),
|
|
68
|
+
storagePoolId: z.string().describe('The ID of the storage pool to delete'),
|
|
69
|
+
force: z.boolean().optional().describe('Force deletion even if the pool contains resources'),
|
|
70
|
+
},
|
|
71
|
+
outputSchema: {
|
|
72
|
+
success: z.boolean().describe('Whether the deletion was successful'),
|
|
73
|
+
operationId: z.string().optional().describe('The ID of the long-running operation'),
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
// Get Storage Pool Tool
|
|
77
|
+
export const getStoragePoolTool = {
|
|
78
|
+
name: 'gcnv_storage_pool_get',
|
|
79
|
+
title: 'Get Storage Pool',
|
|
80
|
+
description: 'Gets details of a specific storage pool',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
83
|
+
location: z.string().describe('The location of the storage pool'),
|
|
84
|
+
storagePoolId: z.string().describe('The ID of the storage pool to retrieve'),
|
|
85
|
+
},
|
|
86
|
+
outputSchema: {
|
|
87
|
+
name: z.string().describe('The name of the storage pool'),
|
|
88
|
+
storagePoolId: z.string().describe('The ID of the storage pool'),
|
|
89
|
+
serviceLevel: z.string().describe('The service level of the storage pool'),
|
|
90
|
+
capacityGib: z.number().describe('The capacity of the storage pool in GiB'),
|
|
91
|
+
volumeCapacityGib: z.number().describe('The total volume capacity in GiB'),
|
|
92
|
+
volumecount: z.number().describe('The number of volumes in the storage pool'),
|
|
93
|
+
state: z.string().describe('The current state of the storage pool'),
|
|
94
|
+
createTime: z.date().describe('The timestamp when the storage pool was created'),
|
|
95
|
+
description: z.string().optional().describe('The description of the storage pool'),
|
|
96
|
+
labels: z.record(z.string()).optional().describe('Labels applied to the storage pool'),
|
|
97
|
+
network: z.string().optional().describe('The VPC network used by the storage pool'),
|
|
98
|
+
activeDirectory: z
|
|
99
|
+
.string()
|
|
100
|
+
.optional()
|
|
101
|
+
.describe('The Active Directory policy attached to SMB volumes'),
|
|
102
|
+
kmsConfig: z.string().optional().describe('The CMEK KMS config applied to the pool'),
|
|
103
|
+
encryptionType: z.string().optional().describe('The encryption type configured for the pool'),
|
|
104
|
+
ldapEnabled: z.boolean().optional().describe('Whether LDAP is enabled for NFS volume access'),
|
|
105
|
+
psaRange: z
|
|
106
|
+
.string()
|
|
107
|
+
.optional()
|
|
108
|
+
.describe('CIDR range for Private Service Access allocated to the pool'),
|
|
109
|
+
globalAccessAllowed: z
|
|
110
|
+
.boolean()
|
|
111
|
+
.optional()
|
|
112
|
+
.describe('Indicates if cross-region volume access is allowed'),
|
|
113
|
+
allowAutoTiering: z
|
|
114
|
+
.boolean()
|
|
115
|
+
.optional()
|
|
116
|
+
.describe('Whether auto-tiering is enabled for the pool'),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
// List Storage Pools Tool
|
|
120
|
+
export const listStoragePoolsTool = {
|
|
121
|
+
name: 'gcnv_storage_pool_list',
|
|
122
|
+
title: 'List Storage Pools',
|
|
123
|
+
description: 'Lists all storage pools in the specified project and location',
|
|
124
|
+
inputSchema: {
|
|
125
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
126
|
+
location: z.string().describe('The location to list storage pools from'),
|
|
127
|
+
filter: z.string().optional().describe('Filter expression for filtering results'),
|
|
128
|
+
pageSize: z.number().optional().describe('The maximum number of storage pools to return'),
|
|
129
|
+
pageToken: z.string().optional().describe('Page token from a previous list request'),
|
|
130
|
+
},
|
|
131
|
+
outputSchema: {
|
|
132
|
+
storagePools: z
|
|
133
|
+
.array(z.object({
|
|
134
|
+
name: z.string().describe('The name of the storage pool'),
|
|
135
|
+
storagePoolId: z.string().describe('The ID of the storage pool'),
|
|
136
|
+
serviceLevel: z.string().describe('The service level of the storage pool'),
|
|
137
|
+
capacityGib: z.number().describe('The capacity of the storage pool in GiB'),
|
|
138
|
+
volumeCapacityGib: z.number().describe('The total volume capacity in GiB'),
|
|
139
|
+
volumecount: z.number().describe('The number of volumes in the storage pool'),
|
|
140
|
+
state: z.string().describe('The current state of the storage pool'),
|
|
141
|
+
createTime: z.date().describe('The timestamp when the storage pool was created'),
|
|
142
|
+
description: z.string().optional().describe('The description of the storage pool'),
|
|
143
|
+
labels: z.record(z.string()).optional().describe('Labels applied to the storage pool'),
|
|
144
|
+
network: z.string().optional().describe('The VPC network used by the storage pool'),
|
|
145
|
+
activeDirectory: z
|
|
146
|
+
.string()
|
|
147
|
+
.optional()
|
|
148
|
+
.describe('The Active Directory policy attached to SMB volumes'),
|
|
149
|
+
kmsConfig: z.string().optional().describe('The CMEK KMS config applied to the pool'),
|
|
150
|
+
encryptionType: z
|
|
151
|
+
.string()
|
|
152
|
+
.optional()
|
|
153
|
+
.describe('The encryption type configured for the pool'),
|
|
154
|
+
ldapEnabled: z
|
|
155
|
+
.boolean()
|
|
156
|
+
.optional()
|
|
157
|
+
.describe('Whether LDAP is enabled for NFS volume access'),
|
|
158
|
+
psaRange: z
|
|
159
|
+
.string()
|
|
160
|
+
.optional()
|
|
161
|
+
.describe('CIDR range for Private Service Access allocated to the pool'),
|
|
162
|
+
globalAccessAllowed: z
|
|
163
|
+
.boolean()
|
|
164
|
+
.optional()
|
|
165
|
+
.describe('Indicates if cross-region volume access is allowed'),
|
|
166
|
+
allowAutoTiering: z
|
|
167
|
+
.boolean()
|
|
168
|
+
.optional()
|
|
169
|
+
.describe('Whether auto-tiering is enabled for the pool'),
|
|
170
|
+
}))
|
|
171
|
+
.describe('List of storage pools'),
|
|
172
|
+
nextPageToken: z.string().optional().describe('Token to retrieve the next page of results'),
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
// Update Storage Pool Tool
|
|
176
|
+
export const updateStoragePoolTool = {
|
|
177
|
+
name: 'gcnv_storage_pool_update',
|
|
178
|
+
title: 'Update Storage Pool',
|
|
179
|
+
description: 'Updates a storage pool in the specified project and location',
|
|
180
|
+
inputSchema: {
|
|
181
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
182
|
+
location: z.string().describe('The location of the storage pool'),
|
|
183
|
+
storagePoolId: z.string().describe('The ID of the storage pool to update'),
|
|
184
|
+
capacityGib: z.number().optional().describe('The new capacity of the storage pool in GiB'),
|
|
185
|
+
description: z.string().optional().describe('New description of the storage pool'),
|
|
186
|
+
labels: z.record(z.string()).optional().describe('New labels to apply to the storage pool'),
|
|
187
|
+
},
|
|
188
|
+
outputSchema: {
|
|
189
|
+
name: z.string().describe('The name of the updated storage pool'),
|
|
190
|
+
operationId: z
|
|
191
|
+
.string()
|
|
192
|
+
.optional()
|
|
193
|
+
.describe('The ID of the long-running operation for updating the storage pool'),
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
// Validate Directory Service Tool
|
|
197
|
+
export const validateDirectoryServiceTool = {
|
|
198
|
+
name: 'gcnv_storage_pool_validate_directory_service',
|
|
199
|
+
title: 'Validate Directory Service',
|
|
200
|
+
description: 'Validates directory service policy attached to a storage pool',
|
|
201
|
+
inputSchema: {
|
|
202
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
203
|
+
location: z.string().describe('The location of the storage pool'),
|
|
204
|
+
storagePoolId: z.string().describe('The ID of the storage pool'),
|
|
205
|
+
directoryServiceType: z
|
|
206
|
+
.enum(['ACTIVE_DIRECTORY', 'LDAP'])
|
|
207
|
+
.describe('Type of directory service policy attached to the storage pool'),
|
|
208
|
+
},
|
|
209
|
+
outputSchema: {
|
|
210
|
+
success: z.boolean().describe('Whether the validation was successful'),
|
|
211
|
+
operationId: z
|
|
212
|
+
.string()
|
|
213
|
+
.describe('The ID of the long-running operation for validating directory service'),
|
|
214
|
+
},
|
|
215
|
+
};
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// Create Volume Tool
|
|
3
|
+
export const createVolumeTool = {
|
|
4
|
+
name: 'gcnv_volume_create',
|
|
5
|
+
title: 'Create Volume',
|
|
6
|
+
description: 'Creates a new volume in the specified storage pool',
|
|
7
|
+
inputSchema: {
|
|
8
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
9
|
+
location: z.string().describe('The location where the volume should be created'),
|
|
10
|
+
storagePoolId: z.string().describe('The ID of the storage pool to create the volume in'),
|
|
11
|
+
volumeId: z.string().describe('The ID to assign to the volume'),
|
|
12
|
+
capacityGib: z.number().describe('The capacity of the volume in GiB'),
|
|
13
|
+
protocols: z
|
|
14
|
+
.array(z.enum(['NFSV3', 'NFSV4', 'SMB', 'DUAL']))
|
|
15
|
+
.describe('The file share protocols to enable'),
|
|
16
|
+
description: z.string().optional().describe('Optional description of the volume'),
|
|
17
|
+
shareName: z.string().optional().describe('Optional name of the file share'),
|
|
18
|
+
labels: z.record(z.string()).optional().describe('Optional labels to apply to the volume'),
|
|
19
|
+
backupConfig: z
|
|
20
|
+
.object({
|
|
21
|
+
backupPolicies: z
|
|
22
|
+
.array(z.string())
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Backup policy resource names (projects/.../backupPolicies/ID)'),
|
|
25
|
+
backupVault: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Backup vault resource name (projects/.../backupVaults/ID)'),
|
|
29
|
+
scheduledBackupEnabled: z.boolean().optional().describe('Enable scheduled backups'),
|
|
30
|
+
})
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Backup configuration'),
|
|
33
|
+
exportPolicy: z
|
|
34
|
+
.object({
|
|
35
|
+
rules: z
|
|
36
|
+
.array(z.object({
|
|
37
|
+
allowedClients: z.string().describe('CIDR range of client IPs to allow'),
|
|
38
|
+
accessType: z
|
|
39
|
+
.enum(['READ_ONLY', 'READ_WRITE'])
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Access permission type'),
|
|
42
|
+
nfsv3: z.boolean().optional().describe('Whether NFSv3 is allowed'),
|
|
43
|
+
nfsv4: z.boolean().optional().describe('Whether NFSv4 is allowed'),
|
|
44
|
+
hasRootAccess: z.boolean().optional().describe('Whether root access is allowed'),
|
|
45
|
+
nfsOptions: z
|
|
46
|
+
.object({
|
|
47
|
+
rootSquash: z.boolean().optional().describe('Whether to enable root squashing'),
|
|
48
|
+
anon: z.string().optional().describe('Anonymous user ID for mapped root user'),
|
|
49
|
+
})
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('NFS-specific options'),
|
|
52
|
+
kerberos5ReadOnly: z
|
|
53
|
+
.boolean()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Whether Kerberos5 is required for read-only operations'),
|
|
56
|
+
kerberos5ReadWrite: z
|
|
57
|
+
.boolean()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe('Whether Kerberos5 is required for read-write operations'),
|
|
60
|
+
kerberos5iReadOnly: z
|
|
61
|
+
.boolean()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Whether Kerberos5i is required for read-only operations'),
|
|
64
|
+
kerberos5iReadWrite: z
|
|
65
|
+
.boolean()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe('Whether Kerberos5i is required for read-write operations'),
|
|
68
|
+
kerberos5pReadOnly: z
|
|
69
|
+
.boolean()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Whether Kerberos5p is required for read-only operations'),
|
|
72
|
+
kerberos5pReadWrite: z
|
|
73
|
+
.boolean()
|
|
74
|
+
.optional()
|
|
75
|
+
.describe('Whether Kerberos5p is required for read-write operations'),
|
|
76
|
+
}))
|
|
77
|
+
.describe('List of export policy rules'),
|
|
78
|
+
})
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('NFS export policy configuration'),
|
|
81
|
+
},
|
|
82
|
+
outputSchema: {
|
|
83
|
+
name: z.string().describe('The name of the created volume'),
|
|
84
|
+
operationId: z
|
|
85
|
+
.string()
|
|
86
|
+
.describe('The ID of the long-running operation for creating the volume'),
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
// Delete Volume Tool
|
|
90
|
+
export const deleteVolumeTool = {
|
|
91
|
+
name: 'gcnv_volume_delete',
|
|
92
|
+
title: 'Delete Volume',
|
|
93
|
+
description: 'Deletes a volume in the specified storage pool',
|
|
94
|
+
inputSchema: {
|
|
95
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
96
|
+
location: z.string().describe('The location of the volume'),
|
|
97
|
+
volumeId: z.string().describe('The ID of the volume to delete'),
|
|
98
|
+
force: z.boolean().optional().describe('Force deletion even if the volume has snapshots'),
|
|
99
|
+
},
|
|
100
|
+
outputSchema: {
|
|
101
|
+
success: z.boolean().describe('Whether the deletion was successful'),
|
|
102
|
+
operationId: z.string().optional().describe('The ID of the long-running operation'),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
// Get Volume Tool
|
|
106
|
+
export const getVolumeTool = {
|
|
107
|
+
name: 'gcnv_volume_get',
|
|
108
|
+
title: 'Get Volume',
|
|
109
|
+
description: 'Gets details of a specific volume',
|
|
110
|
+
inputSchema: {
|
|
111
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
112
|
+
location: z.string().describe('The location of the volume'),
|
|
113
|
+
volumeId: z.string().describe('The ID of the volume to retrieve'),
|
|
114
|
+
},
|
|
115
|
+
// Allow any additional fields from the API
|
|
116
|
+
outputSchema: {
|
|
117
|
+
volume: z.record(z.any()).describe('Volume details'),
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
// List Volumes Tool
|
|
121
|
+
export const listVolumesTool = {
|
|
122
|
+
name: 'gcnv_volume_list',
|
|
123
|
+
title: 'List Volumes',
|
|
124
|
+
description: 'Lists all volumes in the specified storage pool',
|
|
125
|
+
inputSchema: {
|
|
126
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
127
|
+
location: z.string().describe('The location to list volumes from'),
|
|
128
|
+
filter: z.string().optional().describe('Filter expression for filtering results'),
|
|
129
|
+
pageSize: z.number().optional().describe('The maximum number of volumes to return'),
|
|
130
|
+
pageToken: z.string().optional().describe('Page token from a previous list request'),
|
|
131
|
+
},
|
|
132
|
+
outputSchema: {
|
|
133
|
+
volumes: z.array(z.record(z.any())).describe('List of volumes'),
|
|
134
|
+
nextPageToken: z.string().optional().describe('Token to retrieve the next page of results'),
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
// Update Volume Tool
|
|
138
|
+
export const updateVolumeTool = {
|
|
139
|
+
name: 'gcnv_volume_update',
|
|
140
|
+
title: 'Update Volume',
|
|
141
|
+
description: 'Updates a volume in the specified storage pool',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
projectId: z.string().describe('The ID of the Google Cloud project'),
|
|
144
|
+
location: z.string().describe('The location of the volume'),
|
|
145
|
+
volumeId: z.string().describe('The ID of the volume to update'),
|
|
146
|
+
capacityGib: z.number().optional().describe('The new capacity of the volume in GiB'),
|
|
147
|
+
description: z.string().optional().describe('New description of the volume'),
|
|
148
|
+
labels: z.record(z.string()).optional().describe('New labels to apply to the volume'),
|
|
149
|
+
backupConfig: z
|
|
150
|
+
.object({
|
|
151
|
+
backupPolicies: z
|
|
152
|
+
.array(z.string())
|
|
153
|
+
.describe('Backup policy resource names (projects/.../backupPolicies/ID)'),
|
|
154
|
+
backupVault: z
|
|
155
|
+
.string()
|
|
156
|
+
.describe('Backup vault resource name (projects/.../backupVaults/ID)'),
|
|
157
|
+
scheduledBackupEnabled: z.boolean().describe('Enable scheduled backups'),
|
|
158
|
+
})
|
|
159
|
+
.optional()
|
|
160
|
+
.describe('Backup configuration'),
|
|
161
|
+
exportPolicy: z
|
|
162
|
+
.object({
|
|
163
|
+
rules: z
|
|
164
|
+
.array(z.object({
|
|
165
|
+
allowedClients: z.string().optional().describe('CIDR range of client IPs to allow'),
|
|
166
|
+
accessType: z
|
|
167
|
+
.enum(['READ_ONLY', 'READ_WRITE'])
|
|
168
|
+
.optional()
|
|
169
|
+
.describe('Access permission type'),
|
|
170
|
+
nfsv3: z.boolean().optional().describe('Whether NFSv3 is allowed'),
|
|
171
|
+
nfsv4: z.boolean().optional().describe('Whether NFSv4 is allowed'),
|
|
172
|
+
nfsOptions: z
|
|
173
|
+
.object({
|
|
174
|
+
rootSquash: z.boolean().optional().describe('Whether to enable root squashing'),
|
|
175
|
+
anon: z.string().optional().describe('Anonymous user ID for mapped root user'),
|
|
176
|
+
})
|
|
177
|
+
.optional()
|
|
178
|
+
.describe('NFS-specific options'),
|
|
179
|
+
kerberos5ReadOnly: z
|
|
180
|
+
.boolean()
|
|
181
|
+
.optional()
|
|
182
|
+
.describe('Whether Kerberos5 is required for read-only operations'),
|
|
183
|
+
kerberos5ReadWrite: z
|
|
184
|
+
.boolean()
|
|
185
|
+
.optional()
|
|
186
|
+
.describe('Whether Kerberos5 is required for read-write operations'),
|
|
187
|
+
kerberos5iReadOnly: z
|
|
188
|
+
.boolean()
|
|
189
|
+
.optional()
|
|
190
|
+
.describe('Whether Kerberos5i is required for read-only operations'),
|
|
191
|
+
kerberos5iReadWrite: z
|
|
192
|
+
.boolean()
|
|
193
|
+
.optional()
|
|
194
|
+
.describe('Whether Kerberos5i is required for read-write operations'),
|
|
195
|
+
kerberos5pReadOnly: z
|
|
196
|
+
.boolean()
|
|
197
|
+
.optional()
|
|
198
|
+
.describe('Whether Kerberos5p is required for read-only operations'),
|
|
199
|
+
kerberos5pReadWrite: z
|
|
200
|
+
.boolean()
|
|
201
|
+
.optional()
|
|
202
|
+
.describe('Whether Kerberos5p is required for read-write operations'),
|
|
203
|
+
}))
|
|
204
|
+
.describe('List of export policy rules'),
|
|
205
|
+
})
|
|
206
|
+
.optional()
|
|
207
|
+
.describe('Updated NFS export policy configuration'),
|
|
208
|
+
},
|
|
209
|
+
outputSchema: {
|
|
210
|
+
name: z.string().describe('The name of the updated volume'),
|
|
211
|
+
operationId: z
|
|
212
|
+
.string()
|
|
213
|
+
.optional()
|
|
214
|
+
.describe('The ID of the long-running operation for updating the volume'),
|
|
215
|
+
},
|
|
216
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NetAppClient } from '@google-cloud/netapp';
|
|
2
|
+
/**
|
|
3
|
+
* Factory class for creating NetAppClient instances
|
|
4
|
+
* This centralizes client creation and allows for easier testing and configuration
|
|
5
|
+
*/
|
|
6
|
+
export class NetAppClientFactory {
|
|
7
|
+
// Cache for storing client instances (singleton pattern)
|
|
8
|
+
static clientCache = {};
|
|
9
|
+
// Default configuration that will be used if no specific options are provided
|
|
10
|
+
static defaultConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new NetAppClient instance
|
|
13
|
+
*
|
|
14
|
+
* @param options - Options for the NetApp client, will override default config if both exist
|
|
15
|
+
* @param cacheKey - Optional key for caching the client instance
|
|
16
|
+
* @returns A configured NetAppClient instance
|
|
17
|
+
*/
|
|
18
|
+
static createClient(options, cacheKey) {
|
|
19
|
+
// If a cache key is provided and a client exists, return the cached client
|
|
20
|
+
if (cacheKey && this.clientCache[cacheKey]) {
|
|
21
|
+
return this.clientCache[cacheKey];
|
|
22
|
+
}
|
|
23
|
+
// Merge default config with provided options, with options taking precedence
|
|
24
|
+
let mergedOptions;
|
|
25
|
+
if (this.defaultConfig || options) {
|
|
26
|
+
mergedOptions = {
|
|
27
|
+
...(this.defaultConfig || {}),
|
|
28
|
+
...(options || {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Create a new client with the merged options
|
|
32
|
+
const client = mergedOptions ? new NetAppClient(mergedOptions) : new NetAppClient();
|
|
33
|
+
// If a cache key is provided, store the client for future use
|
|
34
|
+
if (cacheKey) {
|
|
35
|
+
this.clientCache[cacheKey] = client;
|
|
36
|
+
}
|
|
37
|
+
return client;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Clear the client cache
|
|
41
|
+
* Useful for testing or when configuration changes
|
|
42
|
+
*/
|
|
43
|
+
static clearCache() {
|
|
44
|
+
this.clientCache = {};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Reset the factory to its initial state
|
|
48
|
+
* Clears both the cache and default configuration
|
|
49
|
+
*/
|
|
50
|
+
static reset() {
|
|
51
|
+
this.clearCache();
|
|
52
|
+
}
|
|
53
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gcnv/gcnv-mcp-server",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Google Cloud NetApp Volumes MCP Server - A Model Context Protocol server for managing GCNV Backup, StoragePool, Volume and Replication resources",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gcnv-mcp": "build/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"build",
|
|
11
|
+
"GEMINI.md",
|
|
12
|
+
"gemini-extension.json",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"prepack": "npm run build",
|
|
25
|
+
"build": "npm run lint && npm run format && tsc",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"lint": "eslint . --ext .ts --max-warnings=0",
|
|
28
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
29
|
+
"format": "prettier --check .",
|
|
30
|
+
"format:fix": "prettier --write .",
|
|
31
|
+
"start": "node build/index.js",
|
|
32
|
+
"start:stdio": "node build/index.js --transport stdio",
|
|
33
|
+
"start:http": "node build/index.js --transport http",
|
|
34
|
+
"dev": "tsx src/index.ts",
|
|
35
|
+
"dev:http": "tsx src/index.ts --transport http"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"mcp",
|
|
39
|
+
"google",
|
|
40
|
+
"netapp",
|
|
41
|
+
"ontap",
|
|
42
|
+
"storage",
|
|
43
|
+
"api"
|
|
44
|
+
],
|
|
45
|
+
"author": "",
|
|
46
|
+
"license": "Apache-2.0",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@eslint/js": "^9.39.1",
|
|
49
|
+
"@types/node": "^24.1.0",
|
|
50
|
+
"eslint": "^9.39.1",
|
|
51
|
+
"eslint-config-prettier": "^10.1.1",
|
|
52
|
+
"prettier": "^3.4.1",
|
|
53
|
+
"tsx": "^4.19.1",
|
|
54
|
+
"typescript": "^5.8.3",
|
|
55
|
+
"typescript-eslint": "^8.48.0"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@google-cloud/netapp": "^0.15.0",
|
|
59
|
+
"@google-cloud/local-auth": "3.0.1",
|
|
60
|
+
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
61
|
+
"axios": "^1.6.3",
|
|
62
|
+
"pino": "^9.5.0",
|
|
63
|
+
"pino-pretty": "^11.3.0",
|
|
64
|
+
"zod": "^3.25.76"
|
|
65
|
+
}
|
|
66
|
+
}
|