Skip to content

feat(mcp): serve pull requests, diffs, files and commits as resources, with prompts and completions - #693

Merged
vriesdemichael merged 6 commits into
nextfrom
cc/mcp-resources-685
Sep 27, 2026
Merged

vriesdemichael merged 6 commits into
nextfrom
cc/mcp-resources-685

Conversation

@vriesdemichael

Copy link
Copy Markdown
Owner

Implements #685: bb's MCP server serves Bitbucket content as resources, with prompts and completions, so the person can hand a pull request, a diff or a file to the model from a picker.

What changes

  • Resource templates under bitbucket://projects/{project}/repos/{repo}/:

    • a pull request, its diff and its open threads;
    • a file at a ref (files/{+path}{?at});
    • a commit.

    bb reads them with its own credentials, so the client never contacts Bitbucket. Each answers with what its tool answers, through the same function, bounded as ADR-094 asks: the diff is capped at 128 KiB and the threads at 100.

  • Served with their tools. A template is served while the tool it answers like is exposed, a prompt while every tool it embeds is, and the list while list_pull_requests and get_pull_request are. --tools and --exclude therefore decide them too, and capabilities follow what is served.

  • resources/list holds your open pull requests and those waiting on your review, 25 of each. The dashboard narrows by project and repository inside its walk, so the cap counts what is in scope.

  • completion/complete completes project, repository, pull request, path and ref, using the listing the shell uses, which moves to internal/services/listing. Each server runs at most two at a time, with at most 100 values an answer.

  • Prompts: review_pull_request (details, diff and open threads embedded) and explain_pull_request (details and diff).

  • Governance.

    • --project/--repo bind reads, the list, prompts and completions.
    • Under a scope, a project or repository completion is answered without asking Bitbucket.
    • Reads, the list and prompts are audited as mcp_resource_read, mcp_resource_list and mcp_prompt_get. Completions are not audited.
  • Links. get_pull_request, get_pr_diff, get_file_content and get_commit add a resource_link beside their content, for clients on protocol revision 2025-06-18 or later.

  • Video. get_file_content addresses a returned video by its bitbucket:// URI instead of its web page, which a client could fetch without the credentials.

  • 2026-07-28 rules. A missing resource is -32602, reads and the list are cacheScope: private, and every capability is declared bare.

  • URIs. bb builds and parses its URIs itself, escaped as UTF-8. The URI template library go-sdk routes with encodes non-ASCII as code points and refuses U+FFFD.

Review before pushing

A second pass (mine plus an independent review) found and fixed:

  • A crash: U+FFFD in a prompt argument, or in a path or ref that a tool call succeeded with, made the URI library fail, and bb panicked.
  • Wrong links for non-ASCII: "é" encoded as %E9, not UTF-8.
  • Unfiltered resources: --tools/--exclude did not govern resources, so the hardening guide's allowlist still served files.
  • Links to old clients: links went to revisions without resource_link, and list_pr_comments linked a resource other than its result.
  • Missing pull requests: the list under --repo could leave out pull requests past the project-wide cap.
  • Unscoped listing: scoped completions listed the whole instance before discarding the answer.
  • A flaky subtest: the live project completion.

Tests

  • Unit (no mocked Bitbucket):

    • template guards;
    • URI round trips with non-ASCII, ?, # and U+FFFD;
    • refused shapes;
    • -32602 for what does not exist;
    • scope on reads, prompts, the list and completions, including a middleware test that the pinned context reaches the listing;
    • audit events;
    • the tool filters;
    • the protocol gate for links;
    • the answer bounds.
  • Guards broken first: every guard above failed when broken (17 mutations).

  • Live: TestLiveMCPResourcesReadWhatTheToolsRead, 13 subtests:

    • each template read;
    • a refusal for what doesn't exist, and for a pull request in a sibling repository outside --repo;
    • the list, which leaves that pull request out;
    • completions;
    • the prompt;
    • audit events;
    • links.

    The file-content live tests check the link on every read. All 19 live MCP tests pass locally, and task quality:verify passes.

Records

ADR-099 is new. It amends ADR-062 and ADR-094, and records the alternatives other MCP servers take for resources in tool results. The PR also updates ADR-067's guard list, AGENTS.md, the generated MCP reference, the AI page, the hardening guide, the threat model, and the v5.0.0 notes (item 6, with an audit sample).

