@samanhappy/mcphub 0.6.2 → 0.7.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/README.md +36 -18
- package/README.zh.md +35 -17
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/controllers/configController.js +28 -0
- package/dist/controllers/configController.js.map +1 -0
- package/dist/controllers/serverController.js +83 -2
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/db/connection.js +279 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/entities/VectorEmbedding.js +62 -0
- package/dist/db/entities/VectorEmbedding.js.map +1 -0
- package/dist/db/entities/index.js +6 -0
- package/dist/db/entities/index.js.map +1 -0
- package/dist/db/index.js +32 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/repositories/BaseRepository.js +58 -0
- package/dist/db/repositories/BaseRepository.js.map +1 -0
- package/dist/db/repositories/VectorEmbeddingRepository.js +173 -0
- package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -0
- package/dist/db/repositories/index.js +4 -0
- package/dist/db/repositories/index.js.map +1 -0
- package/dist/db/subscribers/VectorEmbeddingSubscriber.js +56 -0
- package/dist/db/subscribers/VectorEmbeddingSubscriber.js.map +1 -0
- package/dist/db/types/postgresVectorType.js +33 -0
- package/dist/db/types/postgresVectorType.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.js +18 -8
- package/dist/middlewares/index.js.map +1 -1
- package/dist/routes/index.js +13 -9
- package/dist/routes/index.js.map +1 -1
- package/dist/server.js +18 -9
- package/dist/server.js.map +1 -1
- package/dist/services/mcpService.js +185 -3
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/sseService.js +15 -8
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/vectorSearchService.js +603 -0
- package/dist/services/vectorSearchService.js.map +1 -0
- package/frontend/dist/assets/favicon-DJnZjsC8.ico +0 -0
- package/frontend/dist/assets/index-D9p3VMBc.css +1 -0
- package/frontend/dist/assets/index-D_eNkDvW.js +148 -0
- package/frontend/dist/assets/index-D_eNkDvW.js.map +1 -0
- package/frontend/dist/index.html +3 -3
- package/package.json +15 -7
- package/frontend/dist/assets/favicon-DKeT5aEu.ico +0 -0
- package/frontend/dist/assets/index-B7KNaMJO.js +0 -148
- package/frontend/dist/assets/index-B7KNaMJO.js.map +0 -1
- package/frontend/dist/assets/index-DDs5RqXX.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/repositories/index.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,MAAM,gCAAgC,CAAC;AAEvE,0BAA0B;AAC1B,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { EventSubscriber } from 'typeorm';
|
|
8
|
+
import { VectorEmbedding } from '../entities/VectorEmbedding.js';
|
|
9
|
+
/**
|
|
10
|
+
* A subscriber to format vector embeddings before saving to database
|
|
11
|
+
*/
|
|
12
|
+
let VectorEmbeddingSubscriber = class VectorEmbeddingSubscriber {
|
|
13
|
+
/**
|
|
14
|
+
* Indicates that this subscriber only listens to VectorEmbedding events
|
|
15
|
+
*/
|
|
16
|
+
listenTo() {
|
|
17
|
+
return VectorEmbedding;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Called before entity insertion
|
|
21
|
+
*/
|
|
22
|
+
beforeInsert(event) {
|
|
23
|
+
this.formatEmbedding(event.entity);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Called before entity update
|
|
27
|
+
*/
|
|
28
|
+
beforeUpdate(event) {
|
|
29
|
+
if (event.entity && event.entity.embedding) {
|
|
30
|
+
this.formatEmbedding(event.entity);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format embedding as a proper vector string
|
|
35
|
+
*/
|
|
36
|
+
formatEmbedding(entity) {
|
|
37
|
+
if (!entity || !entity.embedding || !Array.isArray(entity.embedding)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// If the embedding is already a string, don't process it
|
|
41
|
+
if (typeof entity.embedding === 'string') {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Format array as proper pgvector string
|
|
45
|
+
// Ensure the string starts with '[' and ends with ']' as required by pgvector
|
|
46
|
+
const vectorString = `[${entity.embedding.join(',')}]`;
|
|
47
|
+
// Store the string directly (TypeORM will handle conversion)
|
|
48
|
+
// We need to use 'as any' because the type is declared as number[] but we're setting a string
|
|
49
|
+
entity.embedding = vectorString;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
VectorEmbeddingSubscriber = __decorate([
|
|
53
|
+
EventSubscriber()
|
|
54
|
+
], VectorEmbeddingSubscriber);
|
|
55
|
+
export { VectorEmbeddingSubscriber };
|
|
56
|
+
//# sourceMappingURL=VectorEmbeddingSubscriber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VectorEmbeddingSubscriber.js","sourceRoot":"","sources":["../../../src/db/subscribers/VectorEmbeddingSubscriber.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAA6B,eAAe,EAA4B,MAAM,SAAS,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE;;GAEG;AAEI,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;IACpC;;OAEG;IACH,QAAQ;QACN,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,KAAmC;QAC9C,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,KAAmC;QAC9C,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,MAAyB,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,MAAmC;QACzD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YACrE,OAAO;QACT,CAAC;QAED,yDAAyD;QACzD,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACzC,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,8EAA8E;QAC9E,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAEvD,6DAA6D;QAC7D,8FAA8F;QAC7F,MAAc,CAAC,SAAS,GAAG,YAAY,CAAC;IAC3C,CAAC;CACF,CAAA;AA7CY,yBAAyB;IADrC,eAAe,EAAE;GACL,yBAAyB,CA6CrC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register the PostgreSQL vector type with TypeORM
|
|
3
|
+
* @param dataSource TypeORM data source
|
|
4
|
+
*/
|
|
5
|
+
export function registerPostgresVectorType(dataSource) {
|
|
6
|
+
// Skip if not postgres
|
|
7
|
+
if (dataSource.driver.options.type !== 'postgres') {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
// Get the postgres driver
|
|
11
|
+
const pgDriver = dataSource.driver;
|
|
12
|
+
// Add 'vector' to the list of supported column types
|
|
13
|
+
if (pgDriver.supportedDataTypes) {
|
|
14
|
+
pgDriver.supportedDataTypes.push('vector');
|
|
15
|
+
}
|
|
16
|
+
// Override the normalization for the vector type
|
|
17
|
+
if (pgDriver.dataTypeDefaults) {
|
|
18
|
+
pgDriver.dataTypeDefaults['vector'] = {
|
|
19
|
+
type: 'vector',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Override the column type resolver to prevent it from converting vector to other types
|
|
23
|
+
const originalColumnTypeResolver = pgDriver.columnTypeResolver;
|
|
24
|
+
if (originalColumnTypeResolver) {
|
|
25
|
+
pgDriver.columnTypeResolver = (column) => {
|
|
26
|
+
if (column.type === 'vector') {
|
|
27
|
+
return 'vector';
|
|
28
|
+
}
|
|
29
|
+
return originalColumnTypeResolver(column);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=postgresVectorType.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresVectorType.js","sourceRoot":"","sources":["../../../src/db/types/postgresVectorType.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,UAAsB;IAC/D,uBAAuB;IACvB,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAClD,OAAO;IACT,CAAC;IAED,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC;IAEnC,qDAAqD;IACrD,IAAI,QAAQ,CAAC,kBAAkB,EAAE,CAAC;QAChC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAe,CAAC,CAAC;IACpD,CAAC;IAED,iDAAiD;IACjD,IAAK,QAAgB,CAAC,gBAAgB,EAAE,CAAC;QACtC,QAAgB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG;YAC7C,IAAI,EAAE,QAAQ;SACf,CAAC;IACJ,CAAC;IAED,wFAAwF;IACxF,MAAM,0BAA0B,GAAI,QAAgB,CAAC,kBAAkB,CAAC;IACxE,IAAI,0BAA0B,EAAE,CAAC;QAC9B,QAAgB,CAAC,kBAAkB,GAAG,CAAC,MAAW,EAAE,EAAE;YACrD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,OAAO,0BAA0B,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;AAElC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,UAAU,EAAE,CAAC;QAC7B,SAAS,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC;AAEP,eAAe,SAAS,CAAC,MAAM,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;AAElC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,UAAU,EAAE,CAAC;QAC7B,SAAS,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC;AAEP,eAAe,SAAS,CAAC,MAAM,EAAE,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { dirname } from 'path';
|
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import { auth } from './auth.js';
|
|
7
7
|
import { initializeDefaultUser } from '../models/User.js';
|
|
8
|
+
import config from '../config/index.js';
|
|
8
9
|
// Create __dirname equivalent for ES modules
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = dirname(__filename);
|
|
@@ -34,9 +35,14 @@ export const errorHandler = (err, _req, res, _next) => {
|
|
|
34
35
|
};
|
|
35
36
|
export const initMiddlewares = (app) => {
|
|
36
37
|
// Serve static files from the dynamically determined frontend path
|
|
37
|
-
|
|
38
|
+
// Note: Static files will be handled by the server directly, not here
|
|
38
39
|
app.use((req, res, next) => {
|
|
39
|
-
|
|
40
|
+
const basePath = config.basePath;
|
|
41
|
+
// Only apply JSON parsing for API and auth routes, not for SSE or message endpoints
|
|
42
|
+
if (req.path !== `${basePath}/sse` &&
|
|
43
|
+
req.path !== `${basePath}/messages` &&
|
|
44
|
+
!req.path.startsWith(`${basePath}/sse/`) &&
|
|
45
|
+
!req.path.startsWith(`${basePath}/mcp/`)) {
|
|
40
46
|
express.json()(req, res, next);
|
|
41
47
|
}
|
|
42
48
|
else {
|
|
@@ -44,14 +50,18 @@ export const initMiddlewares = (app) => {
|
|
|
44
50
|
}
|
|
45
51
|
});
|
|
46
52
|
// Initialize default admin user if no users exist
|
|
47
|
-
initializeDefaultUser().catch(err => {
|
|
53
|
+
initializeDefaultUser().catch((err) => {
|
|
48
54
|
console.error('Error initializing default user:', err);
|
|
49
55
|
});
|
|
50
|
-
// Protect
|
|
51
|
-
app.use(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
// Protect API routes with authentication middleware, but exclude auth endpoints
|
|
57
|
+
app.use(`${config.basePath}/api`, (req, res, next) => {
|
|
58
|
+
// Skip authentication for login and register endpoints
|
|
59
|
+
if (req.path === '/auth/login' || req.path === '/auth/register') {
|
|
60
|
+
next();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
auth(req, res, next);
|
|
64
|
+
}
|
|
55
65
|
});
|
|
56
66
|
app.use(errorHandler);
|
|
57
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAA4C,MAAM,SAAS,CAAC;AACnE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middlewares/index.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import { check } from 'express-validator';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import config from '../config/index.js';
|
|
4
|
+
import { getAllServers, getAllSettings, createServer, updateServer, deleteServer, toggleServer, updateSystemConfig, } from '../controllers/serverController.js';
|
|
5
|
+
import { getGroups, getGroup, createNewGroup, updateExistingGroup, deleteExistingGroup, addServerToExistingGroup, removeServerFromExistingGroup, getGroupServers, updateGroupServersBatch, } from '../controllers/groupController.js';
|
|
6
|
+
import { getAllMarketServers, getMarketServer, getAllMarketCategories, getAllMarketTags, searchMarketServersByQuery, getMarketServersByCategory, getMarketServersByTag, } from '../controllers/marketController.js';
|
|
6
7
|
import { login, register, getCurrentUser, changePassword } from '../controllers/authController.js';
|
|
7
8
|
import { getAllLogs, clearLogs, streamLogs } from '../controllers/logController.js';
|
|
9
|
+
import { getRuntimeConfig } from '../controllers/configController.js';
|
|
8
10
|
import { auth } from '../middlewares/auth.js';
|
|
9
11
|
const router = express.Router();
|
|
10
12
|
export const initRoutes = (app) => {
|
|
@@ -39,23 +41,25 @@ export const initRoutes = (app) => {
|
|
|
39
41
|
router.get('/logs', getAllLogs);
|
|
40
42
|
router.delete('/logs', clearLogs);
|
|
41
43
|
router.get('/logs/stream', streamLogs);
|
|
42
|
-
// Auth routes
|
|
43
|
-
|
|
44
|
+
// Auth routes - move to router instead of app directly
|
|
45
|
+
router.post('/auth/login', [
|
|
44
46
|
check('username', 'Username is required').not().isEmpty(),
|
|
45
47
|
check('password', 'Password is required').not().isEmpty(),
|
|
46
48
|
], login);
|
|
47
|
-
|
|
49
|
+
router.post('/auth/register', [
|
|
48
50
|
check('username', 'Username is required').not().isEmpty(),
|
|
49
51
|
check('password', 'Password must be at least 6 characters').isLength({ min: 6 }),
|
|
50
52
|
], register);
|
|
51
|
-
|
|
53
|
+
router.get('/auth/user', auth, getCurrentUser);
|
|
52
54
|
// Add change password route
|
|
53
|
-
|
|
55
|
+
router.post('/auth/change-password', [
|
|
54
56
|
auth,
|
|
55
57
|
check('currentPassword', 'Current password is required').not().isEmpty(),
|
|
56
58
|
check('newPassword', 'New password must be at least 6 characters').isLength({ min: 6 }),
|
|
57
59
|
], changePassword);
|
|
58
|
-
|
|
60
|
+
// Runtime configuration endpoint (no auth required for frontend initialization)
|
|
61
|
+
app.get(`${config.basePath}/config`, getRuntimeConfig);
|
|
62
|
+
app.use(`${config.basePath}/api`, router);
|
|
59
63
|
};
|
|
60
64
|
export default router;
|
|
61
65
|
//# sourceMappingURL=index.js.map
|
package/dist/routes/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -16,6 +16,7 @@ export class AppServer {
|
|
|
16
16
|
this.frontendPath = null;
|
|
17
17
|
this.app = express();
|
|
18
18
|
this.port = config.port;
|
|
19
|
+
this.basePath = config.basePath;
|
|
19
20
|
}
|
|
20
21
|
async initialize() {
|
|
21
22
|
try {
|
|
@@ -27,11 +28,11 @@ export class AppServer {
|
|
|
27
28
|
initUpstreamServers()
|
|
28
29
|
.then(() => {
|
|
29
30
|
console.log('MCP server initialized successfully');
|
|
30
|
-
this.app.get(
|
|
31
|
-
this.app.post(
|
|
32
|
-
this.app.post(
|
|
33
|
-
this.app.get(
|
|
34
|
-
this.app.delete(
|
|
31
|
+
this.app.get(`${this.basePath}/sse/:group?`, (req, res) => handleSseConnection(req, res));
|
|
32
|
+
this.app.post(`${this.basePath}/messages`, handleSseMessage);
|
|
33
|
+
this.app.post(`${this.basePath}/mcp/:group?`, handleMcpPostRequest);
|
|
34
|
+
this.app.get(`${this.basePath}/mcp/:group?`, handleMcpOtherRequest);
|
|
35
|
+
this.app.delete(`${this.basePath}/mcp/:group?`, handleMcpOtherRequest);
|
|
35
36
|
})
|
|
36
37
|
.catch((error) => {
|
|
37
38
|
console.error('Error initializing MCP server:', error);
|
|
@@ -52,17 +53,25 @@ export class AppServer {
|
|
|
52
53
|
this.frontendPath = this.findFrontendDistPath();
|
|
53
54
|
if (this.frontendPath) {
|
|
54
55
|
console.log(`Serving frontend from: ${this.frontendPath}`);
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
// Serve static files with base path
|
|
57
|
+
this.app.use(this.basePath, express.static(this.frontendPath));
|
|
58
|
+
// Add the wildcard route for SPA with base path
|
|
57
59
|
if (fs.existsSync(path.join(this.frontendPath, 'index.html'))) {
|
|
58
|
-
this.app.get(
|
|
60
|
+
this.app.get(`${this.basePath}/*`, (_req, res) => {
|
|
59
61
|
res.sendFile(path.join(this.frontendPath, 'index.html'));
|
|
60
62
|
});
|
|
63
|
+
// Also handle root redirect if base path is set
|
|
64
|
+
if (this.basePath) {
|
|
65
|
+
this.app.get('/', (_req, res) => {
|
|
66
|
+
res.redirect(this.basePath);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
else {
|
|
64
72
|
console.warn('Frontend dist directory not found. Server will run without frontend.');
|
|
65
|
-
this.
|
|
73
|
+
const rootPath = this.basePath || '/';
|
|
74
|
+
this.app.get(rootPath, (_req, res) => {
|
|
66
75
|
res
|
|
67
76
|
.status(404)
|
|
68
77
|
.send('Frontend not found. MCPHub API is running, but the UI is not available.');
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,MAAM,MAAM,mBAAmB,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,gCAAgC;AAChC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,OAAO,SAAS;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ import { loadSettings, saveSettings, expandEnvVars } from '../config/index.js';
|
|
|
8
8
|
import config from '../config/index.js';
|
|
9
9
|
import { getGroup } from './sseService.js';
|
|
10
10
|
import { getServersInGroup } from './groupService.js';
|
|
11
|
+
import { saveToolsAsVectorEmbeddings, searchToolsByVector } from './vectorSearchService.js';
|
|
11
12
|
const servers = {};
|
|
12
13
|
export const initUpstreamServers = async () => {
|
|
13
14
|
await registerAllTools(true);
|
|
@@ -87,12 +88,17 @@ export const initializeClientsFromSettings = (isInit) => {
|
|
|
87
88
|
env['PATH'] = expandEnvVars(process.env.PATH) || '';
|
|
88
89
|
// Add UV_DEFAULT_INDEX from settings if available (for Python packages)
|
|
89
90
|
const settings = loadSettings(); // Add UV_DEFAULT_INDEX from settings if available (for Python packages)
|
|
90
|
-
if (settings.systemConfig?.install?.pythonIndexUrl &&
|
|
91
|
+
if (settings.systemConfig?.install?.pythonIndexUrl &&
|
|
92
|
+
(conf.command === 'uvx' || conf.command === 'uv' || conf.command === 'python')) {
|
|
91
93
|
env['UV_DEFAULT_INDEX'] = settings.systemConfig.install.pythonIndexUrl;
|
|
92
94
|
}
|
|
93
95
|
// Add npm_config_registry from settings if available (for NPM packages)
|
|
94
96
|
if (settings.systemConfig?.install?.npmRegistry &&
|
|
95
|
-
(conf.command === 'npm' ||
|
|
97
|
+
(conf.command === 'npm' ||
|
|
98
|
+
conf.command === 'npx' ||
|
|
99
|
+
conf.command === 'pnpm' ||
|
|
100
|
+
conf.command === 'yarn' ||
|
|
101
|
+
conf.command === 'node')) {
|
|
96
102
|
env['npm_config_registry'] = settings.systemConfig.install.npmRegistry;
|
|
97
103
|
}
|
|
98
104
|
transport = new StdioClientTransport({
|
|
@@ -147,6 +153,20 @@ export const initializeClientsFromSettings = (isInit) => {
|
|
|
147
153
|
}));
|
|
148
154
|
serverInfo.status = 'connected';
|
|
149
155
|
serverInfo.error = null;
|
|
156
|
+
// Save tools as vector embeddings for search (only when smart routing is enabled)
|
|
157
|
+
if (serverInfo.tools.length > 0) {
|
|
158
|
+
try {
|
|
159
|
+
const settings = loadSettings();
|
|
160
|
+
const smartRoutingEnabled = settings.systemConfig?.smartRouting?.enabled || false;
|
|
161
|
+
if (smartRoutingEnabled) {
|
|
162
|
+
console.log(`Smart routing enabled - saving vector embeddings for server ${name}`);
|
|
163
|
+
saveToolsAsVectorEmbeddings(name, serverInfo.tools);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (vectorError) {
|
|
167
|
+
console.warn(`Failed to save vector embeddings for server ${name}:`, vectorError);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
150
170
|
})
|
|
151
171
|
.catch((error) => {
|
|
152
172
|
console.error(`Failed to list tools for server ${name} by error: ${error} with stack: ${error.stack}`);
|
|
@@ -223,7 +243,6 @@ export const addServer = async (name, config) => {
|
|
|
223
243
|
if (!saveSettings(settings)) {
|
|
224
244
|
return { success: false, message: 'Failed to save settings' };
|
|
225
245
|
}
|
|
226
|
-
registerAllTools(false);
|
|
227
246
|
return { success: true, message: 'Server added successfully' };
|
|
228
247
|
}
|
|
229
248
|
catch (error) {
|
|
@@ -316,6 +335,66 @@ const handleListToolsRequest = async (_, extra) => {
|
|
|
316
335
|
const sessionId = extra.sessionId || '';
|
|
317
336
|
const group = getGroup(sessionId);
|
|
318
337
|
console.log(`Handling ListToolsRequest for group: ${group}`);
|
|
338
|
+
// Special handling for $smart group to return special tools
|
|
339
|
+
if (group === '$smart') {
|
|
340
|
+
return {
|
|
341
|
+
tools: [
|
|
342
|
+
{
|
|
343
|
+
name: 'search_tools',
|
|
344
|
+
description: (() => {
|
|
345
|
+
// Get info about available servers
|
|
346
|
+
const availableServers = serverInfos.filter((server) => server.status === 'connected' && server.enabled !== false);
|
|
347
|
+
// Create simple server information with only server names
|
|
348
|
+
const serversList = availableServers
|
|
349
|
+
.map((server) => {
|
|
350
|
+
return `${server.name}`;
|
|
351
|
+
})
|
|
352
|
+
.join(', ');
|
|
353
|
+
return `STEP 1 of 2: Use this tool FIRST to discover and search for relevant tools across all available servers. This tool and call_tool work together as a two-step process: 1) search_tools to find what you need, 2) call_tool to execute it.
|
|
354
|
+
|
|
355
|
+
For optimal results, use specific queries matching your exact needs. Call this tool multiple times with different queries for different parts of complex tasks. Example queries: "image generation tools", "code review tools", "data analysis", "translation capabilities", etc. Results are sorted by relevance using vector similarity.
|
|
356
|
+
|
|
357
|
+
After finding relevant tools, you MUST use the call_tool to actually execute them. The search_tools only finds tools - it doesn't execute them.
|
|
358
|
+
|
|
359
|
+
Available servers: ${serversList}`;
|
|
360
|
+
})(),
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: 'object',
|
|
363
|
+
properties: {
|
|
364
|
+
query: {
|
|
365
|
+
type: 'string',
|
|
366
|
+
description: 'The search query to find relevant tools. Be specific and descriptive about the task you want to accomplish.',
|
|
367
|
+
},
|
|
368
|
+
limit: {
|
|
369
|
+
type: 'integer',
|
|
370
|
+
description: 'Maximum number of results to return. Use higher values (20-30) for broad searches and lower values (5-10) for specific searches.',
|
|
371
|
+
default: 10,
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
required: ['query'],
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
name: 'call_tool',
|
|
379
|
+
description: "STEP 2 of 2: Use this tool AFTER search_tools to actually execute/invoke any tool you found. This is the execution step - search_tools finds tools, call_tool runs them.\n\nWorkflow: search_tools → examine results → call_tool with the chosen tool name and required arguments.\n\nIMPORTANT: Always check the tool's inputSchema from search_tools results before invoking to ensure you provide the correct arguments. The search results will show you exactly what parameters each tool expects.",
|
|
380
|
+
inputSchema: {
|
|
381
|
+
type: 'object',
|
|
382
|
+
properties: {
|
|
383
|
+
toolName: {
|
|
384
|
+
type: 'string',
|
|
385
|
+
description: 'The exact name of the tool to invoke (from search_tools results)',
|
|
386
|
+
},
|
|
387
|
+
arguments: {
|
|
388
|
+
type: 'object',
|
|
389
|
+
description: 'The arguments to pass to the tool based on its inputSchema (optional if tool requires no arguments)',
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
required: ['toolName'],
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
};
|
|
397
|
+
}
|
|
319
398
|
const allServerInfos = serverInfos.filter((serverInfo) => {
|
|
320
399
|
if (serverInfo.enabled === false)
|
|
321
400
|
return false;
|
|
@@ -339,6 +418,109 @@ const handleListToolsRequest = async (_, extra) => {
|
|
|
339
418
|
const handleCallToolRequest = async (request, extra) => {
|
|
340
419
|
console.log(`Handling CallToolRequest for tool: ${request.params.name}`);
|
|
341
420
|
try {
|
|
421
|
+
// Special handling for agent group tools
|
|
422
|
+
if (request.params.name === 'search_tools') {
|
|
423
|
+
const { query, limit = 10 } = request.params.arguments || {};
|
|
424
|
+
if (!query || typeof query !== 'string') {
|
|
425
|
+
throw new Error('Query parameter is required and must be a string');
|
|
426
|
+
}
|
|
427
|
+
const limitNum = Math.min(Math.max(parseInt(String(limit)) || 10, 1), 100);
|
|
428
|
+
// Dynamically adjust threshold based on query characteristics
|
|
429
|
+
let thresholdNum = 0.3; // Default threshold
|
|
430
|
+
// For more general queries, use a lower threshold to get more diverse results
|
|
431
|
+
if (query.length < 10 || query.split(' ').length <= 2) {
|
|
432
|
+
thresholdNum = 0.2;
|
|
433
|
+
}
|
|
434
|
+
// For very specific queries, use a higher threshold for more precise results
|
|
435
|
+
if (query.length > 30 || query.includes('specific') || query.includes('exact')) {
|
|
436
|
+
thresholdNum = 0.4;
|
|
437
|
+
}
|
|
438
|
+
console.log(`Using similarity threshold: ${thresholdNum} for query: "${query}"`);
|
|
439
|
+
const servers = undefined; // No server filtering
|
|
440
|
+
const searchResults = await searchToolsByVector(query, limitNum, thresholdNum, servers);
|
|
441
|
+
console.log(`Search results: ${JSON.stringify(searchResults)}`);
|
|
442
|
+
// Find actual tool information from serverInfos by serverName and toolName
|
|
443
|
+
const tools = searchResults.map((result) => {
|
|
444
|
+
// Find the server in serverInfos
|
|
445
|
+
const server = serverInfos.find((serverInfo) => serverInfo.name === result.serverName &&
|
|
446
|
+
serverInfo.status === 'connected' &&
|
|
447
|
+
serverInfo.enabled !== false);
|
|
448
|
+
if (server && server.tools && server.tools.length > 0) {
|
|
449
|
+
// Find the tool in server.tools
|
|
450
|
+
const actualTool = server.tools.find((tool) => tool.name === result.toolName);
|
|
451
|
+
if (actualTool) {
|
|
452
|
+
// Return the actual tool info from serverInfos
|
|
453
|
+
return actualTool;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Fallback to search result if server or tool not found
|
|
457
|
+
return {
|
|
458
|
+
name: result.toolName,
|
|
459
|
+
description: result.description || '',
|
|
460
|
+
inputSchema: result.inputSchema || {},
|
|
461
|
+
};
|
|
462
|
+
});
|
|
463
|
+
// Add usage guidance to the response
|
|
464
|
+
const response = {
|
|
465
|
+
tools,
|
|
466
|
+
metadata: {
|
|
467
|
+
query: query,
|
|
468
|
+
threshold: thresholdNum,
|
|
469
|
+
totalResults: tools.length,
|
|
470
|
+
guideline: tools.length > 0
|
|
471
|
+
? "Found relevant tools. If these tools don't match exactly what you need, try another search with more specific keywords."
|
|
472
|
+
: 'No tools found. Try broadening your search or using different keywords.',
|
|
473
|
+
nextSteps: tools.length > 0
|
|
474
|
+
? 'To use a tool, call call_tool with the toolName and required arguments.'
|
|
475
|
+
: 'Consider searching for related capabilities or more general terms.',
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
// Return in the same format as handleListToolsRequest
|
|
479
|
+
return {
|
|
480
|
+
content: [
|
|
481
|
+
{
|
|
482
|
+
type: 'text',
|
|
483
|
+
text: JSON.stringify(response),
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
// Special handling for call_tool
|
|
489
|
+
if (request.params.name === 'call_tool') {
|
|
490
|
+
const { toolName, arguments: toolArgs = {} } = request.params.arguments || {};
|
|
491
|
+
if (!toolName) {
|
|
492
|
+
throw new Error('toolName parameter is required');
|
|
493
|
+
}
|
|
494
|
+
// arguments parameter is now optional
|
|
495
|
+
let targetServerInfo;
|
|
496
|
+
// Find the first server that has this tool
|
|
497
|
+
targetServerInfo = serverInfos.find((serverInfo) => serverInfo.status === 'connected' &&
|
|
498
|
+
serverInfo.enabled !== false &&
|
|
499
|
+
serverInfo.tools.some((tool) => tool.name === toolName));
|
|
500
|
+
if (!targetServerInfo) {
|
|
501
|
+
throw new Error(`No available servers found with tool: ${toolName}`);
|
|
502
|
+
}
|
|
503
|
+
// Check if the tool exists on the server
|
|
504
|
+
const toolExists = targetServerInfo.tools.some((tool) => tool.name === toolName);
|
|
505
|
+
if (!toolExists) {
|
|
506
|
+
throw new Error(`Tool '${toolName}' not found on server '${targetServerInfo.name}'`);
|
|
507
|
+
}
|
|
508
|
+
// Call the tool on the target server
|
|
509
|
+
const client = targetServerInfo.client;
|
|
510
|
+
if (!client) {
|
|
511
|
+
throw new Error(`Client not found for server: ${targetServerInfo.name}`);
|
|
512
|
+
}
|
|
513
|
+
// Use toolArgs if it has properties, otherwise fallback to request.params.arguments
|
|
514
|
+
const finalArgs = toolArgs && Object.keys(toolArgs).length > 0 ? toolArgs : request.params.arguments || {};
|
|
515
|
+
console.log(`Invoking tool '${toolName}' on server '${targetServerInfo.name}' with arguments: ${JSON.stringify(finalArgs)}`);
|
|
516
|
+
const result = await client.callTool({
|
|
517
|
+
name: toolName,
|
|
518
|
+
arguments: finalArgs,
|
|
519
|
+
});
|
|
520
|
+
console.log(`Tool invocation result: ${JSON.stringify(result)}`);
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
523
|
+
// Regular tool handling
|
|
342
524
|
const serverInfo = getServerByTool(request.params.name);
|
|
343
525
|
if (!serverInfo) {
|
|
344
526
|
throw new Error(`Server not found: ${request.params.name}`);
|