Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions cartridges/domains/development/bug-filing-mcp/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
= bug-filing-mcp

Autonomous bug-report filing cartridge. It is the boj-side packaging of the
real *feedback-o-tron* engine for the autonomous bug-reporting pipeline
(see `feedback-o-tron/docs/AUTONOMOUS-BUG-PIPELINE.adoc`).

[IMPORTANT]
====
*This is not `feedback-mcp`.* `feedback-mcp` is an unrelated in-memory *sentiment
counter*. Per owner decision *D0 = new wrapping cartridge*, that cartridge is left
untouched and this *new* cartridge wraps the real bug-filing engine. The two only
share the `127.0.0.1:7722` placeholder port; run one backend or the other.
====

== What it does

Exposes a single tool, `submit_feedback`, that files a bug report / feedback /
proposal to one or more forges (GitHub, GitLab, Bitbucket, Codeberg, Bugzilla,
email) through the feedback-o-tron engine — with deduplication against existing
issues and audit logging handled engine-side.

== How it wires

[source,text]
----
boj gateway :7700
POST /cartridge/bug-filing-mcp/invoke {tool:"submit_feedback", arguments:{title,body,repo}}
-> bug-filing-mcp/mod.js (Deno JS worker)
-> POST http://127.0.0.1:7722/api/v1/submit_feedback
-> feedback-o-tron Submitter -> gh / glab / Bugzilla REST / ...
----

The cartridge is a thin HTTP client; all submission logic (dedup, audit, rate
limiting, dry-run) lives in the engine, reached over its localhost HTTP intake.

== Prerequisites

Run the feedback-o-tron engine with its HTTP intake enabled:

[source,sh]
----
FEEDBACK_A_TRON_HTTP=1 feedback-a-tron # listens on 127.0.0.1:7722
# override: FEEDBACK_A_TRON_HTTP_PORT, FEEDBACK_A_TRON_HTTP_BIND
----

Point the cartridge elsewhere with `BUG_FILING_BACKEND_URL` if needed.

== Tool: `submit_feedback`

[cols="1,1,3",options="header"]
|===
| Field | Required | Meaning
| `title` | yes | Issue title
| `body` | yes | Issue body (markdown)
| `repo` | yes | Target repo, `owner/repo`
| `platforms` | no | Subset of `github,gitlab,bitbucket,codeberg,bugzilla,email` (default `github`)
| `labels` | no | Labels to apply (platform-dependent)
| `dry_run` | no | Preview without filing
| `skip_dedupe` | no | Skip duplicate checking
|===

If the backend is not running, the cartridge returns a `503` with a hint to
start the engine with `FEEDBACK_A_TRON_HTTP=1`.
69 changes: 69 additions & 0 deletions cartridges/domains/development/bug-filing-mcp/cartridge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"$schema": "https://hyperpolymath.dev/standards/cartridges/cartridge-v1.json",
"spdx": "MPL-2.0",
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)",
"name": "bug-filing-mcp",
"version": "0.1.0",
"description": "Autonomous bug-report filing cartridge -- wraps the real feedback-o-tron engine (multi-forge issue submission with deduplication and audit logging) via its localhost HTTP intake. This is the boj-side packaging of the engine for the autonomous bug-reporting pipeline (feedback-o-tron/docs/AUTONOMOUS-BUG-PIPELINE.adoc, D0 = new wrapping cartridge). NOT the same as feedback-mcp, which is an unrelated in-memory sentiment counter.",
"domain": "development",
"category": "domain",
"tier": "Ayo",
"protocols": [
"MCP",
"REST"
],
"auth": {
"method": "none",
"env_var": null,
"credential_source": null
},
"api": {
"base_url": "http://127.0.0.1:7722",
"content_type": "application/json"
},
"tools": [
{
"name": "submit_feedback",
"description": "File a bug report / feedback / proposal to one or more forges (GitHub, GitLab, Bitbucket, Codeberg, Bugzilla, email) via the feedback-o-tron engine. Includes deduplication against existing issues and audit logging. Use dry_run to preview without filing.",
"inputSchema": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Issue/feedback title"
},
"body": {
"type": "string",
"description": "Issue/feedback body (markdown supported)"
},
"repo": {
"type": "string",
"description": "Target repository (owner/repo format)"
},
"platforms": {
"type": "array",
"items": {
"type": "string",
"enum": ["github", "gitlab", "bitbucket", "codeberg", "bugzilla", "email"]
},
"description": "Platforms to submit to (default: github)"
},
"labels": {
"type": "array",
"items": { "type": "string" },
"description": "Labels to apply (platform-dependent)"
},
"dry_run": {
"type": "boolean",
"description": "If true, show what would be submitted without actually submitting"
},
"skip_dedupe": {
"type": "boolean",
"description": "If true, skip duplicate checking"
}
},
"required": ["title", "body", "repo"]
}
}
]
}
53 changes: 53 additions & 0 deletions cartridges/domains/development/bug-filing-mcp/mod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
//
// bug-filing-mcp/mod.js — autonomous bug-report filing.
//
// Wraps the real feedback-o-tron engine via its localhost HTTP intake
// (POST /api/v1/submit_feedback on http://127.0.0.1:7722; run the engine with
// FEEDBACK_A_TRON_HTTP=1). Override the backend with BUG_FILING_BACKEND_URL.
//
// This is the boj-side packaging of the engine for the autonomous bug-reporting
// pipeline (feedback-o-tron/docs/AUTONOMOUS-BUG-PIPELINE.adoc, contract C4 dispatch
// under D0 = new wrapping cartridge). It is NOT feedback-mcp (an unrelated
// in-memory sentiment counter that happens to share the 7722 placeholder port).

const BASE_URL = Deno.env.get("BUG_FILING_BACKEND_URL") ?? "http://127.0.0.1:7722";
const TIMEOUT_MS = 30_000;

async function post(path, payload) {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), TIMEOUT_MS);
try {
const r = await fetch(`${BASE_URL}${path}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload ?? {}),
signal: ctrl.signal,
});
const data = await r.json().catch(() => ({ error: "non-JSON response from bug-filing backend" }));
return { status: r.status, data };
} catch (e) {
if (e.name === "AbortError") {
return { status: 504, data: { error: "bug-filing backend (feedback-o-tron) timed out" } };
}
return {
status: 503,
data: {
error: `bug-filing backend unavailable: ${e.message}. ` +
`Start feedback-o-tron with FEEDBACK_A_TRON_HTTP=1 (listening on ${BASE_URL}).`,
},
};
} finally {
clearTimeout(t);
}
}

export async function handleTool(toolName, args) {
switch (toolName) {
case "submit_feedback":
return post("/api/v1/submit_feedback", args ?? {});
default:
return { status: 404, data: { error: `Unknown tool: ${toolName}` } };
}
}
Loading