Refs #685

🤖 Generated with Claude Code

vriesdemichael and others added 4 commits September 27, 2026 13:15
…m one place

The shell's completion knows that Bitbucket filters projects and
repositories by display name while the value being completed is a key or a
slug, and that a directory is read through /browse rather than /files. The
MCP server is about to complete the same values, and internal/mcp cannot
import internal/cli/completion, which imports it. The listings move to
internal/services/listing, which both use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, with prompts and completions

The person can now hand Bitbucket content to the model: a pull request,
its diff, its open threads, a file at a ref and a commit are resource
templates under bitbucket://projects/{project}/repos/{repo}/. bb reads
them with its own credentials, so the client never contacts Bitbucket.
Each answers with what the matching tool answers, through the same code,
bounded as ADR-094 asks.

- A template is served while the tool it answers like is exposed, a
  prompt while every tool it embeds is, and the list while
  list_pull_requests and get_pull_request are, so --tools and --exclude
  decide them as they decide tools.
- resources/list holds the caller's open pull requests and those waiting
  on their review, 25 of each, narrowed to the scope inside the
  dashboard walk.
- completion/complete lists project keys, repository slugs, pull
  requests, paths and refs through internal/services/listing, two at a
  time per server and at most 100 values an answer.
- review_pull_request and explain_pull_request embed the resources they
  are about.
- The governance middleware binds reads, the list, prompts and
  completions to --project and --repo, and records reads, the list and
  prompts as mcp_resource_read, mcp_resource_list and mcp_prompt_get.
- bb builds and parses its resource URIs itself, escaping every value as
  UTF-8. The URI template library go-sdk routes with encodes non-ASCII
  as code points and refuses U+FFFD, which would have crashed the server.
- A missing resource is -32602, reads and the list are cacheScope
  private, and the server declares only what it serves.
- get_pull_request, get_pr_diff, get_file_content and get_commit link the
  resource they came from beside their content, for clients on protocol
  revision 2025-06-18 or later, and get_file_content addresses a returned
  video by its bitbucket:// URI.

ADR-099 records it and amends ADR-062 and ADR-094.

Closes #685

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m, and how they are audited

The AI page says a person can attach pull requests, diffs, files and
commits, and pick prompts. The hardening guide says the scope covers
resource reads, the list, prompts and completions, and shows the new
audit events; the threat model adds them to TB-5. The v5.0.0 notes list
the feature and the three audit events a SIEM rule needs to allow for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ADR-099 now names the alternatives found in other servers' source, each
with why bb does not take it: GitHub's server carrying a file as an
embedded resource, and linking instead of content from 1 MB; most servers
linking nothing; Grafana's server linking a web page; AWS's code
interpreter answering a listing with a link per item. It asks a future
change to the links to first find out which clients act on one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@vriesdemichael vriesdemichael left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May auto merge after changing th preamble as in the comment.

Comment thread docs/release-notes/v5.0.0.md Outdated
}
```

6. **The MCP server serves pull requests, diffs, files and commits as resources you can attach, with prompts and completions ([ADR-099](https://vriesdemichael.github.io/bitbucket-data-center-cli/latest/adr/099-mcp-resources-prompts-and-completions/), [#685](https://github.com/vriesdemichael/bitbucket-data-center-cli/issues/685)):**

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads too technical, make it clear what changes for users, give an example. Explain why it is useful

…h an example

The v5.0.0 note on resources opens with what changes: the person can now
put a pull request, its diff or a file in front of the model themselves,
with a VS Code example of attaching a diff and of the review prompt, and
why that helps. The administrator and audit details follow in one bullet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vriesdemichael
vriesdemichael enabled auto-merge (rebase) September 27, 2026 13:19
Item 6 now reads as a changelog entry rather than a checklist: why the
server serves resources (the AI no longer sees only what it goes looking
for), what a person can do with them, and a VS Code example, in prose.
The administrator's note on --tools, --exclude and the audit events stays
as one bullet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vriesdemichael
vriesdemichael enabled auto-merge (rebase) September 27, 2026 13:26
@vriesdemichael
vriesdemichael merged commit ddde2a7 into next Sep 27, 2026
20 checks passed
@vriesdemichael
vriesdemichael deleted the cc/mcp-resources-685 branch September 27, 2026 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant