nodebb-plugin-ai-connect
v1.0.7
Published
Goldnat AI Connect — WebMCP Protocol Bridge for NodeBB
Maintainers
Readme
NodeBB AI Connect
GoldT WebMCP bridge for NodeBB. Implements the GACP (GoldT AI Connect Protocol) — an OAuth2 / PKCE authenticated bridge that exposes 12 AI tools over a stable HTTP+JSON contract, so any GACP-aware AI agent (Claude, ChatGPT, Gemini, Grok, etc.) can read and manage your NodeBB forum.
- 7 free tools —
getCategories,getTopics,getTopic,getPost,searchTopics,getUserProfile,getRecentTopics - 5 pro tools —
createTopic,replyToTopic,editPost,sendMessage,followTopic - OAuth 2.0 authorization-code flow with mandatory PKCE (S256)
- Per-token rate limiting (configurable per-minute + per-hour windows)
- Token Management UI at
/account/tokens(list / filter / revoke) - Audit log for all OAuth events and tool executions
- Cascade revoke on user delete + lazy auto-cleanup of expired tokens
Architecture
┌─────────────┐ HTTPS ┌──────────────────┐
│ AI agent │ ──────────► │ NodeBB │
│ (Claude…) │ │ (Express) │
└─────────────┘ │ │
│ /api/ai-connect │
│ /oauth │
│ /account/tokens │
│ │
└────────┬─────────┘
│
▼
┌──────────────────────┐
│ MariaDB │
│ (nodebb_aiconnect) │
└──────────────────────┘The plugin mounts as a standard NodeBB plugin (static:app.load hook) and
adds Express routes on top of NodeBB. It stores OAuth clients, codes,
tokens, rate-limit counters, audit log, and the user token registry in its
own MariaDB database — separate from NodeBB's main DB.
Prerequisites
| Component | Version | |-----------|---------| | NodeBB | ≥ 3.0.0 | | Node.js | ≥ 18.0.0 | | MariaDB / MySQL | 10.5+ / 8.0+ |
Installation
# 1. Clone into NodeBB plugins directory
cd /path/to/nodebb/node_modules
git clone https://github.com/chgold/nodebb-ai-connect.git nodebb-plugin-ai-connect
# 2. Install deps
cd nodebb-plugin-ai-connect
npm install
# 3. Configure env
cp .env.example .env
$EDITOR .env
# 4. Activate plugin in NodeBB admin → Extend → Plugins
# 5. Restart NodeBB
./nodebb restartThe plugin auto-creates its database schema on first start (idempotent — safe to re-run).
Environment variables
All variables marked required are validated at startup; NodeBB will log a fatal error if any are missing.
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| NODEBB_AI_CONNECT_URL | yes | — | Public URL used in manifest + OAuth redirects |
| NODEBB_AICONNECT_DB_HOST | no | 127.0.0.1 | DB host (ignored if DB_SOCKET is set) |
| NODEBB_AICONNECT_DB_PORT | no | 3306 | DB port |
| NODEBB_AICONNECT_DB_SOCKET | no | /run/mysqld/mysqld.sock | Unix socket path for DB |
| NODEBB_AICONNECT_DB_USER | yes | — | DB user |
| NODEBB_AICONNECT_DB_PASSWORD | yes | — | DB password |
| NODEBB_AICONNECT_DB_NAME | yes | — | DB name (must already exist) |
| NODEBB_AICONNECT_RL_PER_MINUTE | no | 50 | Hard limit per token per minute |
| NODEBB_AICONNECT_RL_PER_HOUR | no | 1000 | Hard limit per token per hour |
| NODEBB_AICONNECT_ALLOW_INSECURE_REDIRECT | no | false | Allow http:// redirect_uri (DEV ONLY) |
| NODEBB_AICONNECT_CLEANUP_CRON | no | 0 3 * * * | Daily cron schedule for expired-token cleanup |
| NODE_ENV | no | development | production enables strict redirect_uri validation |
OAuth setup walkthrough
- Manifest discovery. The AI agent fetches
GET /api/ai-connect/manifestto learn endpoints, scopes, and the list of 12 tools. - Authorization (PKCE-only). Agent generates a 32-byte random
code_verifier, computescode_challenge = base64url(SHA-256(code_verifier)), and opens a browser at/oauth/authorize?response_type=code&client_id=…&code_challenge=…&code_challenge_method=S256&scope=read+write&state=… - Consent. The user logs in (NodeBB session) and approves the request.
- Token exchange. Agent POSTs to
/api/ai-connect/tokenwithgrant_type=authorization_code, thecode, the matchingcode_verifierand the sameclient_id. The bridge verifies the SHA-256 match and returnsaccess_token(1h) +refresh_token(30d). - Tool calls. Agent sends
Authorization: Bearer <access_token>to any of the 12 tool endpoints.
Tools
Free tools (read-only — scope read)
# 1. List categories
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getCategories \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -d '{}'
# 2. List topics in a category
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getTopics \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"cid": 1, "limit": 20}'
# 3. Get a topic with its posts
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getTopic \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tid": 42}'
# 4. Get a single post
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getPost \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"pid": 123}'
# 5. Search topics
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.searchTopics \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"query": "welcome", "limit": 10}'
# 6. Get user profile
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getUserProfile \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"uid": 1}'
# 7. Recent topics across all categories
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.getRecentTopics \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"limit": 10}'Pro tools (require write scope)
# 8. Create new topic
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.createTopic \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"cid": 1, "title": "Hello", "content": "Hi from AI"}'
# 9. Reply to topic
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.replyToTopic \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tid": 42, "content": "Great post!"}'
# 10. Edit a post
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.editPost \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"pid": 123, "content": "Updated text"}'
# 11. Send a private message
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.sendMessage \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"toUid": 2, "content": "Hello"}'
# 12. Follow / unfollow a topic
curl -X POST http://localhost:8089/api/ai-connect/v1/tools/nodebb.followTopic \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"tid": 42, "follow": true}'All endpoints return:
{ "success": true, "data": { /* tool-specific payload */ } }…or on failure:
{ "success": false, "code": "invalid_input|not_found|unauthorized|forbidden|rate_limited|upstream_error|internal_error", "message": "human-readable" }Response headers
Every response carries:
| Header | Meaning |
|--------|---------|
| X-Request-Id | uuid v4 for request correlation |
| X-RateLimit-Limit | per-minute cap |
| X-RateLimit-Remaining | remaining requests in current minute window |
| X-RateLimit-Reset | epoch seconds when the minute window resets |
| X-RateLimit-Limit-Hour / -Remaining-Hour / -Reset-Hour | same for hour window |
| Retry-After | (on 429) seconds to wait before retrying |
Token Management UI
Users manage their own AI Connect tokens at /account/tokens:
- 5 filters: active / unused (≥30d) / inactive (≥180d) / expired / revoked
- Bulk revoke: unused, inactive, or all tokens at once
- Last-used tracking:
last_used_at,last_used_ip,last_used_uaper token - Cascade revoke on user delete (
static:user.deletehook) - Lazy auto-cleanup triggered by Bearer auth middleware (configurable rules)
Admin API (admin-only):
GET /api/ai-connect/admin/tokens— list with same 5 filtersPOST /api/ai-connect/admin/tokens/revoke-unused— revoke all unused tokensPOST /api/ai-connect/admin/tokens/revoke-inactive— revoke all inactivePOST /api/ai-connect/admin/tokens/revoke-all— revoke everything (use with care)
Development
npm install
cp .env.example .env
npm test # 130 tests across 10 suites (mocha)
npm run test:coverage # nyc HTML report
npm run lint
npm run build # produces dist/nodebb-ai-connect-X.Y.Z.zipTests use a hand-rolled in-memory DB adapter (test/helpers/mockDb.js) so
no real MariaDB is required.
Health
curl http://localhost:8089/api/ai-connect/info
# {"name":"AI Connect","version":"1.0.1","tools":12,...}License
GPL-3.0 — see LICENSE.
