@dpesch/mantisbt-mcp-server 1.14.1 → 1.15.0
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.
- package/CHANGELOG.md +45 -0
- package/README.de.md +117 -28
- package/README.md +117 -28
- package/dist/client.js +4 -0
- package/dist/coerce.js +8 -0
- package/dist/config.js +3 -0
- package/dist/deprecation.js +9 -0
- package/dist/index.js +20 -31
- package/dist/issue-enrich.js +23 -0
- package/dist/issue-envelope.js +4 -0
- package/dist/prompts/index.js +4 -4
- package/dist/resources/index.js +4 -8
- package/dist/search/index.js +9 -7
- package/dist/search/tools.js +18 -20
- package/dist/tools/config.js +9 -4
- package/dist/tools/files.js +12 -5
- package/dist/tools/index.js +34 -0
- package/dist/tools/issues.js +285 -147
- package/dist/tools/metadata.js +99 -40
- package/dist/tools/monitors.js +145 -20
- package/dist/tools/notes.js +67 -9
- package/dist/tools/project-versions.js +40 -18
- package/dist/tools/projects.js +109 -37
- package/dist/tools/users.js +3 -1
- package/dist/tools/version.js +61 -35
- package/dist/toolsets.js +104 -0
- package/docs/cookbook.de.md +600 -181
- package/docs/cookbook.md +600 -181
- package/docs/examples.de.md +27 -3
- package/docs/examples.md +27 -3
- package/package.json +2 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,51 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [1.15.0] – 2026-10-31
|
|
15
|
+
|
|
16
|
+
### Deprecated
|
|
17
|
+
|
|
18
|
+
- `add_monitor` — use `update_issue` with `add_monitors` instead; `add_monitor` will be removed in 2.0.0.
|
|
19
|
+
- `remove_monitor` — use `update_issue` with `remove_monitors` instead; `remove_monitor` will be removed in 2.0.0.
|
|
20
|
+
- `get_issues` — use `get_issue` with `ids` instead; `get_issues` will be removed in 2.0.0.
|
|
21
|
+
- `list_notes` — use `get_issue` with `select: "notes"` instead; `list_notes` will be removed in 2.0.0.
|
|
22
|
+
- `list_issue_files` — use `get_issue` with `select: "attachments"` instead; `list_issue_files` will be removed in 2.0.0.
|
|
23
|
+
- `get_project_categories`, `get_project_users`, `get_project_versions` — use `get_project` with `include: ["categories"]`, `["users"]` or `["versions"]` instead; they will be removed in 2.0.0.
|
|
24
|
+
- `find_project_member` — use `get_project` with `member_query` instead; `find_project_member` will be removed in 2.0.0. Unlike `find_project_member`, `get_project` has no `limit` and returns all matching users.
|
|
25
|
+
- `get_metadata_full` — use `get_metadata` with `detail: "full"` instead; `sync_metadata` — use `get_metadata` with `refresh: true`; `get_search_index_status` — use `get_metadata` (field `search_index`). All three will be removed in 2.0.0.
|
|
26
|
+
- `get_mcp_version`, `get_mantis_version` — use `get_version` instead; they will be removed in 2.0.0.
|
|
27
|
+
- `get_issue_fields`, `get_issue_enums` — use `get_issue_schema` instead; they will be removed in 2.0.0. The resource `mantis://enums` stays.
|
|
28
|
+
- `list_languages` — use `get_current_user` (field `language`) instead; `list_languages` will be removed in 2.0.0. Despite its name it never listed languages: MantisBT's `GET /lang` returns only the current user's language.
|
|
29
|
+
- `release_version` — use `update_version` with `released: true`, `timestamp`, and optionally `next_version` instead; `release_version` will be removed in 2.0.0.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- `update_issue` accepts two new optional parameters `add_monitors` and `remove_monitors` (arrays of MantisBT login names, case-insensitive). `fields` may now be omitted when only monitor changes or a note are given. The response contains a `monitors` key with `added?`, `removed?`, `not_monitoring?`, and `current`. The steps run in order — fields, monitors, note. Once one of them succeeded, a later failure is reported inline (`monitors_error`, `note_error`) instead of failing the call, so changes that went through are not retried; only when every requested step failed does the call return an error. A user in both lists is rejected; a call with nothing to change is rejected. `dry_run` additionally shows `would_add_monitors` / `would_remove_monitors`.
|
|
34
|
+
- `update_issue` can edit existing notes: `fields.notes` takes `[{ id, text?, view_state? }]`. MantisBT has no REST route for editing a note, but its issue update applies note edits by ID. Note edits keep the note's current visibility unless `view_state` is given — the tool reads the current `view_state` first and sends it along. Note IDs that do not belong to the issue are rejected before anything is written. After the update the tool checks text and visibility in the response and reports edits MantisBT did not apply as `notes_error` (or as an error when the notes were the only field). `dry_run` shows the edit including the filled-in `view_state`. New notes are still added with the `note` parameter or `add_note`; no new tool.
|
|
35
|
+
- `get_issue` accepts `ids` (1–50 issue IDs) as an alternative to `id` — pass exactly one of the two. With `ids` the response is `{ issues, requested, found, failed }` as with `get_issues`, missing or inaccessible IDs give `null` at their position; `select` applies to every issue, and `view_url` is set even when `select` leaves out `id`.
|
|
36
|
+
- New tool `get_project`: master data of one project plus, on request, its categories, users and versions in one call. `include` takes any of `"categories"`, `"users"`, `"versions"`; `access_level` and `member_query` (case-insensitive substring search in login name, real name and email — all matches are returned) imply `"users"`, `obsolete` and `inherit` imply `"versions"`. Categories come without the `[All Projects] ` prefix and cost no extra request. Users come from the metadata cache when it is fresh and no `access_level` is given.
|
|
37
|
+
- Attachments in `get_issue` and `list_issue_files` now carry a `download_url`.
|
|
38
|
+
- `get_metadata` accepts `detail` (`"summary"`, the default and previous behaviour, or `"full"` for the complete raw cache) and `refresh` (`true` re-fetches all metadata first). With semantic search enabled the response also contains a `search_index` block (indexed, total, percent, last sync).
|
|
39
|
+
- New tool `get_version`: version of this MCP server and of the connected MantisBT installation in one response, `{ mcp_server: { version }, mantis: { installed_version, latest_version?, status? } }`. `check_latest` (default `true`) compares MantisBT with its latest GitHub release. If MantisBT cannot be reached, `mantis` holds an `error` and the MCP server version is still returned.
|
|
40
|
+
- New tool `get_issue_schema` (`project_id` optional): the valid `select` fields and the enum values (severity, status, priority, resolution, reproducibility) in one response.
|
|
41
|
+
- `list_issues` accepts `group_by` (`"status"`, `"handler"`, `"priority"`, `"category"`): the server counts all matching issues itself and returns `{ group_by, total, groups: [{ id, name, label?, count }] }` instead of an issue list. All filters still apply; `page`, `page_size` and `select` are ignored. Issues without a handler are counted as `"(unassigned)"`. The server pages through MantisBT 1,000 issues at a time with only the fields it needs (about 1 s for 7,700 issues); if it stops at its limit of 50,000 issues, the response says `"truncated": true`.
|
|
42
|
+
- `list_issues` with client-side filters (`status`, `assigned_to`, `reporter_id`, date filters) now says `"truncated": true` when its scan limit of 500 issues ended the search before the requested page was full. Before, such a page simply came back short without a hint.
|
|
43
|
+
- Token benchmark `npm run benchmark` (`scripts/benchmark-tokens.ts`): measures the response sizes of typical tasks with and without the server doing the work, against a live MantisBT (`BENCHMARK_PROJECT_ID`, `BENCHMARK_ISSUE_IDS`).
|
|
44
|
+
- New env var `MANTIS_TOOLSETS`: a comma-separated list of tool groups to offer — `issues`, `notes`, `links`, `files`, `projects`, `versions`, `meta`, `search` (case-insensitive). Unset or empty means all groups, as before. A deprecated tool belongs to the group of its replacement (e.g. `list_notes` to `issues`). The `search` group additionally needs `MANTIS_SEARCH_ENABLED=true`; without the group the search module is not started at all. An unknown group name stops the server at startup with a message listing the valid names.
|
|
45
|
+
- New env var `MANTIS_DISABLE_DESTRUCTIVE=true`: hides every tool marked as destructive — `delete_issue`, `delete_note`, `delete_version`, `remove_relationship`, `remove_monitor` — regardless of the groups.
|
|
46
|
+
- `get_current_user` now describes its fields and points out `language` — the user's MantisBT language, as a hint for the language of issue texts and notes.
|
|
47
|
+
- `update_version` accepts a new optional `next_version` parameter (only allowed together with `released: true`): creates a follow-up version in the same call. With `next_version` the response is `{ version: <updated>, next_version: <created> }` — or `{ version, next_version_error: <message> }` when creating the follow-up fails (the update itself stays in effect). Without `next_version` the response is unchanged (the updated version object).
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Semantic search: the server no longer loads the whole vector index before it starts answering. On startup it read and parsed `index.json` only to count its entries — a number it needs only when `last_total.txt` is missing. With an index of about 70 MB (8,000 issues) the server is now ready roughly 0.2 s sooner on every session start; the background sync still loads the index afterwards.
|
|
52
|
+
- `list_issue_files` promised a `download_url` per attachment, but MantisBT sends it only via SOAP, never via REST. The server now builds it (`file_download.php?file_id=…&type=bug`), for `get_issue` as well.
|
|
53
|
+
- `update_issue` returned the raw MantisBT envelope `{ issues: [issue], view_url }` instead of the issue itself. MantisBT answers `PATCH /issues/{id}` with an `issues` array (unlike `POST /issues`, which answers `{ issue }`), but the tool expected `{ issue }`. The response is now the updated issue with `view_url`, the same shape as `get_issue` and `create_issue`. Combined with `remove_monitors`, the monitor list from the field update is reused, which saves one request.
|
|
54
|
+
- `add_monitor` always subscribed the owner of the API key instead of the given user. It sent `{ name }`, but MantisBT reads only a `users` array and falls back to the logged-in user when it is missing. The tool now sends `{ users: [{ name }] }` and checks the returned monitor list; the response is now `{ success, monitors }` instead of the full issue object.
|
|
55
|
+
- `remove_monitor` always failed with a 404: it called `DELETE /issues/{id}/monitors/{username}`, a route MantisBT (up to 2.28) does not have. The tool now reads the issue's monitors and sends `PATCH /issues/{id}` with the list minus the user — MantisBT treats `monitors` as the complete list. If the user is not a monitor, the call succeeds without changes (`removed: false`). Because MantisBT silently skips monitors the caller may not remove, the tool checks the result and returns an error if the user is still listed (removing other users requires `monitor_delete_others_bug_threshold`). The response now also lists the remaining monitors.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
14
59
|
## [1.14.1] – 2026-10-24
|
|
15
60
|
|
|
16
61
|
### Fixed
|
package/README.de.md
CHANGED
|
@@ -83,6 +83,69 @@ npm run build
|
|
|
83
83
|
| `MANTIS_SEARCH_MODEL` | – | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | Embedding-Modell (wird beim ersten Start einmalig heruntergeladen, ~80 MB) |
|
|
84
84
|
| `MANTIS_SEARCH_THREADS` | – | `1` | Anzahl der ONNX-Intra-Op-Threads für das Embedding-Modell. Standard ist 1, um CPU-Sättigung auf Mehrkernsystemen und in WSL zu verhindern. Nur erhöhen, wenn die Indexierungsgeschwindigkeit kritisch ist und der Host ausschließlich für diese Last vorgesehen ist. |
|
|
85
85
|
| `MANTIS_UPLOAD_DIR` | – | – | Schränkt den `file_path` von `upload_file` auf dieses Verzeichnis ein (Pfad-Traversal via `../` wird blockiert). Im **stdio-Modus** ist `file_path` ohne diese Variable unbeschränkt. Im **HTTP-Modus** liest `file_path` aus dem Dateisystem des Servers und ist deshalb **deaktiviert, sofern diese Variable nicht gesetzt ist** – HTTP-Clients sollten stattdessen den Parameter `content` (Base64) verwenden. |
|
|
86
|
+
| `MANTIS_TOOLSETS` | – | – (alle) | Kommagetrennte Liste der anzubietenden Tool-Gruppen: `issues`, `notes`, `links`, `files`, `projects`, `versions`, `meta`, `search` (Groß-/Kleinschreibung egal). Nicht gesetzt oder leer bedeutet alle Gruppen. Die Gruppe `search` erfordert zusätzlich `MANTIS_SEARCH_ENABLED=true`; ohne die Gruppe wird das Such-Modul gar nicht gestartet. Ein unbekannter Gruppenname stoppt den Server beim Start mit einer Meldung, die die gültigen Namen auflistet. Siehe [Angebotene Tools einschränken](#angebotene-tools-einschränken) und das [Cookbook](docs/cookbook.de.md#nur-bestimmte-tool-gruppen-anbieten). |
|
|
87
|
+
| `MANTIS_DISABLE_DESTRUCTIVE` | – | `false` | Auf `true` setzen, um alle destruktiven Tools auszublenden – `delete_issue`, `delete_note`, `delete_version`, `remove_relationship`, `remove_monitor` – unabhängig von den aktiven Gruppen. Ausgeblendete Tools werden nicht aufgelistet und liefern »Tool … not found«, wenn sie aufgerufen werden. |
|
|
88
|
+
|
|
89
|
+
### Angebotene Tools einschränken
|
|
90
|
+
|
|
91
|
+
Zwei Umgebungsvariablen reduzieren die dem Modell angebotene Tool-Oberfläche – sinnvoll, um den Kontext des Modells kürzer zu halten und versehentliche destruktive Operationen zu verhindern:
|
|
92
|
+
|
|
93
|
+
- **`MANTIS_TOOLSETS`** – nur die aufgelisteten Gruppen einbinden (kommagetrennt, Groß-/Kleinschreibung egal)
|
|
94
|
+
- **`MANTIS_DISABLE_DESTRUCTIVE=true`** – zusätzlich `delete_issue`, `delete_note`, `delete_version`, `remove_relationship` und `remove_monitor` ausblenden, unabhängig von den aktiven Gruppen
|
|
95
|
+
|
|
96
|
+
Ausgeblendete Tools werden nicht aufgelistet und liefern »Tool … not found«, wenn sie aufgerufen werden.
|
|
97
|
+
|
|
98
|
+
| Gruppe | Tools |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `issues` | `get_issue`, `list_issues`, `create_issue`, `update_issue`, `delete_issue`¹, `get_issues`†, `list_notes`†, `list_issue_files`†, `add_monitor`†, `remove_monitor`†¹ |
|
|
101
|
+
| `notes` | `add_note`, `delete_note`¹ |
|
|
102
|
+
| `links` | `add_relationship`, `remove_relationship`¹, `attach_tags`, `detach_tag`, `list_tags` |
|
|
103
|
+
| `files` | `upload_file` |
|
|
104
|
+
| `projects` | `list_projects`, `get_project`, `list_filters`, `get_project_categories`†, `get_project_users`†, `get_project_versions`†, `find_project_member`† |
|
|
105
|
+
| `versions` | `create_version`, `update_version`, `delete_version`¹, `release_version`† |
|
|
106
|
+
| `meta` | `get_metadata`, `get_issue_schema`, `get_config`, `get_version`, `get_current_user`, `get_metadata_full`†, `sync_metadata`†, `get_search_index_status`†, `get_issue_fields`†, `get_issue_enums`†, `get_mcp_version`†, `get_mantis_version`†, `list_languages`† |
|
|
107
|
+
| `search` | `search_issues`, `rebuild_search_index` ² |
|
|
108
|
+
|
|
109
|
+
¹ wird von `MANTIS_DISABLE_DESTRUCTIVE=true` ausgeblendet · † veraltet, wird in 2.0.0 entfernt · ² erfordert zusätzlich `MANTIS_SEARCH_ENABLED=true`; ohne die Gruppe `search` wird das Such-Modul gar nicht gestartet
|
|
110
|
+
|
|
111
|
+
Veraltete Tools gehören immer zur gleichen Gruppe wie ihr Ersatz – eine Gruppe zu deaktivieren blendet sowohl den alten als auch den neuen Namen aus.
|
|
112
|
+
|
|
113
|
+
**Beispiel A – Triage-Setup** (Issues, Notizen und Metadaten; keine destruktiven Operationen):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"mantisbt": {
|
|
119
|
+
"command": "npx",
|
|
120
|
+
"args": ["-y", "@dpesch/mantisbt-mcp-server"],
|
|
121
|
+
"env": {
|
|
122
|
+
"MANTIS_BASE_URL": "https://deine-mantis-instanz.example.com/api/rest",
|
|
123
|
+
"MANTIS_API_KEY": "dein-api-token",
|
|
124
|
+
"MANTIS_TOOLSETS": "issues,notes,meta",
|
|
125
|
+
"MANTIS_DISABLE_DESTRUCTIVE": "true"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Beispiel B – alle Gruppen, nur Löschschutz** (36 von 41 Standard-Tools):
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"mcpServers": {
|
|
137
|
+
"mantisbt": {
|
|
138
|
+
"command": "npx",
|
|
139
|
+
"args": ["-y", "@dpesch/mantisbt-mcp-server"],
|
|
140
|
+
"env": {
|
|
141
|
+
"MANTIS_BASE_URL": "https://deine-mantis-instanz.example.com/api/rest",
|
|
142
|
+
"MANTIS_API_KEY": "dein-api-token",
|
|
143
|
+
"MANTIS_DISABLE_DESTRUCTIVE": "true"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
86
149
|
|
|
87
150
|
## Verfügbare Tools
|
|
88
151
|
|
|
@@ -90,18 +153,18 @@ npm run build
|
|
|
90
153
|
|
|
91
154
|
| Tool | Beschreibung |
|
|
92
155
|
|---|---|
|
|
93
|
-
| `get_issue` | Ein Issue
|
|
94
|
-
| `get_issues` |
|
|
95
|
-
| `list_issues` | Issues nach Projekt, Status, Autor u.v.m. filtern; optionales `select` für Feldprojektion und `status` für clientseitige Statusfilterung – kanonische englische Statusnamen (z.B. `"new"`, `"resolved"`) werden per ID abgeglichen und funktionieren damit sprachunabhängig auf lokalisierten Installationen |
|
|
96
|
-
| `create_issue` | Neues Issue anlegen; `severity` und `priority` müssen kanonische englische Namen sein (z.B. `minor`, `major`, `normal`, `high`) – `
|
|
97
|
-
| `update_issue` | Bestehendes Issue bearbeiten; Enum-Felder (`status`, `priority`, `severity`, `resolution`, `reproducibility`) akzeptieren kanonische englische Namen, lokalisierte Namen oder numerische IDs – der Server löst Namen automatisch zu IDs auf; unterstützt `custom_fields` sowie einen optionalen `note`-Parameter, der im selben Aufruf eine Notiz anhängt (
|
|
156
|
+
| `get_issue` | Ein Issue per `id` oder mehrere per `ids` (1–50) in einem Aufruf abrufen – genau eines von beiden angeben; mit `ids` lautet die Antwort `{ issues, requested, found, failed }`, nicht zugängliche IDs liefern `null` an ihrer Position; optionales `select` zur Feldauswahl |
|
|
157
|
+
| `get_issues` | **Veraltet:** stattdessen `get_issue` mit `ids` verwenden – wird in 2.0.0 entfernt |
|
|
158
|
+
| `list_issues` | Issues nach Projekt, Status, Autor u.v.m. filtern; optionales `select` für Feldprojektion und `status` für clientseitige Statusfilterung – kanonische englische Statusnamen (z.B. `"new"`, `"resolved"`) werden per ID abgeglichen und funktionieren damit sprachunabhängig auf lokalisierten Installationen; `group_by` (`"status"`, `"handler"`, `"priority"`, `"category"`) liefert statt einer Issue-Liste Zählwerte pro Gruppe – alle Filter greifen weiterhin, `page`, `page_size` und `select` werden ignoriert |
|
|
159
|
+
| `create_issue` | Neues Issue anlegen; `severity` und `priority` müssen kanonische englische Namen sein (z.B. `minor`, `major`, `normal`, `high`) – `get_issue_schema` aufrufen, um alle gültigen Werte und deren lokalisierte Bezeichnungen zu sehen; optionaler `handler`-Parameter akzeptiert einen Benutzernamen als Alternative zu `handler_id` (wird gegen die Projektmitglieder aufgelöst); optionales `custom_fields` zum Setzen benutzerdefinierter Felder |
|
|
160
|
+
| `update_issue` | Bestehendes Issue bearbeiten; Enum-Felder (`status`, `priority`, `severity`, `resolution`, `reproducibility`) akzeptieren kanonische englische Namen, lokalisierte Namen oder numerische IDs – der Server löst Namen automatisch zu IDs auf; unterstützt `custom_fields` sowie einen optionalen `note`-Parameter, der im selben Aufruf eine Notiz anhängt; `fields` darf entfallen, wenn nur `add_monitors`, `remove_monitors` oder `note` angegeben werden; mit `add_monitors` / `remove_monitors` (Arrays von Login-Namen) können Beobachter hinzugefügt oder entfernt werden – die Antwort enthält einen `monitors`-Schlüssel mit der aktuellen und der geänderten Beobachterliste; mit `fields.notes` lassen sich bestehende Notizen per ID bearbeiten (Notiz-ID aus `get_issue`) |
|
|
98
161
|
| `delete_issue` | Issue löschen |
|
|
99
162
|
|
|
100
163
|
### Notizen
|
|
101
164
|
|
|
102
165
|
| Tool | Beschreibung |
|
|
103
166
|
|---|---|
|
|
104
|
-
| `list_notes` |
|
|
167
|
+
| `list_notes` | **Veraltet:** stattdessen `get_issue` mit `select: "notes"` verwenden – wird in 2.0.0 entfernt |
|
|
105
168
|
| `add_note` | Notiz zu einem Issue hinzufügen |
|
|
106
169
|
| `delete_note` | Notiz löschen |
|
|
107
170
|
|
|
@@ -109,7 +172,7 @@ npm run build
|
|
|
109
172
|
|
|
110
173
|
| Tool | Beschreibung |
|
|
111
174
|
|---|---|
|
|
112
|
-
| `list_issue_files` |
|
|
175
|
+
| `list_issue_files` | **Veraltet:** stattdessen `get_issue` mit `select: "attachments"` verwenden – wird in 2.0.0 entfernt |
|
|
113
176
|
| `upload_file` | Datei an ein Issue anhängen – bevorzugt: lokaler `file_path` (der Server liest und kodiert die Datei automatisch); Fallback: Base64-kodiertes `content` + `filename` (nur verwenden, wenn `file_path` nicht verfügbar ist) |
|
|
114
177
|
|
|
115
178
|
### Beziehungen
|
|
@@ -123,14 +186,14 @@ npm run build
|
|
|
123
186
|
|
|
124
187
|
| Tool | Beschreibung |
|
|
125
188
|
|---|---|
|
|
126
|
-
| `add_monitor` |
|
|
127
|
-
| `remove_monitor` |
|
|
189
|
+
| `add_monitor` | **Veraltet:** stattdessen `update_issue` mit `add_monitors` verwenden – wird in 2.0.0 entfernt |
|
|
190
|
+
| `remove_monitor` | **Veraltet:** stattdessen `update_issue` mit `remove_monitors` verwenden – wird in 2.0.0 entfernt |
|
|
128
191
|
|
|
129
192
|
### Tags
|
|
130
193
|
|
|
131
194
|
| Tool | Beschreibung |
|
|
132
195
|
|---|---|
|
|
133
|
-
| `list_tags` | Alle verfügbaren Tags auflisten; greift auf den Metadaten-Cache zurück, wenn `GET /tags` mit 404 antwortet (vorher `
|
|
196
|
+
| `list_tags` | Alle verfügbaren Tags auflisten; greift auf den Metadaten-Cache zurück, wenn `GET /tags` mit 404 antwortet (vorher `get_metadata` mit `refresh: true` ausführen) |
|
|
134
197
|
| `attach_tags` | Tags an ein Issue hängen |
|
|
135
198
|
| `detach_tag` | Tag von einem Issue entfernen |
|
|
136
199
|
|
|
@@ -138,15 +201,16 @@ npm run build
|
|
|
138
201
|
|
|
139
202
|
| Tool | Beschreibung |
|
|
140
203
|
|---|---|
|
|
141
|
-
| `list_projects` | Alle zugänglichen Projekte auflisten; gibt normalisierte Projektdaten zurück (konsistent mit dem
|
|
142
|
-
| `
|
|
204
|
+
| `list_projects` | Alle zugänglichen Projekte auflisten; gibt normalisierte Projektdaten zurück (konsistent mit dem Metadaten-Cache) |
|
|
205
|
+
| `get_project` | Stammdaten eines Projekts (id, name, status, enabled, Unterprojekte) sowie auf Anfrage Kategorien, Benutzer und/oder Versionen in einem Aufruf; `access_level` und `member_query` implizieren `users`; `obsolete`/`inherit` implizieren `versions` |
|
|
206
|
+
| `get_project_versions` | **Veraltet:** stattdessen `get_project` mit `include: ["versions"]` verwenden – wird in 2.0.0 entfernt |
|
|
143
207
|
| `create_version` | Neue Version in einem Projekt erstellen; gibt das erstellte Versionsobjekt zurück (id, name, description, released, obsolete, timestamp); erfordert `manage_project_threshold` (Standard: Manager) |
|
|
144
|
-
| `update_version` | Bestehende Version aktualisieren; nur übergebene Felder werden geändert (mindestens eines erforderlich); Umbenennen schreibt version/target_version/fixed_in_version aller referenzierenden Issues neu; erfordert `manage_project_threshold` (Standard: Manager) |
|
|
145
|
-
| `release_version` |
|
|
208
|
+
| `update_version` | Bestehende Version aktualisieren; nur übergebene Felder werden geändert (mindestens eines erforderlich); Umbenennen schreibt version/target_version/fixed_in_version aller referenzierenden Issues neu; optionales `next_version` (nur zusammen mit `released: true`) legt eine Folgeversion im gleichen Aufruf an; erfordert `manage_project_threshold` (Standard: Manager) |
|
|
209
|
+
| `release_version` | **Veraltet:** stattdessen `update_version` mit `released: true`, `timestamp` und optional `next_version` verwenden – wird in 2.0.0 entfernt |
|
|
146
210
|
| `delete_version` | Version dauerhaft löschen – nicht umkehrbar, MantisBT leert version/target_version/fixed_in_version aller referenzierenden Issues; `update_version` mit `obsolete=true` als nicht-destruktive Alternative bevorzugen; erfordert `manage_project_threshold` (Standard: Manager) |
|
|
147
|
-
| `get_project_categories` |
|
|
148
|
-
| `get_project_users` |
|
|
149
|
-
| `find_project_member` |
|
|
211
|
+
| `get_project_categories` | **Veraltet:** stattdessen `get_project` mit `include: ["categories"]` verwenden – wird in 2.0.0 entfernt |
|
|
212
|
+
| `get_project_users` | **Veraltet:** stattdessen `get_project` mit `include: ["users"]` verwenden – wird in 2.0.0 entfernt |
|
|
213
|
+
| `find_project_member` | **Veraltet:** stattdessen `get_project` mit `member_query` verwenden (kein `limit`, liefert alle Treffer) – wird in 2.0.0 entfernt |
|
|
150
214
|
|
|
151
215
|
### Semantische Suche *(optional)*
|
|
152
216
|
|
|
@@ -164,7 +228,7 @@ Aktivierung mit `MANTIS_SEARCH_ENABLED=true`.
|
|
|
164
228
|
|---|---|
|
|
165
229
|
| `search_issues` | Natürlichsprachige Suche über alle indizierten Issues – liefert Top-N-Ergebnisse mit Cosine-Similarity-Score; optionales `select` (kommagetrennte Feldnamen) reichert jedes Ergebnis mit den angeforderten Issue-Feldern an; optionales `highlight` (boolean, Standard `false`) fügt je Ergebnis ein `highlights`-Feld mit keyword-basierten Ausschnitten aus `summary` und `description` hinzu (Treffer werden in `**fett**` dargestellt) |
|
|
166
230
|
| `rebuild_search_index` | Suchindex aufbauen oder aktualisieren; `full: true` löscht und baut ihn vollständig neu |
|
|
167
|
-
| `get_search_index_status` |
|
|
231
|
+
| `get_search_index_status` | **Veraltet:** stattdessen `get_metadata` (Feld `search_index`) verwenden – wird in 2.0.0 entfernt |
|
|
168
232
|
|
|
169
233
|
#### Welches Backend wählen?
|
|
170
234
|
|
|
@@ -186,17 +250,41 @@ npm install sqlite-vec better-sqlite3
|
|
|
186
250
|
|
|
187
251
|
| Tool | Beschreibung |
|
|
188
252
|
|---|---|
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
253
|
+
| `get_metadata` | Gecachte Metadaten abrufen: `detail: "summary"` (Standard) liefert Projekt-/Tag-Zählwerte und Benutzer-/Versions-/Kategorie-Zählwerte je Projekt; `detail: "full"` liefert den vollständigen rohen Cache; `refresh: true` lädt alle Daten zuerst von MantisBT nach; mit aktivierter semantischer Suche enthält die Antwort zusätzlich einen `search_index`-Block |
|
|
254
|
+
| `get_version` | Version dieses MCP-Servers und der verbundenen MantisBT-Installation in einer Antwort; `check_latest` (Standard `true`) vergleicht MantisBT mit dem neuesten GitHub-Release; `mantis` enthält `error`, wenn MantisBT nicht erreichbar ist |
|
|
255
|
+
| `get_issue_schema` | Gültige `select`-Felder (`fields`, `fields_source`) und Enum-Werte (`enums`: severity, status, priority, resolution, reproducibility) für diesen MantisBT-Server in einer Antwort; optionale `project_id` schränkt die Feldermittlung ein – vor `create_issue` / `update_issue` oder beim Aufbau eines `select`-Strings verwenden |
|
|
256
|
+
| `get_issue_fields` | **Veraltet:** stattdessen `get_issue_schema` verwenden – wird in 2.0.0 entfernt |
|
|
257
|
+
| `get_issue_enums` | **Veraltet:** stattdessen `get_issue_schema` verwenden; die Ressource `mantis://enums` bleibt – wird in 2.0.0 entfernt |
|
|
258
|
+
| `get_metadata_full` | **Veraltet:** stattdessen `get_metadata` mit `detail: "full"` verwenden – wird in 2.0.0 entfernt |
|
|
259
|
+
| `sync_metadata` | **Veraltet:** stattdessen `get_metadata` mit `refresh: true` verwenden – wird in 2.0.0 entfernt |
|
|
193
260
|
| `list_filters` | Gespeicherte Filter auflisten |
|
|
194
|
-
| `get_current_user` | Eigenes Benutzerprofil abrufen |
|
|
195
|
-
| `list_languages` |
|
|
261
|
+
| `get_current_user` | Eigenes Benutzerprofil abrufen – enthält `language` (die MantisBT-Sprache des Benutzers, ein Hinweis auf die Sprache für Issue-Texte und Notizen) |
|
|
262
|
+
| `list_languages` | **Veraltet:** stattdessen `get_current_user` (Feld `language`) verwenden – wird in 2.0.0 entfernt |
|
|
196
263
|
| `get_config` | Server-Konfiguration (Basis-URL, Cache-TTL) anzeigen |
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
|
|
264
|
+
| `get_mantis_version` | **Veraltet:** stattdessen `get_version` verwenden – wird in 2.0.0 entfernt |
|
|
265
|
+
| `get_mcp_version` | **Veraltet:** stattdessen `get_version` verwenden – wird in 2.0.0 entfernt |
|
|
266
|
+
|
|
267
|
+
## Token-Verbrauch
|
|
268
|
+
|
|
269
|
+
Der Server übernimmt das Zählen und die Feldprojektion selbst – das Modell erhält eine kompakte Zusammenfassung, statt rohe Issue-Listen zu lesen. Gemessen am 2026-10-31 an einer MantisBT-2.28-Installation (604 Issues, fünf Issues mit langen Beschreibungen und Notizen):
|
|
270
|
+
|
|
271
|
+
| Aufgabe | Vorher | Tokens | Nachher | Tokens | Ersparnis |
|
|
272
|
+
|---|---|---:|---|---:|---:|
|
|
273
|
+
| Statusübersicht eines Projekts (604 Issues) | `list_issues`, alle Seiten | 1.274.398 | `list_issues` + `group_by: "status"` | 165 | 99,9 % |
|
|
274
|
+
| Offene Issues je Bearbeiter | `list_issues` Status `"open"` + `select`, alle Seiten ¹ | 2.686 | `list_issues` + `group_by: "handler"` | 108 | 95,9 % |
|
|
275
|
+
| 5 Issues mit ausgewählten Feldern | `get_issue` ids, ohne `select` | 16.272 | `get_issue` ids + `select` | 623 | 96,1 % |
|
|
276
|
+
|
|
277
|
+
¹ `list_issues` durchsucht bei aktiven clientseitigen Filtern höchstens 500 Issues – der »Vorher«-Wert ist daher zu niedrig angesetzt.
|
|
278
|
+
|
|
279
|
+
Tokens geschätzt als Zeichen / 4. Zur Reproduktion an der eigenen Instanz (erfordert einen Git-Checkout, nicht per npx verfügbar):
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
MANTIS_BASE_URL=… MANTIS_API_KEY=… \
|
|
283
|
+
BENCHMARK_PROJECT_ID=12 BENCHMARK_ISSUE_IDS=101,102,103,104,105 \
|
|
284
|
+
npm run benchmark
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Anmeldedaten können auch aus `.env.local` kommen.
|
|
200
288
|
|
|
201
289
|
## Verfügbare Ressourcen
|
|
202
290
|
|
|
@@ -205,7 +293,7 @@ MCP-Ressourcen sind URI-adressierbare, schreibgeschützte Daten, die Clients dir
|
|
|
205
293
|
| Ressource-URI | Beschreibung |
|
|
206
294
|
|---|---|
|
|
207
295
|
| `mantis://me` | Profil des authentifizierten API-Benutzers (Live-Abruf) |
|
|
208
|
-
| `mantis://projects` | Alle zugänglichen MantisBT-Projekte als kompakte Liste (Cache-basiert, Aktualisierung via `
|
|
296
|
+
| `mantis://projects` | Alle zugänglichen MantisBT-Projekte als kompakte Liste (Cache-basiert, Aktualisierung via `get_metadata` mit `refresh: true`) |
|
|
209
297
|
| `mantis://projects/{id}` | Kombinierte Projektansicht: Projektfelder + Benutzer + Versionen + Kategorien in einem Aufruf; Cache-first, List-Support zur Aufzählung aller verfügbaren Projekt-URIs |
|
|
210
298
|
| `mantis://enums` | Gültige Werte für alle Issue-Enum-Felder: Severity, Priority, Status, Resolution, Reproducibility (Live-Abruf) |
|
|
211
299
|
|
|
@@ -252,6 +340,7 @@ npm run dev # Watch-Modus für Entwicklung
|
|
|
252
340
|
npm test # Tests ausführen (vitest)
|
|
253
341
|
npm run test:watch # Tests im Watch-Modus
|
|
254
342
|
npm run test:coverage # Coverage-Report
|
|
343
|
+
npm run benchmark # Token-Benchmark gegen eine Live-MantisBT-Instanz (siehe Token-Verbrauch oben)
|
|
255
344
|
```
|
|
256
345
|
|
|
257
346
|
## Lizenz
|
package/README.md
CHANGED
|
@@ -83,6 +83,69 @@ npm run build
|
|
|
83
83
|
| `MANTIS_SEARCH_MODEL` | – | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | Embedding model name (downloaded once on first use, ~80 MB) |
|
|
84
84
|
| `MANTIS_SEARCH_THREADS` | – | `1` | Number of ONNX intra-op threads for the embedding model. Default is 1 to prevent CPU saturation on multi-core machines and WSL. Increase only if index rebuild speed matters and the host is dedicated to this workload. |
|
|
85
85
|
| `MANTIS_UPLOAD_DIR` | – | – | Restrict `upload_file`'s `file_path` to files within this directory (path traversal via `../` is blocked). In **stdio mode** `file_path` is unrestricted unless this is set. In **HTTP mode** `file_path` reads from the server's filesystem, so it is **disabled unless this variable is set** — HTTP clients should upload via the `content` (Base64) parameter instead. |
|
|
86
|
+
| `MANTIS_TOOLSETS` | – | – (all) | Comma-separated list of tool groups to offer: `issues`, `notes`, `links`, `files`, `projects`, `versions`, `meta`, `search` (case-insensitive). Unset or empty means all groups. The `search` group additionally requires `MANTIS_SEARCH_ENABLED=true`; without the group the search module is not started at all. An unknown group name stops the server at startup with a message listing the valid names. See [Limit the offered tools](#limit-the-offered-tools) and the [cookbook](docs/cookbook.md#offer-only-some-tool-groups). |
|
|
87
|
+
| `MANTIS_DISABLE_DESTRUCTIVE` | – | `false` | Set to `true` to hide every destructive tool — `delete_issue`, `delete_note`, `delete_version`, `remove_relationship`, `remove_monitor` — regardless of the active groups. Hidden tools are not listed and return "Tool … not found" when called. |
|
|
88
|
+
|
|
89
|
+
### Limit the offered tools
|
|
90
|
+
|
|
91
|
+
Two env vars reduce the tool surface offered to the model — useful to keep the model's context shorter and to prevent accidental destructive operations:
|
|
92
|
+
|
|
93
|
+
- **`MANTIS_TOOLSETS`** — include only the listed groups (comma-separated, case-insensitive)
|
|
94
|
+
- **`MANTIS_DISABLE_DESTRUCTIVE=true`** — additionally hide `delete_issue`, `delete_note`, `delete_version`, `remove_relationship`, and `remove_monitor` regardless of the active groups
|
|
95
|
+
|
|
96
|
+
Hidden tools are not listed and return "Tool … not found" when called.
|
|
97
|
+
|
|
98
|
+
| Group | Tools |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `issues` | `get_issue`, `list_issues`, `create_issue`, `update_issue`, `delete_issue`¹, `get_issues`†, `list_notes`†, `list_issue_files`†, `add_monitor`†, `remove_monitor`†¹ |
|
|
101
|
+
| `notes` | `add_note`, `delete_note`¹ |
|
|
102
|
+
| `links` | `add_relationship`, `remove_relationship`¹, `attach_tags`, `detach_tag`, `list_tags` |
|
|
103
|
+
| `files` | `upload_file` |
|
|
104
|
+
| `projects` | `list_projects`, `get_project`, `list_filters`, `get_project_categories`†, `get_project_users`†, `get_project_versions`†, `find_project_member`† |
|
|
105
|
+
| `versions` | `create_version`, `update_version`, `delete_version`¹, `release_version`† |
|
|
106
|
+
| `meta` | `get_metadata`, `get_issue_schema`, `get_config`, `get_version`, `get_current_user`, `get_metadata_full`†, `sync_metadata`†, `get_search_index_status`†, `get_issue_fields`†, `get_issue_enums`†, `get_mcp_version`†, `get_mantis_version`†, `list_languages`† |
|
|
107
|
+
| `search` | `search_issues`, `rebuild_search_index` ² |
|
|
108
|
+
|
|
109
|
+
¹ hidden by `MANTIS_DISABLE_DESTRUCTIVE=true` · † deprecated, removed in 2.0.0 · ² additionally requires `MANTIS_SEARCH_ENABLED=true`; without the `search` group the search module is not started at all
|
|
110
|
+
|
|
111
|
+
Deprecated tools always belong to the same group as their replacement — disabling a group hides old and new name together.
|
|
112
|
+
|
|
113
|
+
**Example A — triage setup** (issues, notes, and metadata; no destructive operations):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"mantisbt": {
|
|
119
|
+
"command": "npx",
|
|
120
|
+
"args": ["-y", "@dpesch/mantisbt-mcp-server"],
|
|
121
|
+
"env": {
|
|
122
|
+
"MANTIS_BASE_URL": "https://your-mantis.example.com/api/rest",
|
|
123
|
+
"MANTIS_API_KEY": "your-api-token",
|
|
124
|
+
"MANTIS_TOOLSETS": "issues,notes,meta",
|
|
125
|
+
"MANTIS_DISABLE_DESTRUCTIVE": "true"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Example B — all groups, delete-protection only** (36 of the 41 default tools):
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"mcpServers": {
|
|
137
|
+
"mantisbt": {
|
|
138
|
+
"command": "npx",
|
|
139
|
+
"args": ["-y", "@dpesch/mantisbt-mcp-server"],
|
|
140
|
+
"env": {
|
|
141
|
+
"MANTIS_BASE_URL": "https://your-mantis.example.com/api/rest",
|
|
142
|
+
"MANTIS_API_KEY": "your-api-token",
|
|
143
|
+
"MANTIS_DISABLE_DESTRUCTIVE": "true"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
86
149
|
|
|
87
150
|
## Available tools
|
|
88
151
|
|
|
@@ -90,18 +153,18 @@ npm run build
|
|
|
90
153
|
|
|
91
154
|
| Tool | Description |
|
|
92
155
|
|---|---|
|
|
93
|
-
| `get_issue` | Retrieve an issue by
|
|
94
|
-
| `get_issues` |
|
|
95
|
-
| `list_issues` | Filter issues by project, status, author, and more; optional `select` for field projection and `status` for client-side status filtering — canonical English status names (e.g. `"new"`, `"resolved"`) are matched by ID, making the filter language-independent on localized installations |
|
|
96
|
-
| `create_issue` | Create a new issue; `severity` and `priority` must be canonical English names (e.g. `minor`, `major`, `normal`, `high`) — call `
|
|
97
|
-
| `update_issue` | Update an existing issue; enum fields (`status`, `priority`, `severity`, `resolution`, `reproducibility`) accept canonical English names, localized names, or numeric IDs — the server resolves names to IDs automatically; supports `custom_fields` and an optional `note` parameter that appends a note in the same call (
|
|
156
|
+
| `get_issue` | Retrieve an issue by `id`, or several by `ids` (1–50) in one call — pass exactly one; with `ids` returns `{ issues, requested, found, failed }`, missing or inaccessible IDs give `null` at their position; optional `select` for field projection |
|
|
157
|
+
| `get_issues` | **Deprecated:** use `get_issue` with `ids` instead — will be removed in 2.0.0 |
|
|
158
|
+
| `list_issues` | Filter issues by project, status, author, and more; optional `select` for field projection and `status` for client-side status filtering — canonical English status names (e.g. `"new"`, `"resolved"`) are matched by ID, making the filter language-independent on localized installations; `group_by` (`"status"`, `"handler"`, `"priority"`, `"category"`) returns counts per group instead of an issue list — all filters still apply, `page`, `page_size`, and `select` are ignored |
|
|
159
|
+
| `create_issue` | Create a new issue; `severity` and `priority` must be canonical English names (e.g. `minor`, `major`, `normal`, `high`) — call `get_issue_schema` to see all valid values and their localized labels; optional `handler` parameter accepts a username as alternative to `handler_id` (resolved against project members); optional `custom_fields` to set custom field values |
|
|
160
|
+
| `update_issue` | Update an existing issue; enum fields (`status`, `priority`, `severity`, `resolution`, `reproducibility`) accept canonical English names, localized names, or numeric IDs — the server resolves names to IDs automatically; supports `custom_fields` and an optional `note` parameter that appends a note in the same call; `fields` may be omitted when only `add_monitors`, `remove_monitors`, or `note` are given; use `add_monitors` / `remove_monitors` (arrays of login names) to add or remove watchers — the response includes a `monitors` key with the current and changed monitor lists; use `fields.notes` to edit existing notes by ID (note ID from `get_issue`) |
|
|
98
161
|
| `delete_issue` | Delete an issue |
|
|
99
162
|
|
|
100
163
|
### Notes
|
|
101
164
|
|
|
102
165
|
| Tool | Description |
|
|
103
166
|
|---|---|
|
|
104
|
-
| `list_notes` |
|
|
167
|
+
| `list_notes` | **Deprecated:** use `get_issue` with `select: "notes"` instead — will be removed in 2.0.0 |
|
|
105
168
|
| `add_note` | Add a note to an issue |
|
|
106
169
|
| `delete_note` | Delete a note |
|
|
107
170
|
|
|
@@ -109,7 +172,7 @@ npm run build
|
|
|
109
172
|
|
|
110
173
|
| Tool | Description |
|
|
111
174
|
|---|---|
|
|
112
|
-
| `list_issue_files` |
|
|
175
|
+
| `list_issue_files` | **Deprecated:** use `get_issue` with `select: "attachments"` instead — will be removed in 2.0.0 |
|
|
113
176
|
| `upload_file` | Upload a file to an issue — preferred: local `file_path` (server reads and encodes automatically); fallback: Base64-encoded `content` + `filename` (use only when `file_path` is not available) |
|
|
114
177
|
|
|
115
178
|
### Relationships
|
|
@@ -123,14 +186,14 @@ npm run build
|
|
|
123
186
|
|
|
124
187
|
| Tool | Description |
|
|
125
188
|
|---|---|
|
|
126
|
-
| `add_monitor` |
|
|
127
|
-
| `remove_monitor` |
|
|
189
|
+
| `add_monitor` | **Deprecated:** use `update_issue` with `add_monitors` instead — will be removed in 2.0.0 |
|
|
190
|
+
| `remove_monitor` | **Deprecated:** use `update_issue` with `remove_monitors` instead — will be removed in 2.0.0 |
|
|
128
191
|
|
|
129
192
|
### Tags
|
|
130
193
|
|
|
131
194
|
| Tool | Description |
|
|
132
195
|
|---|---|
|
|
133
|
-
| `list_tags` | List all available tags; falls back to the metadata cache when `GET /tags` returns 404 (run `
|
|
196
|
+
| `list_tags` | List all available tags; falls back to the metadata cache when `GET /tags` returns 404 (run `get_metadata` with `refresh: true` first to populate) |
|
|
134
197
|
| `attach_tags` | Attach tags to an issue |
|
|
135
198
|
| `detach_tag` | Remove a tag from an issue |
|
|
136
199
|
|
|
@@ -138,15 +201,16 @@ npm run build
|
|
|
138
201
|
|
|
139
202
|
| Tool | Description |
|
|
140
203
|
|---|---|
|
|
141
|
-
| `list_projects` | List all accessible projects; returns normalized project data (consistent with
|
|
142
|
-
| `
|
|
204
|
+
| `list_projects` | List all accessible projects; returns normalized project data (consistent with the metadata cache) |
|
|
205
|
+
| `get_project` | Get one project's master data (id, name, status, enabled, subprojects) plus, on request, its categories, users and/or versions in one call; `access_level` and `member_query` imply `users`; `obsolete`/`inherit` imply `versions` |
|
|
206
|
+
| `get_project_versions` | **Deprecated:** use `get_project` with `include: ["versions"]` instead — will be removed in 2.0.0 |
|
|
143
207
|
| `create_version` | Create a new version in a project; returns the created version object (id, name, description, released, obsolete, timestamp); requires `manage_project_threshold` (default: manager) |
|
|
144
|
-
| `update_version` | Update an existing version; only the fields you pass are changed (at least one required); renaming rewrites version/target_version/fixed_in_version on all referencing issues; requires `manage_project_threshold` (default: manager) |
|
|
145
|
-
| `release_version` |
|
|
208
|
+
| `update_version` | Update an existing version; only the fields you pass are changed (at least one required); renaming rewrites version/target_version/fixed_in_version on all referencing issues; optional `next_version` (only with `released: true`) creates a follow-up version in the same call; requires `manage_project_threshold` (default: manager) |
|
|
209
|
+
| `release_version` | **Deprecated:** use `update_version` with `released: true`, `timestamp`, and optionally `next_version` instead — will be removed in 2.0.0 |
|
|
146
210
|
| `delete_version` | Permanently delete a version — irreversible, MantisBT clears version/target_version/fixed_in_version on all referencing issues; prefer `update_version` with `obsolete=true` as the non-destructive alternative; requires `manage_project_threshold` (default: manager) |
|
|
147
|
-
| `get_project_categories` |
|
|
148
|
-
| `get_project_users` |
|
|
149
|
-
| `find_project_member` |
|
|
211
|
+
| `get_project_categories` | **Deprecated:** use `get_project` with `include: ["categories"]` instead — will be removed in 2.0.0 |
|
|
212
|
+
| `get_project_users` | **Deprecated:** use `get_project` with `include: ["users"]` instead — will be removed in 2.0.0 |
|
|
213
|
+
| `find_project_member` | **Deprecated:** use `get_project` with `member_query` instead (no `limit`, returns all matches) — will be removed in 2.0.0 |
|
|
150
214
|
|
|
151
215
|
### Semantic search *(optional)*
|
|
152
216
|
|
|
@@ -164,7 +228,7 @@ Activate with `MANTIS_SEARCH_ENABLED=true`.
|
|
|
164
228
|
|---|---|
|
|
165
229
|
| `search_issues` | Natural language search over all indexed issues — returns top-N results with cosine similarity score; optional `select` (comma-separated field names) enriches each result with the requested issue fields; optional `highlight` (boolean, default `false`) adds a `highlights` field per result with keyword-matched excerpts from `summary` and `description` (matched terms shown in `**bold**`) |
|
|
166
230
|
| `rebuild_search_index` | Build or update the search index; `full: true` clears and rebuilds from scratch |
|
|
167
|
-
| `get_search_index_status` |
|
|
231
|
+
| `get_search_index_status` | **Deprecated:** use `get_metadata` (field `search_index`) instead — will be removed in 2.0.0 |
|
|
168
232
|
|
|
169
233
|
#### Which backend to choose?
|
|
170
234
|
|
|
@@ -186,17 +250,41 @@ npm install sqlite-vec better-sqlite3
|
|
|
186
250
|
|
|
187
251
|
| Tool | Description |
|
|
188
252
|
|---|---|
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
253
|
+
| `get_metadata` | Retrieve cached metadata: `detail: "summary"` (default) returns project/tag counts and per-project user/version/category counts; `detail: "full"` returns the complete raw cache; `refresh: true` re-fetches from MantisBT first; with semantic search enabled the response also contains a `search_index` block |
|
|
254
|
+
| `get_version` | Version of this MCP server and of the connected MantisBT installation in one response; `check_latest` (default `true`) compares MantisBT with the latest GitHub release; `mantis` holds `error` when MantisBT cannot be reached |
|
|
255
|
+
| `get_issue_schema` | Valid `select` fields (`fields`, `fields_source`) and enum values (`enums`: severity, status, priority, resolution, reproducibility) for this MantisBT server in one response; optional `project_id` scopes the field discovery — use before `create_issue` / `update_issue` or when building a `select` string |
|
|
256
|
+
| `get_issue_fields` | **Deprecated:** use `get_issue_schema` instead — will be removed in 2.0.0 |
|
|
257
|
+
| `get_issue_enums` | **Deprecated:** use `get_issue_schema` instead; the resource `mantis://enums` stays — will be removed in 2.0.0 |
|
|
258
|
+
| `get_metadata_full` | **Deprecated:** use `get_metadata` with `detail: "full"` instead — will be removed in 2.0.0 |
|
|
259
|
+
| `sync_metadata` | **Deprecated:** use `get_metadata` with `refresh: true` instead — will be removed in 2.0.0 |
|
|
193
260
|
| `list_filters` | List saved filters |
|
|
194
|
-
| `get_current_user` | Retrieve your own user profile |
|
|
195
|
-
| `list_languages` |
|
|
261
|
+
| `get_current_user` | Retrieve your own user profile — includes `language` (the user's MantisBT language, a hint for which language to use in issue texts and notes) |
|
|
262
|
+
| `list_languages` | **Deprecated:** use `get_current_user` (field `language`) instead — will be removed in 2.0.0 |
|
|
196
263
|
| `get_config` | Show server configuration (base URL, cache TTL) |
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
|
|
264
|
+
| `get_mantis_version` | **Deprecated:** use `get_version` instead — will be removed in 2.0.0 |
|
|
265
|
+
| `get_mcp_version` | **Deprecated:** use `get_version` instead — will be removed in 2.0.0 |
|
|
266
|
+
|
|
267
|
+
## Token usage
|
|
268
|
+
|
|
269
|
+
The server handles counting and field projection itself — the model receives a compact summary instead of reading raw issue lists. Measured on 2026-10-31 against a MantisBT 2.28 installation (604 issues, five issues with long descriptions/notes):
|
|
270
|
+
|
|
271
|
+
| Task | Before | Tokens | After | Tokens | Saved |
|
|
272
|
+
|---|---|---:|---|---:|---:|
|
|
273
|
+
| Status overview of a project (604 issues) | `list_issues`, all pages | 1,274,398 | `list_issues` + `group_by: "status"` | 165 | 99.9 % |
|
|
274
|
+
| Open issues per handler | `list_issues` status `"open"` + `select`, all pages ¹ | 2,686 | `list_issues` + `group_by: "handler"` | 108 | 95.9 % |
|
|
275
|
+
| 5 issues with selected fields | `get_issue` ids, no `select` | 16,272 | `get_issue` ids + `select` | 623 | 96.1 % |
|
|
276
|
+
|
|
277
|
+
¹ `list_issues` scans at most 500 issues when client-side filters are active, so this "before" value is understated.
|
|
278
|
+
|
|
279
|
+
Tokens estimated as characters / 4. To reproduce against your own instance (requires a git checkout, not available via npx):
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
MANTIS_BASE_URL=… MANTIS_API_KEY=… \
|
|
283
|
+
BENCHMARK_PROJECT_ID=12 BENCHMARK_ISSUE_IDS=101,102,103,104,105 \
|
|
284
|
+
npm run benchmark
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Credentials may also come from `.env.local`.
|
|
200
288
|
|
|
201
289
|
## Available resources
|
|
202
290
|
|
|
@@ -205,7 +293,7 @@ MCP Resources are URI-addressable, read-only data that clients can fetch directl
|
|
|
205
293
|
| Resource URI | Description |
|
|
206
294
|
|---|---|
|
|
207
295
|
| `mantis://me` | Profile of the authenticated API user (live fetch) |
|
|
208
|
-
| `mantis://projects` | All accessible MantisBT projects as a compact list (cache-backed, refreshed via `
|
|
296
|
+
| `mantis://projects` | All accessible MantisBT projects as a compact list (cache-backed, refreshed via `get_metadata` with `refresh: true`) |
|
|
209
297
|
| `mantis://projects/{id}` | Combined project view: project fields + users + versions + categories in one call; cache-first, list-support for enumerating all available project URIs |
|
|
210
298
|
| `mantis://enums` | Valid values for all issue enum fields: severity, priority, status, resolution, reproducibility (live fetch) |
|
|
211
299
|
|
|
@@ -252,6 +340,7 @@ npm run dev # Watch mode for development
|
|
|
252
340
|
npm test # Run tests (vitest)
|
|
253
341
|
npm run test:watch # Run tests in watch mode
|
|
254
342
|
npm run test:coverage # Coverage report
|
|
343
|
+
npm run benchmark # Token benchmark against a live MantisBT (see Token usage above)
|
|
255
344
|
```
|
|
256
345
|
|
|
257
346
|
## License
|
package/dist/client.js
CHANGED
|
@@ -38,6 +38,10 @@ export function buildIssueViewUrl(baseUrl, issueId) {
|
|
|
38
38
|
export function buildNoteViewUrl(baseUrl, issueId, noteId) {
|
|
39
39
|
return `${baseUrl}/view.php?id=${issueId}#bugnote${noteId}`;
|
|
40
40
|
}
|
|
41
|
+
/** MantisBT sends download_url for attachments only via SOAP, so the REST tools build it themselves. */
|
|
42
|
+
export function buildAttachmentDownloadUrl(baseUrl, fileId) {
|
|
43
|
+
return `${baseUrl}/file_download.php?file_id=${fileId}&type=bug`;
|
|
44
|
+
}
|
|
41
45
|
// ---------------------------------------------------------------------------
|
|
42
46
|
// MantisApiError
|
|
43
47
|
// ---------------------------------------------------------------------------
|
package/dist/coerce.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns the strings "true"/"false" into booleans before zod validation. Some
|
|
3
|
+
* MCP clients send boolean tool arguments as strings. Anything else is passed
|
|
4
|
+
* through unchanged, so zod still rejects invalid input.
|
|
5
|
+
*
|
|
6
|
+
* Use as z.preprocess(coerceBool, z.boolean()…).
|
|
7
|
+
*/
|
|
8
|
+
export const coerceBool = (val) => val === 'true' ? true : val === 'false' ? false : val;
|
package/dist/config.js
CHANGED
|
@@ -3,6 +3,7 @@ import { homedir } from 'node:os';
|
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { normalizeBaseUrl, usesIndexPhpEntryPoint } from './client.js';
|
|
6
|
+
import { parseToolsets } from './toolsets.js';
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
// .env.local loader
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
@@ -70,6 +71,8 @@ function readNonCredentialConfig() {
|
|
|
70
71
|
numThreads: searchNumThreads,
|
|
71
72
|
},
|
|
72
73
|
testEnvironment: process.env.MCP_TEST_ENVIRONMENT === 'true',
|
|
74
|
+
toolsets: parseToolsets(process.env.MANTIS_TOOLSETS),
|
|
75
|
+
disableDestructive: process.env.MANTIS_DISABLE_DESTRUCTIVE === 'true',
|
|
73
76
|
};
|
|
74
77
|
}
|
|
75
78
|
/**
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Major version in which deprecated tools are removed (see versioning rules in CLAUDE.md). */
|
|
2
|
+
export const REMOVAL_VERSION = '2.0.0';
|
|
3
|
+
/**
|
|
4
|
+
* First line of the description of a deprecated tool. Keeping the wording in
|
|
5
|
+
* one place keeps README, CHANGELOG and tests consistent.
|
|
6
|
+
*/
|
|
7
|
+
export function deprecationNote(tool, replacement) {
|
|
8
|
+
return `Deprecated: use ${replacement} instead — ${tool} will be removed in ${REMOVAL_VERSION}.`;
|
|
9
|
+
}
|