Skip to content

Scope MCP work-proof issue lookup by repo#351

Merged
ramimbo merged 1 commit into
ramimbo:mainfrom
TUPM96:codex/mcp-repo-selector-315
May 26, 2026
Merged

Scope MCP work-proof issue lookup by repo#351
ramimbo merged 1 commit into
ramimbo:mainfrom
TUPM96:codex/mcp-repo-selector-315

Conversation

@TUPM96
Copy link
Copy Markdown
Contributor

@TUPM96 TUPM96 commented May 26, 2026

Refs #315

Summary

  • Add an optional repo selector to MCP submit_work_proof when selecting by issue_number.
  • Scope issue-number lookup with case-insensitive repository matching so agents can disambiguate duplicated issue numbers across repos.
  • Reject repo unless issue_number is present, and validate non-string or oversized repo selectors.

Evidence

  • uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 12 passed.
  • uv run --extra dev ruff check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.
  • uv run --extra dev ruff format --check app/main.py app/mcp.py tests/test_api_mcp.py -> 3 files already formatted.
  • uv run --extra dev python -m mypy app/main.py app/mcp.py -> success.
  • git diff --check origin/main..HEAD -> clean.

No private keys, seed material, secrets, deployment credentials, private vulnerability details, payout credentials, or MRWK price claims are included.

Summary by CodeRabbit

  • New Features

    • Optional repo selector added to submit_work_proof to disambiguate bounties with the same issue number.
  • Bug Fixes

    • repo input is normalized (trimmed, lowercased, max 200 chars) and accepted only when paired with an issue_number; bounty_id and issue_number remain mutually exclusive.
  • Documentation

    • Tool description clarified to note optional repo scoping and text/JSON response formats.
  • Tests

    • Added tests covering repo scoping, casing, format, and invalid argument combinations.

Review Change Stack

Copilot AI review requested due to automatic review settings May 26, 2026 01:24
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 84944113-4ca7-411c-a208-b6f8a86410bf

📥 Commits

Reviewing files that changed from the base of the PR and between 77be52e and 0473eba.

📒 Files selected for processing (3)
  • app/main.py
  • app/mcp.py
  • tests/test_api_mcp.py

📝 Walkthrough

Walkthrough

The PR extends the submit_work_proof MCP tool to accept an optional repo argument, adds repo sanitization and validation (repo only allowed with issue_number), filters issue_number lookups by repo when given, updates the tool description, and adds tests for valid and invalid repo usage.

Changes

Repo selector feature for issue number disambiguation

Layer / File(s) Summary
Repo selector implementation and documentation
app/main.py, app/mcp.py
Adds a repo argument helper (trim, lowercase, max 200, None when empty). Validation enforces repo may only be used with issue_number (keeps bounty_id vs issue_number exclusion). issue_number lookup is constrained by Bounty.repo == repo_selector when provided. Tool description updated to mention optional repo scoping and text/JSON output.
Test coverage for repo scoping
tests/test_api_mcp.py
Adds integration test that disambiguates identical issue_number bounties across repos (sends mixed-case repo, requests format: "json") and extends invalid-selector parametrized cases covering repo-only, repo with bounty_id, non-string repo, and oversized repo, expecting invalid tool arguments.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ramimbo/mergework#287: Modifies the same submit_work_proof MCP tool selector handling and validation logic around issue_number flow.
  • ramimbo/mergework#317: Updates the same submit_work_proof MCP tool implementation to extend argument parsing and output handling.

Suggested labels

mrwk:accepted, mrwk:paid

Suggested reviewers

  • TateLyman
  • weilixiong
  • ayskobtw-lil
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding optional repo scoping to MCP work-proof issue lookup.
Description check ✅ Passed The description includes all required template sections: Summary with clear objectives, Evidence with test and lint validation results, and MRWK reference (#315). All critical information is present and well-documented.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR extends the MCP submit_work_proof tool so that selecting a bounty by issue_number can be disambiguated by providing a repo selector, and adds tests for the new behavior and validation.

Changes:

  • Add optional repo argument parsing/validation for MCP submit_work_proof.
  • Filter bounty lookup by repo when selecting by issue_number.
  • Add test coverage for repo-scoped selection and new invalid selector cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
tests/test_api_mcp.py Adds coverage for repo-scoped bounty selection and repo argument validation.
app/mcp.py Updates MCP tool description to mention repo scoping and JSON/text output.
app/main.py Implements repo selector parsing and applies it to the issue_number lookup query.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/main.py Outdated
Bounty.issue_number == positive_int_arg("issue_number")
)
if repo_selector is not None:
issue_query = issue_query.where(func.lower(Bounty.repo) == repo_selector)
Comment thread tests/test_api_mcp.py Outdated
Comment on lines +1546 to +1569
create_schema(sqlite_url)
with session_scope(sqlite_url) as session:
ensure_genesis(session)
create_bounty(
session,
repo="ramimbo/mergework",
issue_number=284,
issue_url="https://github.com/ramimbo/mergework/issues/284",
title="First bounty",
reward_mrwk="100",
acceptance="First acceptance.",
)
target = create_bounty(
session,
repo="example/mergework",
issue_number=284,
issue_url="https://github.com/example/mergework/issues/284",
title="Second bounty",
reward_mrwk="250",
acceptance="Second acceptance.",
)
target_id = target.id

