@stubbedev/atlassian-mcp 0.5.16 → 0.5.18

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.
Files changed (2) hide show
  1. package/README.md +82 -3
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -28,7 +28,7 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for **s
28
28
  |---|---|
29
29
  | `jira_search` | Discover resources: `issues`, `projects`, `issue_types`, `boards`, `sprints`, `board_overview`, `versions`, `components`, `fields`, or `users` via `resource` param |
30
30
  | `jira_get` | Full details for one issue: summary, description, status, sprint, transitions, comments, and attachment list |
31
- | `jira_mutate` | Create, update, transition, comment (`commentAction`: `add` / `update` / `delete`), upload local files as attachments, link, add to sprint, log work, change issue type, set any custom field by name (`create.customFields` / `update.customFields`), or manage a fix version (`version.action`: `create` / `update` / `release` / `archive` / `delete`) — several in one call. Markdown in any text field is converted to Jira wiki markup |
31
+ | `jira_mutate` | Create, update, transition, comment (`commentAction`: `add` / `update` / `delete`), upload attachments from a local path, URL, or `data:` URI, link, add to sprint, log work, change issue type, set any custom field by name (`create.customFields` / `update.customFields`), or manage a fix version (`version.action`: `create` / `update` / `release` / `archive` / `delete`) — several in one call. Markdown in any text field is converted to Jira wiki markup |
32
32
 
33
33
  ### Bitbucket
34
34
 
@@ -36,8 +36,8 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for **s
36
36
  |---|---|
37
37
  | `bitbucket_search` | Discover resources: `pull_requests` (default), `repos`, `branches`, or `users` via `resource` param; `mine=true` for your inbox, narrowed with `role=author` / `reviewer` / `participant` |
38
38
  | `bitbucket_get_pr` | Full PR details: metadata, commits, comments, blockers, build status, optional diff, and any attachments referenced from the description or comments |
39
- | `bitbucket_mutate` | Create/update a PR, or perform lifecycle actions: `approve`, `unapprove`, `needs_work`, `merge`, `decline`. Reviewer names are verified against Bitbucket, and an update that would drop existing reviewers needs `update.replaceReviewers=true`. `create.attachments` / `update.attachments` upload local files (screenshots, logs) to the repo and reference them from the description |
40
- | `bitbucket_comment` | Add, update, or delete a PR comment; for code changes use `suggestion` so Bitbucket shows Apply suggestion. Enforced here: one reply per thread, no new top-level comment on your own PR (`asAuthor=true` to override), `#123` references rewritten as links. `pending=true` posts an unpublished draft-review comment. `attachments` uploads local files and references them from the comment |
39
+ | `bitbucket_mutate` | Create/update a PR, or perform lifecycle actions: `approve`, `unapprove`, `needs_work`, `merge`, `decline`. Reviewer names are verified against Bitbucket, and an update that would drop existing reviewers needs `update.replaceReviewers=true`. `create.attachments` / `update.attachments` upload files (local path, URL, or `data:` URI) to the repo and reference them from the description |
40
+ | `bitbucket_comment` | Add, update, or delete a PR comment; for code changes use `suggestion` so Bitbucket shows Apply suggestion. Enforced here: one reply per thread, no new top-level comment on your own PR (`asAuthor=true` to override), `#123` references rewritten as links. `pending=true` posts an unpublished draft-review comment. `attachments` uploads files (local path, URL, or `data:` URI) and references them from the comment |
41
41
  | `bitbucket_get_file` | Raw file content at a branch, tag, or commit — or pass `prId` to read the PR source branch. Every response names the path and ref it came from, and pages via `maxChars`/`charOffset` |
42
42
  | `bitbucket_pr_tasks` | Manage PR tasks (checklist items): `list`, `create`, `resolve`, `reopen`, `delete` |
43
43
 
@@ -46,6 +46,7 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for **s
46
46
  | Tool | Description |
47
47
  |---|---|
48
48
  | `get_attachment` | Fetch an attachment by ID from Jira (`source=jira`, IDs from `jira_get`) or Bitbucket (`source=bitbucket`, IDs from `bitbucket_get_pr`). Images, videos, animated images (GIF/APNG/animated WebP), audio, and PDFs are decoded inline so the model can see/hear them; text/JSON inline. Oversized or non-renderable attachments are auto-saved to a temp file and the path is returned. `saveTo=/absolute/path` streams the original to disk |
49
+ | `attach_files` | Open an upload panel in the chat so the user can pick, drag or **paste** files onto a Jira issue or Bitbucket PR. The panel runs in the host (MCP Apps) and uploads directly, so it works where this server cannot read the filesystem — notably sandboxed Claude Desktop extensions. Degrades to a text answer on hosts without MCP Apps |
49
50
 
50
51
  ### Resources
51
52
 
@@ -528,6 +529,84 @@ Client config for an already-running HTTP server (Claude Code example):
528
529
  claude mcp add --transport http atlassian http://127.0.0.1:7337/mcp
