fa-mcp-sdk 0.2.144 → 0.2.174
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 +1 -1
- package/bin/fa-mcp.js +66 -54
- package/cli-template/.env.example +2 -2
- package/cli-template/README.md +2 -2
- package/cli-template/fa-mcp-sdk-spec.md +122 -41
- package/cli-template/package.json +3 -3
- package/cli-template/r/TEST HTTP.xml +9 -0
- package/cli-template/{run/TEST SSE.run.xml → r/TEST SSE.xml } +2 -2
- package/cli-template/{run/TEST STDIO.run.xml → r/TEST STDIO.xml } +2 -2
- package/cli-template/r/generate-token.xml +14 -0
- package/cli-template/{run/kill-server.run.xml → r/kill-server.xml} +2 -2
- package/cli-template/{run/kill-token-gen-server.xml → r/remove-nul.xml} +4 -5
- package/{cli-template/config → config}/_local.yaml +28 -14
- package/{cli-template/config → config}/custom-environment-variables.yaml +3 -0
- package/{cli-template/config → config}/default.yaml +50 -10
- package/{cli-template/config → config}/development.yaml +4 -4
- package/config/local.yaml +81 -0
- package/{cli-template/config → config}/production.yaml +4 -4
- package/dist/core/_types_/active-directory-config.d.ts +3 -0
- package/dist/core/_types_/active-directory-config.d.ts.map +1 -1
- package/dist/core/_types_/config.d.ts +5 -1
- package/dist/core/_types_/config.d.ts.map +1 -1
- package/dist/core/_types_/types.d.ts +5 -1
- package/dist/core/_types_/types.d.ts.map +1 -1
- package/dist/core/ad/group-checker.d.ts +13 -0
- package/dist/core/ad/group-checker.d.ts.map +1 -0
- package/dist/core/ad/group-checker.js +86 -0
- package/dist/core/ad/group-checker.js.map +1 -0
- package/dist/core/auth/admin-auth.d.ts +16 -0
- package/dist/core/auth/admin-auth.d.ts.map +1 -0
- package/dist/core/auth/admin-auth.js +159 -0
- package/dist/core/auth/admin-auth.js.map +1 -0
- package/dist/core/auth/basic.d.ts +6 -0
- package/dist/core/auth/basic.d.ts.map +1 -0
- package/dist/core/auth/basic.js +26 -0
- package/dist/core/auth/basic.js.map +1 -0
- package/dist/core/auth/{jwt-validation.d.ts → jwt.d.ts} +4 -3
- package/dist/core/auth/jwt.d.ts.map +1 -0
- package/dist/core/auth/{jwt-validation.js → jwt.js} +9 -19
- package/dist/core/auth/jwt.js.map +1 -0
- package/dist/core/auth/middleware.d.ts.map +1 -1
- package/dist/core/auth/middleware.js +3 -3
- package/dist/core/auth/middleware.js.map +1 -1
- package/dist/core/auth/multi-auth.d.ts +14 -6
- package/dist/core/auth/multi-auth.d.ts.map +1 -1
- package/dist/core/auth/multi-auth.js +151 -141
- package/dist/core/auth/multi-auth.js.map +1 -1
- package/dist/core/auth/permanent.d.ts +6 -0
- package/dist/core/auth/permanent.d.ts.map +1 -0
- package/dist/core/auth/permanent.js +15 -0
- package/dist/core/auth/permanent.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.d.ts.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js +8 -10
- package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.d.ts.map +1 -1
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.js +9 -2
- package/dist/core/auth/token-generator/ntlm/ntlm-integration.js.map +1 -1
- package/dist/core/auth/token-generator/server.d.ts.map +1 -1
- package/dist/core/auth/token-generator/server.js +59 -25
- package/dist/core/auth/token-generator/server.js.map +1 -1
- package/dist/core/auth/types.d.ts +4 -3
- package/dist/core/auth/types.d.ts.map +1 -1
- package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
- package/dist/core/bootstrap/startup-info.js +19 -0
- package/dist/core/bootstrap/startup-info.js.map +1 -1
- package/dist/core/consul/access-points-updater.js +1 -1
- package/dist/core/consul/access-points-updater.js.map +1 -1
- package/dist/core/consul/get-consul-api.d.ts +1 -1
- package/dist/core/consul/get-consul-api.d.ts.map +1 -1
- package/dist/core/consul/get-consul-api.js +1 -1
- package/dist/core/consul/get-consul-api.js.map +1 -1
- package/dist/core/consul/register.d.ts +1 -1
- package/dist/core/consul/register.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/init-mcp-server.d.ts.map +1 -1
- package/dist/core/init-mcp-server.js +1 -1
- package/dist/core/init-mcp-server.js.map +1 -1
- package/dist/core/utils/testing/McpSseClient.js.map +1 -1
- package/dist/core/web/admin-router.d.ts +10 -0
- package/dist/core/web/admin-router.d.ts.map +1 -0
- package/dist/core/web/admin-router.js +227 -0
- package/dist/core/web/admin-router.js.map +1 -0
- package/dist/core/web/favicon-svg.d.ts +1 -1
- package/dist/core/web/favicon-svg.d.ts.map +1 -1
- package/dist/core/web/favicon-svg.js +21 -3
- package/dist/core/web/favicon-svg.js.map +1 -1
- package/dist/core/web/home-api.d.ts +7 -0
- package/dist/core/web/home-api.d.ts.map +1 -0
- package/dist/core/web/home-api.js +93 -0
- package/dist/core/web/home-api.js.map +1 -0
- package/dist/core/web/server-http.d.ts +1 -0
- package/dist/core/web/server-http.d.ts.map +1 -1
- package/dist/core/web/server-http.js +60 -25
- package/dist/core/web/server-http.js.map +1 -1
- package/dist/core/web/static/home/index.html +206 -0
- package/dist/core/web/static/home/script.js +636 -0
- package/dist/core/web/{about-page/css.js → static/styles.css} +435 -105
- package/dist/core/web/static/token-gen/index.html +82 -0
- package/dist/core/web/static/token-gen/jwt-icon.svg +3 -0
- package/dist/core/web/static/token-gen/logout.svg +4 -0
- package/dist/core/web/static/token-gen/script.js +365 -0
- package/dist/core/web/static/token-gen/user.svg +4 -0
- package/dist/core/web/svg-icons.d.ts +7 -0
- package/dist/core/web/svg-icons.d.ts.map +1 -0
- package/dist/core/web/svg-icons.js +78 -0
- package/dist/core/web/svg-icons.js.map +1 -0
- package/package.json +7 -3
- package/scripts/copy-static.js +31 -0
- package/src/template/_examples/multi-auth-examples.ts +14 -47
- package/src/template/_types_/custom-config.ts +83 -0
- package/src/template/asset/logo.svg +4 -0
- package/src/template/start.ts +3 -3
- package/src/template/tools/handle-tool-call.ts +2 -1
- package/src/tests/mcp/test-http.js +10 -2
- package/src/tests/mcp/test-sse.js +10 -2
- package/src/tests/mcp/test-stdio.js +1 -2
- package/cli-template/run/TEST HTTP.run.xml +0 -5
- package/cli-template/run/TEST search.run.xml +0 -11
- package/cli-template/run/remove-nul.js.run.xml +0 -5
- package/dist/core/auth/jwt-validation.d.ts.map +0 -1
- package/dist/core/auth/jwt-validation.js.map +0 -1
- package/dist/core/auth/token-generator/html.d.ts +0 -9
- package/dist/core/auth/token-generator/html.d.ts.map +0 -1
- package/dist/core/auth/token-generator/html.js +0 -862
- package/dist/core/auth/token-generator/html.js.map +0 -1
- package/dist/core/web/about-page/css.d.ts +0 -2
- package/dist/core/web/about-page/css.d.ts.map +0 -1
- package/dist/core/web/about-page/css.js.map +0 -1
- package/dist/core/web/about-page/render.d.ts +0 -2
- package/dist/core/web/about-page/render.d.ts.map +0 -1
- package/dist/core/web/about-page/render.js +0 -773
- package/dist/core/web/about-page/render.js.map +0 -1
- /package/cli-template/{run/== START ==.run.xml → r/== START ==.xml} +0 -0
- /package/cli-template/{run/cb.run.xml → r/cb.xml} +0 -0
- /package/cli-template/{run/ci.run.xml → r/ci.xml} +0 -0
- /package/cli-template/{run/lint.run.xml → r/lint.xml} +0 -0
- /package/cli-template/{run/lint_fix.run.xml → r/lint_fix.xml} +0 -0
- /package/cli-template/{run/reinstall.run.xml → r/reinstall.xml} +0 -0
- /package/{cli-template/config → config}/test.yaml +0 -0
- /package/{src/template/asset/favicon.svg → dist/core/web/static/logo.svg} +0 -0
- /package/{cli-template/scripts → scripts}/kill-port.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/patch_node_modules.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/run.js +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-ci.ps1 +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-ci.sh +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.ps1 +0 -0
- /package/{cli-template/scripts → scripts}/npm/yarn-reinstall.sh +0 -0
- /package/{cli-template/scripts → scripts}/pre-commit +0 -0
- /package/{cli-template/scripts → scripts}/remove-nul.js +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin panel router - Token Generator & Validator
|
|
3
|
+
* Endpoints for JWT token generation and validation
|
|
4
|
+
*/
|
|
5
|
+
import { Router } from 'express';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { appConfig } from '../bootstrap/init-config.js';
|
|
10
|
+
import { checkJwtToken, generateToken } from '../auth/jwt.js';
|
|
11
|
+
import { isNTLMEnabled } from '../auth/token-generator/ntlm/ntlm-domain-config.js';
|
|
12
|
+
import { getSessionStats } from '../auth/token-generator/ntlm/ntlm-session-storage.js';
|
|
13
|
+
import { getLoginPageHTML } from '../auth/token-generator/ntlm/ntlm-templates.js';
|
|
14
|
+
import { createAdminAuthMW } from '../auth/admin-auth.js';
|
|
15
|
+
import { logger as lgr } from '../logger.js';
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
// Path to static files (relative to compiled JS location in dist/)
|
|
19
|
+
const staticPath = join(__dirname, 'static/token-gen');
|
|
20
|
+
const logger = lgr.getSubLogger({ name: chalk.bgCyan('admin-router') });
|
|
21
|
+
const timeToSeconds = {
|
|
22
|
+
minutes: 60,
|
|
23
|
+
hours: 60 * 60,
|
|
24
|
+
days: 60 * 60 * 24,
|
|
25
|
+
months: 60 * 60 * 24 * 30,
|
|
26
|
+
years: 60 * 60 * 24 * 365,
|
|
27
|
+
};
|
|
28
|
+
const { adminAuth } = appConfig.webServer || {};
|
|
29
|
+
const adminAuthType = adminAuth?.enabled === true ? adminAuth.type : undefined;
|
|
30
|
+
const ntlmEnabled = adminAuthType === 'ntlm' && isNTLMEnabled;
|
|
31
|
+
/**
|
|
32
|
+
* Creates admin router with all token generation endpoints
|
|
33
|
+
*/
|
|
34
|
+
export function createAdminRouter() {
|
|
35
|
+
const router = Router();
|
|
36
|
+
// Apply admin authentication middleware to all admin routes
|
|
37
|
+
const adminAuthMW = createAdminAuthMW();
|
|
38
|
+
router.use(adminAuthMW);
|
|
39
|
+
// Note: Static files (CSS, JS) are served globally at /static/token-gen/ by server-http.ts
|
|
40
|
+
// Main admin page - Token Generator UI
|
|
41
|
+
router.get('/', (req, res) => {
|
|
42
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
43
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
44
|
+
const isAuthenticated = req.ntlm?.isAuthenticated || false;
|
|
45
|
+
logger.info(`Admin page accessed by: ${domain}\\${username} (Authenticated: ${isAuthenticated})`);
|
|
46
|
+
// Serve static index.html
|
|
47
|
+
res.sendFile(join(staticPath, 'index.html'));
|
|
48
|
+
});
|
|
49
|
+
// Login page (for NTLM)
|
|
50
|
+
router.get('/login', (req, res) => {
|
|
51
|
+
res.send(getLoginPageHTML(req.ntlm?.username || ''));
|
|
52
|
+
});
|
|
53
|
+
// Logout endpoint
|
|
54
|
+
router.get('/logout', (req, res) => {
|
|
55
|
+
logger.info(`Logout requested by: ${req.ntlm?.domain || 'Unknown'}\\${req.ntlm?.username || 'Unknown'}`);
|
|
56
|
+
if (adminAuthType === 'ntlm') {
|
|
57
|
+
// NTLM logout - send 401 to trigger browser auth prompt
|
|
58
|
+
res.setHeader('WWW-Authenticate', 'NTLM');
|
|
59
|
+
res.setHeader('Clear-Site-Data', '"cookies", "storage"');
|
|
60
|
+
return res.status(401).send('Authentication required - please login again');
|
|
61
|
+
}
|
|
62
|
+
// For other auth types, just clear the session indication
|
|
63
|
+
res.setHeader('Clear-Site-Data', '"cookies", "storage"');
|
|
64
|
+
return res.status(401).json({
|
|
65
|
+
success: true,
|
|
66
|
+
message: 'Logged out successfully',
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
// Debug endpoint for session stats (development only)
|
|
70
|
+
router.get('/debug/sessions', (req, res) => {
|
|
71
|
+
if (process.env.NODE_ENV === 'production') {
|
|
72
|
+
return res.status(404).json({ error: 'Not available in production' });
|
|
73
|
+
}
|
|
74
|
+
const stats = getSessionStats();
|
|
75
|
+
return res.json({
|
|
76
|
+
message: 'Admin Panel Session Statistics',
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
...stats,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// API: Generate token
|
|
82
|
+
router.post('/api/generate-token', (req, res) => {
|
|
83
|
+
try {
|
|
84
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
85
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
86
|
+
const authenticatedUser = `${domain}\\${username}`;
|
|
87
|
+
const { user, timeValue, timeUnit, payload } = req.body;
|
|
88
|
+
if (!user || !timeValue || !timeUnit) {
|
|
89
|
+
logger.info(`Token generation failed (missing parameters) by: ${authenticatedUser}`);
|
|
90
|
+
return res.json({
|
|
91
|
+
success: false,
|
|
92
|
+
error: 'Need to fill in the user and token lifetime',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const multiplier = timeToSeconds[timeUnit];
|
|
96
|
+
if (!multiplier) {
|
|
97
|
+
logger.info(`Token generation failed (invalid time unit) by: ${authenticatedUser}`);
|
|
98
|
+
return res.json({
|
|
99
|
+
success: false,
|
|
100
|
+
error: 'Invalid Time Unit',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const liveTimeSec = timeValue * multiplier;
|
|
104
|
+
const token = generateToken(user, liveTimeSec, payload || {});
|
|
105
|
+
logger.info(`Generated token for user: ${user}, duration: ${timeValue} ${timeUnit}, requested by: ${authenticatedUser}`);
|
|
106
|
+
return res.json({
|
|
107
|
+
success: true,
|
|
108
|
+
token: token,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
113
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
114
|
+
logger.error(`Error generating token for ${domain}\\${username}:`, error);
|
|
115
|
+
return res.json({
|
|
116
|
+
success: false,
|
|
117
|
+
error: error.message,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
// API: Validate token
|
|
122
|
+
router.post('/api/validate-token', (req, res) => {
|
|
123
|
+
try {
|
|
124
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
125
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
126
|
+
const authenticatedUser = `${domain}\\${username}`;
|
|
127
|
+
const { token } = req.body;
|
|
128
|
+
if (!token) {
|
|
129
|
+
logger.info(`Token validation failed (no token provided) by: ${authenticatedUser}`);
|
|
130
|
+
return res.json({
|
|
131
|
+
success: false,
|
|
132
|
+
error: 'Token Not Transferred',
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
const result = checkJwtToken({ token });
|
|
136
|
+
if (result.errorReason) {
|
|
137
|
+
logger.info(`Token validation failed (${result.errorReason}) by: ${authenticatedUser}`);
|
|
138
|
+
return res.json({
|
|
139
|
+
success: false,
|
|
140
|
+
error: result.errorReason,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
logger.info(`Token validated successfully for user: ${result.payload?.user}, requested by: ${authenticatedUser}`);
|
|
144
|
+
return res.json({
|
|
145
|
+
success: true,
|
|
146
|
+
payload: result.payload,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
151
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
152
|
+
logger.error(`Error validating token for ${domain}\\${username}:`, error);
|
|
153
|
+
return res.json({
|
|
154
|
+
success: false,
|
|
155
|
+
error: error.message,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
// API: Service info
|
|
160
|
+
router.get('/api/service-info', (req, res) => {
|
|
161
|
+
try {
|
|
162
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
163
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
164
|
+
const isAuthenticated = req.ntlm?.isAuthenticated || false;
|
|
165
|
+
logger.info(`Service info requested by: ${domain}\\${username}`);
|
|
166
|
+
res.json({
|
|
167
|
+
success: true,
|
|
168
|
+
serviceName: appConfig.name,
|
|
169
|
+
primaryColor: appConfig.uiColor.primary,
|
|
170
|
+
authenticatedUser: `${domain}\\${username}`,
|
|
171
|
+
isAuthenticated,
|
|
172
|
+
authType: adminAuthType,
|
|
173
|
+
ntlmEnabled,
|
|
174
|
+
timestamp: new Date().toISOString(),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
179
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
180
|
+
logger.error(`Error getting service info for ${domain}\\${username}:`, error);
|
|
181
|
+
res.json({
|
|
182
|
+
success: false,
|
|
183
|
+
error: error.message,
|
|
184
|
+
serviceName: appConfig.name,
|
|
185
|
+
authType: adminAuthType,
|
|
186
|
+
ntlmEnabled,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// API: Auth status
|
|
191
|
+
router.get('/api/auth-status', (req, res) => {
|
|
192
|
+
try {
|
|
193
|
+
const username = req.ntlm?.username || 'Unknown';
|
|
194
|
+
const domain = req.ntlm?.domain || 'Unknown';
|
|
195
|
+
const isAuthenticated = req.ntlm?.isAuthenticated || false;
|
|
196
|
+
// Determine if logout is available (only for basic and ntlm)
|
|
197
|
+
const canLogout = isAuthenticated && (adminAuthType === 'basic' || adminAuthType === 'ntlm');
|
|
198
|
+
// Format user display based on auth type
|
|
199
|
+
let userDisplay = null;
|
|
200
|
+
if (isAuthenticated) {
|
|
201
|
+
if (adminAuthType === 'ntlm') {
|
|
202
|
+
userDisplay = `${domain}\\${username}`;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
userDisplay = username;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
res.json({
|
|
209
|
+
success: true,
|
|
210
|
+
authType: adminAuthType || null,
|
|
211
|
+
isAuthenticated,
|
|
212
|
+
user: userDisplay,
|
|
213
|
+
canLogout,
|
|
214
|
+
timestamp: new Date().toISOString(),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
res.json({
|
|
219
|
+
success: false,
|
|
220
|
+
error: error.message,
|
|
221
|
+
authType: adminAuthType || null,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
return router;
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=admin-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-router.js","sourceRoot":"","sources":["../../../src/core/web/admin-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favicon-svg.d.ts","sourceRoot":"","sources":["../../../src/core/web/favicon-svg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"favicon-svg.d.ts","sourceRoot":"","sources":["../../../src/core/web/favicon-svg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAoC1E,eAAO,MAAM,UAAU,QAAO,MAI7B,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAO,cAyB7B,CAAC"}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
2
5
|
import { config, getProjectData } from '../bootstrap/init-config.js';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
3
8
|
const ONE_YEAR_MS = 60 * 60 * 24 * 365 * 1000; // 1 year
|
|
9
|
+
// Default logo SVG (loaded from static/logo.svg)
|
|
10
|
+
let defaultLogoSvg = null;
|
|
11
|
+
const loadDefaultLogo = () => {
|
|
12
|
+
if (defaultLogoSvg === null) {
|
|
13
|
+
try {
|
|
14
|
+
defaultLogoSvg = readFileSync(join(__dirname, 'static/logo.svg'), 'utf-8');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
defaultLogoSvg = '<svg><!-- No logo provided --></svg>';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return defaultLogoSvg;
|
|
21
|
+
};
|
|
4
22
|
const etagS = (entity) => {
|
|
5
23
|
// compute hash of entity
|
|
6
24
|
const hash = crypto
|
|
@@ -10,9 +28,9 @@ const etagS = (entity) => {
|
|
|
10
28
|
.substring(0, 27);
|
|
11
29
|
return `"${Buffer.byteLength(entity, 'utf8').toString(16)}-${hash}"`;
|
|
12
30
|
};
|
|
13
|
-
export const
|
|
31
|
+
export const getLogoSvg = () => {
|
|
14
32
|
const { assets } = getProjectData();
|
|
15
|
-
let svg = assets?.
|
|
33
|
+
let svg = assets?.logoSvg || loadDefaultLogo();
|
|
16
34
|
return svg.replace('fill="currentColor"', `fill="${config.uiColor.primary}"`);
|
|
17
35
|
};
|
|
18
36
|
/**
|
|
@@ -32,7 +50,7 @@ export const faviconSvg = () => {
|
|
|
32
50
|
return;
|
|
33
51
|
}
|
|
34
52
|
// Lazy load SVG when needed
|
|
35
|
-
const svg =
|
|
53
|
+
const svg = getLogoSvg();
|
|
36
54
|
res.setHeader('Cache-Control', `public, max-age=${Math.floor(ONE_YEAR_MS / 1000)}`);
|
|
37
55
|
res.setHeader('ETag', etagS(svg));
|
|
38
56
|
res.setHeader('Content-Length', svg.length);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favicon-svg.js","sourceRoot":"","sources":["../../../src/core/web/favicon-svg.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,SAAS;AAExD,MAAM,KAAK,GAAG,CAAC,MAAc,EAAU,EAAE;IACvC,yBAAyB;IACzB,MAAM,IAAI,GAAG,MAAM;SAChB,UAAU,CAAC,MAAM,CAAC;SAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;SACtB,MAAM,CAAC,QAAQ,CAAC;SAChB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpB,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"favicon-svg.js","sourceRoot":"","sources":["../../../src/core/web/favicon-svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home-api.d.ts","sourceRoot":"","sources":["../../../src/core/web/home-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAyB5C,wBAAsB,cAAc,CAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAqEjF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Home page API endpoint
|
|
3
|
+
* Returns all dynamic data needed for the home page
|
|
4
|
+
*/
|
|
5
|
+
import { getResourcesList } from '../mcp/resources.js';
|
|
6
|
+
import { getPromptsList } from '../mcp/prompts.js';
|
|
7
|
+
import { getMainDBConnectionStatus } from '../db/pg-db.js';
|
|
8
|
+
import { getLogoSvg } from './favicon-svg.js';
|
|
9
|
+
import { appConfig, getProjectData } from '../bootstrap/init-config.js';
|
|
10
|
+
const startTime = new Date();
|
|
11
|
+
const getUptime = () => {
|
|
12
|
+
const uptimeMs = Date.now() - startTime.getTime();
|
|
13
|
+
const uptimeSeconds = Math.floor(uptimeMs / 1000);
|
|
14
|
+
const hours = Math.floor(uptimeSeconds / 3600);
|
|
15
|
+
const minutes = Math.floor((uptimeSeconds % 3600) / 60);
|
|
16
|
+
const seconds = uptimeSeconds % 60;
|
|
17
|
+
if (hours > 0) {
|
|
18
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
19
|
+
}
|
|
20
|
+
else if (minutes > 0) {
|
|
21
|
+
return `${minutes}m ${seconds}s`;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return `${seconds}s`;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export async function handleHomeInfo(_req, res) {
|
|
28
|
+
try {
|
|
29
|
+
const { version, repo } = appConfig;
|
|
30
|
+
const serviceTitle = appConfig.productName.replace(/MCP/i, '').replace(/\s{2,}/g, ' ').trim();
|
|
31
|
+
const logoSvg = getLogoSvg();
|
|
32
|
+
const { resources } = getResourcesList();
|
|
33
|
+
const { prompts } = getPromptsList();
|
|
34
|
+
const { tools, httpComponents } = global.__MCP_PROJECT_DATA__;
|
|
35
|
+
const { getConsulUIAddress = (_s) => '', assets } = getProjectData();
|
|
36
|
+
// Build footer HTML
|
|
37
|
+
const footerParts = [];
|
|
38
|
+
if (repo) {
|
|
39
|
+
footerParts.push(`<a href="${repo}" target="_blank" rel="noopener">GitHub Repository</a>`);
|
|
40
|
+
}
|
|
41
|
+
if (assets?.maintainerHtml) {
|
|
42
|
+
footerParts.push(assets.maintainerHtml);
|
|
43
|
+
}
|
|
44
|
+
// Database info
|
|
45
|
+
let db = null;
|
|
46
|
+
if (appConfig.isMainDBUsed) {
|
|
47
|
+
const dbStatus = await getMainDBConnectionStatus();
|
|
48
|
+
const { host, port, database } = appConfig.db.postgres.dbs.main;
|
|
49
|
+
db = {
|
|
50
|
+
connection: `${host}:${port}/${database}`,
|
|
51
|
+
status: dbStatus,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Consul info
|
|
55
|
+
let consul = null;
|
|
56
|
+
if (appConfig.consul.service.enable) {
|
|
57
|
+
const { id } = appConfig.consul.service;
|
|
58
|
+
if (id) {
|
|
59
|
+
consul = {
|
|
60
|
+
id,
|
|
61
|
+
url: getConsulUIAddress(id),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const response = {
|
|
66
|
+
serviceTitle,
|
|
67
|
+
description: appConfig.description,
|
|
68
|
+
version,
|
|
69
|
+
uptime: getUptime(),
|
|
70
|
+
primaryColor: appConfig.uiColor.primary,
|
|
71
|
+
logoSvg,
|
|
72
|
+
toolsCount: tools.length,
|
|
73
|
+
resourcesCount: resources.length,
|
|
74
|
+
promptsCount: prompts.length,
|
|
75
|
+
tools,
|
|
76
|
+
resources,
|
|
77
|
+
prompts,
|
|
78
|
+
db,
|
|
79
|
+
swagger: !!httpComponents?.swagger,
|
|
80
|
+
consul,
|
|
81
|
+
repo,
|
|
82
|
+
footer: footerParts.join(' • '),
|
|
83
|
+
};
|
|
84
|
+
res.json(response);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
res.status(500).json({
|
|
88
|
+
error: 'Failed to get home info',
|
|
89
|
+
message: error.message,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=home-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home-api.js","sourceRoot":"","sources":["../../../src/core/web/home-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-http.d.ts","sourceRoot":"","sources":["../../../src/core/web/server-http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-http.d.ts","sourceRoot":"","sources":["../../../src/core/web/server-http.ts"],"names":[],"mappings":"AAqCA,eAAO,MAAM,cAAc,SAA8B,CAAC;AAyC1D;;GAEG;AACH,wBAAsB,eAAe,IAAK,OAAO,CAAC,IAAI,CAAC,CA+ZtD"}
|
|
@@ -3,6 +3,8 @@ import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
|
3
3
|
import express from 'express';
|
|
4
4
|
import helmet from 'helmet';
|
|
5
5
|
import { RateLimiterMemory } from 'rate-limiter-flexible';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
6
8
|
import { appConfig, getProjectData } from '../bootstrap/init-config.js';
|
|
7
9
|
import { getResource, getResourcesList } from '../mcp/resources.js';
|
|
8
10
|
import { createAuthMW } from '../auth/middleware.js';
|
|
@@ -15,10 +17,19 @@ import { applyCors } from './cors.js';
|
|
|
15
17
|
import { faviconSvg } from './favicon-svg.js';
|
|
16
18
|
import chalk from 'chalk';
|
|
17
19
|
import { getPrompt, getPromptsList } from '../mcp/prompts.js';
|
|
18
|
-
import {
|
|
20
|
+
import { handleHomeInfo } from './home-api.js';
|
|
19
21
|
import { getMainDBConnectionStatus } from '../db/pg-db.js';
|
|
20
22
|
import { normalizeHeaders } from '../utils/utils.js';
|
|
23
|
+
import { createAdminRouter } from './admin-router.js';
|
|
24
|
+
import { validateAdminAuthConfig } from '../auth/admin-auth.js';
|
|
25
|
+
import { createSvgRouter } from './svg-icons.js';
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = dirname(__filename);
|
|
28
|
+
// Path to static files
|
|
29
|
+
const staticPath = join(__dirname, 'static');
|
|
21
30
|
const logger = lgr.getSubLogger({ name: chalk.bgYellow('server-http') });
|
|
31
|
+
const { adminAuth } = appConfig.webServer || {};
|
|
32
|
+
export const isAdminEnabled = adminAuth?.enabled === true;
|
|
22
33
|
/**
|
|
23
34
|
* Handle rate limiting with consistent error response
|
|
24
35
|
*/
|
|
@@ -71,16 +82,15 @@ export async function startHttpServer() {
|
|
|
71
82
|
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
72
83
|
applyCors(app);
|
|
73
84
|
app.use(faviconSvg());
|
|
74
|
-
//
|
|
75
|
-
app.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
85
|
+
// Serve static files (CSS, JS, SVG)
|
|
86
|
+
app.use('/static', express.static(staticPath));
|
|
87
|
+
// SVG icons with color substitution
|
|
88
|
+
app.use('/svg', createSvgRouter());
|
|
89
|
+
// Home page API endpoint
|
|
90
|
+
app.get('/api/home-info', handleHomeInfo);
|
|
91
|
+
// Root endpoint - serve static Home page
|
|
92
|
+
app.get('/', (req, res) => {
|
|
93
|
+
res.sendFile(join(staticPath, 'home', 'index.html'));
|
|
84
94
|
});
|
|
85
95
|
// Health check endpoint
|
|
86
96
|
app.get('/health', async (req, res) => {
|
|
@@ -112,21 +122,33 @@ export async function startHttpServer() {
|
|
|
112
122
|
if (apiRouter) {
|
|
113
123
|
app.use('/api', apiRouter);
|
|
114
124
|
}
|
|
125
|
+
// Admin panel routes (Token Generator & Validator)
|
|
126
|
+
if (isAdminEnabled) {
|
|
127
|
+
const adminConfigError = validateAdminAuthConfig();
|
|
128
|
+
if (adminConfigError) {
|
|
129
|
+
logger.error(`Admin auth configuration error: ${adminConfigError}`);
|
|
130
|
+
throw new Error(`Admin auth configuration error: ${adminConfigError}`);
|
|
131
|
+
}
|
|
132
|
+
const adminRouter = createAdminRouter();
|
|
133
|
+
app.use('/admin', adminRouter);
|
|
134
|
+
logger.info('Admin panel mounted at /admin');
|
|
135
|
+
}
|
|
115
136
|
// SSE endpoints for legacy MCP communication
|
|
116
|
-
// Store SSE transports by session ID with transport, server, and
|
|
137
|
+
// Store SSE transports by session ID with transport, server, preserved headers, and auth payload
|
|
117
138
|
const sseTransports = new Map();
|
|
118
|
-
// Create SSE server instance with preserved headers from connection establishment
|
|
119
|
-
async function createSseServer(preservedHeaders) {
|
|
139
|
+
// Create SSE server instance with preserved headers and auth payload from connection establishment
|
|
140
|
+
async function createSseServer(preservedHeaders, authPayload) {
|
|
120
141
|
const sseServer = createMcpServer();
|
|
121
|
-
// Override the tool call handler to include rate limiting and
|
|
142
|
+
// Override the tool call handler to include rate limiting, preserved headers and auth payload
|
|
122
143
|
sseServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
123
144
|
// Apply rate limiting for each SSE tool call
|
|
124
145
|
const toolCallClientId = 'sse-tool-unknown';
|
|
125
146
|
await handleRateLimit(rateLimiter, toolCallClientId, 'unknown', `SSE tool call | tool: ${request.params.name}`);
|
|
126
|
-
// Execute the tool call with preserved headers from SSE connection establishment
|
|
147
|
+
// Execute the tool call with preserved headers and payload from SSE connection establishment
|
|
127
148
|
const result = await toolHandler({
|
|
128
149
|
...request.params,
|
|
129
|
-
headers: preservedHeaders // Use headers from when SSE connection was established
|
|
150
|
+
headers: preservedHeaders, // Use headers from when SSE connection was established
|
|
151
|
+
payload: authPayload // Use auth payload from when SSE connection was established
|
|
130
152
|
});
|
|
131
153
|
return {
|
|
132
154
|
content: result.content,
|
|
@@ -144,15 +166,19 @@ export async function startHttpServer() {
|
|
|
144
166
|
// Preserve normalized headers from SSE connection establishment
|
|
145
167
|
const preservedHeaders = normalizeHeaders(req.headers);
|
|
146
168
|
logger.debug('SSE connection headers preserved:', Object.keys(preservedHeaders));
|
|
169
|
+
// Extract auth payload from middleware (set by authMW)
|
|
170
|
+
const authInfo = req.authInfo;
|
|
171
|
+
const authPayload = authInfo?.payload;
|
|
147
172
|
// Create SSE transport that will use the same endpoint for POST requests
|
|
148
173
|
const transport = new SSEServerTransport('/sse', res);
|
|
149
|
-
// Create a dedicated server instance with preserved headers for this SSE connection
|
|
150
|
-
const sseServer = await createSseServer(preservedHeaders);
|
|
151
|
-
// Store transport, server, and
|
|
174
|
+
// Create a dedicated server instance with preserved headers and auth payload for this SSE connection
|
|
175
|
+
const sseServer = await createSseServer(preservedHeaders, authPayload);
|
|
176
|
+
// Store transport, server, headers, and payload for cleanup and reference
|
|
152
177
|
sseTransports.set(transport.sessionId, {
|
|
153
178
|
transport,
|
|
154
179
|
server: sseServer,
|
|
155
|
-
headers: preservedHeaders
|
|
180
|
+
headers: preservedHeaders,
|
|
181
|
+
payload: authPayload
|
|
156
182
|
});
|
|
157
183
|
// Clean up transport and server on connection close
|
|
158
184
|
res.on('close', () => {
|
|
@@ -275,9 +301,12 @@ export async function startHttpServer() {
|
|
|
275
301
|
// Apply rate limiting for tool calls
|
|
276
302
|
const toolCallClientId = `tool-${req.ip || 'unknown'}`;
|
|
277
303
|
await handleRateLimit(rateLimiter, toolCallClientId, req.ip || 'unknown', `tool call | tool: ${params?.name || 'unknown'}`, res, id);
|
|
304
|
+
// Extract auth payload from middleware (set by authMW)
|
|
305
|
+
const mcpAuthPayload = req.authInfo?.payload;
|
|
278
306
|
result = await toolHandler({
|
|
279
307
|
...params,
|
|
280
|
-
headers: normalizeHeaders(req.headers)
|
|
308
|
+
headers: normalizeHeaders(req.headers),
|
|
309
|
+
payload: mcpAuthPayload
|
|
281
310
|
});
|
|
282
311
|
break;
|
|
283
312
|
case 'prompts/list':
|
|
@@ -345,7 +374,7 @@ export async function startHttpServer() {
|
|
|
345
374
|
// 404 handler for unknown routes
|
|
346
375
|
app.use((req, res) => {
|
|
347
376
|
const availableEndpoints = {
|
|
348
|
-
|
|
377
|
+
home: 'GET /',
|
|
349
378
|
health: 'GET /health',
|
|
350
379
|
sse: 'GET /sse, POST /sse',
|
|
351
380
|
messages: 'POST /messages',
|
|
@@ -354,6 +383,9 @@ export async function startHttpServer() {
|
|
|
354
383
|
if (swagger) {
|
|
355
384
|
availableEndpoints.docs = 'GET /docs';
|
|
356
385
|
}
|
|
386
|
+
if (isAdminEnabled) {
|
|
387
|
+
availableEndpoints.admin = 'GET /admin';
|
|
388
|
+
}
|
|
357
389
|
Object.assign(availableEndpoints, {
|
|
358
390
|
...(httpComponents?.endpointsOn404 || {}),
|
|
359
391
|
});
|
|
@@ -373,8 +405,11 @@ export async function startHttpServer() {
|
|
|
373
405
|
// Start HTTP server
|
|
374
406
|
const port = appConfig.webServer.port;
|
|
375
407
|
app.listen(port, '0.0.0.0', () => {
|
|
376
|
-
|
|
377
|
-
|
|
408
|
+
let msg = `${chalk.magenta(appConfig.productName)} started with ${chalk.blue('HTTP')} transport on port ${chalk.blue(port)}
|
|
409
|
+
Home page: http://localhost:${port}/`;
|
|
410
|
+
if (isAdminEnabled) {
|
|
411
|
+
msg += `\nAdmin panel: http://localhost:${port}/admin`;
|
|
412
|
+
}
|
|
378
413
|
console.log(msg);
|
|
379
414
|
});
|
|
380
415
|
}
|