Forward feedback to GitHub Issues
Connect your site to a GitHub repo so feedback submitted through the widget becomes an issue automatically, and closing the issue resolves the feedback in your dashboard. Two-way sync, no scripts, no SQL.
How it works
One install on the MCPFeedback GitHub App and a save in the dashboard wires up both directions. Here's the round-trip:
Round-trip latency targets: outbound forward ≤ 60s (cron-drained queue); inbound sync ≤ 5s (webhook-driven). Tenant routing is on the (installation_id, repo_owner, repo_name, site_id) tuple, so two customers can't see each other's events even if they share a repo name.
What you get
- Every new feedback (or only the ones you click Forward on) becomes a GitHub issue in your repo within 60 seconds.
- Closing or reopening the GitHub issue flips the feedback status in MCPFeedback within 5 seconds.
- Default labels, per-feedback-type label maps, default assignee, and default milestone — all set once, applied to every issue.
- A live health panel on the Integrations tab shows queued, in-flight, failed, and dead-letter forwards with a per-row Retry button.
- If GitHub ever revokes the connection or a repo gets archived, the integration flips to Action Required and you get one email per 24 hours until you fix it — no spam.
Before you start
- A MCPFeedback account with at least one site created (create one here).
- A GitHub repo you have admin rights on (or someone with admin rights who can install the MCPFeedback app for you).
- Roughly two minutes — the only step that takes any real time is picking labels and assignee.
Connect (GitHub App — recommended)
The App path is the easiest and most stable. You install the MCPFeedback app on your GitHub account or org, pick which repos it can see, and you're done. No tokens to rotate, no webhooks to set up — MCPFeedback handles all of that.
Open your site's Integrations tab
Sign in to mcpfeedback.com, open your sites list, click the site you want to connect, then click Manage GitHub integration → near the bottom of the site detail page. Direct link pattern: mcpfeedback.com/sites/{your-site-id}/integrations.
Click "Connect with GitHub"
You'll be redirected to the MCPFeedback GitHub App to install it on the account or organization that owns the repo. On GitHub, pick Only select repositories and choose exactly the repos you want feedback forwarded to. You can change this any time from your personal installed apps or your org's installed apps page.
Authorize and come back
GitHub redirects you back to the Integrations tab once the install completes. Your connection status pill turns green and the repo picker appears.
Pick the target repo
Open the repo dropdown — it live-fetches every repo the installation has push access to. Archived repos appear with a (read-only) tag and are not selectable. Pick the one feedback should land in.
Choose default labels and (optionally) a per-type label map
Add default labels that get applied to every forwarded issue (e.g. "user-feedback"). For more control, set a label map so each feedback type — bug, feature, UX, comment — gets its own label set automatically (e.g. type=bug → ["bug", "triage"]).
Pick default assignee and milestone (optional)
Type a GitHub username to assign every new issue to that person. Pick an open milestone if you triage by milestone. Both are optional and can be left blank.
Choose forward mode
Manual: nothing forwards automatically — you click Forward on any feedback row you want sent to GitHub. Auto: every new feedback submission forwards as soon as it lands. Pick Auto if you want all feedback in GitHub by default.
Confirm PII visibility (only for public repos)
If the target repo is public, MCPFeedback will warn that issue bodies — including end-user emails and any URLs they submitted — will be visible to the world. Tick the confirmation box if that's intended, or pick a private repo instead.
Save
Click Save. The connection becomes live immediately. From this point, submitted feedback (or feedback you click Forward on) appears as a GitHub issue within 60 seconds. The "Recent forwards" panel below shows live status for everything in flight.
Smoke test (do this right after connecting)
Five steps that confirm both directions of sync are working end-to-end. Takes under three minutes.
Submit a test feedback
Open your widget on a page where MCPFeedback is embedded, submit a short test message ("hello from setup"), and note the time you submitted.
Confirm the GitHub issue
Within ~60 seconds you'll see a new GitHub issue in the repo you connected. Open the feedback row in the dashboard — it has a GitHub icon with the issue number, and clicking it jumps straight to the issue.
Close the issue on GitHub
Click Close issue on the GitHub issue. Within 5 seconds the matching feedback row flips to Resolved in your dashboard. (Tip: keep both tabs side-by-side for the first run — the activity log in MCPFeedback shows the github_sync_inbound_closed event the moment the webhook lands.)
Reopen to verify two-way sync
Click Reopen on the same issue. The feedback row flips back to whatever status it had before (or New if it had none).
Done
Two-way sync is working. Status updates flow in both directions; activity log shows every event with its source so you can audit anything later.
PAT mode (alternative)
Use this when your org doesn't allow third-party GitHub Apps and you can't install MCPFeedback as an App. You generate a fine-grained (or classic) personal access token on GitHub, paste it into the dashboard, and MCPFeedback uses your token to call the GitHub API on your behalf. Less convenient than the App path — when the token expires you have to repeat the setup — but functionally equivalent.
Open Developer settings on GitHub
Go to Fine-grained personal access tokens (recommended) or Tokens (classic) if your org requires the classic format.
Generate a token with two scopes
Select the single repo you want MCPFeedback to write to (or All repositories for broader access). Grant Issues: Read and write, Metadata: Read (always required), and add admin:repo_hook so MCPFeedback can create the repo webhook on your behalf. Set the expiry to at least 90 days — when it expires you'll need to repeat this step. See GitHub's PAT docs for screenshots.
Paste the token into the dashboard
Back on mcpfeedback.com/sites/{your-site-id}/integrations, open the Use a personal access token instead panel under the Connect button. Paste the token, type owner/repo (e.g. acme-corp/website), confirm PII visibility for public repos, and click Save.
MCPFeedback creates the webhook for you
On save, MCPFeedback uses your token to install a webhook on the repo so close/reopen events flow back to your feedback rows. If the token is missing admin:repo_hook scope you'll get a clear error and nothing is persisted — fix the scope on GitHub and retry.
Disconnect
On the Integrations tab, click Disconnect. MCPFeedback removes the webhook from your repo (App path: nothing to remove on your side; PAT path: we delete the webhook we created during setup) and clears the saved configuration. Existing forwarded issues stay in GitHub untouched — disconnect only stops new forwards and inbound syncs. Your feedback rows keep their links to existing issues for history.
To uninstall the MCPFeedback app from GitHub entirely (App path), go to github.com/settings/installations (personal) or your org's installed-apps page, find MCPFeedback, and click Configure → Uninstall.
Troubleshooting
The connection pill says "Action Required"
Hover the pill for the exact reason — usually "Repository archived", "Token revoked", or "Installation removed by admin". Click Test connection on the same panel to verify; fix the underlying issue on GitHub (unarchive, regenerate token, reinstall app) and the pill recovers automatically on the next successful forward.
Issue created on GitHub but feedback didn't flip when I closed it
Two-way sync runs through a webhook on the repo. If you disconnected and reconnected, or moved the repo, the webhook may have been removed. Open the integration in the dashboard, click Test connection, then re-save — that re-creates the webhook on the PAT path. On the App path the webhook is App-level so it can't be accidentally deleted from the repo.
A specific feedback failed to forward
Look at the Recent forwards panel. Failed rows show the exact error (e.g. "Invalid label name", "Repository archived"). Click Retry to re-queue with a fresh attempt budget. If the same row dead-letters twice, the dead-letter list shows it persistently — fix the underlying problem (e.g. delete a missing label from your defaults) and Retry once more.
PAT save failed with "Your token needs admin:repo_hook scope"
MCPFeedback needs to create a repo webhook so it can receive close/reopen events from GitHub. Regenerate the token with both repo and admin:repo_hook scopes and paste again.
The repo I want isn't in the picker
MCPFeedback only shows repos the installation has push access to and that aren't archived. Two common fixes: on GitHub, go to your installed apps, click Configure on MCPFeedback, and add the missing repo under "Repository access". Or, if the repo is archived, unarchive it on GitHub first.
I'm not getting Action-Required emails
Action-Required emails are deduped to at most one per integration per 24 hours, so a flapping integration won't spam you. The email goes to the site owner's email address on file. Check your spam folder; if you're still not seeing anything, the integration may not actually be in a non-recoverable state — transient retries don't trigger the email, only permanent failures do.
Privacy & security
- Public repos: issue bodies (which include end-user emails, URLs, and free-text comments) become world-readable the moment they're created. The dashboard always asks you to confirm this before saving against a public repo.
- PAT storage: personal access tokens are encrypted at rest with pgcrypto and never logged. The dashboard shows only the last four characters.
- Webhook verification: every inbound delivery is HMAC-verified against the shared webhook secret. Unsigned or mis-signed deliveries are rejected with 401 and logged.
- Cross-tenant isolation: webhook events are routed on the
(installation_id, repo_owner, repo_name, site_id)tuple — never installation_id alone — so two customers using the same repo name under different installations can't see each other's feedback. - Sync loop prevention: every status mutation is tagged with its source (
ui,mcp, orgithub_webhook) and the forwarder skips anything tagged as already-from-GitHub. A webhook-driven close can't re-fire the forwarder.