Skip to content

Commit b5c9e08

Browse files
facundofariasclaude
andcommitted
feat: Change read-only mode default to FALSE (deployments allowed)
Changed the default behavior from read-only enabled to deployments allowed by default. This makes the MCP server more permissive out of the box while still allowing users to enable read-only mode for security if needed. Changes: - Default: readOnlyMode = false (deployments allowed) - Configuration parsing updated in src/config.ts - Server factory default changed in src/mcp-server.ts - Error message updated to reflect optional security feature - All tests updated to expect new default behavior - Documentation comments updated throughout Users can still enable read-only mode by: - Setting DEPLOYHQ_READ_ONLY=true environment variable - Using --read-only CLI flag 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent f5660b6 commit b5c9e08

File tree

4 files changed

+20
-18
lines changed

4 files changed

+20
-18
lines changed

src/__tests__/config.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ describe('Configuration Parsing', () => {
1818

1919
describe('parseServerConfig', () => {
2020
describe('Default behavior', () => {
21-
it('should default to read-only mode enabled', () => {
21+
it('should default to read-only mode disabled (deployments allowed)', () => {
2222
// Clear any existing config
2323
delete process.env.DEPLOYHQ_READ_ONLY;
2424
process.argv = ['node', 'test.js'];
2525

2626
const config = parseServerConfig();
2727

28-
expect(config.readOnlyMode).toBe(true);
28+
expect(config.readOnlyMode).toBe(false);
2929
});
3030
});
3131

@@ -129,13 +129,14 @@ describe('Configuration Parsing', () => {
129129
expect(config.readOnlyMode).toBe(false);
130130
});
131131

132-
it('should default to true for unrecognized values', () => {
132+
it('should fall back to default for unrecognized values', () => {
133133
process.env.DEPLOYHQ_READ_ONLY = 'maybe';
134134
process.argv = ['node', 'test.js'];
135135

136136
const config = parseServerConfig();
137137

138-
expect(config.readOnlyMode).toBe(true);
138+
// Unrecognized values are ignored and we use the default (false)
139+
expect(config.readOnlyMode).toBe(false);
139140
});
140141
});
141142

@@ -274,7 +275,7 @@ describe('Configuration Parsing', () => {
274275

275276
const config = parseServerConfig();
276277

277-
expect(config.readOnlyMode).toBe(true);
278+
expect(config.readOnlyMode).toBe(false);
278279
});
279280
});
280281
});
@@ -333,7 +334,8 @@ describe('Configuration Parsing', () => {
333334

334335
const config = parseServerConfig();
335336

336-
expect(config.readOnlyMode).toBe(true);
337+
// Empty string is ignored and we use the default (false)
338+
expect(config.readOnlyMode).toBe(false);
337339
});
338340

339341
it('should handle multiple --read-only flags (last one wins)', () => {

src/__tests__/read-only-mode.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ describe('Read-Only Mode Integration', () => {
9191
expect(response.content[0].text).toContain('test-deployment-uuid');
9292
});
9393

94-
it('should use default read-only mode (enabled) when no config provided', async () => {
94+
it('should use default read-only mode (disabled) when no config provided', async () => {
9595
const server = createMCPServer(
9696
9797
'api-key',
9898
'test-account'
99-
// No config provided - should default to read-only
99+
// No config provided - should default to deployments allowed
100100
);
101101

102102
const response = await invokeToolForTest(server, 'create_deployment', {
@@ -106,9 +106,9 @@ describe('Read-Only Mode Integration', () => {
106106
end_revision: 'def456',
107107
});
108108

109-
// Should return an error response (read-only by default)
110-
expect(response.isError).toBe(true);
111-
expect(response.content[0].text).toContain('read-only mode');
109+
// Should return a successful response (deployments allowed by default)
110+
expect(response.isError).toBeUndefined();
111+
expect(response.content[0].text).toContain('identifier');
112112
});
113113

114114
it('should include helpful error message with configuration instructions', async () => {

src/config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
export interface ServerConfig {
77
/**
88
* Read-only mode: when enabled, write operations (like create_deployment) are blocked
9-
* Default: true (read-only enabled by default for security)
9+
* Default: false (deployments allowed by default)
1010
*/
1111
readOnlyMode: boolean;
1212
}
@@ -68,7 +68,7 @@ function parseReadOnlyFlag(): boolean | undefined {
6868
* Precedence (highest to lowest):
6969
* 1. CLI flags (--read-only)
7070
* 2. Environment variables (DEPLOYHQ_READ_ONLY)
71-
* 3. Default values (read-only mode enabled by default)
71+
* 3. Default values (deployments allowed by default)
7272
*
7373
* @returns ServerConfig object with parsed configuration
7474
*/
@@ -86,8 +86,8 @@ export function parseServerConfig(): ServerConfig {
8686
return { readOnlyMode: envValue };
8787
}
8888

89-
// Default to read-only mode enabled (secure by default)
90-
return { readOnlyMode: true };
89+
// Default to read-only mode disabled (deployments allowed by default)
90+
return { readOnlyMode: false };
9191
}
9292

9393
/**

src/mcp-server.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function createMCPServer(
2929
username: string,
3030
password: string,
3131
account: string,
32-
config: ServerConfig = { readOnlyMode: true }
32+
config: ServerConfig = { readOnlyMode: false }
3333
): Server {
3434
// Create DeployHQ client with user credentials
3535
const client = new DeployHQClient({
@@ -127,10 +127,10 @@ export function createMCPServer(
127127
throw new Error(
128128
'FORBIDDEN: Server is running in read-only mode. ' +
129129
'Deployment creation is disabled for security.\n\n' +
130-
'To enable deployments:\n' +
130+
'To disable read-only mode:\n' +
131131
'- Set environment variable: DEPLOYHQ_READ_ONLY=false\n' +
132132
'- Or use CLI flag: --read-only=false\n\n' +
133-
'Read-only mode is enabled by default to prevent ' +
133+
'Read-only mode can be enabled to prevent ' +
134134
'accidental deployments when using AI assistants.'
135135
);
136136
}

0 commit comments

Comments
 (0)