agentstudio 0.1.20 → 0.1.21
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/index.d.ts.map +1 -1
- package/index.js +5 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/{AgentsPage-CKTz2ND6.js → AgentsPage-Nvg2xu6K.js} +2 -2
- package/public/assets/{Button-Dg6ni5Yl.js → Button-Co56C389.js} +1 -1
- package/public/assets/{ChatPage-DkO3kzY2.js → ChatPage-D6sol0ad.js} +5 -5
- package/public/assets/{CommandForm-CIfw9mVj.js → CommandForm-Bk7F_HU8.js} +1 -1
- package/public/assets/{CommandsPage-BgN0E41K.js → CommandsPage-DZHyOdKd.js} +1 -1
- package/public/assets/{DashboardPage-Duu6pBON.js → DashboardPage-29qC7Ev1.js} +2 -2
- package/public/assets/{FileBrowser-Bnm7ZyGT.js → FileBrowser-BYweUPH4.js} +4 -4
- package/public/assets/FileExplorer-DNYj6Tsx.js +1 -0
- package/public/assets/{GeneralSettingsPage-BJTiwSqP.js → GeneralSettingsPage-D9Xa7Nd8.js} +1 -1
- package/public/assets/LandingPage-CjnT-cvO.js +1 -0
- package/public/assets/{LoginPage-DCI_RABC.js → LoginPage-DcaGNCXH.js} +3 -3
- package/public/assets/McpAdminSettingsPage-DgR3E2Bd.js +7 -0
- package/public/assets/{McpPage-Dj4bE6a2.js → McpPage-CtWf1CoL.js} +1 -1
- package/public/assets/{MemorySettingsPage-v7kI6DEB.js → MemorySettingsPage-JTry4Ccp.js} +1 -1
- package/public/assets/PluginsPage-D-BHjQ3P.js +1 -0
- package/public/assets/{ProjectSelector-DKkhmVGz.js → ProjectSelector-DSXOjMQC.js} +1 -1
- package/public/assets/{ProjectsPage-6nGz1v6U.js → ProjectsPage-lLUk4-Xa.js} +5 -5
- package/public/assets/ScheduledTasksPage-5hPbd9Vs.js +1 -0
- package/public/assets/{SettingsLayout-stXQCl6u.js → SettingsLayout-DGJspXLp.js} +1 -1
- package/public/assets/SkillsPage-DBw0m7D2.js +18 -0
- package/public/assets/{SubagentForm-iYJ0l9vh.js → SubagentForm-BdUK1U4y.js} +1 -1
- package/public/assets/{SubagentsPage-ksh-LWAC.js → SubagentsPage-Dnq70IFd.js} +1 -1
- package/public/assets/{ToastTestPage-pxyInZeD.js → ToastTestPage-BfJQRFIm.js} +1 -1
- package/public/assets/{ToolsList-CWZLcBx2.js → ToolsList-Dl5F2fWk.js} +1 -1
- package/public/assets/UnifiedToolSelector-CNbPsiuq.js +1 -0
- package/public/assets/{VersionSettingsPage-ClLBqAIC.js → VersionSettingsPage-BfoCcham.js} +1 -1
- package/public/assets/{_basePickBy-Ce1_TuBk.js → _basePickBy-7C_e0Xv1.js} +1 -1
- package/public/assets/{_baseUniq-Dt6C4BgZ.js → _baseUniq-eGJNLBzx.js} +1 -1
- package/public/assets/{agents-C4aCwcCz.js → agents-ChrA1R0y.js} +1 -1
- package/public/assets/arc-CuA752eE.js +1 -0
- package/public/assets/{architectureDiagram-VXUJARFQ-rnurJGX4.js → architectureDiagram-VXUJARFQ-BnPYh1OW.js} +1 -1
- package/public/assets/{blockDiagram-VD42YOAC-CM33sjhb.js → blockDiagram-VD42YOAC-72nsMt_i.js} +1 -1
- package/public/assets/{c4Diagram-YG6GDRKO-B1tJjciL.js → c4Diagram-YG6GDRKO-BNJSAXcg.js} +1 -1
- package/public/assets/channel-CIunGC5m.js +1 -0
- package/public/assets/{chunk-4BX2VUAB-vbzk_8Ta.js → chunk-4BX2VUAB-RPxkCWhH.js} +1 -1
- package/public/assets/{chunk-55IACEB6-CNXjTgeK.js → chunk-55IACEB6-3ePDt0kp.js} +1 -1
- package/public/assets/{chunk-B4BG7PRW-CykotMKj.js → chunk-B4BG7PRW-CBg_BBfl.js} +1 -1
- package/public/assets/{chunk-DI55MBZ5-DbZodDrP.js → chunk-DI55MBZ5-DIh69TUJ.js} +1 -1
- package/public/assets/{chunk-FMBD7UC4-u0h-4JXb.js → chunk-FMBD7UC4-BbjwhyTe.js} +1 -1
- package/public/assets/{chunk-QN33PNHL-B7VLbRpC.js → chunk-QN33PNHL-BpH-o_YR.js} +1 -1
- package/public/assets/{chunk-QZHKN3VN-DfcZEdwM.js → chunk-QZHKN3VN-DYB7rh5Q.js} +1 -1
- package/public/assets/{chunk-TZMSLE5B-BP4O9iGm.js → chunk-TZMSLE5B-DPCYEVb3.js} +1 -1
- package/public/assets/classDiagram-2ON5EDUG-aUQHFsTA.js +1 -0
- package/public/assets/classDiagram-v2-WZHVMYZB-aUQHFsTA.js +1 -0
- package/public/assets/clone-Ckf7tA1V.js +1 -0
- package/public/assets/{cose-bilkent-S5V4N54A-CSV8iDOr.js → cose-bilkent-S5V4N54A-CnpfmL-Y.js} +1 -1
- package/public/assets/{dagre-6UL2VRFP-S5vHkFwY.js → dagre-6UL2VRFP-DR9x77Xf.js} +1 -1
- package/public/assets/{diagram-PSM6KHXK-Bl4NbJsm.js → diagram-PSM6KHXK-SONPsQNx.js} +1 -1
- package/public/assets/{diagram-QEK2KX5R-D-6ipdkt.js → diagram-QEK2KX5R-BKYFSfC1.js} +1 -1
- package/public/assets/{diagram-S2PKOQOG-DBuN3kfb.js → diagram-S2PKOQOG-CkM0APZj.js} +1 -1
- package/public/assets/{erDiagram-Q2GNP2WA-DEhlyUw1.js → erDiagram-Q2GNP2WA-BX1DpOGx.js} +1 -1
- package/public/assets/{flowDiagram-NV44I4VS-PsSk5-Xf.js → flowDiagram-NV44I4VS-HAAlzNbq.js} +1 -1
- package/public/assets/{ganttDiagram-LVOFAZNH-PfD-vtKp.js → ganttDiagram-LVOFAZNH-BqzWexqa.js} +1 -1
- package/public/assets/{gitGraphDiagram-NY62KEGX-CUq51Mt1.js → gitGraphDiagram-NY62KEGX-CIPmSp43.js} +1 -1
- package/public/assets/{graph-Bc5M3bvZ.js → graph-m515btDj.js} +1 -1
- package/public/assets/{index-ImPzdvfG.js → index-Bn3v3S9-.js} +47 -47
- package/public/assets/index-DWieeYj4.css +1 -0
- package/public/assets/infoDiagram-F6ZHWCRC-Pn4yNWrF.js +2 -0
- package/public/assets/{journeyDiagram-XKPGCS4Q-CTyau8Sh.js → journeyDiagram-XKPGCS4Q-BfzTomS0.js} +1 -1
- package/public/assets/{kanban-definition-3W4ZIXB7-2R3dHQq1.js → kanban-definition-3W4ZIXB7-Cgju7b-L.js} +1 -1
- package/public/assets/{layout-BCktuL_6.js → layout-BKQfQSxJ.js} +1 -1
- package/public/assets/{linear-lHuinZOC.js → linear-DigtLz3B.js} +1 -1
- package/public/assets/{mindmap-definition-VGOIOE7T-Dl8qR3zk.js → mindmap-definition-VGOIOE7T-qopraVFy.js} +1 -1
- package/public/assets/{pieDiagram-ADFJNKIX-Bqcukh_c.js → pieDiagram-ADFJNKIX-BcoaAI-L.js} +2 -2
- package/public/assets/{quadrantDiagram-AYHSOK5B-C_uML1JV.js → quadrantDiagram-AYHSOK5B-D-DwcoSd.js} +1 -1
- package/public/assets/{requirementDiagram-UZGBJVZJ-QUbH9ShO.js → requirementDiagram-UZGBJVZJ-DbQCpx77.js} +1 -1
- package/public/assets/{sankeyDiagram-TZEHDZUN-CEomXpQ1.js → sankeyDiagram-TZEHDZUN-BVk8387S.js} +1 -1
- package/public/assets/{sequenceDiagram-WL72ISMW-DNsDMjTd.js → sequenceDiagram-WL72ISMW-BdzICjxO.js} +1 -1
- package/public/assets/{stateDiagram-FKZM4ZOC-BA_Narwp.js → stateDiagram-FKZM4ZOC-CYY-uUvJ.js} +1 -1
- package/public/assets/stateDiagram-v2-4FDKWEC3-Dh2Kvomq.js +1 -0
- package/public/assets/{tabManager-CkNKjP4G.js → tabManager-B2LQO_Ll.js} +1 -1
- package/public/assets/{table-CSWCaVuS.js → table-D0L2RL5i.js} +1 -1
- package/public/assets/{timeline-definition-IT6M3QCI-DeEgHBeI.js → timeline-definition-IT6M3QCI-BAvjPYvX.js} +1 -1
- package/public/assets/{tools-C7xmF_rB.js → tools-IcPNZlPj.js} +1 -1
- package/public/assets/{treemap-KMMF4GRG-5HQSTjk6.js → treemap-KMMF4GRG-DtkpVA56.js} +1 -1
- package/public/assets/{ui-components-BNdpaz32.js → ui-components-D1St49qC.js} +129 -119
- package/public/assets/{useAgents-C9aEFOWD.js → useAgents-BnDTkOG8.js} +1 -1
- package/public/assets/{useClaudeVersions-CcFqpR2o.js → useClaudeVersions-CD59tFWM.js} +1 -1
- package/public/assets/{useCommands-BadxYHf2.js → useCommands-mvMu3mMD.js} +1 -1
- package/public/assets/{useProjects-Dgk7ldPq.js → useProjects-YXOjaOwL.js} +1 -1
- package/public/assets/{xychartDiagram-PRI3JC2R-C7BNHmgo.js → xychartDiagram-PRI3JC2R-ByBTDWE2.js} +1 -1
- package/public/index.html +5 -5
- package/routes/mcp.d.ts +23 -0
- package/routes/mcp.d.ts.map +1 -1
- package/routes/mcp.js +21 -18
- package/routes/mcp.js.map +1 -1
- package/routes/mcpAdmin.d.ts +16 -0
- package/routes/mcpAdmin.d.ts.map +1 -0
- package/routes/mcpAdmin.js +308 -0
- package/routes/mcpAdmin.js.map +1 -0
- package/routes/mcpAdminManagement.d.ts +17 -0
- package/routes/mcpAdminManagement.d.ts.map +1 -0
- package/routes/mcpAdminManagement.js +345 -0
- package/routes/mcpAdminManagement.js.map +1 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js +289 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js +345 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js +453 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/tools.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/tools.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/tools.test.js +371 -0
- package/services/mcpAdmin/__tests__/tools.test.js.map +1 -0
- package/services/mcpAdmin/adminApiKeyService.d.ts +61 -0
- package/services/mcpAdmin/adminApiKeyService.d.ts.map +1 -0
- package/services/mcpAdmin/adminApiKeyService.js +270 -0
- package/services/mcpAdmin/adminApiKeyService.js.map +1 -0
- package/services/mcpAdmin/index.d.ts +10 -0
- package/services/mcpAdmin/index.d.ts.map +1 -0
- package/services/mcpAdmin/index.js +43 -0
- package/services/mcpAdmin/index.js.map +1 -0
- package/services/mcpAdmin/mcpAdminServer.d.ts +76 -0
- package/services/mcpAdmin/mcpAdminServer.d.ts.map +1 -0
- package/services/mcpAdmin/mcpAdminServer.js +243 -0
- package/services/mcpAdmin/mcpAdminServer.js.map +1 -0
- package/services/mcpAdmin/tools/agentTools.d.ts +27 -0
- package/services/mcpAdmin/tools/agentTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/agentTools.js +359 -0
- package/services/mcpAdmin/tools/agentTools.js.map +1 -0
- package/services/mcpAdmin/tools/index.d.ts +15 -0
- package/services/mcpAdmin/tools/index.d.ts.map +1 -0
- package/services/mcpAdmin/tools/index.js +30 -0
- package/services/mcpAdmin/tools/index.js.map +1 -0
- package/services/mcpAdmin/tools/mcpServerTools.d.ts +27 -0
- package/services/mcpAdmin/tools/mcpServerTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/mcpServerTools.js +334 -0
- package/services/mcpAdmin/tools/mcpServerTools.js.map +1 -0
- package/services/mcpAdmin/tools/projectTools.d.ts +27 -0
- package/services/mcpAdmin/tools/projectTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/projectTools.js +353 -0
- package/services/mcpAdmin/tools/projectTools.js.map +1 -0
- package/services/mcpAdmin/tools/systemTools.d.ts +23 -0
- package/services/mcpAdmin/tools/systemTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/systemTools.js +241 -0
- package/services/mcpAdmin/tools/systemTools.js.map +1 -0
- package/services/mcpAdmin/types.d.ts +124 -0
- package/services/mcpAdmin/types.d.ts.map +1 -0
- package/services/mcpAdmin/types.js +18 -0
- package/services/mcpAdmin/types.js.map +1 -0
- package/public/assets/FileExplorer-Dy8ZFDtK.js +0 -1
- package/public/assets/LandingPage-CCqtSDce.js +0 -1
- package/public/assets/PluginsPage-CQ08px0h.js +0 -1
- package/public/assets/ScheduledTasksPage-Dv8qPeLY.js +0 -1
- package/public/assets/SkillsPage-DlQPlwG5.js +0 -18
- package/public/assets/UnifiedToolSelector-A2UIt1Xn.js +0 -1
- package/public/assets/arc-c63c3GDw.js +0 -1
- package/public/assets/channel-6fK1csbi.js +0 -1
- package/public/assets/classDiagram-2ON5EDUG-PrDkNsdA.js +0 -1
- package/public/assets/classDiagram-v2-WZHVMYZB-PrDkNsdA.js +0 -1
- package/public/assets/clone-CXX9AxT7.js +0 -1
- package/public/assets/index-TEVaBQiv.css +0 -1
- package/public/assets/infoDiagram-F6ZHWCRC-BTR1hJCm.js +0 -2
- package/public/assets/stateDiagram-v2-4FDKWEC3-Cy5am68v.js +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Admin Routes
|
|
4
|
+
*
|
|
5
|
+
* HTTP endpoints for the MCP Admin Server.
|
|
6
|
+
* Implements MCP HTTP Streamable protocol with pure JSON responses.
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - POST /api/mcp-admin - Handle MCP JSON-RPC requests
|
|
10
|
+
* - GET /api/mcp-admin/keys - List admin API keys (requires existing admin auth)
|
|
11
|
+
* - POST /api/mcp-admin/keys - Create admin API key (requires existing admin auth)
|
|
12
|
+
* - DELETE /api/mcp-admin/keys/:keyId - Revoke admin API key
|
|
13
|
+
*/
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const express_1 = __importDefault(require("express"));
|
|
19
|
+
const index_js_1 = require("../services/mcpAdmin/index.js");
|
|
20
|
+
const types_js_1 = require("../services/mcpAdmin/types.js");
|
|
21
|
+
const router = express_1.default.Router();
|
|
22
|
+
// Initialize MCP Admin Server with all tools
|
|
23
|
+
const mcpServer = (0, index_js_1.getMcpAdminServer)();
|
|
24
|
+
mcpServer.registerTools(index_js_1.allTools);
|
|
25
|
+
console.info(`[MCP Admin] Server initialized with ${mcpServer.getToolCount()} tools`);
|
|
26
|
+
async function adminAuth(req, res, next) {
|
|
27
|
+
try {
|
|
28
|
+
const authHeader = req.headers.authorization;
|
|
29
|
+
if (!authHeader) {
|
|
30
|
+
res.status(401).json({
|
|
31
|
+
jsonrpc: '2.0',
|
|
32
|
+
id: null,
|
|
33
|
+
error: {
|
|
34
|
+
code: -32001,
|
|
35
|
+
message: 'Missing Authorization header',
|
|
36
|
+
data: 'Include: Authorization: Bearer <admin-api-key>',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!authHeader.startsWith('Bearer ')) {
|
|
42
|
+
res.status(401).json({
|
|
43
|
+
jsonrpc: '2.0',
|
|
44
|
+
id: null,
|
|
45
|
+
error: {
|
|
46
|
+
code: -32001,
|
|
47
|
+
message: 'Invalid Authorization header format',
|
|
48
|
+
data: 'Use: Authorization: Bearer <admin-api-key>',
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const apiKey = authHeader.substring(7);
|
|
54
|
+
if (!apiKey) {
|
|
55
|
+
res.status(401).json({
|
|
56
|
+
jsonrpc: '2.0',
|
|
57
|
+
id: null,
|
|
58
|
+
error: {
|
|
59
|
+
code: -32001,
|
|
60
|
+
message: 'Empty API key',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const validation = await (0, index_js_1.validateAdminApiKey)(apiKey);
|
|
66
|
+
if (!validation.valid) {
|
|
67
|
+
console.warn('[MCP Admin] Failed authentication attempt:', {
|
|
68
|
+
timestamp: new Date().toISOString(),
|
|
69
|
+
ip: req.ip,
|
|
70
|
+
disabled: validation.disabled,
|
|
71
|
+
});
|
|
72
|
+
res.status(401).json({
|
|
73
|
+
jsonrpc: '2.0',
|
|
74
|
+
id: null,
|
|
75
|
+
error: {
|
|
76
|
+
code: -32001,
|
|
77
|
+
message: validation.disabled ? 'API key is disabled' : 'Invalid or revoked API key',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Attach admin context to request
|
|
83
|
+
req.adminContext = {
|
|
84
|
+
apiKeyId: validation.keyId,
|
|
85
|
+
permissions: validation.permissions,
|
|
86
|
+
allowedTools: validation.allowedTools,
|
|
87
|
+
};
|
|
88
|
+
console.info('[MCP Admin] Authenticated request:', {
|
|
89
|
+
keyId: validation.keyId,
|
|
90
|
+
allowedTools: validation.allowedTools ? `${validation.allowedTools.length} tools` : 'all',
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
});
|
|
93
|
+
next();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error('[MCP Admin] Authentication error:', error);
|
|
97
|
+
res.status(500).json({
|
|
98
|
+
jsonrpc: '2.0',
|
|
99
|
+
id: null,
|
|
100
|
+
error: {
|
|
101
|
+
code: types_js_1.JSON_RPC_ERRORS.INTERNAL_ERROR.code,
|
|
102
|
+
message: 'Authentication error',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// =============================================================================
|
|
108
|
+
// POST /api/mcp-admin - Handle MCP JSON-RPC requests
|
|
109
|
+
// =============================================================================
|
|
110
|
+
router.post('/', adminAuth, async (req, res) => {
|
|
111
|
+
try {
|
|
112
|
+
const request = req.body;
|
|
113
|
+
// Validate basic JSON-RPC structure
|
|
114
|
+
if (!request || typeof request !== 'object') {
|
|
115
|
+
res.status(400).json({
|
|
116
|
+
jsonrpc: '2.0',
|
|
117
|
+
id: null,
|
|
118
|
+
error: types_js_1.JSON_RPC_ERRORS.PARSE_ERROR,
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!request.method) {
|
|
123
|
+
res.status(400).json({
|
|
124
|
+
jsonrpc: '2.0',
|
|
125
|
+
id: request.id ?? null,
|
|
126
|
+
error: {
|
|
127
|
+
...types_js_1.JSON_RPC_ERRORS.INVALID_REQUEST,
|
|
128
|
+
data: 'Missing method',
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Handle the request
|
|
134
|
+
const response = await mcpServer.handleRequest(request, req.adminContext);
|
|
135
|
+
// Return pure JSON response
|
|
136
|
+
res.setHeader('Content-Type', 'application/json');
|
|
137
|
+
res.json(response);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error('[MCP Admin] Request handling error:', error);
|
|
141
|
+
res.status(500).json({
|
|
142
|
+
jsonrpc: '2.0',
|
|
143
|
+
id: null,
|
|
144
|
+
error: {
|
|
145
|
+
...types_js_1.JSON_RPC_ERRORS.INTERNAL_ERROR,
|
|
146
|
+
data: error instanceof Error ? error.message : String(error),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// Admin API Key Management Endpoints
|
|
153
|
+
// =============================================================================
|
|
154
|
+
// GET /api/mcp-admin/keys - List admin API keys
|
|
155
|
+
router.get('/keys', adminAuth, async (req, res) => {
|
|
156
|
+
try {
|
|
157
|
+
// Check permission
|
|
158
|
+
const hasAdminPerm = req.adminContext?.permissions.includes('admin:*');
|
|
159
|
+
if (!hasAdminPerm) {
|
|
160
|
+
res.status(403).json({
|
|
161
|
+
error: 'Permission denied',
|
|
162
|
+
message: 'admin:* permission required',
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const keys = await (0, index_js_1.listAdminApiKeys)();
|
|
167
|
+
// Sanitize keys for response
|
|
168
|
+
const sanitizedKeys = keys.map((key) => ({
|
|
169
|
+
id: key.id,
|
|
170
|
+
description: key.description,
|
|
171
|
+
permissions: key.permissions,
|
|
172
|
+
createdAt: key.createdAt,
|
|
173
|
+
lastUsedAt: key.lastUsedAt,
|
|
174
|
+
revokedAt: key.revokedAt,
|
|
175
|
+
// Only show decrypted key if not revoked
|
|
176
|
+
key: key.revokedAt ? null : key.decryptedKey,
|
|
177
|
+
}));
|
|
178
|
+
res.json({ keys: sanitizedKeys });
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error('[MCP Admin] Error listing keys:', error);
|
|
182
|
+
res.status(500).json({
|
|
183
|
+
error: 'Failed to list keys',
|
|
184
|
+
details: error instanceof Error ? error.message : String(error),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
// POST /api/mcp-admin/keys - Create admin API key
|
|
189
|
+
router.post('/keys', adminAuth, async (req, res) => {
|
|
190
|
+
try {
|
|
191
|
+
// Check permission
|
|
192
|
+
const hasAdminPerm = req.adminContext?.permissions.includes('admin:*');
|
|
193
|
+
if (!hasAdminPerm) {
|
|
194
|
+
res.status(403).json({
|
|
195
|
+
error: 'Permission denied',
|
|
196
|
+
message: 'admin:* permission required',
|
|
197
|
+
});
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const { description, permissions } = req.body;
|
|
201
|
+
if (!description) {
|
|
202
|
+
res.status(400).json({
|
|
203
|
+
error: 'Description is required',
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const parsedPermissions = permissions || ['admin:*'];
|
|
208
|
+
const { key, keyData } = await (0, index_js_1.generateAdminApiKey)(description, parsedPermissions);
|
|
209
|
+
res.status(201).json({
|
|
210
|
+
id: keyData.id,
|
|
211
|
+
key, // Only shown once!
|
|
212
|
+
description: keyData.description,
|
|
213
|
+
permissions: keyData.permissions,
|
|
214
|
+
createdAt: keyData.createdAt,
|
|
215
|
+
message: 'Save this key now - it will not be shown again',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
console.error('[MCP Admin] Error creating key:', error);
|
|
220
|
+
res.status(500).json({
|
|
221
|
+
error: 'Failed to create key',
|
|
222
|
+
details: error instanceof Error ? error.message : String(error),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// DELETE /api/mcp-admin/keys/:keyId - Revoke admin API key
|
|
227
|
+
router.delete('/keys/:keyId', adminAuth, async (req, res) => {
|
|
228
|
+
try {
|
|
229
|
+
// Check permission
|
|
230
|
+
const hasAdminPerm = req.adminContext?.permissions.includes('admin:*');
|
|
231
|
+
if (!hasAdminPerm) {
|
|
232
|
+
res.status(403).json({
|
|
233
|
+
error: 'Permission denied',
|
|
234
|
+
message: 'admin:* permission required',
|
|
235
|
+
});
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const { keyId } = req.params;
|
|
239
|
+
// Prevent self-revocation
|
|
240
|
+
if (keyId === req.adminContext?.apiKeyId) {
|
|
241
|
+
res.status(400).json({
|
|
242
|
+
error: 'Cannot revoke your own API key',
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const success = await (0, index_js_1.revokeAdminApiKey)(keyId);
|
|
247
|
+
if (!success) {
|
|
248
|
+
res.status(404).json({
|
|
249
|
+
error: 'Key not found',
|
|
250
|
+
});
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
res.json({
|
|
254
|
+
success: true,
|
|
255
|
+
message: 'API key revoked',
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error('[MCP Admin] Error revoking key:', error);
|
|
260
|
+
res.status(500).json({
|
|
261
|
+
error: 'Failed to revoke key',
|
|
262
|
+
details: error instanceof Error ? error.message : String(error),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
// =============================================================================
|
|
267
|
+
// Bootstrap endpoint (no auth required) - Create first admin key
|
|
268
|
+
// =============================================================================
|
|
269
|
+
router.post('/bootstrap', async (req, res) => {
|
|
270
|
+
try {
|
|
271
|
+
// Check if any admin keys exist
|
|
272
|
+
const existingKeys = await (0, index_js_1.listAdminApiKeys)();
|
|
273
|
+
const activeKeys = existingKeys.filter((k) => !k.revokedAt);
|
|
274
|
+
if (activeKeys.length > 0) {
|
|
275
|
+
res.status(403).json({
|
|
276
|
+
error: 'Bootstrap not allowed',
|
|
277
|
+
message: 'Admin keys already exist. Use an existing key to create new ones.',
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const { description } = req.body;
|
|
282
|
+
if (!description) {
|
|
283
|
+
res.status(400).json({
|
|
284
|
+
error: 'Description is required',
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const { key, keyData } = await (0, index_js_1.generateAdminApiKey)(description, ['admin:*']);
|
|
289
|
+
console.info('[MCP Admin] Bootstrap: First admin key created');
|
|
290
|
+
res.status(201).json({
|
|
291
|
+
id: keyData.id,
|
|
292
|
+
key, // Only shown once!
|
|
293
|
+
description: keyData.description,
|
|
294
|
+
permissions: keyData.permissions,
|
|
295
|
+
createdAt: keyData.createdAt,
|
|
296
|
+
message: 'IMPORTANT: Save this key now - it will NEVER be shown again!',
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.error('[MCP Admin] Bootstrap error:', error);
|
|
301
|
+
res.status(500).json({
|
|
302
|
+
error: 'Bootstrap failed',
|
|
303
|
+
details: error instanceof Error ? error.message : String(error),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
exports.default = router;
|
|
308
|
+
//# sourceMappingURL=mcpAdmin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpAdmin.js","sourceRoot":"","sources":["../../src/routes/mcpAdmin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Admin Management Routes
|
|
3
|
+
*
|
|
4
|
+
* HTTP endpoints for managing MCP Admin Server settings and API keys.
|
|
5
|
+
* These routes use JWT authentication (regular user auth) instead of Admin API keys.
|
|
6
|
+
*
|
|
7
|
+
* Endpoints:
|
|
8
|
+
* - GET /api/mcp-admin-management/status - Get MCP Admin Server status
|
|
9
|
+
* - GET /api/mcp-admin-management/keys - List admin API keys
|
|
10
|
+
* - POST /api/mcp-admin-management/keys - Create admin API key
|
|
11
|
+
* - DELETE /api/mcp-admin-management/keys/:keyId - Revoke admin API key
|
|
12
|
+
* - GET /api/mcp-admin-management/config-snippet - Get config snippet for Cursor/Claude Desktop
|
|
13
|
+
*/
|
|
14
|
+
import { Router } from 'express';
|
|
15
|
+
declare const router: Router;
|
|
16
|
+
export default router;
|
|
17
|
+
//# sourceMappingURL=mcpAdminManagement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpAdminManagement.d.ts","sourceRoot":"","sources":["../../src/routes/mcpAdminManagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAgB,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAW7D,QAAA,MAAM,MAAM,EAAE,MAAyB,CAAC;AAwTxC,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Admin Management Routes
|
|
4
|
+
*
|
|
5
|
+
* HTTP endpoints for managing MCP Admin Server settings and API keys.
|
|
6
|
+
* These routes use JWT authentication (regular user auth) instead of Admin API keys.
|
|
7
|
+
*
|
|
8
|
+
* Endpoints:
|
|
9
|
+
* - GET /api/mcp-admin-management/status - Get MCP Admin Server status
|
|
10
|
+
* - GET /api/mcp-admin-management/keys - List admin API keys
|
|
11
|
+
* - POST /api/mcp-admin-management/keys - Create admin API key
|
|
12
|
+
* - DELETE /api/mcp-admin-management/keys/:keyId - Revoke admin API key
|
|
13
|
+
* - GET /api/mcp-admin-management/config-snippet - Get config snippet for Cursor/Claude Desktop
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
49
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
50
|
+
};
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
const express_1 = __importDefault(require("express"));
|
|
53
|
+
const index_js_1 = require("../services/mcpAdmin/index.js");
|
|
54
|
+
const mcpAdminServer_js_1 = require("../services/mcpAdmin/mcpAdminServer.js");
|
|
55
|
+
const router = express_1.default.Router();
|
|
56
|
+
/**
|
|
57
|
+
* GET /api/mcp-admin-management/status
|
|
58
|
+
* Get MCP Admin Server status and info
|
|
59
|
+
*/
|
|
60
|
+
router.get('/status', async (req, res) => {
|
|
61
|
+
try {
|
|
62
|
+
const server = (0, mcpAdminServer_js_1.getMcpAdminServer)();
|
|
63
|
+
const toolCount = server.getToolCount();
|
|
64
|
+
const keys = await (0, index_js_1.listAdminApiKeys)();
|
|
65
|
+
const activeKeys = keys.filter((k) => !k.revokedAt);
|
|
66
|
+
res.json({
|
|
67
|
+
enabled: true,
|
|
68
|
+
version: '1.0.0',
|
|
69
|
+
endpoint: '/api/mcp-admin',
|
|
70
|
+
toolCount,
|
|
71
|
+
activeKeyCount: activeKeys.length,
|
|
72
|
+
totalKeyCount: keys.length,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error('[MCP Admin Management] Error getting status:', error);
|
|
77
|
+
res.status(500).json({
|
|
78
|
+
error: 'Failed to get status',
|
|
79
|
+
details: error instanceof Error ? error.message : String(error),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* GET /api/mcp-admin-management/keys
|
|
85
|
+
* List all admin API keys
|
|
86
|
+
*/
|
|
87
|
+
router.get('/keys', async (req, res) => {
|
|
88
|
+
try {
|
|
89
|
+
const keys = await (0, index_js_1.listAdminApiKeys)();
|
|
90
|
+
// Return keys with both masked and full key (full key only for non-revoked)
|
|
91
|
+
const sanitizedKeys = keys.map((key) => ({
|
|
92
|
+
id: key.id,
|
|
93
|
+
description: key.description,
|
|
94
|
+
permissions: key.permissions,
|
|
95
|
+
allowedTools: key.allowedTools,
|
|
96
|
+
enabled: key.enabled !== false, // Default to true if not specified
|
|
97
|
+
createdAt: key.createdAt,
|
|
98
|
+
lastUsedAt: key.lastUsedAt,
|
|
99
|
+
revokedAt: key.revokedAt,
|
|
100
|
+
// Mask the key - show first 8 chars + ... + last 4 chars
|
|
101
|
+
maskedKey: key.decryptedKey
|
|
102
|
+
? `${key.decryptedKey.substring(0, 8)}...${key.decryptedKey.substring(key.decryptedKey.length - 4)}`
|
|
103
|
+
: null,
|
|
104
|
+
// Full key is only available for non-revoked keys
|
|
105
|
+
fullKey: !key.revokedAt ? key.decryptedKey : null,
|
|
106
|
+
isRevoked: !!key.revokedAt,
|
|
107
|
+
}));
|
|
108
|
+
res.json({ keys: sanitizedKeys });
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error('[MCP Admin Management] Error listing keys:', error);
|
|
112
|
+
res.status(500).json({
|
|
113
|
+
error: 'Failed to list keys',
|
|
114
|
+
details: error instanceof Error ? error.message : String(error),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
/**
|
|
119
|
+
* POST /api/mcp-admin-management/keys
|
|
120
|
+
* Create a new admin API key
|
|
121
|
+
*/
|
|
122
|
+
router.post('/keys', async (req, res) => {
|
|
123
|
+
try {
|
|
124
|
+
const { description, permissions, allowedTools } = req.body;
|
|
125
|
+
if (!description) {
|
|
126
|
+
res.status(400).json({
|
|
127
|
+
error: 'Description is required',
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const parsedPermissions = permissions || ['admin:*'];
|
|
132
|
+
const parsedAllowedTools = allowedTools || undefined;
|
|
133
|
+
const { key, keyData } = await (0, index_js_1.generateAdminApiKey)(description, parsedPermissions, parsedAllowedTools);
|
|
134
|
+
res.status(201).json({
|
|
135
|
+
id: keyData.id,
|
|
136
|
+
key, // Only shown once!
|
|
137
|
+
description: keyData.description,
|
|
138
|
+
permissions: keyData.permissions,
|
|
139
|
+
allowedTools: keyData.allowedTools,
|
|
140
|
+
createdAt: keyData.createdAt,
|
|
141
|
+
message: 'Save this key now - it will not be shown again',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error('[MCP Admin Management] Error creating key:', error);
|
|
146
|
+
res.status(500).json({
|
|
147
|
+
error: 'Failed to create key',
|
|
148
|
+
details: error instanceof Error ? error.message : String(error),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
/**
|
|
153
|
+
* PUT /api/mcp-admin-management/keys/:keyId
|
|
154
|
+
* Update an admin API key (description, allowedTools)
|
|
155
|
+
*/
|
|
156
|
+
router.put('/keys/:keyId', async (req, res) => {
|
|
157
|
+
try {
|
|
158
|
+
const { keyId } = req.params;
|
|
159
|
+
const { description, allowedTools } = req.body;
|
|
160
|
+
const updatedKey = await (0, index_js_1.updateAdminApiKey)(keyId, { description, allowedTools });
|
|
161
|
+
if (!updatedKey) {
|
|
162
|
+
res.status(404).json({
|
|
163
|
+
error: 'Key not found',
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
res.json({
|
|
168
|
+
success: true,
|
|
169
|
+
key: {
|
|
170
|
+
id: updatedKey.id,
|
|
171
|
+
description: updatedKey.description,
|
|
172
|
+
allowedTools: updatedKey.allowedTools,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.error('[MCP Admin Management] Error updating key:', error);
|
|
178
|
+
res.status(500).json({
|
|
179
|
+
error: 'Failed to update key',
|
|
180
|
+
details: error instanceof Error ? error.message : String(error),
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
/**
|
|
185
|
+
* POST /api/mcp-admin-management/keys/:keyId/toggle
|
|
186
|
+
* Enable or disable an admin API key
|
|
187
|
+
*/
|
|
188
|
+
router.post('/keys/:keyId/toggle', async (req, res) => {
|
|
189
|
+
try {
|
|
190
|
+
const { keyId } = req.params;
|
|
191
|
+
const { enabled } = req.body;
|
|
192
|
+
if (typeof enabled !== 'boolean') {
|
|
193
|
+
res.status(400).json({
|
|
194
|
+
error: 'enabled must be a boolean',
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const success = await (0, index_js_1.toggleAdminApiKey)(keyId, enabled);
|
|
199
|
+
if (!success) {
|
|
200
|
+
res.status(404).json({
|
|
201
|
+
error: 'Key not found',
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
res.json({
|
|
206
|
+
success: true,
|
|
207
|
+
enabled,
|
|
208
|
+
message: enabled ? 'API key enabled' : 'API key disabled',
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error('[MCP Admin Management] Error toggling key:', error);
|
|
213
|
+
res.status(500).json({
|
|
214
|
+
error: 'Failed to toggle key',
|
|
215
|
+
details: error instanceof Error ? error.message : String(error),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
/**
|
|
220
|
+
* DELETE /api/mcp-admin-management/keys/:keyId
|
|
221
|
+
* Revoke an admin API key
|
|
222
|
+
*/
|
|
223
|
+
router.delete('/keys/:keyId', async (req, res) => {
|
|
224
|
+
try {
|
|
225
|
+
const { keyId } = req.params;
|
|
226
|
+
const success = await (0, index_js_1.revokeAdminApiKey)(keyId);
|
|
227
|
+
if (!success) {
|
|
228
|
+
res.status(404).json({
|
|
229
|
+
error: 'Key not found',
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
res.json({
|
|
234
|
+
success: true,
|
|
235
|
+
message: 'API key revoked',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
console.error('[MCP Admin Management] Error revoking key:', error);
|
|
240
|
+
res.status(500).json({
|
|
241
|
+
error: 'Failed to revoke key',
|
|
242
|
+
details: error instanceof Error ? error.message : String(error),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* GET /api/mcp-admin-management/config-snippet
|
|
248
|
+
* Get configuration snippet for Cursor or Claude Desktop
|
|
249
|
+
*/
|
|
250
|
+
router.get('/config-snippet', async (req, res) => {
|
|
251
|
+
try {
|
|
252
|
+
const { platform, apiKey, serverUrl } = req.query;
|
|
253
|
+
if (!apiKey) {
|
|
254
|
+
res.status(400).json({
|
|
255
|
+
error: 'API key is required',
|
|
256
|
+
});
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// Get the base URL from the request or use provided serverUrl
|
|
260
|
+
const baseUrl = serverUrl || `${req.protocol}://${req.get('host')}`;
|
|
261
|
+
const mcpEndpoint = `${baseUrl}/api/mcp-admin`;
|
|
262
|
+
const cursorConfig = {
|
|
263
|
+
mcpServers: {
|
|
264
|
+
'agentstudio-admin': {
|
|
265
|
+
url: mcpEndpoint,
|
|
266
|
+
headers: {
|
|
267
|
+
Authorization: `Bearer ${apiKey}`,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
const claudeDesktopConfig = {
|
|
273
|
+
mcpServers: {
|
|
274
|
+
'agentstudio-admin': {
|
|
275
|
+
url: mcpEndpoint,
|
|
276
|
+
headers: {
|
|
277
|
+
Authorization: `Bearer ${apiKey}`,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
if (platform === 'cursor') {
|
|
283
|
+
res.json({
|
|
284
|
+
platform: 'cursor',
|
|
285
|
+
configPath: '~/.cursor/mcp.json',
|
|
286
|
+
config: cursorConfig,
|
|
287
|
+
configString: JSON.stringify(cursorConfig, null, 2),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
else if (platform === 'claude-desktop') {
|
|
291
|
+
res.json({
|
|
292
|
+
platform: 'claude-desktop',
|
|
293
|
+
configPath: '~/Library/Application Support/Claude/claude_desktop_config.json',
|
|
294
|
+
config: claudeDesktopConfig,
|
|
295
|
+
configString: JSON.stringify(claudeDesktopConfig, null, 2),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
res.json({
|
|
300
|
+
cursor: {
|
|
301
|
+
configPath: '~/.cursor/mcp.json',
|
|
302
|
+
config: cursorConfig,
|
|
303
|
+
configString: JSON.stringify(cursorConfig, null, 2),
|
|
304
|
+
},
|
|
305
|
+
claudeDesktop: {
|
|
306
|
+
configPath: '~/Library/Application Support/Claude/claude_desktop_config.json',
|
|
307
|
+
config: claudeDesktopConfig,
|
|
308
|
+
configString: JSON.stringify(claudeDesktopConfig, null, 2),
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error('[MCP Admin Management] Error generating config:', error);
|
|
315
|
+
res.status(500).json({
|
|
316
|
+
error: 'Failed to generate config',
|
|
317
|
+
details: error instanceof Error ? error.message : String(error),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
/**
|
|
322
|
+
* GET /api/mcp-admin-management/tools
|
|
323
|
+
* List available MCP Admin tools
|
|
324
|
+
*/
|
|
325
|
+
router.get('/tools', async (req, res) => {
|
|
326
|
+
try {
|
|
327
|
+
const { allTools } = await Promise.resolve().then(() => __importStar(require('../services/mcpAdmin/tools/index.js')));
|
|
328
|
+
const tools = allTools.map((tool) => ({
|
|
329
|
+
name: tool.tool.name,
|
|
330
|
+
description: tool.tool.description,
|
|
331
|
+
requiredPermissions: tool.requiredPermissions,
|
|
332
|
+
inputSchema: tool.tool.inputSchema,
|
|
333
|
+
}));
|
|
334
|
+
res.json({ tools });
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
console.error('[MCP Admin Management] Error listing tools:', error);
|
|
338
|
+
res.status(500).json({
|
|
339
|
+
error: 'Failed to list tools',
|
|
340
|
+
details: error instanceof Error ? error.message : String(error),
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
exports.default = router;
|
|
345
|
+
//# sourceMappingURL=mcpAdminManagement.js.map
|