fa-mcp-sdk 0.2.121 → 0.2.125
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/bin/fa-mcp.js +1 -0
- package/cli-template/config/_local.yaml +21 -1
- package/cli-template/config/custom-environment-variables.yaml +11 -1
- package/cli-template/config/default.yaml +11 -1
- package/cli-template/fa-mcp-sdk-spec.md +385 -2
- package/cli-template/package.json +72 -73
- package/cli-template/src/_examples/custom-basic-auth-example.ts +252 -0
- package/cli-template/src/_examples/multi-auth-examples.ts +333 -0
- package/cli-template/src/custom-resources.ts +1 -0
- package/cli-template/yarn.lock +6375 -0
- package/dist/core/_types_/TNtlm.d.ts +5 -0
- package/dist/core/_types_/TNtlm.d.ts.map +1 -0
- package/dist/core/_types_/TNtlm.js +2 -0
- package/dist/core/_types_/TNtlm.js.map +1 -0
- package/dist/core/_types_/config.d.ts +88 -0
- package/dist/core/_types_/config.d.ts.map +1 -0
- package/dist/core/_types_/config.js +2 -0
- package/dist/core/_types_/config.js.map +1 -0
- package/dist/core/_types_/types.d.ts +8 -0
- package/dist/core/_types_/types.d.ts.map +1 -1
- package/dist/core/{token/token-core.d.ts → auth/jwt-validation.d.ts} +2 -2
- package/dist/core/auth/jwt-validation.d.ts.map +1 -0
- package/dist/core/{token/token-core.js → auth/jwt-validation.js} +4 -4
- package/dist/core/auth/jwt-validation.js.map +1 -0
- package/dist/core/auth/middleware.d.ts +47 -0
- package/dist/core/auth/middleware.d.ts.map +1 -0
- package/dist/core/{token/token-auth.js → auth/middleware.js} +114 -2
- package/dist/core/auth/middleware.js.map +1 -0
- package/dist/core/auth/multi-auth.d.ts +27 -0
- package/dist/core/auth/multi-auth.d.ts.map +1 -0
- package/dist/core/auth/multi-auth.js +300 -0
- package/dist/core/auth/multi-auth.js.map +1 -0
- package/dist/core/auth/token-generator/html.d.ts.map +1 -0
- package/dist/core/{token/gen-token-app → auth/token-generator}/html.js +2 -2
- package/dist/core/auth/token-generator/html.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm-auth-options.d.ts.map +1 -0
- package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-auth-options.js +1 -1
- package/dist/core/auth/token-generator/ntlm-auth-options.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm-domain-config.d.ts.map +1 -0
- package/dist/core/auth/token-generator/ntlm-domain-config.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm-integration.d.ts.map +1 -0
- package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-integration.js +4 -4
- package/dist/core/auth/token-generator/ntlm-integration.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm-session-storage.d.ts.map +1 -0
- package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-session-storage.js +1 -1
- package/dist/core/auth/token-generator/ntlm-session-storage.js.map +1 -0
- package/dist/core/auth/token-generator/ntlm-templates.d.ts.map +1 -0
- package/dist/core/auth/token-generator/ntlm-templates.js.map +1 -0
- package/dist/core/{token/gen-token-app/gen-token-server.d.ts → auth/token-generator/server.d.ts} +1 -1
- package/dist/core/auth/token-generator/server.d.ts.map +1 -0
- package/dist/core/{token/gen-token-app/gen-token-server.js → auth/token-generator/server.js} +3 -3
- package/dist/core/auth/token-generator/server.js.map +1 -0
- package/dist/core/auth/types.d.ts +35 -0
- package/dist/core/auth/types.d.ts.map +1 -0
- package/dist/core/auth/types.js +14 -0
- package/dist/core/auth/types.js.map +1 -0
- package/dist/core/cache/cache.d.ts.map +1 -1
- package/dist/core/cache/cache.js +3 -2
- package/dist/core/cache/cache.js.map +1 -1
- package/dist/core/index.d.ts +5 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/web/server-http.js +1 -1
- package/dist/core/web/server-http.js.map +1 -1
- package/package.json +2 -2
- package/dist/core/token/gen-token-app/gen-token-server.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/gen-token-server.js.map +0 -1
- package/dist/core/token/gen-token-app/html.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/html.js.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-auth-options.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-auth-options.js.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-domain-config.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-domain-config.js.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-integration.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-integration.js.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-session-storage.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-session-storage.js.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-templates.d.ts.map +0 -1
- package/dist/core/token/gen-token-app/ntlm-templates.js.map +0 -1
- package/dist/core/token/i-token.d.ts +0 -13
- package/dist/core/token/i-token.d.ts.map +0 -1
- package/dist/core/token/i-token.js +0 -2
- package/dist/core/token/i-token.js.map +0 -1
- package/dist/core/token/token-auth.d.ts +0 -17
- package/dist/core/token/token-auth.d.ts.map +0 -1
- package/dist/core/token/token-auth.js.map +0 -1
- package/dist/core/token/token-core.d.ts.map +0 -1
- package/dist/core/token/token-core.js.map +0 -1
- /package/dist/core/{token/gen-token-app → auth/token-generator}/html.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-auth-options.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-domain-config.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-domain-config.js +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-integration.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-session-storage.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-templates.d.ts +0 -0
- /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-templates.js +0 -0
package/bin/fa-mcp.js
CHANGED
|
@@ -723,6 +723,7 @@ certificate's public and private keys`,
|
|
|
723
723
|
|
|
724
724
|
async handlePackageJson (content, config) {
|
|
725
725
|
try {
|
|
726
|
+
content = content.replace('"project.name"', '"{{project.name}}"');
|
|
726
727
|
// First replace all template parameters in the content string
|
|
727
728
|
let updatedContent = content;
|
|
728
729
|
for (const [param, value] of Object.entries(config)) {
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Copy this file to local.yaml and update with your database credentials
|
|
2
2
|
# local.yaml is gitignored and won't be committed
|
|
3
3
|
---
|
|
4
|
+
#ad:
|
|
5
|
+
# domains:
|
|
6
|
+
# MYDOMAIN:
|
|
7
|
+
# default: true
|
|
8
|
+
# controllers:
|
|
9
|
+
# - 'ldap://c1.corp.com'
|
|
10
|
+
# - 'ldap://c2.corp.com'
|
|
11
|
+
# username: '***'
|
|
12
|
+
# password: '***'
|
|
13
|
+
|
|
4
14
|
# --------------------------------------------------
|
|
5
15
|
# CACHING Reduces API calls by caching responses
|
|
6
16
|
# --------------------------------------------------
|
|
@@ -69,8 +79,18 @@ webServer:
|
|
|
69
79
|
enabled: {{webServer.auth.enabled}} # Enables/disables token authorization
|
|
70
80
|
# An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
|
|
71
81
|
permanentServerTokens: []
|
|
72
|
-
|
|
82
|
+
jwtToken:
|
|
73
83
|
# Symmetric encryption key to generate a token for this MCP
|
|
74
84
|
encryptKey: '{{webServer.auth.token.encryptKey}}'
|
|
75
85
|
# If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
|
|
76
86
|
checkMCPName: {{webServer.auth.token.checkMCPName}}
|
|
87
|
+
#basic:
|
|
88
|
+
# username: '***'
|
|
89
|
+
# password: '***'
|
|
90
|
+
#oauth2:
|
|
91
|
+
# type: 'oauth2';
|
|
92
|
+
# clientId: '***'
|
|
93
|
+
# clientSecret: '***'
|
|
94
|
+
# redirectUri?: 'string'
|
|
95
|
+
# tokenEndpoint?: string # For custom OAuth providers // VVR
|
|
96
|
+
#pat: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
cache:
|
|
2
2
|
ttlSeconds: CACHE_TTL_SECONDS
|
|
3
3
|
maxItems: CACHE_MAX_ITEMS
|
|
4
|
+
checkPeriod: CACHE_CHECK_PERIOD
|
|
4
5
|
|
|
5
6
|
db:
|
|
6
7
|
postgres:
|
|
@@ -33,6 +34,15 @@ webServer:
|
|
|
33
34
|
auth:
|
|
34
35
|
enabled: WS_AUTH_ENABLED
|
|
35
36
|
permanentServerTokens: WS_SERVER_TOKENS # comma separated list
|
|
36
|
-
|
|
37
|
+
jwtToken:
|
|
37
38
|
encryptKey: WS_TOKEN_ENCRYPT_KEY
|
|
38
39
|
checkMCPName: WS_CHECK_MC_NAME
|
|
40
|
+
basic:
|
|
41
|
+
username: WS_AUTH_BASIC_USERNAME
|
|
42
|
+
password: WS_AUTH_BASIC_PASSWORD
|
|
43
|
+
oauth2:
|
|
44
|
+
clientId: WS_AUTH_OAUTH2_CLIENT_ID
|
|
45
|
+
clientSecret: WS_AUTH_OAUTH2_CLIENT_SECRET
|
|
46
|
+
redirectUri: WS_AUTH_OAUTH2_REDIRECT_URI
|
|
47
|
+
tokenEndpoint: WS_AUTH_OAUTH2_TOKEN_ENDPOINT # For custom OAuth providers // VVR
|
|
48
|
+
pat: WS_AUTH_PAT
|
|
@@ -114,8 +114,18 @@ webServer:
|
|
|
114
114
|
enabled: false # Enables/disables token authorization
|
|
115
115
|
# An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
|
|
116
116
|
permanentServerTokens: []
|
|
117
|
-
|
|
117
|
+
jwtToken:
|
|
118
118
|
# Symmetric encryption key to generate a token for this MCP
|
|
119
119
|
encryptKey: '***'
|
|
120
120
|
# If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
|
|
121
121
|
checkMCPName: true
|
|
122
|
+
#basic:
|
|
123
|
+
# username: '***'
|
|
124
|
+
# password: '***'
|
|
125
|
+
#oauth2:
|
|
126
|
+
# type: 'oauth2';
|
|
127
|
+
# clientId: '***'
|
|
128
|
+
# clientSecret: '***'
|
|
129
|
+
# redirectUri?: 'string'
|
|
130
|
+
# tokenEndpoint?: string # For custom OAuth providers // VVR
|
|
131
|
+
#pat: string;
|
|
@@ -58,17 +58,27 @@ The primary function for starting your MCP server.
|
|
|
58
58
|
**Example Usage in `src/start.ts`:**
|
|
59
59
|
|
|
60
60
|
```typescript
|
|
61
|
-
import { initMcpServer, McpServerData } from 'fa-mcp-sdk';
|
|
61
|
+
import { initMcpServer, McpServerData, CustomBasicAuthValidator } from 'fa-mcp-sdk';
|
|
62
62
|
import { tools } from './tools/tools.js';
|
|
63
63
|
import { handleToolCall } from './tools/handle-tool-call.js';
|
|
64
64
|
import { AGENT_BRIEF } from './prompts/agent-brief.js';
|
|
65
65
|
import { AGENT_PROMPT } from './prompts/agent-prompt.js';
|
|
66
66
|
|
|
67
|
+
// Optional: Custom Basic Authentication validator
|
|
68
|
+
const customAuthValidator: CustomBasicAuthValidator = async (username: string, password: string): Promise<boolean> => {
|
|
69
|
+
// Your custom authentication logic here (database, LDAP, API, etc.)
|
|
70
|
+
return await authenticateUser(username, password);
|
|
71
|
+
};
|
|
72
|
+
|
|
67
73
|
const serverData: McpServerData = {
|
|
68
74
|
tools,
|
|
69
75
|
toolHandler: handleToolCall,
|
|
70
76
|
agentBrief: AGENT_BRIEF,
|
|
71
77
|
agentPrompt: AGENT_PROMPT,
|
|
78
|
+
|
|
79
|
+
// Optional: Provide custom Basic Authentication
|
|
80
|
+
customBasicAuthValidator: customAuthValidator,
|
|
81
|
+
|
|
72
82
|
// ... other configuration
|
|
73
83
|
};
|
|
74
84
|
|
|
@@ -96,6 +106,9 @@ interface McpServerData {
|
|
|
96
106
|
requiredHttpHeaders?: IRequiredHttpHeader[] | null; // HTTP headers for authentication
|
|
97
107
|
customResources?: IResourceData[] | null; // Custom resource definitions
|
|
98
108
|
|
|
109
|
+
// Authentication
|
|
110
|
+
customBasicAuthValidator?: CustomBasicAuthValidator; // Custom Basic Authentication validator function
|
|
111
|
+
|
|
99
112
|
// HTTP Server Components (for HTTP transport)
|
|
100
113
|
httpComponents?: {
|
|
101
114
|
apiRouter?: Router | null; // Express router for additional endpoints
|
|
@@ -386,11 +399,21 @@ webServer:
|
|
|
386
399
|
enabled: false # Enables/disables token authorization
|
|
387
400
|
# An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
|
|
388
401
|
permanentServerTokens: []
|
|
389
|
-
|
|
402
|
+
jwtToken:
|
|
390
403
|
# Symmetric encryption key to generate a token for this MCP
|
|
391
404
|
encryptKey: '***'
|
|
392
405
|
# If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
|
|
393
406
|
checkMCPName: true
|
|
407
|
+
#basic:
|
|
408
|
+
# username: '***'
|
|
409
|
+
# password: '***'
|
|
410
|
+
#oauth2:
|
|
411
|
+
# type: 'oauth2';
|
|
412
|
+
# clientId: '***'
|
|
413
|
+
# clientSecret: '***'
|
|
414
|
+
# redirectUri?: 'string'
|
|
415
|
+
# tokenEndpoint?: string # For custom OAuth providers // VVR
|
|
416
|
+
#pat: string;
|
|
394
417
|
```
|
|
395
418
|
|
|
396
419
|
**`config/local.yaml`** - local overrides. Usually contains secrets.
|
|
@@ -822,6 +845,366 @@ await generateTokenApp(); // Uses default configuration from appConfig
|
|
|
822
845
|
// domainController: 'dc.domain.com'
|
|
823
846
|
```
|
|
824
847
|
|
|
848
|
+
#### Multi-Authentication System
|
|
849
|
+
|
|
850
|
+
The FA-MCP-SDK supports a comprehensive multi-authentication system that allows multiple authentication methods to work together with CPU-optimized performance ordering.
|
|
851
|
+
|
|
852
|
+
##### Types and Interfaces
|
|
853
|
+
|
|
854
|
+
```typescript
|
|
855
|
+
import {
|
|
856
|
+
AuthType,
|
|
857
|
+
AuthResult,
|
|
858
|
+
AuthDetectionResult,
|
|
859
|
+
CustomBasicAuthValidator,
|
|
860
|
+
checkMultiAuth,
|
|
861
|
+
detectAuthConfiguration,
|
|
862
|
+
logAuthConfiguration,
|
|
863
|
+
enhancedAuthTokenMW,
|
|
864
|
+
createConfigurableAuthMiddleware,
|
|
865
|
+
getAuthInfo,
|
|
866
|
+
getMultiAuthError
|
|
867
|
+
} from 'fa-mcp-sdk';
|
|
868
|
+
|
|
869
|
+
// Authentication types in CPU priority order (low to high cost)
|
|
870
|
+
export type AuthType = 'permanentServerTokens' | 'pat' | 'basic' | 'jwtToken' | 'oauth2';
|
|
871
|
+
|
|
872
|
+
// Custom Basic Authentication validator function
|
|
873
|
+
export type CustomBasicAuthValidator = (username: string, password: string) => Promise<boolean> | boolean;
|
|
874
|
+
|
|
875
|
+
// Authentication result interface
|
|
876
|
+
export interface AuthResult {
|
|
877
|
+
success: boolean;
|
|
878
|
+
error?: string;
|
|
879
|
+
authType?: AuthType;
|
|
880
|
+
tokenType?: string;
|
|
881
|
+
username?: string;
|
|
882
|
+
accessToken?: string;
|
|
883
|
+
payload?: any;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// Authentication detection result
|
|
887
|
+
export interface AuthDetectionResult {
|
|
888
|
+
configured: AuthType[]; // Authentication types found in configuration
|
|
889
|
+
valid: AuthType[]; // Authentication types properly configured and ready
|
|
890
|
+
errors: Record<string, string[]>; // Configuration errors by auth type
|
|
891
|
+
}
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
##### Core Multi-Authentication Functions
|
|
895
|
+
|
|
896
|
+
```typescript
|
|
897
|
+
// checkMultiAuth - validate token using all configured authentication methods
|
|
898
|
+
// Function Signature:
|
|
899
|
+
async function checkMultiAuth(
|
|
900
|
+
token: string,
|
|
901
|
+
authConfig: AppConfig['webServer']['auth']
|
|
902
|
+
): Promise<AuthResult> {...}
|
|
903
|
+
|
|
904
|
+
// Example:
|
|
905
|
+
const authConfig = appConfig.webServer.auth;
|
|
906
|
+
const result = await checkMultiAuth('user_token', authConfig);
|
|
907
|
+
|
|
908
|
+
if (result.success) {
|
|
909
|
+
console.log(`Authenticated via ${result.authType} as ${result.username}`);
|
|
910
|
+
} else {
|
|
911
|
+
console.log('Authentication failed:', result.error);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// detectAuthConfiguration - analyze auth configuration
|
|
915
|
+
// Function Signature:
|
|
916
|
+
function detectAuthConfiguration(authConfig: AppConfig['webServer']['auth']): AuthDetectionResult {...}
|
|
917
|
+
|
|
918
|
+
// Example:
|
|
919
|
+
const detection = detectAuthConfiguration(appConfig.webServer.auth);
|
|
920
|
+
console.log('Configured auth types:', detection.configured);
|
|
921
|
+
console.log('Valid auth types:', detection.valid);
|
|
922
|
+
console.log('Configuration errors:', detection.errors);
|
|
923
|
+
|
|
924
|
+
// logAuthConfiguration - log auth system status (debugging)
|
|
925
|
+
// Function Signature:
|
|
926
|
+
function logAuthConfiguration(authConfig: AppConfig['webServer']['auth']): void {...}
|
|
927
|
+
|
|
928
|
+
// Example:
|
|
929
|
+
logAuthConfiguration(appConfig.webServer.auth);
|
|
930
|
+
// Output:
|
|
931
|
+
// Auth system configuration:
|
|
932
|
+
// - enabled: true
|
|
933
|
+
// - configured types: permanentServerTokens, basic, pat
|
|
934
|
+
// - valid types: permanentServerTokens, pat
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
##### Multi-Authentication Middleware
|
|
938
|
+
|
|
939
|
+
```typescript
|
|
940
|
+
import express from 'express';
|
|
941
|
+
import {
|
|
942
|
+
enhancedAuthTokenMW,
|
|
943
|
+
createConfigurableAuthMiddleware,
|
|
944
|
+
getMultiAuthError,
|
|
945
|
+
getAuthInfo
|
|
946
|
+
} from 'fa-mcp-sdk';
|
|
947
|
+
|
|
948
|
+
// enhancedAuthTokenMW - automatic multi-auth middleware
|
|
949
|
+
// Automatically detects if multi-auth is needed based on configuration
|
|
950
|
+
const app = express();
|
|
951
|
+
app.use('/api', enhancedAuthTokenMW);
|
|
952
|
+
|
|
953
|
+
app.get('/api/protected', (req, res) => {
|
|
954
|
+
const authInfo = (req as any).authInfo;
|
|
955
|
+
res.json({
|
|
956
|
+
message: 'Access granted',
|
|
957
|
+
authType: authInfo?.authType,
|
|
958
|
+
username: authInfo?.username,
|
|
959
|
+
tokenType: authInfo?.tokenType
|
|
960
|
+
});
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
// createConfigurableAuthMiddleware - configurable middleware
|
|
964
|
+
// Function Signature:
|
|
965
|
+
function createConfigurableAuthMiddleware(options: {
|
|
966
|
+
forceMultiAuth?: boolean;
|
|
967
|
+
logConfiguration?: boolean;
|
|
968
|
+
} = {}): (req: Request, res: Response, next: NextFunction) => void {...}
|
|
969
|
+
|
|
970
|
+
// Example:
|
|
971
|
+
const authMW = createConfigurableAuthMiddleware({
|
|
972
|
+
logConfiguration: true, // Log auth config on first request
|
|
973
|
+
forceMultiAuth: false // Auto-detect multi-auth need
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
app.use('/api/v2', authMW);
|
|
977
|
+
|
|
978
|
+
// getMultiAuthError - programmatic auth checking
|
|
979
|
+
// Function Signature:
|
|
980
|
+
async function getMultiAuthError(req: Request): Promise<{ code: number, message: string } | undefined> {...}
|
|
981
|
+
|
|
982
|
+
// Example - Custom middleware with different auth levels
|
|
983
|
+
app.use('/api/custom', async (req, res, next) => {
|
|
984
|
+
if (req.path.startsWith('/api/custom/public')) {
|
|
985
|
+
return next(); // Public endpoints
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
if (req.path.startsWith('/api/custom/admin')) {
|
|
989
|
+
// Admin endpoints - require server tokens only
|
|
990
|
+
const token = (req.headers.authorization || '').replace(/^Bearer */, '');
|
|
991
|
+
if (appConfig.webServer.auth.permanentServerTokens.includes(token)) {
|
|
992
|
+
return next();
|
|
993
|
+
}
|
|
994
|
+
return res.status(403).json({ error: 'Admin access required' });
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// Regular endpoints - use full multi-auth
|
|
998
|
+
try {
|
|
999
|
+
const authError = await getMultiAuthError(req);
|
|
1000
|
+
if (authError) {
|
|
1001
|
+
res.status(authError.code).send(authError.message);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
next();
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
res.status(500).send('Authentication error');
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
// getAuthInfo - get current authentication configuration info
|
|
1011
|
+
// Function Signature:
|
|
1012
|
+
function getAuthInfo(): {
|
|
1013
|
+
enabled: boolean;
|
|
1014
|
+
configured: AuthType[];
|
|
1015
|
+
valid: AuthType[];
|
|
1016
|
+
errors: Record<string, string[]>;
|
|
1017
|
+
usingMultiAuth: boolean;
|
|
1018
|
+
} {...}
|
|
1019
|
+
|
|
1020
|
+
// Example:
|
|
1021
|
+
app.get('/auth/info', (req, res) => {
|
|
1022
|
+
const authInfo = getAuthInfo();
|
|
1023
|
+
res.json(authInfo);
|
|
1024
|
+
});
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
##### Custom Basic Authentication
|
|
1028
|
+
|
|
1029
|
+
You can provide custom Basic Authentication validation functions through the `McpServerData` interface:
|
|
1030
|
+
|
|
1031
|
+
```typescript
|
|
1032
|
+
import { McpServerData, CustomBasicAuthValidator } from 'fa-mcp-sdk';
|
|
1033
|
+
|
|
1034
|
+
// Database-backed authentication
|
|
1035
|
+
const databaseAuthValidator: CustomBasicAuthValidator = async (username: string, password: string): Promise<boolean> => {
|
|
1036
|
+
try {
|
|
1037
|
+
const user = await getUserFromDatabase(username);
|
|
1038
|
+
if (!user) return false;
|
|
1039
|
+
|
|
1040
|
+
return await comparePassword(password, user.hashedPassword);
|
|
1041
|
+
} catch (error) {
|
|
1042
|
+
console.error('Database authentication error:', error);
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
// LDAP/Active Directory authentication
|
|
1048
|
+
const ldapAuthValidator: CustomBasicAuthValidator = async (username: string, password: string): Promise<boolean> => {
|
|
1049
|
+
try {
|
|
1050
|
+
const result = await authenticateWithLDAP(username, password);
|
|
1051
|
+
return result.success;
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
console.error('LDAP authentication error:', error);
|
|
1054
|
+
return false;
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
// External API authentication
|
|
1059
|
+
const apiAuthValidator: CustomBasicAuthValidator = async (username: string, password: string): Promise<boolean> => {
|
|
1060
|
+
try {
|
|
1061
|
+
const response = await fetch('https://auth.example.com/validate', {
|
|
1062
|
+
method: 'POST',
|
|
1063
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1064
|
+
body: JSON.stringify({ username, password })
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
if (!response.ok) return false;
|
|
1068
|
+
const result = await response.json();
|
|
1069
|
+
return result.valid === true;
|
|
1070
|
+
} catch (error) {
|
|
1071
|
+
console.error('API authentication error:', error);
|
|
1072
|
+
return false;
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
|
|
1076
|
+
// Multi-factor authentication
|
|
1077
|
+
const mfaAuthValidator: CustomBasicAuthValidator = async (username: string, password: string): Promise<boolean> => {
|
|
1078
|
+
try {
|
|
1079
|
+
// Password format: "actualPassword:mfaToken"
|
|
1080
|
+
const [actualPassword, mfaToken] = password.split(':');
|
|
1081
|
+
if (!actualPassword || !mfaToken) return false;
|
|
1082
|
+
|
|
1083
|
+
// Validate base credentials
|
|
1084
|
+
const user = await getUserFromDatabase(username);
|
|
1085
|
+
if (!user || !(await comparePassword(actualPassword, user.hashedPassword))) {
|
|
1086
|
+
return false;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Validate MFA token
|
|
1090
|
+
return await validateMFAToken(username, mfaToken);
|
|
1091
|
+
} catch (error) {
|
|
1092
|
+
console.error('MFA authentication error:', error);
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1097
|
+
// Use custom validator in MCP server
|
|
1098
|
+
const serverData: McpServerData = {
|
|
1099
|
+
tools,
|
|
1100
|
+
toolHandler,
|
|
1101
|
+
agentBrief: 'My MCP Server',
|
|
1102
|
+
agentPrompt: 'Server with custom authentication',
|
|
1103
|
+
|
|
1104
|
+
// Provide custom basic auth validator
|
|
1105
|
+
customBasicAuthValidator: databaseAuthValidator, // or ldapAuthValidator, apiAuthValidator, mfaAuthValidator
|
|
1106
|
+
|
|
1107
|
+
// ... other configuration
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
await initMcpServer(serverData);
|
|
1111
|
+
```
|
|
1112
|
+
|
|
1113
|
+
##### Authentication Configuration
|
|
1114
|
+
|
|
1115
|
+
Multi-authentication is configured in `config/default.yaml`:
|
|
1116
|
+
|
|
1117
|
+
```yaml
|
|
1118
|
+
webServer:
|
|
1119
|
+
auth:
|
|
1120
|
+
enabled: true
|
|
1121
|
+
|
|
1122
|
+
# Permanent server tokens (CPU priority: 1 - fastest)
|
|
1123
|
+
permanentServerTokens:
|
|
1124
|
+
- 'server-token-1'
|
|
1125
|
+
- 'server-token-2'
|
|
1126
|
+
|
|
1127
|
+
# Personal Access Tokens (CPU priority: 2)
|
|
1128
|
+
pat: 'ATATT3xFfGF0...'
|
|
1129
|
+
|
|
1130
|
+
# Basic Authentication (CPU priority: 3)
|
|
1131
|
+
basic:
|
|
1132
|
+
type: 'basic'
|
|
1133
|
+
username: 'admin'
|
|
1134
|
+
password: 'password'
|
|
1135
|
+
# Note: When using customBasicAuthValidator, username/password can be omitted
|
|
1136
|
+
|
|
1137
|
+
# JWT Tokens (CPU priority: 4)
|
|
1138
|
+
jwtToken:
|
|
1139
|
+
encryptKey: 'your-secret-key'
|
|
1140
|
+
checkMCPName: true
|
|
1141
|
+
|
|
1142
|
+
# OAuth2 (CPU priority: 5 - most expensive)
|
|
1143
|
+
oauth2:
|
|
1144
|
+
type: 'oauth2'
|
|
1145
|
+
clientId: 'your-client-id'
|
|
1146
|
+
clientSecret: 'your-client-secret'
|
|
1147
|
+
accessToken: 'your-access-token'
|
|
1148
|
+
refreshToken: 'your-refresh-token'
|
|
1149
|
+
redirectUri: 'https://example.com/callback'
|
|
1150
|
+
tokenEndpoint: 'https://auth.provider.com/token'
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
##### Usage Examples
|
|
1154
|
+
|
|
1155
|
+
```typescript
|
|
1156
|
+
// Test authentication programmatically
|
|
1157
|
+
app.post('/test-token', async (req, res) => {
|
|
1158
|
+
const { token } = req.body;
|
|
1159
|
+
if (!token) {
|
|
1160
|
+
return res.status(400).json({ error: 'Token required' });
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
try {
|
|
1164
|
+
const result = await checkMultiAuth(token, appConfig.webServer.auth);
|
|
1165
|
+
res.json({
|
|
1166
|
+
valid: result.success,
|
|
1167
|
+
authType: result.authType,
|
|
1168
|
+
tokenType: result.tokenType,
|
|
1169
|
+
error: result.error,
|
|
1170
|
+
username: result.username,
|
|
1171
|
+
hasPayload: !!result.payload
|
|
1172
|
+
});
|
|
1173
|
+
} catch (error) {
|
|
1174
|
+
res.status(500).json({ error: 'Authentication test failed' });
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
|
|
1178
|
+
// Different authentication requirements for different endpoints
|
|
1179
|
+
app.use('/rest', enhancedAuthTokenMW); // Any valid auth
|
|
1180
|
+
app.use('/graphql', userLevelAuthOnly); // No server tokens
|
|
1181
|
+
app.use('/websocket', sessionTokensOnly); // JWT/OAuth2 only
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
**Client Usage Examples:**
|
|
1185
|
+
|
|
1186
|
+
```bash
|
|
1187
|
+
# Using permanent server token
|
|
1188
|
+
curl -H "Authorization: Bearer server-token-1" http://localhost:3000/mcp
|
|
1189
|
+
|
|
1190
|
+
# Using JWT token
|
|
1191
|
+
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhb..." http://localhost:3000/mcp
|
|
1192
|
+
|
|
1193
|
+
# Using Basic Authentication
|
|
1194
|
+
curl -H "Authorization: Basic $(echo -n 'admin:password' | base64)" http://localhost:3000/mcp
|
|
1195
|
+
|
|
1196
|
+
# Using PAT
|
|
1197
|
+
curl -H "Authorization: Bearer ATATT3xFfGF0..." http://localhost:3000/mcp
|
|
1198
|
+
|
|
1199
|
+
# Using OAuth2
|
|
1200
|
+
curl -H "Authorization: Bearer ya29.A0AfH6..." http://localhost:3000/mcp
|
|
1201
|
+
|
|
1202
|
+
# Using MFA Basic Auth (if custom validator supports it)
|
|
1203
|
+
curl -H "Authorization: Basic $(echo -n 'admin:password:123456' | base64)" http://localhost:3000/mcp
|
|
1204
|
+
```
|
|
1205
|
+
|
|
1206
|
+
The multi-authentication system automatically tries authentication methods in CPU-optimized order (fastest first) and returns on the first successful match, providing both performance and flexibility.
|
|
1207
|
+
|
|
825
1208
|
### Utility Functions
|
|
826
1209
|
|
|
827
1210
|
#### General Utilities
|
|
@@ -1,73 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "
|
|
3
|
-
"productName": "{{project.productName}}",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"description": "{{project.description}}",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "dist/src/start.js",
|
|
8
|
-
"engines": {
|
|
9
|
-
"node": ">=20.0.0"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"start": "node dist/src/start.js",
|
|
13
|
-
"build": "tsc",
|
|
14
|
-
"clean": "rimraf dist",
|
|
15
|
-
"cb": "npm run clean && npm run build",
|
|
16
|
-
"ci": "node --no-deprecation ./scripts/npm/run.js",
|
|
17
|
-
"reinstall": "node --no-deprecation ./scripts/npm/run.js reinstall",
|
|
18
|
-
"typecheck": "tsc --noEmit",
|
|
19
|
-
"lint": "eslint .",
|
|
20
|
-
"lint:fix": "eslint --fix .",
|
|
21
|
-
"generate-token": "node node_modules/fa-mcp-sdk/dist/core/
|
|
22
|
-
"dead:exports": "ts-prune",
|
|
23
|
-
"dead:files": "knip",
|
|
24
|
-
"postinstall": "node scripts/npm/patch_node_modules.js",
|
|
25
|
-
"consul:unreg": "node node_modules/fa-mcp-sdk/dist/core/consul/deregister.js",
|
|
26
|
-
"test": "jest",
|
|
27
|
-
"test:mcp": "node scripts/test-mcp-tools.js",
|
|
28
|
-
"test:mcp-http": "node tests/mcp/test-http.js",
|
|
29
|
-
"test:mcp-sse": "node tests/mcp/test-sse.js",
|
|
30
|
-
"test:mcp-stdio": "node tests/mcp/test-stdio.js"
|
|
31
|
-
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"mcp",
|
|
34
|
-
"model-context-protocol",
|
|
35
|
-
"typescript",
|
|
36
|
-
"template",
|
|
37
|
-
"ai",
|
|
38
|
-
"prompts",
|
|
39
|
-
"tools",
|
|
40
|
-
"resources"
|
|
41
|
-
],
|
|
42
|
-
"author": {
|
|
43
|
-
"name": "{{author.name}}",
|
|
44
|
-
"email": "{{author.email}}"
|
|
45
|
-
},
|
|
46
|
-
"license": "MIT",
|
|
47
|
-
"dependencies": {
|
|
48
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
49
|
-
"dotenv": "^17.2.3",
|
|
50
|
-
"fa-mcp-sdk": "^0.2.
|
|
51
|
-
"swagger-jsdoc": "^6.2.8",
|
|
52
|
-
"swagger-ui-express": "^5.0.1"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@types/express": "^5.0.
|
|
56
|
-
"@types/jest": "^30.0.0",
|
|
57
|
-
"@types/node": "^24.10.1",
|
|
58
|
-
"@types/swagger-jsdoc": "^6.0.4",
|
|
59
|
-
"@types/swagger-ui-express": "^4.1.8",
|
|
60
|
-
"cross-env": "^10.1.0",
|
|
61
|
-
"eslint-config-at-25": "^25.9.6",
|
|
62
|
-
"jest": "^30.2.0",
|
|
63
|
-
"rimraf": "^6.1.0",
|
|
64
|
-
"ts-jest": "^29.4.5",
|
|
65
|
-
"tsx": "^4.20.6",
|
|
66
|
-
"typescript": "^5.9.3"
|
|
67
|
-
},
|
|
68
|
-
"repository": {
|
|
69
|
-
"type": "git",
|
|
70
|
-
"url": "git+https://{{git-base-url}}/{{project.name}}.git"
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "project.name",
|
|
3
|
+
"productName": "{{project.productName}}",
|
|
4
|
+
"version": "0.0.3",
|
|
5
|
+
"description": "{{project.description}}",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/src/start.js",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20.0.0"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node dist/src/start.js",
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"clean": "rimraf dist",
|
|
15
|
+
"cb": "npm run clean && npm run build",
|
|
16
|
+
"ci": "node --no-deprecation ./scripts/npm/run.js",
|
|
17
|
+
"reinstall": "node --no-deprecation ./scripts/npm/run.js reinstall",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"lint": "eslint .",
|
|
20
|
+
"lint:fix": "eslint --fix .",
|
|
21
|
+
"generate-token": "node node_modules/fa-mcp-sdk/dist/core/auth/token-generator/server.js",
|
|
22
|
+
"dead:exports": "ts-prune",
|
|
23
|
+
"dead:files": "knip",
|
|
24
|
+
"postinstall": "node scripts/npm/patch_node_modules.js",
|
|
25
|
+
"consul:unreg": "node node_modules/fa-mcp-sdk/dist/core/consul/deregister.js",
|
|
26
|
+
"test": "jest",
|
|
27
|
+
"test:mcp": "node scripts/test-mcp-tools.js",
|
|
28
|
+
"test:mcp-http": "node tests/mcp/test-http.js",
|
|
29
|
+
"test:mcp-sse": "node tests/mcp/test-sse.js",
|
|
30
|
+
"test:mcp-stdio": "node tests/mcp/test-stdio.js"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mcp",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"typescript",
|
|
36
|
+
"template",
|
|
37
|
+
"ai",
|
|
38
|
+
"prompts",
|
|
39
|
+
"tools",
|
|
40
|
+
"resources"
|
|
41
|
+
],
|
|
42
|
+
"author": {
|
|
43
|
+
"name": "{{author.name}}",
|
|
44
|
+
"email": "{{author.email}}"
|
|
45
|
+
},
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
49
|
+
"dotenv": "^17.2.3",
|
|
50
|
+
"fa-mcp-sdk": "^0.2.125",
|
|
51
|
+
"swagger-jsdoc": "^6.2.8",
|
|
52
|
+
"swagger-ui-express": "^5.0.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/express": "^5.0.6",
|
|
56
|
+
"@types/jest": "^30.0.0",
|
|
57
|
+
"@types/node": "^24.10.1",
|
|
58
|
+
"@types/swagger-jsdoc": "^6.0.4",
|
|
59
|
+
"@types/swagger-ui-express": "^4.1.8",
|
|
60
|
+
"cross-env": "^10.1.0",
|
|
61
|
+
"eslint-config-at-25": "^25.9.6",
|
|
62
|
+
"jest": "^30.2.0",
|
|
63
|
+
"rimraf": "^6.1.0",
|
|
64
|
+
"ts-jest": "^29.4.5",
|
|
65
|
+
"tsx": "^4.20.6",
|
|
66
|
+
"typescript": "^5.9.3"
|
|
67
|
+
},
|
|
68
|
+
"repository": {
|
|
69
|
+
"type": "git",
|
|
70
|
+
"url": "git+https://{{git-base-url}}/{{project.name}}.git"
|
|
71
|
+
}
|
|
72
|
+
}
|