client = TestClient(create_app(database_url=sqlite_url, webhook_secret="secret"))
Comment thread app/mcp.py Outdated
Comment on lines +42 to +43
"Return submission instructions, optionally for a bounty_id or issue_number "
"and repo, with text or json format"
Copy link
Copy Markdown
Contributor

@TateLyman TateLyman left a comment

Choose a reason for hiding this comment

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

Reviewed the repo-scoped submit_work_proof lookup for Bounty #315.\n\nWhat I checked:\n- app/main.py: repo is accepted only with issue_number, validated as a non-empty string through the existing clean-string helper, capped at 200 chars, lowercased, and applied as func.lower(Bounty.repo) == repo_selector before the existing two-row ambiguity check.\n- app/mcp.py: tool description now advertises the repo selector alongside text/json output.\n- tests/test_api_mcp.py: added a duplicate-issue fixture proving repo: Example/MergeWork selects the intended example/mergework bounty, plus invalid selector coverage for repo without issue_number, repo with bounty_id, non-string repo, and oversized repo.\n\nValidation run locally on current head d16094c:\n- uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_ambiguous_issue_number -q -> 13 passed.\n- uv run --extra dev python -m pytest tests/test_api_mcp.py -q -> 81 passed.\n- uv run --extra dev ruff check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.\n- uv run --extra dev ruff format --check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.\n- uv run --extra dev python -m mypy app/main.py app/mcp.py -> passed.\n- uv run --extra dev python scripts/docs_smoke.py -> docs smoke ok.\n- git diff --check origin/main...HEAD -> clean.\n\nNo blocker found on this head. Caveat for merge sequencing: this branch touches app/mcp.py near the same tool metadata recently changed by PR #345, so it should be rechecked if #345 lands first.

@TUPM96
Copy link
Copy Markdown
Contributor Author

TUPM96 commented May 26, 2026

Updated after review:

  • repo filtering now uses direct Bounty.repo == repo_selector because bounty repos are stored normalized lowercase.
  • Tool description now spells out that repo only scopes issue_number lookups.
  • The repo-scoping regression now relies on create_app() for schema/genesis setup before seeding test bounties.

Revalidated:

  • uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 12 passed.
  • uv run --extra dev ruff check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.
  • uv run --extra dev ruff format --check app/main.py app/mcp.py tests/test_api_mcp.py -> 3 files already formatted.
  • uv run --extra dev python -m mypy app/main.py app/mcp.py -> success.

Copy link
Copy Markdown
Contributor

@AugmentSecurity AugmentSecurity left a comment

Choose a reason for hiding this comment

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

Reviewed PR #351 on head d16094c.

No blockers found. Evidence checked:

  • Inspected app/main.py and confirmed repo is accepted only with issue_number, normalized through the existing clean-string path plus lowercase conversion, capped at 200 chars, and applied as func.lower(Bounty.repo) == repo_selector before the existing two-row ambiguity check.
  • Confirmed the bounty_id selector path remains separate, so repo cannot alter direct bounty-id lookup.
  • Inspected app/mcp.py; this branch exposes MCP tool descriptions only, so there is no inputSchema mismatch to update here.
  • Inspected tests/test_api_mcp.py and confirmed coverage for duplicate issue numbers across repos, case-insensitive repo selection, JSON structured output identity, repo-only rejection, repo-with-bounty-id rejection, non-string repo rejection, and oversized repo rejection.

Validation:

  • ./.venv/bin/python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 12 passed.
  • ./.venv/bin/python -m pytest tests/test_api_mcp.py -q -> 81 passed.
  • ./.venv/bin/python -m ruff check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.
  • ./.venv/bin/python -m ruff format --check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.
  • ./.venv/bin/python -m mypy app/main.py app/mcp.py -> passed.
  • git diff --check origin/main...HEAD -> clean.

Copy link
Copy Markdown
Contributor

@AugmentSecurity AugmentSecurity left a comment

Choose a reason for hiding this comment

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

Correction after the head moved while my previous review was being submitted: current head 77be52e has blockers.

Requested changes:

  • tests/test_api_mcp.py::test_mcp_tools_list_and_call now fails because the updated submit_work_proof description no longer contains the existing expected phrase bounty_id or issue_number. Hosted CI is failing for the same reason.
  • The current lookup uses Bounty.repo == repo_selector while repo_selector is lowercased. That no longer provides the case-insensitive repository matching described in the PR body and tool behavior; it only works when stored repo names are already lowercase. Use func.lower(Bounty.repo) == repo_selector or add equivalent normalization and a mixed-case stored-repo regression.

