Skip to content

Commit 11b0539

Browse files
mstirijiachengxu
andauthored
feat: Add support for running the server in ReadOnly mode (#50)
* feat: add conditional registration of modification tools based on read-only mode * docs: add instructions for running MCP Server in ReadOnly mode * fix lint --------- Co-authored-by: Jiacheng Xu <xjcmaxwellcjx@gmail.com>
1 parent 301e313 commit 11b0539

File tree

2 files changed

+72
-46
lines changed

2 files changed

+72
-46
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ This disables TLS certificate validation for Node.js when connecting to Argo CD
129129

130130
> **Warning**: Disabling SSL verification reduces security. Use this setting only in development environments or when you understand the security implications.
131131
132+
133+
### Read Only Mode
134+
135+
If you want to run the MCP Server in a ReadOnly mode to avoid resource or application modification, you should set the environment variable:
136+
```
137+
"MCP_READ_ONLY": "true"
138+
```
139+
This will disable the following tools:
140+
- `create_application`
141+
- `update_application`
142+
- `delete_application`
143+
- `sync_application`
144+
- `run_resource_action`
145+
146+
By default, all the tools will be available.
147+
132148
## Available Tools
133149

134150
The server provides the following ArgoCD management tools:

src/server/server.ts

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export class Server extends McpServer {
2525
});
2626
this.argocdClient = new ArgoCDClient(serverInfo.argocdBaseUrl, serverInfo.argocdApiToken);
2727

28+
const isReadOnly =
29+
String(process.env.MCP_READ_ONLY ?? '')
30+
.trim()
31+
.toLowerCase() === 'true';
32+
33+
// Always register read/query tools
2834
this.addJsonOutputTool(
2935
'list_applications',
3036
'list_applications returns list of applications',
@@ -45,35 +51,6 @@ export class Server extends McpServer {
4551
{ applicationName: z.string() },
4652
async ({ applicationName }) => await this.argocdClient.getApplication(applicationName)
4753
);
48-
this.addJsonOutputTool(
49-
'create_application',
50-
'create_application creates application',
51-
{ application: ApplicationSchema },
52-
async ({ application }) =>
53-
await this.argocdClient.createApplication(application as V1alpha1Application)
54-
);
55-
this.addJsonOutputTool(
56-
'update_application',
57-
'update_application updates application',
58-
{ applicationName: z.string(), application: ApplicationSchema },
59-
async ({ applicationName, application }) =>
60-
await this.argocdClient.updateApplication(
61-
applicationName,
62-
application as V1alpha1Application
63-
)
64-
);
65-
this.addJsonOutputTool(
66-
'delete_application',
67-
'delete_application deletes application',
68-
{ applicationName: z.string() },
69-
async ({ applicationName }) => await this.argocdClient.deleteApplication(applicationName)
70-
);
71-
this.addJsonOutputTool(
72-
'sync_application',
73-
'sync_application syncs application',
74-
{ applicationName: z.string() },
75-
async ({ applicationName }) => await this.argocdClient.syncApplication(applicationName)
76-
);
7754
this.addJsonOutputTool(
7855
'get_application_resource_tree',
7956
'get_application_resource_tree returns resource tree for application by application name',
@@ -176,23 +153,56 @@ export class Server extends McpServer {
176153
resourceRef as V1alpha1ResourceResult
177154
)
178155
);
179-
this.addJsonOutputTool(
180-
'run_resource_action',
181-
'run_resource_action runs an action on a resource',
182-
{
183-
applicationName: z.string(),
184-
applicationNamespace: ApplicationNamespaceSchema,
185-
resourceRef: ResourceRefSchema,
186-
action: z.string()
187-
},
188-
async ({ applicationName, applicationNamespace, resourceRef, action }) =>
189-
await this.argocdClient.runResourceAction(
190-
applicationName,
191-
applicationNamespace,
192-
resourceRef as V1alpha1ResourceResult,
193-
action
194-
)
195-
);
156+
157+
// Only register modification tools if not in read-only mode
158+
if (!isReadOnly) {
159+
this.addJsonOutputTool(
160+
'create_application',
161+
'create_application creates application',
162+
{ application: ApplicationSchema },
163+
async ({ application }) =>
164+
await this.argocdClient.createApplication(application as V1alpha1Application)
165+
);
166+
this.addJsonOutputTool(
167+
'update_application',
168+
'update_application updates application',
169+
{ applicationName: z.string(), application: ApplicationSchema },
170+
async ({ applicationName, application }) =>
171+
await this.argocdClient.updateApplication(
172+
applicationName,
173+
application as V1alpha1Application
174+
)
175+
);
176+
this.addJsonOutputTool(
177+
'delete_application',
178+
'delete_application deletes application',
179+
{ applicationName: z.string() },
180+
async ({ applicationName }) => await this.argocdClient.deleteApplication(applicationName)
181+
);
182+
this.addJsonOutputTool(
183+
'sync_application',
184+
'sync_application syncs application',
185+
{ applicationName: z.string() },
186+
async ({ applicationName }) => await this.argocdClient.syncApplication(applicationName)
187+
);
188+
this.addJsonOutputTool(
189+
'run_resource_action',
190+
'run_resource_action runs an action on a resource',
191+
{
192+
applicationName: z.string(),
193+
applicationNamespace: ApplicationNamespaceSchema,
194+
resourceRef: ResourceRefSchema,
195+
action: z.string()
196+
},
197+
async ({ applicationName, applicationNamespace, resourceRef, action }) =>
198+
await this.argocdClient.runResourceAction(
199+
applicationName,
200+
applicationNamespace,
201+
resourceRef as V1alpha1ResourceResult,
202+
action
203+
)
204+
);
205+
}
196206
}
197207

198208
private addJsonOutputTool<Args extends ZodRawShape, T>(

0 commit comments

Comments
 (0)