@lexmata/bitbucket-mcp 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Lexmata LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,281 @@
1
+ # @lexmata/bitbucket-mcp
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@lexmata/bitbucket-mcp.svg)](https://www.npmjs.com/package/@lexmata/bitbucket-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
6
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/)
7
+ [![GitHub stars](https://img.shields.io/github/stars/lexmata/bitbucket-mcp.svg?style=social)](https://github.com/lexmata/bitbucket-mcp)
8
+
9
+ A Model Context Protocol (MCP) server for Bitbucket Cloud - 25+ tools for repositories, pull requests, branches, commits, issues, pipelines, and code search.
10
+
11
+ ## Features
12
+
13
+ - **Full Bitbucket Cloud API Coverage**: Access repositories, pull requests, branches, commits, issues, pipelines, and code search
14
+ - **OAuth 2.0 Authentication**: Secure authentication with automatic token refresh
15
+ - **MCP Tools**: 25+ tools for interacting with Bitbucket
16
+ - **MCP Resources**: Access repositories, pull requests, and files as resources
17
+ - **TypeScript**: Fully typed for reliability and developer experience
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ # Using npm
23
+ npm install -g @lexmata/bitbucket-mcp
24
+
25
+ # Using pnpm
26
+ pnpm add -g @lexmata/bitbucket-mcp
27
+
28
+ # Using yarn
29
+ yarn global add @lexmata/bitbucket-mcp
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ ### Option 1: Access Token (Recommended for personal use)
35
+
36
+ 1. Go to Bitbucket Settings > Personal Settings > App passwords
37
+ 2. Create a new app password with the required permissions:
38
+ - Account: Read
39
+ - Repositories: Read, Write, Admin
40
+ - Pull requests: Read, Write
41
+ - Issues: Read, Write
42
+ - Pipelines: Read, Write
43
+
44
+ 3. Set the environment variable:
45
+
46
+ ```bash
47
+ export BITBUCKET_ACCESS_TOKEN="your-app-password"
48
+ ```
49
+
50
+ ### Option 2: OAuth 2.0 (Recommended for applications)
51
+
52
+ 1. Go to Bitbucket Settings > Workspace Settings > OAuth consumers
53
+ 2. Create a new OAuth consumer with:
54
+ - Callback URL: `http://localhost:8080/callback` (or your callback URL)
55
+ - Permissions: Select required scopes
56
+
57
+ 3. Set the environment variables:
58
+
59
+ ```bash
60
+ export BITBUCKET_CLIENT_ID="your-client-id"
61
+ export BITBUCKET_CLIENT_SECRET="your-client-secret"
62
+ ```
63
+
64
+ ## Usage with Claude Desktop
65
+
66
+ Add the following to your Claude Desktop configuration file:
67
+
68
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
69
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
70
+ **Linux**: `~/.config/Claude/claude_desktop_config.json`
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "bitbucket": {
76
+ "command": "npx",
77
+ "args": ["@lexmata/bitbucket-mcp"],
78
+ "env": {
79
+ "BITBUCKET_ACCESS_TOKEN": "your-access-token"
80
+ }
81
+ }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Or if installed globally:
87
+
88
+ ```json
89
+ {
90
+ "mcpServers": {
91
+ "bitbucket": {
92
+ "command": "bitbucket-mcp",
93
+ "env": {
94
+ "BITBUCKET_ACCESS_TOKEN": "your-access-token"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Available Tools
102
+
103
+ ### Repository Management
104
+
105
+ | Tool | Description |
106
+ | ----------------------- | ------------------------------------ |
107
+ | `list_repositories` | List repositories in a workspace |
108
+ | `get_repository` | Get details of a specific repository |
109
+ | `create_repository` | Create a new repository |
110
+ | `delete_repository` | Delete a repository |
111
+ | `list_repository_forks` | List all forks of a repository |
112
+
113
+ ### Pull Requests
114
+
115
+ | Tool | Description |
116
+ | ---------------------- | ------------------------------------------ |
117
+ | `list_pull_requests` | List pull requests with optional filtering |
118
+ | `get_pull_request` | Get details of a specific pull request |
119
+ | `create_pull_request` | Create a new pull request |
120
+ | `update_pull_request` | Update a pull request |
121
+ | `merge_pull_request` | Merge a pull request |
122
+ | `decline_pull_request` | Decline a pull request |
123
+ | `approve_pull_request` | Approve a pull request |
124
+ | `request_changes` | Request changes on a pull request |
125
+ | `list_pr_comments` | List comments on a pull request |
126
+ | `add_pr_comment` | Add a comment to a pull request |
127
+ | `get_pr_diff` | Get the diff for a pull request |
128
+
129
+ ### Branches
130
+
131
+ | Tool | Description |
132
+ | --------------- | -------------------------------- |
133
+ | `list_branches` | List branches in a repository |
134
+ | `get_branch` | Get details of a specific branch |
135
+ | `create_branch` | Create a new branch |
136
+ | `delete_branch` | Delete a branch |
137
+
138
+ ### Commits
139
+
140
+ | Tool | Description |
141
+ | ----------------- | ------------------------------------ |
142
+ | `list_commits` | List commits with optional filtering |
143
+ | `get_commit` | Get details of a specific commit |
144
+ | `get_commit_diff` | Get the diff for a commit |
145
+
146
+ ### Issues
147
+
148
+ | Tool | Description |
149
+ | -------------- | ------------------------------- |
150
+ | `list_issues` | List issues in a repository |
151
+ | `get_issue` | Get details of a specific issue |
152
+ | `create_issue` | Create a new issue |
153
+ | `update_issue` | Update an issue |
154
+ | `delete_issue` | Delete an issue |
155
+
156
+ ### Pipelines
157
+
158
+ | Tool | Description |
159
+ | ------------------ | ----------------------------- |
160
+ | `list_pipelines` | List pipeline runs |
161
+ | `get_pipeline` | Get details of a pipeline run |
162
+ | `trigger_pipeline` | Trigger a new pipeline run |
163
+ | `stop_pipeline` | Stop a running pipeline |
164
+
165
+ ### Code Search
166
+
167
+ | Tool | Description |
168
+ | ------------- | ------------------------------- |
169
+ | `search_code` | Search code across repositories |
170
+
171
+ ### Files
172
+
173
+ | Tool | Description |
174
+ | ------------------ | ------------------------- |
175
+ | `get_file_content` | Get the content of a file |
176
+
177
+ ## Resources
178
+
179
+ The server provides the following resource types:
180
+
181
+ | Resource URI | Description |
182
+ | ------------------------------------------------- | ---------------------- |
183
+ | `bitbucket://repository/{workspace}/{repo}` | Repository information |
184
+ | `bitbucket://pullrequest/{workspace}/{repo}/{id}` | Pull request details |
185
+ | `bitbucket://file/{workspace}/{repo}/{path}` | File contents |
186
+
187
+ ## Examples
188
+
189
+ ### List repositories in a workspace
190
+
191
+ ```
192
+ Use the list_repositories tool with workspace "my-workspace"
193
+ ```
194
+
195
+ ### Create a pull request
196
+
197
+ ```
198
+ Use the create_pull_request tool with:
199
+ - workspace: "my-workspace"
200
+ - repo_slug: "my-repo"
201
+ - title: "Add new feature"
202
+ - source_branch: "feature/new-feature"
203
+ - destination_branch: "main"
204
+ - description: "This PR adds a new feature"
205
+ ```
206
+
207
+ ### Search for code
208
+
209
+ ```
210
+ Use the search_code tool with:
211
+ - workspace: "my-workspace"
212
+ - search_query: "function handleError"
213
+ ```
214
+
215
+ ### Trigger a pipeline
216
+
217
+ ```
218
+ Use the trigger_pipeline tool with:
219
+ - workspace: "my-workspace"
220
+ - repo_slug: "my-repo"
221
+ - ref_type: "branch"
222
+ - ref_name: "main"
223
+ ```
224
+
225
+ ## Development
226
+
227
+ ### Prerequisites
228
+
229
+ - Node.js 18+
230
+ - pnpm 9+
231
+
232
+ ### Setup
233
+
234
+ ```bash
235
+ # Clone the repository
236
+ git clone https://github.com/lexmata/bitbucket-mcp.git
237
+ cd bitbucket-mcp
238
+
239
+ # Install dependencies
240
+ pnpm install
241
+
242
+ # Build
243
+ pnpm build
244
+
245
+ # Run in development mode
246
+ pnpm dev
247
+ ```
248
+
249
+ ### Scripts
250
+
251
+ | Script | Description |
252
+ | ------------------- | ---------------------------- |
253
+ | `pnpm build` | Build the project with SWC |
254
+ | `pnpm dev` | Run in development mode |
255
+ | `pnpm start` | Run the built server |
256
+ | `pnpm typecheck` | Run TypeScript type checking |
257
+ | `pnpm lint` | Run ESLint |
258
+ | `pnpm lint:fix` | Fix ESLint issues |
259
+ | `pnpm format` | Format code with Prettier |
260
+ | `pnpm format:check` | Check code formatting |
261
+
262
+ ## License
263
+
264
+ MIT License - Copyright (c) 2025 Lexmata LLC
265
+
266
+ See [LICENSE](LICENSE) for details.
267
+
268
+ ## Contributing
269
+
270
+ Contributions are welcome! Please feel free to submit a Pull Request.
271
+
272
+ 1. Fork the repository
273
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
274
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
275
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
276
+ 5. Open a Pull Request
277
+
278
+ ## Support
279
+
280
+ - [Documentation](https://lexmata.github.io/bitbucket-mcp)
281
+ - [Issues](https://github.com/lexmata/bitbucket-mcp/issues)
@@ -0,0 +1,27 @@
1
+ export class BranchesAPI {
2
+ client;
3
+ constructor(client){
4
+ this.client = client;
5
+ }
6
+ async list(params) {
7
+ const { workspace, repo_slug, ...queryParams } = params;
8
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/refs/branches`, queryParams);
9
+ }
10
+ async get(workspace, repo_slug, branch_name) {
11
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/refs/branches/${encodeURIComponent(branch_name)}`);
12
+ }
13
+ async create(params) {
14
+ const { workspace, repo_slug, name, target } = params;
15
+ return this.client.post(`/repositories/${workspace}/${repo_slug}/refs/branches`, {
16
+ name,
17
+ target: {
18
+ hash: target
19
+ }
20
+ });
21
+ }
22
+ async delete(workspace, repo_slug, branch_name) {
23
+ await this.client.delete(`/repositories/${workspace}/${repo_slug}/refs/branches/${encodeURIComponent(branch_name)}`);
24
+ }
25
+ }
26
+
27
+ //# sourceMappingURL=branches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/branches.ts"],"sourcesContent":["import type { BitbucketClient } from './client.js';\nimport type {\n BitbucketBranch,\n PaginatedResponse,\n ListBranchesParams,\n CreateBranchParams,\n} from '../types/index.js';\n\nexport class BranchesAPI {\n constructor(private client: BitbucketClient) {}\n\n /**\n * List branches for a repository\n */\n async list(params: ListBranchesParams): Promise<PaginatedResponse<BitbucketBranch>> {\n const { workspace, repo_slug, ...queryParams } = params;\n return this.client.get<PaginatedResponse<BitbucketBranch>>(\n `/repositories/${workspace}/${repo_slug}/refs/branches`,\n queryParams as Record<string, string | number | undefined>\n );\n }\n\n /**\n * Get a specific branch\n */\n async get(workspace: string, repo_slug: string, branch_name: string): Promise<BitbucketBranch> {\n return this.client.get<BitbucketBranch>(\n `/repositories/${workspace}/${repo_slug}/refs/branches/${encodeURIComponent(branch_name)}`\n );\n }\n\n /**\n * Create a new branch\n */\n async create(params: CreateBranchParams): Promise<BitbucketBranch> {\n const { workspace, repo_slug, name, target } = params;\n return this.client.post<BitbucketBranch>(\n `/repositories/${workspace}/${repo_slug}/refs/branches`,\n {\n name,\n target: { hash: target },\n }\n );\n }\n\n /**\n * Delete a branch\n */\n async delete(workspace: string, repo_slug: string, branch_name: string): Promise<void> {\n await this.client.delete(\n `/repositories/${workspace}/${repo_slug}/refs/branches/${encodeURIComponent(branch_name)}`\n );\n }\n}\n"],"names":["BranchesAPI","client","list","params","workspace","repo_slug","queryParams","get","branch_name","encodeURIComponent","create","name","target","post","hash","delete"],"mappings":"AAQA,OAAO,MAAMA;;IACX,YAAY,AAAQC,MAAuB,CAAE;aAAzBA,SAAAA;IAA0B;IAK9C,MAAMC,KAAKC,MAA0B,EAA+C;QAClF,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,GAAGC,aAAa,GAAGH;QACjD,OAAO,IAAI,CAACF,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,cAAc,CAAC,EACvDC;IAEJ;IAKA,MAAMC,IAAIH,SAAiB,EAAEC,SAAiB,EAAEG,WAAmB,EAA4B;QAC7F,OAAO,IAAI,CAACP,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,eAAe,EAAEI,mBAAmBD,cAAc;IAE9F;IAKA,MAAME,OAAOP,MAA0B,EAA4B;QACjE,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAEM,IAAI,EAAEC,MAAM,EAAE,GAAGT;QAC/C,OAAO,IAAI,CAACF,MAAM,CAACY,IAAI,CACrB,CAAC,cAAc,EAAET,UAAU,CAAC,EAAEC,UAAU,cAAc,CAAC,EACvD;YACEM;YACAC,QAAQ;gBAAEE,MAAMF;YAAO;QACzB;IAEJ;IAKA,MAAMG,OAAOX,SAAiB,EAAEC,SAAiB,EAAEG,WAAmB,EAAiB;QACrF,MAAM,IAAI,CAACP,MAAM,CAACc,MAAM,CACtB,CAAC,cAAc,EAAEX,UAAU,CAAC,EAAEC,UAAU,eAAe,EAAEI,mBAAmBD,cAAc;IAE9F;AACF"}
@@ -0,0 +1,88 @@
1
+ const BITBUCKET_API_URL = 'https://api.bitbucket.org/2.0';
2
+ export class BitbucketClient {
3
+ oauth;
4
+ baseUrl;
5
+ constructor(oauth, baseUrl = BITBUCKET_API_URL){
6
+ this.oauth = oauth;
7
+ this.baseUrl = baseUrl;
8
+ }
9
+ async request(endpoint, options = {}) {
10
+ const token = await this.oauth.getAccessToken();
11
+ const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;
12
+ const response = await fetch(url, {
13
+ ...options,
14
+ headers: {
15
+ Authorization: `Bearer ${token}`,
16
+ 'Content-Type': 'application/json',
17
+ Accept: 'application/json',
18
+ ...options.headers
19
+ }
20
+ });
21
+ if (!response.ok) {
22
+ const errorBody = await response.text();
23
+ let errorMessage;
24
+ try {
25
+ const errorJson = JSON.parse(errorBody);
26
+ errorMessage = errorJson.error?.message ?? errorBody;
27
+ } catch {
28
+ errorMessage = errorBody;
29
+ }
30
+ throw new Error(`Bitbucket API error (${response.status}): ${errorMessage}`);
31
+ }
32
+ if (response.status === 204) {
33
+ return {};
34
+ }
35
+ return response.json();
36
+ }
37
+ async get(endpoint, params) {
38
+ let url = endpoint;
39
+ if (params) {
40
+ const searchParams = new URLSearchParams();
41
+ for (const [key, value] of Object.entries(params)){
42
+ if (value !== undefined) {
43
+ searchParams.set(key, String(value));
44
+ }
45
+ }
46
+ const queryString = searchParams.toString();
47
+ if (queryString) {
48
+ url = `${endpoint}?${queryString}`;
49
+ }
50
+ }
51
+ return this.request(url, {
52
+ method: 'GET'
53
+ });
54
+ }
55
+ async post(endpoint, body) {
56
+ return this.request(endpoint, {
57
+ method: 'POST',
58
+ body: body ? JSON.stringify(body) : undefined
59
+ });
60
+ }
61
+ async put(endpoint, body) {
62
+ return this.request(endpoint, {
63
+ method: 'PUT',
64
+ body: body ? JSON.stringify(body) : undefined
65
+ });
66
+ }
67
+ async delete(endpoint) {
68
+ return this.request(endpoint, {
69
+ method: 'DELETE'
70
+ });
71
+ }
72
+ async getRaw(endpoint) {
73
+ const token = await this.oauth.getAccessToken();
74
+ const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;
75
+ const response = await fetch(url, {
76
+ method: 'GET',
77
+ headers: {
78
+ Authorization: `Bearer ${token}`
79
+ }
80
+ });
81
+ if (!response.ok) {
82
+ throw new Error(`Bitbucket API error (${response.status}): ${await response.text()}`);
83
+ }
84
+ return response.text();
85
+ }
86
+ }
87
+
88
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/client.ts"],"sourcesContent":["import { BitbucketOAuth } from '../auth/oauth.js';\nimport type { BitbucketError } from '../types/index.js';\n\nconst BITBUCKET_API_URL = 'https://api.bitbucket.org/2.0';\n\nexport class BitbucketClient {\n private oauth: BitbucketOAuth;\n private baseUrl: string;\n\n constructor(oauth: BitbucketOAuth, baseUrl: string = BITBUCKET_API_URL) {\n this.oauth = oauth;\n this.baseUrl = baseUrl;\n }\n\n /**\n * Make an authenticated request to the Bitbucket API\n */\n async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const token = await this.oauth.getAccessToken();\n\n const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorBody) as BitbucketError;\n errorMessage = errorJson.error?.message ?? errorBody;\n } catch {\n errorMessage = errorBody;\n }\n\n throw new Error(`Bitbucket API error (${response.status}): ${errorMessage}`);\n }\n\n // Handle 204 No Content\n if (response.status === 204) {\n return {} as T;\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * GET request\n */\n async get<T>(endpoint: string, params?: Record<string, string | number | undefined>): Promise<T> {\n let url = endpoint;\n\n if (params) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n searchParams.set(key, String(value));\n }\n }\n const queryString = searchParams.toString();\n if (queryString) {\n url = `${endpoint}?${queryString}`;\n }\n }\n\n return this.request<T>(url, { method: 'GET' });\n }\n\n /**\n * POST request\n */\n async post<T>(endpoint: string, body?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * PUT request\n */\n async put<T>(endpoint: string, body?: unknown): Promise<T> {\n return this.request<T>(endpoint, {\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(endpoint: string): Promise<T> {\n return this.request<T>(endpoint, { method: 'DELETE' });\n }\n\n /**\n * Get raw file content\n */\n async getRaw(endpoint: string): Promise<string> {\n const token = await this.oauth.getAccessToken();\n const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Bitbucket API error (${response.status}): ${await response.text()}`);\n }\n\n return response.text();\n }\n}\n"],"names":["BITBUCKET_API_URL","BitbucketClient","oauth","baseUrl","request","endpoint","options","token","getAccessToken","url","startsWith","response","fetch","headers","Authorization","Accept","ok","errorBody","text","errorMessage","errorJson","JSON","parse","error","message","Error","status","json","get","params","searchParams","URLSearchParams","key","value","Object","entries","undefined","set","String","queryString","toString","method","post","body","stringify","put","delete","getRaw"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export class CommitsAPI {
2
+ client;
3
+ constructor(client){
4
+ this.client = client;
5
+ }
6
+ async list(params) {
7
+ const { workspace, repo_slug, branch, include, exclude, ...queryParams } = params;
8
+ const allParams = {
9
+ ...queryParams
10
+ };
11
+ if (branch) {
12
+ allParams.include = branch;
13
+ } else if (include) {
14
+ allParams.include = include;
15
+ }
16
+ if (exclude) {
17
+ allParams.exclude = exclude;
18
+ }
19
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/commits`, allParams);
20
+ }
21
+ async get(workspace, repo_slug, commit_hash) {
22
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/commit/${commit_hash}`);
23
+ }
24
+ async getDiff(workspace, repo_slug, commit_hash) {
25
+ return this.client.getRaw(`/repositories/${workspace}/${repo_slug}/diff/${commit_hash}`);
26
+ }
27
+ async listForPullRequest(workspace, repo_slug, pr_id, params) {
28
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pr_id}/commits`, params);
29
+ }
30
+ }
31
+
32
+ //# sourceMappingURL=commits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/commits.ts"],"sourcesContent":["import type { BitbucketClient } from './client.js';\nimport type { BitbucketCommit, PaginatedResponse, ListCommitsParams } from '../types/index.js';\n\nexport class CommitsAPI {\n constructor(private client: BitbucketClient) {}\n\n /**\n * List commits for a repository\n */\n async list(params: ListCommitsParams): Promise<PaginatedResponse<BitbucketCommit>> {\n const { workspace, repo_slug, branch, include, exclude, ...queryParams } = params;\n\n // Build query params\n const allParams: Record<string, string | number | undefined> = {\n ...queryParams,\n };\n\n // For branch filtering, use the include parameter\n if (branch) {\n allParams.include = branch;\n } else if (include) {\n allParams.include = include;\n }\n\n if (exclude) {\n allParams.exclude = exclude;\n }\n\n return this.client.get<PaginatedResponse<BitbucketCommit>>(\n `/repositories/${workspace}/${repo_slug}/commits`,\n allParams\n );\n }\n\n /**\n * Get a specific commit\n */\n async get(workspace: string, repo_slug: string, commit_hash: string): Promise<BitbucketCommit> {\n return this.client.get<BitbucketCommit>(\n `/repositories/${workspace}/${repo_slug}/commit/${commit_hash}`\n );\n }\n\n /**\n * Get diff for a specific commit\n */\n async getDiff(workspace: string, repo_slug: string, commit_hash: string): Promise<string> {\n return this.client.getRaw(`/repositories/${workspace}/${repo_slug}/diff/${commit_hash}`);\n }\n\n /**\n * Get commits for a pull request\n */\n async listForPullRequest(\n workspace: string,\n repo_slug: string,\n pr_id: number,\n params?: { page?: number; pagelen?: number }\n ): Promise<PaginatedResponse<BitbucketCommit>> {\n return this.client.get<PaginatedResponse<BitbucketCommit>>(\n `/repositories/${workspace}/${repo_slug}/pullrequests/${pr_id}/commits`,\n params as Record<string, string | number | undefined>\n );\n }\n}\n"],"names":["CommitsAPI","client","list","params","workspace","repo_slug","branch","include","exclude","queryParams","allParams","get","commit_hash","getDiff","getRaw","listForPullRequest","pr_id"],"mappings":"AAGA,OAAO,MAAMA;;IACX,YAAY,AAAQC,MAAuB,CAAE;aAAzBA,SAAAA;IAA0B;IAK9C,MAAMC,KAAKC,MAAyB,EAA+C;QACjF,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAEC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGC,aAAa,GAAGN;QAG3E,MAAMO,YAAyD;YAC7D,GAAGD,WAAW;QAChB;QAGA,IAAIH,QAAQ;YACVI,UAAUH,OAAO,GAAGD;QACtB,OAAO,IAAIC,SAAS;YAClBG,UAAUH,OAAO,GAAGA;QACtB;QAEA,IAAIC,SAAS;YACXE,UAAUF,OAAO,GAAGA;QACtB;QAEA,OAAO,IAAI,CAACP,MAAM,CAACU,GAAG,CACpB,CAAC,cAAc,EAAEP,UAAU,CAAC,EAAEC,UAAU,QAAQ,CAAC,EACjDK;IAEJ;IAKA,MAAMC,IAAIP,SAAiB,EAAEC,SAAiB,EAAEO,WAAmB,EAA4B;QAC7F,OAAO,IAAI,CAACX,MAAM,CAACU,GAAG,CACpB,CAAC,cAAc,EAAEP,UAAU,CAAC,EAAEC,UAAU,QAAQ,EAAEO,aAAa;IAEnE;IAKA,MAAMC,QAAQT,SAAiB,EAAEC,SAAiB,EAAEO,WAAmB,EAAmB;QACxF,OAAO,IAAI,CAACX,MAAM,CAACa,MAAM,CAAC,CAAC,cAAc,EAAEV,UAAU,CAAC,EAAEC,UAAU,MAAM,EAAEO,aAAa;IACzF;IAKA,MAAMG,mBACJX,SAAiB,EACjBC,SAAiB,EACjBW,KAAa,EACbb,MAA4C,EACC;QAC7C,OAAO,IAAI,CAACF,MAAM,CAACU,GAAG,CACpB,CAAC,cAAc,EAAEP,UAAU,CAAC,EAAEC,UAAU,cAAc,EAAEW,MAAM,QAAQ,CAAC,EACvEb;IAEJ;AACF"}
@@ -0,0 +1,51 @@
1
+ export class IssuesAPI {
2
+ client;
3
+ constructor(client){
4
+ this.client = client;
5
+ }
6
+ async list(params) {
7
+ const { workspace, repo_slug, ...queryParams } = params;
8
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/issues`, queryParams);
9
+ }
10
+ async get(workspace, repo_slug, issue_id) {
11
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/issues/${issue_id}`);
12
+ }
13
+ async create(params) {
14
+ const { workspace, repo_slug, title, content, kind, priority, assignee } = params;
15
+ const body = {
16
+ title
17
+ };
18
+ if (content) {
19
+ body.content = {
20
+ raw: content
21
+ };
22
+ }
23
+ if (kind) body.kind = kind;
24
+ if (priority) body.priority = priority;
25
+ if (assignee) {
26
+ body.assignee = {
27
+ uuid: assignee
28
+ };
29
+ }
30
+ return this.client.post(`/repositories/${workspace}/${repo_slug}/issues`, body);
31
+ }
32
+ async update(workspace, repo_slug, issue_id, updates) {
33
+ const body = {};
34
+ if (updates.title) body.title = updates.title;
35
+ if (updates.content) body.content = {
36
+ raw: updates.content
37
+ };
38
+ if (updates.state) body.state = updates.state;
39
+ if (updates.kind) body.kind = updates.kind;
40
+ if (updates.priority) body.priority = updates.priority;
41
+ if (updates.assignee) body.assignee = {
42
+ uuid: updates.assignee
43
+ };
44
+ return this.client.put(`/repositories/${workspace}/${repo_slug}/issues/${issue_id}`, body);
45
+ }
46
+ async delete(workspace, repo_slug, issue_id) {
47
+ await this.client.delete(`/repositories/${workspace}/${repo_slug}/issues/${issue_id}`);
48
+ }
49
+ }
50
+
51
+ //# sourceMappingURL=issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/issues.ts"],"sourcesContent":["import type { BitbucketClient } from './client.js';\nimport type {\n BitbucketIssue,\n PaginatedResponse,\n ListIssuesParams,\n CreateIssueParams,\n} from '../types/index.js';\n\nexport class IssuesAPI {\n constructor(private client: BitbucketClient) {}\n\n /**\n * List issues for a repository\n */\n async list(params: ListIssuesParams): Promise<PaginatedResponse<BitbucketIssue>> {\n const { workspace, repo_slug, ...queryParams } = params;\n return this.client.get<PaginatedResponse<BitbucketIssue>>(\n `/repositories/${workspace}/${repo_slug}/issues`,\n queryParams as Record<string, string | number | undefined>\n );\n }\n\n /**\n * Get a specific issue\n */\n async get(workspace: string, repo_slug: string, issue_id: number): Promise<BitbucketIssue> {\n return this.client.get<BitbucketIssue>(\n `/repositories/${workspace}/${repo_slug}/issues/${issue_id}`\n );\n }\n\n /**\n * Create a new issue\n */\n async create(params: CreateIssueParams): Promise<BitbucketIssue> {\n const { workspace, repo_slug, title, content, kind, priority, assignee } = params;\n\n const body: Record<string, unknown> = {\n title,\n };\n\n if (content) {\n body.content = { raw: content };\n }\n\n if (kind) body.kind = kind;\n if (priority) body.priority = priority;\n if (assignee) {\n body.assignee = { uuid: assignee };\n }\n\n return this.client.post<BitbucketIssue>(`/repositories/${workspace}/${repo_slug}/issues`, body);\n }\n\n /**\n * Update an issue\n */\n async update(\n workspace: string,\n repo_slug: string,\n issue_id: number,\n updates: {\n title?: string;\n content?: string;\n state?: BitbucketIssue['state'];\n kind?: BitbucketIssue['kind'];\n priority?: BitbucketIssue['priority'];\n assignee?: string;\n }\n ): Promise<BitbucketIssue> {\n const body: Record<string, unknown> = {};\n\n if (updates.title) body.title = updates.title;\n if (updates.content) body.content = { raw: updates.content };\n if (updates.state) body.state = updates.state;\n if (updates.kind) body.kind = updates.kind;\n if (updates.priority) body.priority = updates.priority;\n if (updates.assignee) body.assignee = { uuid: updates.assignee };\n\n return this.client.put<BitbucketIssue>(\n `/repositories/${workspace}/${repo_slug}/issues/${issue_id}`,\n body\n );\n }\n\n /**\n * Delete an issue\n */\n async delete(workspace: string, repo_slug: string, issue_id: number): Promise<void> {\n await this.client.delete(`/repositories/${workspace}/${repo_slug}/issues/${issue_id}`);\n }\n}\n"],"names":["IssuesAPI","client","list","params","workspace","repo_slug","queryParams","get","issue_id","create","title","content","kind","priority","assignee","body","raw","uuid","post","update","updates","state","put","delete"],"mappings":"AAQA,OAAO,MAAMA;;IACX,YAAY,AAAQC,MAAuB,CAAE;aAAzBA,SAAAA;IAA0B;IAK9C,MAAMC,KAAKC,MAAwB,EAA8C;QAC/E,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,GAAGC,aAAa,GAAGH;QACjD,OAAO,IAAI,CAACF,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,OAAO,CAAC,EAChDC;IAEJ;IAKA,MAAMC,IAAIH,SAAiB,EAAEC,SAAiB,EAAEG,QAAgB,EAA2B;QACzF,OAAO,IAAI,CAACP,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,QAAQ,EAAEG,UAAU;IAEhE;IAKA,MAAMC,OAAON,MAAyB,EAA2B;QAC/D,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAEK,KAAK,EAAEC,OAAO,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAGX;QAE3E,MAAMY,OAAgC;YACpCL;QACF;QAEA,IAAIC,SAAS;YACXI,KAAKJ,OAAO,GAAG;gBAAEK,KAAKL;YAAQ;QAChC;QAEA,IAAIC,MAAMG,KAAKH,IAAI,GAAGA;QACtB,IAAIC,UAAUE,KAAKF,QAAQ,GAAGA;QAC9B,IAAIC,UAAU;YACZC,KAAKD,QAAQ,GAAG;gBAAEG,MAAMH;YAAS;QACnC;QAEA,OAAO,IAAI,CAACb,MAAM,CAACiB,IAAI,CAAiB,CAAC,cAAc,EAAEd,UAAU,CAAC,EAAEC,UAAU,OAAO,CAAC,EAAEU;IAC5F;IAKA,MAAMI,OACJf,SAAiB,EACjBC,SAAiB,EACjBG,QAAgB,EAChBY,OAOC,EACwB;QACzB,MAAML,OAAgC,CAAC;QAEvC,IAAIK,QAAQV,KAAK,EAAEK,KAAKL,KAAK,GAAGU,QAAQV,KAAK;QAC7C,IAAIU,QAAQT,OAAO,EAAEI,KAAKJ,OAAO,GAAG;YAAEK,KAAKI,QAAQT,OAAO;QAAC;QAC3D,IAAIS,QAAQC,KAAK,EAAEN,KAAKM,KAAK,GAAGD,QAAQC,KAAK;QAC7C,IAAID,QAAQR,IAAI,EAAEG,KAAKH,IAAI,GAAGQ,QAAQR,IAAI;QAC1C,IAAIQ,QAAQP,QAAQ,EAAEE,KAAKF,QAAQ,GAAGO,QAAQP,QAAQ;QACtD,IAAIO,QAAQN,QAAQ,EAAEC,KAAKD,QAAQ,GAAG;YAAEG,MAAMG,QAAQN,QAAQ;QAAC;QAE/D,OAAO,IAAI,CAACb,MAAM,CAACqB,GAAG,CACpB,CAAC,cAAc,EAAElB,UAAU,CAAC,EAAEC,UAAU,QAAQ,EAAEG,UAAU,EAC5DO;IAEJ;IAKA,MAAMQ,OAAOnB,SAAiB,EAAEC,SAAiB,EAAEG,QAAgB,EAAiB;QAClF,MAAM,IAAI,CAACP,MAAM,CAACsB,MAAM,CAAC,CAAC,cAAc,EAAEnB,UAAU,CAAC,EAAEC,UAAU,QAAQ,EAAEG,UAAU;IACvF;AACF"}
@@ -0,0 +1,34 @@
1
+ export class PipelinesAPI {
2
+ client;
3
+ constructor(client){
4
+ this.client = client;
5
+ }
6
+ async list(params) {
7
+ const { workspace, repo_slug, ...queryParams } = params;
8
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/pipelines`, queryParams);
9
+ }
10
+ async get(workspace, repo_slug, pipeline_uuid) {
11
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}`);
12
+ }
13
+ async trigger(params) {
14
+ const { workspace, repo_slug, target, variables } = params;
15
+ const body = {
16
+ target
17
+ };
18
+ if (variables && variables.length > 0) {
19
+ body.variables = variables;
20
+ }
21
+ return this.client.post(`/repositories/${workspace}/${repo_slug}/pipelines`, body);
22
+ }
23
+ async stop(workspace, repo_slug, pipeline_uuid) {
24
+ await this.client.post(`/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/stopPipeline`);
25
+ }
26
+ async getSteps(workspace, repo_slug, pipeline_uuid) {
27
+ return this.client.get(`/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/steps`);
28
+ }
29
+ async getStepLog(workspace, repo_slug, pipeline_uuid, step_uuid) {
30
+ return this.client.getRaw(`/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/steps/${step_uuid}/log`);
31
+ }
32
+ }
33
+
34
+ //# sourceMappingURL=pipelines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/pipelines.ts"],"sourcesContent":["import type { BitbucketClient } from './client.js';\nimport type {\n BitbucketPipeline,\n PaginatedResponse,\n ListPipelinesParams,\n TriggerPipelineParams,\n} from '../types/index.js';\n\nexport class PipelinesAPI {\n constructor(private client: BitbucketClient) {}\n\n /**\n * List pipelines for a repository\n */\n async list(params: ListPipelinesParams): Promise<PaginatedResponse<BitbucketPipeline>> {\n const { workspace, repo_slug, ...queryParams } = params;\n return this.client.get<PaginatedResponse<BitbucketPipeline>>(\n `/repositories/${workspace}/${repo_slug}/pipelines`,\n queryParams as Record<string, string | number | undefined>\n );\n }\n\n /**\n * Get a specific pipeline\n */\n async get(\n workspace: string,\n repo_slug: string,\n pipeline_uuid: string\n ): Promise<BitbucketPipeline> {\n return this.client.get<BitbucketPipeline>(\n `/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}`\n );\n }\n\n /**\n * Trigger a new pipeline\n */\n async trigger(params: TriggerPipelineParams): Promise<BitbucketPipeline> {\n const { workspace, repo_slug, target, variables } = params;\n\n const body: Record<string, unknown> = {\n target,\n };\n\n if (variables && variables.length > 0) {\n body.variables = variables;\n }\n\n return this.client.post<BitbucketPipeline>(\n `/repositories/${workspace}/${repo_slug}/pipelines`,\n body\n );\n }\n\n /**\n * Stop a running pipeline\n */\n async stop(workspace: string, repo_slug: string, pipeline_uuid: string): Promise<void> {\n await this.client.post(\n `/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/stopPipeline`\n );\n }\n\n /**\n * Get pipeline steps\n */\n async getSteps(\n workspace: string,\n repo_slug: string,\n pipeline_uuid: string\n ): Promise<\n PaginatedResponse<{\n uuid: string;\n name: string;\n state: {\n name: string;\n type: string;\n result?: { name: string };\n };\n started_on?: string;\n completed_on?: string;\n duration_in_seconds?: number;\n }>\n > {\n return this.client.get(\n `/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/steps`\n );\n }\n\n /**\n * Get pipeline step log\n */\n async getStepLog(\n workspace: string,\n repo_slug: string,\n pipeline_uuid: string,\n step_uuid: string\n ): Promise<string> {\n return this.client.getRaw(\n `/repositories/${workspace}/${repo_slug}/pipelines/${pipeline_uuid}/steps/${step_uuid}/log`\n );\n }\n}\n"],"names":["PipelinesAPI","client","list","params","workspace","repo_slug","queryParams","get","pipeline_uuid","trigger","target","variables","body","length","post","stop","getSteps","getStepLog","step_uuid","getRaw"],"mappings":"AAQA,OAAO,MAAMA;;IACX,YAAY,AAAQC,MAAuB,CAAE;aAAzBA,SAAAA;IAA0B;IAK9C,MAAMC,KAAKC,MAA2B,EAAiD;QACrF,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,GAAGC,aAAa,GAAGH;QACjD,OAAO,IAAI,CAACF,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,UAAU,CAAC,EACnDC;IAEJ;IAKA,MAAMC,IACJH,SAAiB,EACjBC,SAAiB,EACjBG,aAAqB,EACO;QAC5B,OAAO,IAAI,CAACP,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,WAAW,EAAEG,eAAe;IAExE;IAKA,MAAMC,QAAQN,MAA6B,EAA8B;QACvE,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAEK,MAAM,EAAEC,SAAS,EAAE,GAAGR;QAEpD,MAAMS,OAAgC;YACpCF;QACF;QAEA,IAAIC,aAAaA,UAAUE,MAAM,GAAG,GAAG;YACrCD,KAAKD,SAAS,GAAGA;QACnB;QAEA,OAAO,IAAI,CAACV,MAAM,CAACa,IAAI,CACrB,CAAC,cAAc,EAAEV,UAAU,CAAC,EAAEC,UAAU,UAAU,CAAC,EACnDO;IAEJ;IAKA,MAAMG,KAAKX,SAAiB,EAAEC,SAAiB,EAAEG,aAAqB,EAAiB;QACrF,MAAM,IAAI,CAACP,MAAM,CAACa,IAAI,CACpB,CAAC,cAAc,EAAEV,UAAU,CAAC,EAAEC,UAAU,WAAW,EAAEG,cAAc,aAAa,CAAC;IAErF;IAKA,MAAMQ,SACJZ,SAAiB,EACjBC,SAAiB,EACjBG,aAAqB,EAcrB;QACA,OAAO,IAAI,CAACP,MAAM,CAACM,GAAG,CACpB,CAAC,cAAc,EAAEH,UAAU,CAAC,EAAEC,UAAU,WAAW,EAAEG,cAAc,MAAM,CAAC;IAE9E;IAKA,MAAMS,WACJb,SAAiB,EACjBC,SAAiB,EACjBG,aAAqB,EACrBU,SAAiB,EACA;QACjB,OAAO,IAAI,CAACjB,MAAM,CAACkB,MAAM,CACvB,CAAC,cAAc,EAAEf,UAAU,CAAC,EAAEC,UAAU,WAAW,EAAEG,cAAc,OAAO,EAAEU,UAAU,IAAI,CAAC;IAE/F;AACF"}