Validation on current head:

  • ./.venv/bin/python -m pytest tests/test_api_mcp.py::test_mcp_tools_list_and_call -q -> fails on the description assertion above.
  • ./.venv/bin/python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 12 passed.
  • git diff --check origin/main...HEAD -> clean.

Copy link
Copy Markdown
Contributor

@TateLyman TateLyman left a comment

Choose a reason for hiding this comment

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

Correction: my earlier no-blockers review was for the previous head d16094c. Current head 77be52e changed while review/claim activity was happening and now has blockers.\n\nRequested changes:\n- tests/test_api_mcp.py::test_mcp_tools_list_and_call fails because the updated tool description no longer contains the existing expected phrase bounty_id or issue_number. Hosted CI is failing on this head as well. Keep the old phrase or update the assertion intentionally with equivalent coverage.\n- The repo lookup now compares Bounty.repo == repo_selector while repo_selector is lowercased. That no longer provides the case-insensitive repository matching described in the PR body unless stored repo names are always already normalized. The previous func.lower(Bounty.repo) == repo_selector version was safer, or add an explicit mixed-case stored-repo regression if relying on normalized storage.\n\nValidation on current head 77be52e:\n- uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_tools_list_and_call -q -> fails on the description assertion.\n- uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 12 passed.\n\nThe repo-scoped selection idea is still useful, but this head needs the CI failure fixed before merge.

@TUPM96 TUPM96 force-pushed the codex/mcp-repo-selector-315 branch from 77be52e to 0473eba Compare May 26, 2026 01:35
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/main.py`:
- Around line 1782-1787: The repo filter on issue_query uses a case-sensitive
equality (Bounty.repo == repo_selector) while other lookups like
find_bounty_by_issue use func.lower(Bounty.repo) for case-insensitive matching;
update the where clause that references repo_selector to compare
lower(Bounty.repo) to a lower-cased repo_selector (e.g. func.lower(Bounty.repo)
== repo_selector.lower()) and ensure func is imported from sqlalchemy so repo
lookups are consistently case-insensitive across functions (reference Bounty,
issue_query, repo_selector, and find_bounty_by_issue).

In `@app/mcp.py`:
- Around line 41-44: The test assertion still expects the old description text
"bounty_id or issue_number"; update the assertion in the failing test to expect
the new description string used in app.mcp (i.e. "Return submission instructions
for bounty_id, or issue_number optionally scoped by repo, with text or json
format") so the test matches the updated tool description.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5a6a02bc-423a-49b6-a55c-81d214fa0c16

📥 Commits

Reviewing files that changed from the base of the PR and between d16094c and 77be52e.

📒 Files selected for processing (3)
  • app/main.py
  • app/mcp.py
  • tests/test_api_mcp.py

Comment thread app/main.py
Comment thread app/mcp.py
Copy link
Copy Markdown
Contributor

@TateLyman TateLyman left a comment

Choose a reason for hiding this comment

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

Rechecked current head 0473eba after the description fix. The hosted test failure from my previous review is fixed: test_mcp_tools_list_and_call now passes, and the description still preserves the discoverable bounty_id or issue_number wording while adding repo scoping.\n\nOn the repo comparison: create_bounty() normalizes stored repo names through _normalize_repo_name(repo).lower(), and optional_repo_selector_arg() lowercases the selector, so the current equality check is consistent with stored data. A mixed-case stored-repo regression would be extra defense, but I no longer consider this a blocker for this PR.\n\nValidation on current head:\n- uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_tools_list_and_call tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 13 passed.\n- uv run --extra dev python -m mypy app/main.py app/mcp.py -> passed.\n- uv run --extra dev ruff check app/main.py app/mcp.py tests/test_api_mcp.py -> passed.\n\nNo blocker remains from my side.

@TUPM96
Copy link
Copy Markdown
Contributor Author

TUPM96 commented May 26, 2026

Final recheck after the description compatibility tweak:

  • uv run --extra dev python -m pytest tests/test_api_mcp.py::test_mcp_tools_list_and_call tests/test_api_mcp.py::test_mcp_submit_work_proof_scopes_issue_number_by_repo tests/test_api_mcp.py::test_mcp_submit_work_proof_rejects_invalid_bounty_selectors -q -> 13 passed.
  • Hosted Quality, readiness, docs, and image checks -> passed.
  • CodeRabbit -> passed with no blocking follow-up.

@ramimbo ramimbo merged commit ad59810 into ramimbo:main May 26, 2026
2 checks passed
@ramimbo ramimbo added the mrwk:paid Ledger payment recorded label May 26, 2026
@ramimbo ramimbo added the mrwk:accepted Maintainer accepted for payout label May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants