@tiledesk/tiledesk-server 2.23.0 → 2.24.1

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 CHANGED
@@ -5,7 +5,16 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
+ # 2.24.1
9
+ - Added native MCP servers catalog and endpoints to list, connect and retrieve tools
10
+ - Added endpoint to save native and custom MCP servers in the project integration
11
+ - Improved MCP authentication with custom headers and additional auth types
12
+ - Improved MCP connection handshake with protocol version fallback and session initialization
13
+
8
14
  # 2.23.1
15
+ - Restored cross-project access for global subscriptions (`id_project: '*'` or `global: true`); bots and project-bound subscriptions remain scoped to their own project
16
+
17
+ # 2.23.0
9
18
  - Deprecated JWT helper routes (`/jwt/decode`, `/jwt/generatetestjwt`); they now return 410
10
19
  - Restricted bot and subscription tokens to their own project (cross-project access denied)
11
20
  - Improved error response sanitization for integration routes
package/Dockerfile CHANGED
@@ -1,7 +1,4 @@
1
- FROM node:18-bullseye
2
-
3
- RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
-
1
+ FROM node:18-bookworm
5
2
 
6
3
  RUN apt-get update
7
4
 
package/Dockerfile-en CHANGED
@@ -1,6 +1,4 @@
1
- FROM node:18-bullseye
2
-
3
- RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
1
+ FROM node:18-bookworm
4
2
 
5
3
  RUN apt-get update
6
4
 
package/Dockerfile-jobs CHANGED
@@ -1,6 +1,4 @@
1
- FROM node:18-bullseye
2
-
3
- RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
1
+ FROM node:18-bookworm
4
2
 
5
3
  RUN apt-get update
6
4
 
@@ -1,7 +1,4 @@
1
- FROM node:18-bullseye
2
-
3
- RUN sed -i 's/stable\/updates/stable-security\/updates/' /etc/apt/sources.list
4
-
1
+ FROM node:18-bookworm
5
2
 
6
3
  RUN apt-get update
7
4
 
package/app.js CHANGED
@@ -93,6 +93,9 @@ let tdCache = new TdCache({
93
93
 
94
94
  tdCache.connect();
95
95
 
96
+ const mcpService = require('./services/mcpService');
97
+ mcpService.setTdCache(tdCache);
98
+
96
99
  // ROUTES DECLARATION
97
100
  var troubleshooting = require('./routes/troubleshooting');
98
101
  var auth = require('./routes/auth');
@@ -0,0 +1,18 @@
1
+ [
2
+ {
3
+ "id": "tiledesk-communicator",
4
+ "name": "Tiledesk Communicator",
5
+ "url": "https://stage.eks.tiledesk.com/mcp-tools/communicator/mcp",
6
+ "native": true,
7
+ "transport": "streamable_http",
8
+ "description": "Tiledesk Communicator is a MCP server that allows you to communicate with the Tiledesk platform."
9
+ },
10
+ {
11
+ "id": "tiledesk-data-table",
12
+ "name": "Tiledesk Data Table",
13
+ "url": "https://stage.eks.tiledesk.com/mcp-tools/data-table/mcp",
14
+ "native": true,
15
+ "transport": "streamable_http",
16
+ "description": "Tiledesk Data Table is a MCP server that allows you to manage data tables in the Tiledesk platform."
17
+ }
18
+ ]
@@ -44,6 +44,9 @@ class RoleChecker {
44
44
  if (!user || user.id_project == null || projectid == null) {
45
45
  return false;
46
46
  }
47
+ if (!(user instanceof Faq_kb) && (String(user.id_project) === '*' || user.global === true)) {
48
+ return true;
49
+ }
47
50
  return String(user.id_project) === String(projectid);
48
51
  }
49
52
 
@@ -321,7 +321,7 @@ module.exports = function(passport) {
321
321
 
322
322
  } else if (subject=="subscription") {
323
323
 
324
- Subscription.findOne({_id: identifier}, function(err, subscription) {
324
+ Subscription.findOne({_id: identifier}).select('+global').exec(function(err, subscription) {
325
325
  if (err) {
326
326
  winston.error("Passport JWT subscription err", err);
327
327
  return done(err, false);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-server",
3
3
  "description": "The Tiledesk server module",
4
- "version": "2.23.0",
4
+ "version": "2.24.1",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -4,13 +4,12 @@ var winston = require('../../config/winston');
4
4
  var configGlobal = require('../../config/global');
5
5
 
6
6
  var port = process.env.PORT || '3000';
7
+ let TILEBOT_ENDPOINT = process.env.API_ENDPOINT ? process.env.API_ENDPOINT + "/modules/tilebot/ext/" : ("http://localhost:" + port + "/modules/tilebot/ext/");
7
8
 
8
- let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";;
9
9
  if (process.env.TILEBOT_ENDPOINT) {
10
- TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/"
10
+ TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/";
11
11
  }
12
-
13
- winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
12
+ winston.info("[tilebot/listener] TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
14
13
 
15
14
  /**
16
15
  * process.env.API_ENDPOINT --> Internal url of the server inside the cluster
@@ -34,11 +34,12 @@ const uuidv4 = require('uuid/v4');
34
34
  var jwt = require('jsonwebtoken');
35
35
 
36
36
  const port = process.env.PORT || '3000';
37
- let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";;
37
+ let TILEBOT_ENDPOINT = process.env.API_ENDPOINT ? process.env.API_ENDPOINT + "/modules/tilebot/ext/" : ("http://localhost:" + port + "/modules/tilebot/ext/");
38
+
38
39
  if (process.env.TILEBOT_ENDPOINT) {
39
- TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/"
40
+ TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/";
40
41
  }
41
- winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
42
+ winston.info("[rulesTrigger] TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
42
43
 
43
44
  class RulesTrigger {
44
45
 
@@ -15,6 +15,12 @@ router.get('/', function (req, res) {
15
15
  function (req, res) {
16
16
  res.send('{"success":true}');
17
17
  });
18
+
19
+ router.get('/subscription', [
20
+ roleChecker.hasRoleOrTypes(null,['subscription'])],
21
+ function (req, res) {
22
+ res.send('{"success":true}');
23
+ });
18
24
 
19
25
  router.get('/noentitycheck',
20
26
  [noentitycheck,
package/routes/faq_kb.js CHANGED
@@ -284,11 +284,12 @@ router.put('/:faq_kbid/publish', roleChecker.hasRole('admin'), async (req, res)
284
284
  botEvent.emit('faqbot.update', updatedForkedChabot);
285
285
 
286
286
  const port = process.env.PORT || '3000';
287
- let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";;
287
+ let TILEBOT_ENDPOINT = process.env.API_ENDPOINT ? process.env.API_ENDPOINT + "/modules/tilebot/ext/" : ("http://localhost:" + port + "/modules/tilebot/ext/");
288
+
288
289
  if (process.env.TILEBOT_ENDPOINT) {
289
- TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/"
290
+ TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/";
290
291
  }
291
- winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
292
+ winston.info("[RequestService] TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
292
293
 
293
294
  let updatedOriginalChabot = await Faq_kb.findByIdAndUpdate(id_faq_kb, { url: TILEBOT_ENDPOINT + forkedChatBotId }, { new: true, upsert: true }).exec();
294
295
  winston.debug("updatedOriginalChabot: ", updatedOriginalChabot);
package/routes/mcp.js CHANGED
@@ -2,36 +2,125 @@ let express = require('express');
2
2
  let router = express.Router();
3
3
  let winston = require('../config/winston');
4
4
  const mcpService = require('../services/mcpService');
5
- const Project = require('../models/project');
5
+
6
+
7
+ /**
8
+ * GET /mcp/native
9
+ * Returns the list of available native MCP servers (without URLs)
10
+ */
11
+ router.get('/native', async (req, res) => {
12
+ try {
13
+ const servers = await mcpService.getNativeServersPublic();
14
+ res.status(200).send(servers);
15
+ } catch (error) {
16
+ winston.error('Error getting native MCP servers:', error);
17
+ res.status(500).send({ success: false, error: error.message || 'Error getting native MCP servers' });
18
+ }
19
+ });
20
+
21
+ /**
22
+ * POST /mcp/native/:nativeId/connect
23
+ * Initializes a connection to a native MCP server
24
+ */
25
+ router.post('/native/:nativeId/connect', async (req, res) => {
26
+ try {
27
+ const id_project = req.projectid;
28
+ const { nativeId } = req.params;
29
+
30
+ const serverConfig = await mcpService.resolveNativeServerConfig(nativeId, id_project);
31
+ const result = await mcpService.connectServer(serverConfig);
32
+
33
+ res.status(200).send({
34
+ success: true,
35
+ message: 'Native MCP server connected successfully',
36
+ nativeId,
37
+ capabilities: result.capabilities,
38
+ tools: result.tools
39
+ });
40
+ } catch (error) {
41
+ winston.error('Error connecting to native MCP server:', error);
42
+ res.status(error.statusCode || 500).send({
43
+ success: false,
44
+ error: error.message || 'Error connecting to native MCP server'
45
+ });
46
+ }
47
+ });
48
+
49
+ /**
50
+ * POST /mcp/native/:nativeId/tools
51
+ * Gets the list of tools from a native MCP server
52
+ */
53
+ router.post('/native/:nativeId/tools', async (req, res) => {
54
+ try {
55
+ const id_project = req.projectid;
56
+ const { nativeId } = req.params;
57
+
58
+ const serverConfig = await mcpService.resolveNativeServerConfig(nativeId, id_project);
59
+ const tools = await mcpService.listTools(serverConfig);
60
+
61
+ res.status(200).send(tools);
62
+ } catch (error) {
63
+ winston.error('Error getting tools from native MCP server:', error);
64
+ res.status(error.statusCode || 500).send({
65
+ success: false,
66
+ error: error.message || 'Error getting tools from native MCP server'
67
+ });
68
+ }
69
+ });
70
+
71
+ /**
72
+ * POST /mcp/servers
73
+ * Adds or updates an MCP server in the project mcp integration
74
+ * Body (native): { type: 'native', nativeId, tools?, selectedTools? }
75
+ * Body (custom): { type: 'custom', name, url, transport?, customHeaders?, tools?, selectedTools?, auth? }
76
+ */
77
+ router.post('/servers', async (req, res) => {
78
+ try {
79
+ const id_project = req.projectid;
80
+ const result = await mcpService.upsertMcpServerInIntegration(id_project, req.body);
81
+
82
+ res.status(200).send({
83
+ success: true,
84
+ server: result.server,
85
+ integration: result.integration
86
+ });
87
+ } catch (error) {
88
+ winston.error('Error saving MCP server in integration:', error);
89
+ res.status(error.statusCode || 500).send({
90
+ success: false,
91
+ error: error.message || 'Error saving MCP server in integration'
92
+ });
93
+ }
94
+ });
6
95
 
7
96
  /**
8
97
  * POST /mcp/connect
9
98
  * Initializes a connection to an MCP server
10
- * Body: { url: string, auth?: { type: 'bearer'|'api_key'|'basic', token?: string, key?: string, username?: string, password?: string } }
99
+ * Body: {
100
+ * url: string,
101
+ * customHeaders?: [{ key: string, value: string }],
102
+ * oauth?: object (not supported yet),
103
+ * auth?: object (legacy, optional)
104
+ * }
11
105
  */
12
106
  router.post('/connect', async (req, res) => {
13
107
  try {
14
108
  const id_project = req.projectid;
15
- const { url, auth } = req.body;
109
+ let serverConfig;
16
110
 
17
- if (!url) {
18
- return res.status(400).send({ success: false, error: "Missing required parameter 'url'" });
111
+ try {
112
+ serverConfig = mcpService.buildServerConfig(id_project, req.body);
113
+ } catch (error) {
114
+ return res.status(400).send({ success: false, error: error.message });
19
115
  }
20
116
 
21
- // Build server configuration
22
- const serverConfig = {
23
- url: url,
24
- projectId: id_project,
25
- auth: auth || undefined
26
- };
27
-
28
- // Initialize the connection
29
- const result = await mcpService.initializeServer(serverConfig);
117
+ const result = await mcpService.connectServer(serverConfig);
30
118
 
31
- res.status(200).send({
32
- success: true,
119
+ res.status(200).send({
120
+ success: true,
33
121
  message: 'MCP server connected successfully',
34
- capabilities: result?.capabilities || {}
122
+ capabilities: result.capabilities,
123
+ tools: result.tools
35
124
  });
36
125
  } catch (error) {
37
126
  winston.error(`Error connecting to MCP server:`, error);
@@ -42,25 +131,27 @@ router.post('/connect', async (req, res) => {
42
131
  /**
43
132
  * POST /mcp/tools
44
133
  * Gets the list of tools from an MCP server
45
- * Body: { url: string, auth?: object }
134
+ * Body: {
135
+ * url: string,
136
+ * customHeaders?: [{ key: string, value: string }],
137
+ * oauth?: object (not supported yet),
138
+ * auth?: object (legacy, optional)
139
+ * }
46
140
  */
47
141
  router.post('/tools', async (req, res) => {
48
142
  try {
49
143
  const id_project = req.projectid;
50
- const { url, auth } = req.body;
144
+ const { url } = req.body;
51
145
 
52
- if (!url) {
53
- return res.status(400).send({ success: false, error: "Missing required parameter 'url' in body" });
54
- }
146
+ winston.info(`MCP /tools called for project ${id_project}, url: ${url}`);
55
147
 
56
- // Build server configuration
57
- const serverConfig = {
58
- url: url,
59
- projectId: id_project,
60
- auth: auth || undefined
61
- };
148
+ let serverConfig;
149
+ try {
150
+ serverConfig = mcpService.buildServerConfig(id_project, req.body);
151
+ } catch (error) {
152
+ return res.status(400).send({ success: false, error: error.message });
153
+ }
62
154
 
63
- // listTools automatically initializes if necessary
64
155
  const tools = await mcpService.listTools(serverConfig);
65
156
 
66
157
  res.status(200).send(tools);
@@ -71,4 +162,3 @@ router.post('/tools', async (req, res) => {
71
162
  });
72
163
 
73
164
  module.exports = router;
74
-
package/routes/webhook.js CHANGED
@@ -13,11 +13,12 @@ var ObjectId = require('mongoose').Types.ObjectId;
13
13
  const default_embedding = require('../config/kb/embedding');
14
14
 
15
15
  const port = process.env.PORT || '3000';
16
- let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";
16
+ let TILEBOT_ENDPOINT = process.env.API_ENDPOINT ? process.env.API_ENDPOINT + "/modules/tilebot/ext/" : ("http://localhost:" + port + "/modules/tilebot/ext/");
17
+
17
18
  if (process.env.TILEBOT_ENDPOINT) {
18
- TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/"
19
+ TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/";
19
20
  }
20
- winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
21
+ winston.info("[RequestService] TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT);
21
22
 
22
23
  const KB_WEBHOOK_TOKEN = process.env.KB_WEBHOOK_TOKEN || 'kbcustomtoken';
23
24
  const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL;