nodebb-plugin-integration 0.5.0 → 0.6.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/docs/MCP.md ADDED
@@ -0,0 +1,718 @@
1
+ # MCP API Reference
2
+
3
+ Version: 0.6.0
4
+
5
+ This document describes all MCP tools exposed by `nodebb-plugin-integration`.
6
+
7
+ ## 1. Overview
8
+
9
+ The plugin exposes a Model Context Protocol (MCP) server using Streamable HTTP transport.
10
+
11
+ Architecture:
12
+
13
+ ```text
14
+ MCP client
15
+ |
16
+ | Streamable HTTP + Bearer token
17
+ v
18
+ MCP child process
19
+ |
20
+ | Internal HTTP API + separate Bearer token
21
+ v
22
+ NodeBB integration plugin
23
+ |
24
+ v
25
+ Native NodeBB APIs and permission checks
26
+ ```
27
+
28
+ The MCP process runs separately from the NodeBB application process and is managed by the plugin.
29
+
30
+ All write operations use the NodeBB account configured as `mcpServiceUid`. MCP clients cannot select or override the acting user.
31
+
32
+ ## 2. Configuration
33
+
34
+ Configure MCP in NodeBB ACP → Plugins → NodeBB Integration.
35
+
36
+ | Setting | Description |
37
+ |---|---|
38
+ | Enable MCP | Enables or disables the MCP server |
39
+ | Bind address | Network interface used by the MCP HTTP server |
40
+ | Port | MCP HTTP port |
41
+ | NodeBB URL | URL used by the MCP process to reach NodeBB |
42
+ | Bearer token | Secret required by MCP clients |
43
+ | Service user UID | NodeBB account used for permission checks and write operations | . Required; must be a positive integer.
44
+
45
+ Default values:
46
+
47
+ - Bind address: `127.0.0.1`
48
+ - Port: `3100`
49
+ - NodeBB URL: `http://127.0.0.1:4567`
50
+
51
+ The plugin generates and stores a separate internal API token automatically.
52
+
53
+ The external MCP Bearer token and internal API token are different secrets.
54
+
55
+ Do not expose the internal API token to MCP clients.
56
+
57
+ ## 3. Authentication and permissions
58
+
59
+ MCP clients authenticate with:
60
+
61
+ ```http
62
+ Authorization: Bearer YOUR_MCP_TOKEN
63
+ ```
64
+
65
+ The MCP child process authenticates its requests to NodeBB using the separate internal API token.
66
+
67
+ The internal API rejects requests when MCP is disabled or the internal token is invalid.
68
+
69
+ ### Acting user
70
+
71
+ The configured `mcpServiceUid` is used for:
72
+
73
+ - Reading posts and topics with permission checks.
74
+ - Semantic search access filtering.
75
+ - Listing topics and posts.
76
+ - Creating topics and replies.
77
+ - Editing, deleting and restoring posts.
78
+ - Deleting and restoring topics.
79
+ - Bulk deletion of a user's replies.
80
+
81
+ The `uid` argument of `delete_user_posts` identifies the target account whose replies are processed. It does not identify the acting account.
82
+
83
+ ### NodeBB permissions
84
+
85
+ Write operations use native NodeBB methods. Native permission checks, restrictions and hooks are preserved.
86
+
87
+ Examples include:
88
+
89
+ - Category permissions for topic creation.
90
+ - Topic reply permissions and topic lock restrictions.
91
+ - Post edit permissions and edit restrictions.
92
+ - Post and topic delete/restore permissions.
93
+ - NodeBB hooks associated with these operations.
94
+
95
+ Read operations that return post or topic content apply NodeBB access checks.
96
+
97
+ `get_user` returns public profile fields and does not expose private account data.
98
+
99
+ Access-check failures deny access.
100
+
101
+ ## 4. Common argument rules
102
+
103
+ - IDs must be positive safe integers.
104
+ - Pagination offsets must be non-negative integers.
105
+ - Unknown arguments are rejected.
106
+ - Additional properties are rejected.
107
+ - Text arguments must not be empty or whitespace-only.
108
+ - Text length limits are measured in JavaScript string characters.
109
+ - Tool arguments must be JSON objects.
110
+
111
+ The MCP server returns tool results as formatted JSON text. Errors are returned as MCP tool results with `isError: true`.
112
+
113
+ ## 5. Tool reference
114
+
115
+ ### 5.1 get_forum_info
116
+
117
+ Returns public forum information.
118
+
119
+ Arguments: none.
120
+
121
+ Example:
122
+
123
+ ```json
124
+ {}
125
+ ```
126
+
127
+ Response fields:
128
+
129
+ | Field | Type | Description |
130
+ |---|---|---|
131
+ | title | string | Forum title |
132
+ | url | string | Forum URL |
133
+ | version | string | NodeBB version |
134
+ | language | string or null | Forum language |
135
+
136
+ Example:
137
+
138
+ ```json
139
+ {
140
+ "title": "Example Forum",
141
+ "url": "https://forum.example.com",
142
+ "version": "4.16.7",
143
+ "language": "en-GB"
144
+ }
145
+ ```
146
+
147
+ ### 5.2 get_post
148
+
149
+ Retrieves a post by ID after checking whether the configured service user can read both the post and its topic.
150
+
151
+ Arguments:
152
+
153
+ | Name | Type | Required | Constraints |
154
+ |---|---|---|---|
155
+ | pid | integer | Yes | Minimum 1 |
156
+
157
+ Example:
158
+
159
+ ```json
160
+ {
161
+ "pid": 123
162
+ }
163
+ ```
164
+
165
+ Response:
166
+
167
+ | Field | Type | Description |
168
+ |---|---|---|
169
+ | pid | integer | Post ID |
170
+ | tid | integer | Topic ID |
171
+ | uid | integer | Author UID |
172
+ | cid | integer | Category ID |
173
+ | content | string | Post content |
174
+ | timestamp | NodeBB timestamp | Post creation timestamp |
175
+
176
+ Deleted posts, missing posts and posts inaccessible to the service user are reported as not found.
177
+
178
+ ### 5.3 get_topic
179
+
180
+ Retrieves topic metadata after checking topic read permissions.
181
+
182
+ Arguments:
183
+
184
+ | Name | Type | Required | Constraints |
185
+ |---|---|---|---|
186
+ | tid | integer | Yes | Minimum 1 |
187
+
188
+ Example:
189
+
190
+ ```json
191
+ {
192
+ "tid": 42
193
+ }
194
+ ```
195
+
196
+ Response:
197
+
198
+ | Field | Type | Description |
199
+ |---|---|---|
200
+ | tid | integer | Topic ID |
201
+ | uid | integer | Topic author UID |
202
+ | title | string | Topic title |
203
+ | cid | integer | Category ID |
204
+ | timestamp | NodeBB timestamp | Topic creation timestamp |
205
+ | mainPid | integer | ID of the first post |
206
+
207
+ The tool returns topic metadata, not the complete list of posts. Use `list_posts` to retrieve posts.
208
+
209
+ ### 5.4 get_user
210
+
211
+ Returns public profile information for a user.
212
+
213
+ The `uid` argument identifies the user whose public profile is requested. It does not change the service user or determine which account performs operations.
214
+
215
+ Arguments:
216
+
217
+ | Name | Type | Required | Constraints |
218
+ |---|---|---|---|
219
+ | uid | integer | Yes | Minimum 1 |
220
+
221
+ Example:
222
+
223
+ ```json
224
+ {
225
+ "uid": 7
226
+ }
227
+ ```
228
+
229
+ Response:
230
+
231
+ | Field | Type | Description |
232
+ |---|---|---|
233
+ | uid | integer | User ID |
234
+ | username | string | Username |
235
+ | userslug | string | URL-safe username |
236
+ | picture | string | Profile picture URL or value provided by NodeBB |
237
+
238
+ Only the fields listed above are returned.
239
+
240
+ ### 5.5 search_knowledge
241
+
242
+ Performs semantic search against the indexed forum knowledge base.
243
+
244
+ Requires the OpenAI provider and a working Qdrant collection.
245
+
246
+ Arguments:
247
+
248
+ | Name | Type | Required | Constraints |
249
+ |---|---|---|---|
250
+ | query | string | Yes | 1–2000 characters |
251
+ | limit | integer | No | 1–20; default 5 |
252
+
253
+ Example:
254
+
255
+ ```json
256
+ {
257
+ "query": "How do I configure forum notifications?",
258
+ "limit": 5
259
+ }
260
+ ```
261
+
262
+ Response:
263
+
264
+ ```json
265
+ {
266
+ "results": [
267
+ {
268
+ "pid": 123,
269
+ "tid": 42,
270
+ "uid": 7,
271
+ "cid": 3,
272
+ "score": 0.91,
273
+ "content": "Post content..."
274
+ }
275
+ ]
276
+ }
277
+ ```
278
+
279
+ Result fields:
280
+
281
+ | Field | Type | Description |
282
+ |---|---|---|
283
+ | pid | integer | Post ID |
284
+ | tid | integer | Topic ID |
285
+ | uid | integer | Author UID |
286
+ | cid | integer | Category ID |
287
+ | score | number | Semantic similarity score from the vector search |
288
+ | content | string | Post content retrieved from NodeBB |
289
+
290
+ Search behavior:
291
+
292
+ 1. Generates an embedding for the query.
293
+ 2. Searches Qdrant for candidate posts.
294
+ 3. Checks candidate category exclusions.
295
+ 4. Checks post and topic read permissions for the service user.
296
+ 5. Retrieves permitted post content from NodeBB.
297
+ 6. Returns at most the requested number of valid results.
298
+
299
+ The implementation may retrieve more candidates than the requested limit to compensate for permission filtering.
300
+
301
+ In Fake AI mode, the tool returns an AI-disabled error. It does not perform semantic search.
302
+
303
+ ### 5.6 create_topic
304
+
305
+ Creates a topic in a NodeBB category as the configured service user.
306
+
307
+ Arguments:
308
+
309
+ | Name | Type | Required | Constraints |
310
+ |---|---|---|---|
311
+ | cid | integer | Yes | Minimum 1 |
312
+ | title | string | Yes | 1–255 characters |
313
+ | content | string | Yes | 1–20000 characters |
314
+ | tags | array of strings | No | Maximum 10 tags; each 1–32 characters |
315
+
316
+ Example:
317
+
318
+ ```json
319
+ {
320
+ "cid": 3,
321
+ "title": "New discussion",
322
+ "content": "The opening post content.",
323
+ "tags": ["discussion", "help"]
324
+ }
325
+ ```
326
+
327
+ If `tags` is omitted, an empty array is used.
328
+
329
+ The title is trimmed before submission. Content is passed to NodeBB without trimming.
330
+
331
+ NodeBB performs category permission checks, posting restrictions, tag validation and native creation hooks.
332
+
333
+ The response is the result returned by the native NodeBB topic creation method.
334
+
335
+ ### 5.7 delete_topic
336
+
337
+ Soft-deletes a topic using native NodeBB permissions and hooks.
338
+
339
+ Arguments:
340
+
341
+ | Name | Type | Required | Constraints |
342
+ |---|---|---|---|
343
+ | tid | integer | Yes | Minimum 1 |
344
+
345
+ Example:
346
+
347
+ ```json
348
+ {
349
+ "tid": 42
350
+ }
351
+ ```
352
+
353
+ This is a soft-delete operation, not permanent deletion.
354
+
355
+ The response is the native NodeBB operation result.
356
+
357
+ ### 5.8 restore_topic
358
+
359
+ Restores a previously soft-deleted topic.
360
+
361
+ Arguments:
362
+
363
+ | Name | Type | Required | Constraints |
364
+ |---|---|---|---|
365
+ | tid | integer | Yes | Minimum 1 |
366
+
367
+ Example:
368
+
369
+ ```json
370
+ {
371
+ "tid": 42
372
+ }
373
+ ```
374
+
375
+ NodeBB checks the acting user's permissions and executes its native restore hooks.
376
+
377
+ Restoring a topic does not automatically restore posts that were separately deleted.
378
+
379
+ The response is the native NodeBB operation result.
380
+
381
+ ### 5.9 list_topics
382
+
383
+ Lists topics visible to the configured service user.
384
+
385
+ Arguments:
386
+
387
+ | Name | Type | Required | Constraints |
388
+ |---|---|---|---|
389
+ | start | integer | No | 0–10000000; default 0 |
390
+ | limit | integer | No | 1–100; default 20 |
391
+ | sort | string | No | One of the supported values; default `recent` |
392
+ | cid | integer | No | Minimum 1; optional category filter |
393
+
394
+ Supported sort values:
395
+
396
+ | Value | Description |
397
+ |---|---|
398
+ | recent | Recent activity |
399
+ | old | Older topics |
400
+ | create | Creation ordering |
401
+ | posts | Post-count ordering |
402
+ | votes | Vote ordering |
403
+ | views | View-count ordering |
404
+
405
+ Example:
406
+
407
+ ```json
408
+ {
409
+ "start": 0,
410
+ "limit": 20,
411
+ "sort": "recent",
412
+ "cid": 3
413
+ }
414
+ ```
415
+
416
+ Response contains the native NodeBB topic listing result and pagination metadata:
417
+
418
+ | Field | Type | Description |
419
+ |---|---|---|
420
+ | topics | array | Topic records returned by NodeBB |
421
+ | topicCount | integer | Total count reported by NodeBB |
422
+ | nextStart | integer | Suggested offset for the next request |
423
+ | hasMore | boolean | `hasMore` is an indication of possible additional results based on NodeBB's total count. It does not guarantee that the next request will return a non-empty page. |
424
+
425
+ The exact topic record fields are provided by the installed NodeBB version.
426
+ ### 5.10 create_post
427
+
428
+ Creates a reply in an existing topic.
429
+
430
+ This tool creates a reply, not a new topic or a replacement for the topic's first post.
431
+
432
+ Arguments:
433
+
434
+ | Name | Type | Required | Constraints |
435
+ |---|---|---|---|
436
+ | tid | integer | Yes | Minimum 1 |
437
+ | content | string | Yes | 1–20000 characters |
438
+
439
+ Example:
440
+
441
+ ```json
442
+ {
443
+ "tid": 42,
444
+ "content": "This is a reply."
445
+ }
446
+ ```
447
+
448
+ The reply is created as the configured service user.
449
+
450
+ NodeBB checks reply permissions, topic state, category permissions and native posting restrictions.
451
+
452
+ The response is the native NodeBB reply creation result.
453
+
454
+ ### 5.11 edit_post
455
+
456
+ Edits an existing post.
457
+
458
+ Arguments:
459
+
460
+ | Name | Type | Required | Constraints |
461
+ |---|---|---|---|
462
+ | pid | integer | Yes | Minimum 1 |
463
+ | content | string | Yes | 1–20000 characters |
464
+
465
+ Example:
466
+
467
+ ```json
468
+ {
469
+ "pid": 123,
470
+ "content": "Updated post content."
471
+ }
472
+ ```
473
+
474
+ The configured service user is the acting user.
475
+
476
+ NodeBB applies native edit permissions and restrictions. Native hooks and edit history behavior are preserved.
477
+
478
+ The response is the native NodeBB edit result.
479
+
480
+ ### 5.12 delete_post
481
+
482
+ Soft-deletes a post.
483
+
484
+ Arguments:
485
+
486
+ | Name | Type | Required | Constraints |
487
+ |---|---|---|---|
488
+ | pid | integer | Yes | Minimum 1 |
489
+
490
+ Example:
491
+
492
+ ```json
493
+ {
494
+ "pid": 123
495
+ }
496
+ ```
497
+
498
+ NodeBB applies native post deletion permissions and hooks.
499
+
500
+ This is not permanent deletion. No purge operation is invoked.
501
+
502
+ The response is the native NodeBB delete result.
503
+
504
+ ### 5.13 restore_post
505
+
506
+ Restores a soft-deleted post.
507
+
508
+ Arguments:
509
+
510
+ | Name | Type | Required | Constraints |
511
+ |---|---|---|---|
512
+ | pid | integer | Yes | Minimum 1 |
513
+
514
+ Example:
515
+
516
+ ```json
517
+ {
518
+ "pid": 123
519
+ }
520
+ ```
521
+
522
+ NodeBB applies native restore permissions and hooks.
523
+
524
+ The response is the native NodeBB restore result.
525
+
526
+ ### 5.14 delete_user_posts
527
+
528
+ Soft-deletes replies authored by a specified user.
529
+
530
+ The first post of every topic is always skipped. The tool does not delete topic main posts.
531
+
532
+ Arguments:
533
+
534
+ | Name | Type | Required | Constraints |
535
+ |---|---|---|---|
536
+ | uid | integer | Yes | Target user UID; minimum 1 |
537
+ | start | integer | No | 0–10000000; default 0 |
538
+ | limit | integer | No | 1–100; default 100 |
539
+
540
+ Example:
541
+
542
+ ```json
543
+ {
544
+ "uid": 25,
545
+ "start": 0,
546
+ "limit": 100
547
+ }
548
+ ```
549
+
550
+ The configured service user performs the deletion. The supplied `uid` identifies the target author only.
551
+
552
+ The operation processes posts sequentially and continues after individual deletion failures.
553
+
554
+ Errors from individual deletion operations are included in the `failed` array. Such errors do not, by themselves, stop processing of the remaining posts or mean that the entire tool call has failed.
555
+
556
+ Posts are skipped when they are invalid, missing, already deleted, no longer belong to the target user, or are the main post of a topic.
557
+
558
+ Response:
559
+
560
+ | Field | Type | Description |
561
+ |---|---|---|
562
+ | uid | integer | Target user UID |
563
+ | scanned | integer | Number of IDs returned by the current page |
564
+ | deleted | integer | Number of successfully soft-deleted replies |
565
+ | skipped | integer | Number of posts skipped |
566
+ | failed | array | Individual deletion failures |
567
+ | hasMore | boolean | Whether the returned ID page filled the requested limit |
568
+ | nextStart | integer | Suggested offset for the next batch |
569
+
570
+ Each `failed` entry contains:
571
+
572
+ ```json
573
+ {
574
+ "pid": 123,
575
+ "error": "Permission denied"
576
+ }
577
+ ```
578
+
579
+ Example response:
580
+
581
+ ```json
582
+ {
583
+ "uid": 25,
584
+ "scanned": 100,
585
+ "deleted": 85,
586
+ "skipped": 10,
587
+ "failed": [
588
+ {
589
+ "pid": 456,
590
+ "error": "Permission denied"
591
+ }
592
+ ],
593
+ "hasMore": true,
594
+ "nextStart": 15
595
+ }
596
+ ```
597
+
598
+ The example is illustrative; actual counts depend on the returned IDs and operation results.
599
+
600
+ #### Batch processing
601
+
602
+ Use `nextStart` from the previous response as the next request's `start`:
603
+
604
+ ```json
605
+ {
606
+ "uid": 25,
607
+ "start": 15,
608
+ "limit": 100
609
+ }
610
+ ```
611
+
612
+ Successful deletions are removed from the user's active post listing. The implementation adjusts `nextStart` by subtracting the number of successfully deleted posts to avoid skipping remaining replies.
613
+
614
+ `hasMore` is based on whether the current ID page contains the full requested number of IDs. It is a pagination hint; an additional request may return an empty page.
615
+
616
+ This operation is not a permanent purge. Topic main posts are never deleted by this tool.
617
+
618
+ ### 5.15 list_posts
619
+
620
+ Lists posts in a topic, using NodeBB access filtering and pagination.
621
+
622
+ Arguments:
623
+
624
+ | Name | Type | Required | Constraints |
625
+ |---|---|---|---|
626
+ | tid | integer | Yes | Minimum 1 |
627
+ | start | integer | No | 0–10000000; default 0 |
628
+ | limit | integer | No | 1–100; default 20 |
629
+ | reverse | boolean | No | Default false |
630
+
631
+ Example:
632
+
633
+ ```json
634
+ {
635
+ "tid": 42,
636
+ "start": 0,
637
+ "limit": 20,
638
+ "reverse": false
639
+ }
640
+ ```
641
+
642
+ Response:
643
+
644
+ | Field | Type | Description |
645
+ |---|---|---|
646
+ | tid | integer | Topic ID |
647
+ | start | integer | Requested offset |
648
+ | limit | integer | Requested page size |
649
+ | reverse | boolean | Reverse ordering flag |
650
+ | posts | array | NodeBB post records returned for the topic |
651
+ | total | integer | Topic post count reported by NodeBB |
652
+ | nextStart | integer | Suggested next offset |
653
+ | hasMore | boolean | `hasMore` is an indication of possible additional results based on NodeBB's total count. It does not guarantee that the next request will return a non-empty page. |
654
+
655
+ Post record fields are provided by the installed NodeBB version.
656
+
657
+ The service user's topic read permission is checked before the post list is retrieved. Deleted or inaccessible topics are not returned.
658
+ ## 6. Pagination
659
+
660
+ The listing tools use zero-based offsets.
661
+
662
+ | Tool | Default start | Default limit | Maximum limit |
663
+ |---|---:|---:|---:|
664
+ | list_topics | 0 | 20 | 100 |
665
+ | list_posts | 0 | 20 | 100 |
666
+ | delete_user_posts | 0 | 100 | 100 |
667
+
668
+ For listing tools, use the returned `nextStart` for the next request when `hasMore` is true.
669
+
670
+ For bulk deletion, always use the returned `nextStart`, because successful deletions change the active post list.
671
+
672
+ ## 7. Errors
673
+
674
+ The MCP server returns execution errors as text with `isError: true`.
675
+
676
+ Common error situations:
677
+
678
+ | Situation | Behavior |
679
+ |---|---|
680
+ | Invalid arguments | Tool validation error |
681
+ | Unknown or extra argument | Rejected |
682
+ | Invalid ID | Rejected |
683
+ | MCP disabled | Internal API rejects the request |
684
+ | Invalid internal token | Internal API returns unauthorized |
685
+ | Missing or inaccessible post/topic | Reported as not found for protected reads |
686
+ | NodeBB permission failure | Native NodeBB operation error |
687
+ | AI provider disabled | Semantic search unavailable |
688
+ | Internal operation failure | Tool returns an error |
689
+
690
+ For `search_knowledge`, AI-disabled mode is an explicit error. Other search infrastructure failures are also reported as errors.
691
+
692
+ Bulk deletion is different from single-item operations: individual failures are collected in `failed`, and processing continues with subsequent IDs.
693
+
694
+ ## 8. Safety and operational notes
695
+
696
+ - Use a dedicated NodeBB service account with only the permissions required for the intended operations.
697
+ - Do not expose the MCP internal API token.
698
+ - Bind to `127.0.0.1` unless remote access is intentionally required.
699
+ - Use a secure network path when exposing MCP remotely.
700
+ - Deletion tools perform soft deletion, not permanent purge.
701
+ - `delete_user_posts` skips topic main posts.
702
+ - Restoring a topic does not restore separately deleted posts.
703
+ - Semantic search returns only posts accessible to the configured service user.
704
+ - The plugin does not trust a client-supplied acting UID.
705
+
706
+ ## 9. Compatibility
707
+
708
+ The plugin targets NodeBB 4.x and requires Node.js >= 22.
709
+
710
+ The 0.6.0 implementation was checked against NodeBB 4.16.7.
711
+
712
+ Native NodeBB response fields may vary between NodeBB versions. The plugin uses native NodeBB methods for creation, editing, deletion, restoration and listing.
713
+
714
+ ## 10. Related documentation
715
+
716
+ - [Project README](../README.md)
717
+ - [Русская документация MCP](MCP.ru.md)
718
+ - [Русский README](../README.ru.md)