529
530
  ```
530
531
 
532
+ ### Attachment upload sources
533
+
534
+ Every `attachments` argument — `jira_mutate`, `bitbucket_mutate` (`create`/`update`) and
535
+ `bitbucket_comment` — takes *sources*, not only paths. Each entry is one of:
536
+
537
+ | Source | Example | Notes |
538
+ | --- | --- | --- |
539
+ | Local file path | `/tmp/shot.png`, `file:///tmp/shot.png` | Requires the server to share a filesystem with the file |
540
+ | `http(s)` URL | `https://example.com/diagram.png` | Downloaded by the server. Filename comes from `Content-Disposition`, else the URL's last path segment, with an extension filled in from `Content-Type` |
541
+ | `data:` URI | `data:text/plain;name=run.log;base64,Ym9vbQ==` | Bytes inlined in the argument. `;name=` titles the file; without it the name is derived from the media type |
542
+
543
+ A URL whose host matches the configured Jira or Bitbucket instance is fetched **with your token**,
544
+ so an attachment that already lives on one service can be re-attached to the other by URL. Tokens
545
+ are never sent to any other host. Downloads are capped at 250 MB.
546
+
547
+ For Bitbucket, a source that already appears in the description or comment text is replaced in place
548
+ by the attachment markup — that works for URLs too, so writing `![the widget](https://…/shot.png)`
549
+ and passing the same URL in `attachments` keeps your caption and swaps in the uploaded file.
550
+
551
+ **Confined hosts.** A host may run this server sandboxed, in which case a path it was not granted
552
+ comes back as a permission error while URL and `data:` sources keep working — neither needs the
553
+ filesystem. The startup log names the config file it read, or the error it got trying, which is the
554
+ quickest way to tell whether the filesystem is restricted on your setup. The same applies to
555
+ chaining with another MCP server: a screenshot another server wrote to *its* temp directory is only
556
+ reachable here if this process is allowed to read that path.
557
+
558
+ > Files a user attaches to the chat itself cannot be uploaded from these arguments: MCP has no
559
+ > mechanism for passing conversation attachments to a server, and the model cannot re-emit image
560
+ > bytes it was shown. Use [`attach_files`](#the-upload-panel-mcp-apps) — the user re-picks or pastes
561
+ > the file into a panel that uploads it directly — or give this server a URL or a readable path.
562
+
563
+ ### The upload panel (MCP Apps)
564
+
565
+ `attach_files` opens a file picker **inside the chat**. It exists for the file that has no
566
+ path to pass:
567
+
568
+ - a screenshot the user pasted or dragged into the conversation is not on disk anywhere
569
+ this server could look, and MCP has no client-to-server file transfer to carry it — the
570
+ model cannot re-emit bytes it was shown.
571
+ [SEP-2631](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/2631)
572
+ would add one; it is still a draft;
573
+ - and a local path only works if the server is both on the same machine *and* permitted to
574
+ read it, which a host that confines the server may not allow.
575
+
576
+ Where a readable path or a URL does exist, the `attachments` arguments remain the better
577
+ route — no user interaction at all.
578
+
579
+ [MCP Apps](https://github.com/modelcontextprotocol/ext-apps) routes around both. The tool
580
+ declares a `ui://` resource, the host renders it as an iframe, and that iframe is an
581
+ ordinary browser: its file picker, drop target and paste handler sit outside the server's
582
+ sandbox. It hands the bytes back as `data:` URIs through `tools/call`, which is the same
583
+ source format the `attachments` arguments take.
584
+
585
+ ```
586
+ attach_files { issueKey: "KON-123" } → panel renders in the chat
587
+ user picks / drops / pastes → FileReader
588
+ panel calls attach_files { files: [...] } → data: URI → upload
589
+ ```
590
+
591
+ The model passes only the target (`issueKey`, or `prId` with an optional `commentId`); it
592
+ never fills in `files` and never sees the file contents. Files are capped at 12 MB each,
593
+ since the bytes ride the JSON-RPC channel as base64 — anything larger should go up by URL.
594
+
595
+ Support is negotiated: hosts advertise MCP Apps through the `io.modelcontextprotocol/ui`
596
+ extension at `initialize`. Where it is absent — **Claude Code today** — the whole surface is
597
+ hidden rather than merely degraded: `attach_files` is filtered out of `tools/list`, the
598
+ widget is filtered out of `resources/list`, and reading it is refused (a client that fetched
599
+ it anyway would take a few hundred KB of inlined SDK into its context for a page it cannot
600
+ draw). Such a host sees exactly the tools it saw before, and is told to ask for a path or
601
+ URL instead.
602
+
603
+ The panel is one self-contained HTML document (`ui/upload.html`, ~19 KB), because the host
604
+ serves it under `default-src 'none'`: no CDN, no second resource, no build step. It carries
605
+ its own ~2 KB MCP Apps bridge rather than the official browser SDK — a view only needs one
606
+ `ui/initialize` round trip, an `initialized` notification, `tool-input` notifications in and
607
+ `tools/call` requests out, and the SDK brings ~400 KB of zod to validate messages this page
608
+ already treats as untrusted. Bundling it with esbuild makes it larger, not smaller.
609
+
531
610
  ### Attachment decoding pipeline
532
611
 
533
612
  The `get_attachment` tool decodes binary attachments into model-readable content before returning them:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stubbedev/atlassian-mcp",
3
- "version": "0.5.16",
3
+ "version": "0.5.18",
4
4
  "description": "MCP server for self-hosted Jira and Bitbucket (Go, distributed as a prebuilt binary)",
5
5
  "license": "MIT",
6
6
  "type": "module",