Skip to content

Commit 1010642

Browse files
authored
Merge pull request #13 from timelfrink/feature/read-only-mode
2 parents e65e499 + bf13631 commit 1010642

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ The server requires configuration in the VSCode MCP settings file. Here's a samp
393393
- `BITBUCKET_TOKEN`: Personal access token
394394
- `BITBUCKET_USERNAME` and `BITBUCKET_PASSWORD`: Basic authentication credentials
395395
- `BITBUCKET_DEFAULT_PROJECT` (optional): Default project key to use when not specified in tool calls
396+
- `BITBUCKET_READ_ONLY` (optional): Set to `true` to enable read-only mode
396397

397398
**Note**: With the new optional project support, you can now:
398399

@@ -401,6 +402,35 @@ The server requires configuration in the VSCode MCP settings file. Here's a samp
401402
- Use `list_repositories` to browse repositories across projects
402403
- Override the default project by specifying the `project` parameter in any tool call
403404

405+
### Read-Only Mode
406+
407+
The server supports a read-only mode for deployments where you want to prevent any modifications to your Bitbucket repositories. When enabled, only safe, non-modifying operations are available.
408+
409+
**To enable read-only mode**: Set the environment variable `BITBUCKET_READ_ONLY=true`
410+
411+
**Available tools in read-only mode:**
412+
- `list_projects` - Browse and list projects
413+
- `list_repositories` - Browse and list repositories
414+
- `get_pull_request` - View pull request details
415+
- `get_diff` - View code changes and diffs
416+
- `get_reviews` - View review history and status
417+
- `get_activities` - View pull request timeline
418+
- `get_comments` - View pull request comments
419+
- `search` - Search code and files across repositories
420+
- `get_file_content` - Read file contents
421+
- `browse_repository` - Browse repository structure
422+
423+
**Disabled tools in read-only mode:**
424+
- `create_pull_request` - Creating new pull requests
425+
- `merge_pull_request` - Merging pull requests
426+
- `decline_pull_request` - Declining pull requests
427+
- `add_comment` - Adding comments to pull requests
428+
429+
**Behavior:**
430+
- When `BITBUCKET_READ_ONLY` is not set or set to any value other than `true`, all tools function normally (backward compatible)
431+
- When `BITBUCKET_READ_ONLY=true`, write operations are filtered out and will return an error if called
432+
- This is perfect for production deployments, CI/CD integration, or any scenario where you need safe, read-only Bitbucket access
433+
404434
## Logging
405435

406436
The server logs all operations to `bitbucket.log` using Winston for debugging and monitoring purposes.

src/index.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ interface BitbucketConfig {
3030
username?: string;
3131
password?: string;
3232
defaultProject?: string;
33+
readOnly?: boolean;
3334
}
3435

3536
interface RepositoryParams {
@@ -106,7 +107,8 @@ class BitbucketServer {
106107
token: process.env.BITBUCKET_TOKEN,
107108
username: process.env.BITBUCKET_USERNAME,
108109
password: process.env.BITBUCKET_PASSWORD,
109-
defaultProject: process.env.BITBUCKET_DEFAULT_PROJECT
110+
defaultProject: process.env.BITBUCKET_DEFAULT_PROJECT,
111+
readOnly: process.env.BITBUCKET_READ_ONLY === 'true'
110112
};
111113

112114
if (!this.config.baseUrl) {
@@ -147,6 +149,8 @@ class BitbucketServer {
147149
}
148150

149151
private setupToolHandlers() {
152+
const readOnlyTools = ['list_projects', 'list_repositories', 'get_pull_request', 'get_diff', 'get_reviews', 'get_activities', 'get_comments', 'search', 'get_file_content', 'browse_repository'];
153+
150154
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
151155
tools: [
152156
{
@@ -358,14 +362,22 @@ class BitbucketServer {
358362
required: ['repository']
359363
}
360364
}
361-
]
365+
].filter(tool => !this.config.readOnly || readOnlyTools.includes(tool.name))
362366
}));
363367

364368
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
365369
try {
366370
logger.info(`Called tool: ${request.params.name}`, { arguments: request.params.arguments });
367371
const args = request.params.arguments ?? {};
368372

373+
// Check if tool is allowed in read-only mode
374+
if (this.config.readOnly && !readOnlyTools.includes(request.params.name)) {
375+
throw new McpError(
376+
ErrorCode.MethodNotFound,
377+
`Tool ${request.params.name} is not available in read-only mode`
378+
);
379+
}
380+
369381
// Helper function to get project with fallback to default
370382
const getProject = (providedProject?: string): string => {
371383
const project = providedProject || this.config.defaultProject;

0 commit comments

Comments
 (0)