@nitrostack/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +80 -0
- package/dist/auth/api-key.d.ts +118 -0
- package/dist/auth/api-key.d.ts.map +1 -0
- package/dist/auth/api-key.js +168 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/client.d.ts +151 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +330 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/index.d.ts +31 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +46 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +95 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +260 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/pkce.d.ts +53 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +105 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/quick-setup.d.ts +94 -0
- package/dist/auth/quick-setup.d.ts.map +1 -0
- package/dist/auth/quick-setup.js +210 -0
- package/dist/auth/quick-setup.js.map +1 -0
- package/dist/auth/secure-secret.d.ts +136 -0
- package/dist/auth/secure-secret.d.ts.map +1 -0
- package/dist/auth/secure-secret.js +182 -0
- package/dist/auth/secure-secret.js.map +1 -0
- package/dist/auth/server-integration.d.ts +97 -0
- package/dist/auth/server-integration.d.ts.map +1 -0
- package/dist/auth/server-integration.js +182 -0
- package/dist/auth/server-integration.js.map +1 -0
- package/dist/auth/server-metadata.d.ts +51 -0
- package/dist/auth/server-metadata.d.ts.map +1 -0
- package/dist/auth/server-metadata.js +106 -0
- package/dist/auth/server-metadata.js.map +1 -0
- package/dist/auth/simple-jwt.d.ts +174 -0
- package/dist/auth/simple-jwt.d.ts.map +1 -0
- package/dist/auth/simple-jwt.js +162 -0
- package/dist/auth/simple-jwt.js.map +1 -0
- package/dist/auth/token-store.d.ts +104 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +205 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/token-validation.d.ts +59 -0
- package/dist/auth/token-validation.d.ts.map +1 -0
- package/dist/auth/token-validation.js +241 -0
- package/dist/auth/token-validation.js.map +1 -0
- package/dist/auth/types.d.ts +215 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/core/apikey-module.d.ts +69 -0
- package/dist/core/apikey-module.d.ts.map +1 -0
- package/dist/core/apikey-module.js +114 -0
- package/dist/core/apikey-module.js.map +1 -0
- package/dist/core/app-decorator.d.ts +59 -0
- package/dist/core/app-decorator.d.ts.map +1 -0
- package/dist/core/app-decorator.js +322 -0
- package/dist/core/app-decorator.js.map +1 -0
- package/dist/core/builders.d.ts +50 -0
- package/dist/core/builders.d.ts.map +1 -0
- package/dist/core/builders.js +139 -0
- package/dist/core/builders.js.map +1 -0
- package/dist/core/component.d.ts +111 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +228 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/config-module.d.ts +62 -0
- package/dist/core/config-module.d.ts.map +1 -0
- package/dist/core/config-module.js +94 -0
- package/dist/core/config-module.js.map +1 -0
- package/dist/core/decorators/cache.decorator.d.ts +61 -0
- package/dist/core/decorators/cache.decorator.d.ts.map +1 -0
- package/dist/core/decorators/cache.decorator.js +115 -0
- package/dist/core/decorators/cache.decorator.js.map +1 -0
- package/dist/core/decorators/health-check.decorator.d.ts +80 -0
- package/dist/core/decorators/health-check.decorator.d.ts.map +1 -0
- package/dist/core/decorators/health-check.decorator.js +153 -0
- package/dist/core/decorators/health-check.decorator.js.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts +63 -0
- package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -0
- package/dist/core/decorators/rate-limit.decorator.js +129 -0
- package/dist/core/decorators/rate-limit.decorator.js.map +1 -0
- package/dist/core/decorators.d.ts +190 -0
- package/dist/core/decorators.d.ts.map +1 -0
- package/dist/core/decorators.js +170 -0
- package/dist/core/decorators.js.map +1 -0
- package/dist/core/di/container.d.ts +64 -0
- package/dist/core/di/container.d.ts.map +1 -0
- package/dist/core/di/container.js +105 -0
- package/dist/core/di/container.js.map +1 -0
- package/dist/core/di/injectable.decorator.d.ts +62 -0
- package/dist/core/di/injectable.decorator.d.ts.map +1 -0
- package/dist/core/di/injectable.decorator.js +66 -0
- package/dist/core/di/injectable.decorator.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +87 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/events/event-emitter.d.ts +50 -0
- package/dist/core/events/event-emitter.d.ts.map +1 -0
- package/dist/core/events/event-emitter.js +94 -0
- package/dist/core/events/event-emitter.js.map +1 -0
- package/dist/core/events/event.decorator.d.ts +48 -0
- package/dist/core/events/event.decorator.d.ts.map +1 -0
- package/dist/core/events/event.decorator.js +72 -0
- package/dist/core/events/event.decorator.js.map +1 -0
- package/dist/core/events/log-emitter.d.ts +14 -0
- package/dist/core/events/log-emitter.d.ts.map +1 -0
- package/dist/core/events/log-emitter.js +20 -0
- package/dist/core/events/log-emitter.js.map +1 -0
- package/dist/core/filters/exception-filter.decorator.d.ts +40 -0
- package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.decorator.js +54 -0
- package/dist/core/filters/exception-filter.decorator.js.map +1 -0
- package/dist/core/filters/exception-filter.interface.d.ts +39 -0
- package/dist/core/filters/exception-filter.interface.d.ts.map +1 -0
- package/dist/core/filters/exception-filter.interface.js +2 -0
- package/dist/core/filters/exception-filter.interface.js.map +1 -0
- package/dist/core/guards/apikey.guard.d.ts +22 -0
- package/dist/core/guards/apikey.guard.d.ts.map +1 -0
- package/dist/core/guards/apikey.guard.js +11 -0
- package/dist/core/guards/apikey.guard.js.map +1 -0
- package/dist/core/guards/guard.interface.d.ts +18 -0
- package/dist/core/guards/guard.interface.d.ts.map +1 -0
- package/dist/core/guards/guard.interface.js +2 -0
- package/dist/core/guards/guard.interface.js.map +1 -0
- package/dist/core/guards/jwt.guard.d.ts +18 -0
- package/dist/core/guards/jwt.guard.d.ts.map +1 -0
- package/dist/core/guards/jwt.guard.js +2 -0
- package/dist/core/guards/jwt.guard.js.map +1 -0
- package/dist/core/guards/oauth.guard.d.ts +35 -0
- package/dist/core/guards/oauth.guard.d.ts.map +1 -0
- package/dist/core/guards/oauth.guard.js +2 -0
- package/dist/core/guards/oauth.guard.js.map +1 -0
- package/dist/core/guards/use-guards.decorator.d.ts +25 -0
- package/dist/core/guards/use-guards.decorator.d.ts.map +1 -0
- package/dist/core/guards/use-guards.decorator.js +32 -0
- package/dist/core/guards/use-guards.decorator.js.map +1 -0
- package/dist/core/health/health-checks.resource.d.ts +14 -0
- package/dist/core/health/health-checks.resource.d.ts.map +1 -0
- package/dist/core/health/health-checks.resource.js +29 -0
- package/dist/core/health/health-checks.resource.js.map +1 -0
- package/dist/core/index.d.ts +57 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +59 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts +37 -0
- package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.decorator.js +51 -0
- package/dist/core/interceptors/interceptor.decorator.js.map +1 -0
- package/dist/core/interceptors/interceptor.interface.d.ts +31 -0
- package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -0
- package/dist/core/interceptors/interceptor.interface.js +2 -0
- package/dist/core/interceptors/interceptor.interface.js.map +1 -0
- package/dist/core/jwt-module.d.ts +51 -0
- package/dist/core/jwt-module.d.ts.map +1 -0
- package/dist/core/jwt-module.js +52 -0
- package/dist/core/jwt-module.js.map +1 -0
- package/dist/core/logger.d.ts +18 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +53 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/middleware/middleware.decorator.d.ts +39 -0
- package/dist/core/middleware/middleware.decorator.d.ts.map +1 -0
- package/dist/core/middleware/middleware.decorator.js +53 -0
- package/dist/core/middleware/middleware.decorator.js.map +1 -0
- package/dist/core/middleware/middleware.interface.d.ts +29 -0
- package/dist/core/middleware/middleware.interface.d.ts.map +1 -0
- package/dist/core/middleware/middleware.interface.js +2 -0
- package/dist/core/middleware/middleware.interface.js.map +1 -0
- package/dist/core/module.d.ts +93 -0
- package/dist/core/module.d.ts.map +1 -0
- package/dist/core/module.js +87 -0
- package/dist/core/module.js.map +1 -0
- package/dist/core/oauth-module.d.ts +123 -0
- package/dist/core/oauth-module.d.ts.map +1 -0
- package/dist/core/oauth-module.js +324 -0
- package/dist/core/oauth-module.js.map +1 -0
- package/dist/core/pipes/pipe.decorator.d.ts +64 -0
- package/dist/core/pipes/pipe.decorator.d.ts.map +1 -0
- package/dist/core/pipes/pipe.decorator.js +85 -0
- package/dist/core/pipes/pipe.decorator.js.map +1 -0
- package/dist/core/pipes/pipe.interface.d.ts +41 -0
- package/dist/core/pipes/pipe.interface.d.ts.map +1 -0
- package/dist/core/pipes/pipe.interface.js +2 -0
- package/dist/core/pipes/pipe.interface.js.map +1 -0
- package/dist/core/prompt.d.ts +46 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +76 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/resource.d.ts +47 -0
- package/dist/core/resource.d.ts.map +1 -0
- package/dist/core/resource.js +90 -0
- package/dist/core/resource.js.map +1 -0
- package/dist/core/server.d.ts +129 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +617 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/tool.d.ts +108 -0
- package/dist/core/tool.d.ts.map +1 -0
- package/dist/core/tool.js +241 -0
- package/dist/core/tool.js.map +1 -0
- package/dist/core/transports/discovery-http-server.d.ts +19 -0
- package/dist/core/transports/discovery-http-server.d.ts.map +1 -0
- package/dist/core/transports/discovery-http-server.js +54 -0
- package/dist/core/transports/discovery-http-server.js.map +1 -0
- package/dist/core/transports/http-server.d.ts +108 -0
- package/dist/core/transports/http-server.d.ts.map +1 -0
- package/dist/core/transports/http-server.js +293 -0
- package/dist/core/transports/http-server.js.map +1 -0
- package/dist/core/transports/streamable-http.d.ts +177 -0
- package/dist/core/transports/streamable-http.d.ts.map +1 -0
- package/dist/core/transports/streamable-http.js +1287 -0
- package/dist/core/transports/streamable-http.js.map +1 -0
- package/dist/core/types.d.ts +195 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/widgets/widget-examples.resource.d.ts +17 -0
- package/dist/core/widgets/widget-examples.resource.d.ts.map +1 -0
- package/dist/core/widgets/widget-examples.resource.js +28 -0
- package/dist/core/widgets/widget-examples.resource.js.map +1 -0
- package/dist/core/widgets/widget-registry.d.ts +56 -0
- package/dist/core/widgets/widget-registry.d.ts.map +1 -0
- package/dist/core/widgets/widget-registry.js +75 -0
- package/dist/core/widgets/widget-registry.js.map +1 -0
- package/dist/testing/index.d.ts +103 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +161 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/ui-next/index.d.ts +31 -0
- package/dist/ui-next/index.d.ts.map +1 -0
- package/dist/ui-next/index.js +687 -0
- package/dist/ui-next/index.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createSimpleJWTAuth, generateJWT } from './simple-jwt.js';
|
|
2
|
+
import { createAPIKeyAuth, generateAPIKey, hashAPIKey } from './api-key.js';
|
|
3
|
+
import { configureServerAuth } from './server-integration.js';
|
|
4
|
+
/**
|
|
5
|
+
* Quick Setup Helpers
|
|
6
|
+
*
|
|
7
|
+
* Make it dead simple to add authentication to NitroStack servers
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Setup Simple JWT Authentication (1-liner!)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const server = createServer({...});
|
|
15
|
+
*
|
|
16
|
+
* // That's it! JWT auth enabled
|
|
17
|
+
* setupJWTAuth(server.app, {
|
|
18
|
+
* secret: process.env.JWT_SECRET!,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* server.start();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function setupJWTAuth(app, config, path = '/mcp') {
|
|
25
|
+
const middleware = createSimpleJWTAuth(config);
|
|
26
|
+
app.use(path, middleware);
|
|
27
|
+
console.log(`✅ Simple JWT auth enabled on ${path}`);
|
|
28
|
+
console.log(` Audience: ${config.audience || 'any'}`);
|
|
29
|
+
console.log(` Issuer: ${config.issuer || 'any'}`);
|
|
30
|
+
console.log(` Algorithm: ${config.algorithm || 'HS256'}`);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Setup API Key Authentication (1-liner!)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const server = createServer({...});
|
|
38
|
+
*
|
|
39
|
+
* // That's it! API key auth enabled
|
|
40
|
+
* setupAPIKeyAuth(server.app, {
|
|
41
|
+
* keys: [process.env.API_KEY!],
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* server.start();
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function setupAPIKeyAuth(app, config, path = '/mcp') {
|
|
48
|
+
const middleware = createAPIKeyAuth(config);
|
|
49
|
+
app.use(path, middleware);
|
|
50
|
+
console.log(`✅ API Key auth enabled on ${path}`);
|
|
51
|
+
console.log(` Header: ${config.headerName || 'X-API-Key'}`);
|
|
52
|
+
console.log(` Keys: ${config.keys.length} configured`);
|
|
53
|
+
console.log(` Query param: ${config.allowQueryParam ? 'enabled' : 'disabled'}`);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Setup OAuth 2.1 Authentication (full enterprise setup)
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const server = createServer({...});
|
|
61
|
+
*
|
|
62
|
+
* // Full OAuth 2.1 with PKCE
|
|
63
|
+
* setupOAuthAuth(server.app, {
|
|
64
|
+
* resourceUri: 'https://mcp.example.com',
|
|
65
|
+
* authorizationServers: ['https://auth.example.com'],
|
|
66
|
+
* tokenIntrospectionEndpoint: '...',
|
|
67
|
+
* tokenIntrospectionClientId: '...',
|
|
68
|
+
* tokenIntrospectionClientSecret: process.env.INTROSPECTION_SECRET,
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* server.start();
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export function setupOAuthAuth(app, config, path = '/mcp') {
|
|
75
|
+
configureServerAuth(app, config, {
|
|
76
|
+
protectRoutes: [path],
|
|
77
|
+
});
|
|
78
|
+
console.log(`✅ OAuth 2.1 auth enabled on ${path}`);
|
|
79
|
+
console.log(` Resource URI: ${config.resourceUri}`);
|
|
80
|
+
console.log(` Auth Servers: ${config.authorizationServers.join(', ')}`);
|
|
81
|
+
console.log(` Scopes: ${config.scopesSupported?.join(', ') || 'none'}`);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generate test credentials (for development)
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const creds = generateTestCredentials();
|
|
89
|
+
* console.log('JWT Secret:', creds.jwtSecret);
|
|
90
|
+
* console.log('API Key:', creds.apiKey);
|
|
91
|
+
* console.log('Sample Token:', creds.sampleToken);
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export function generateTestCredentials(options) {
|
|
95
|
+
const jwtSecret = generateAPIKey('jwt_secret');
|
|
96
|
+
const apiKey = generateAPIKey(options?.apiKeyPrefix);
|
|
97
|
+
const sampleToken = generateJWT({
|
|
98
|
+
secret: jwtSecret,
|
|
99
|
+
payload: {
|
|
100
|
+
sub: 'test-user',
|
|
101
|
+
scopes: ['mcp:read', 'mcp:write'],
|
|
102
|
+
},
|
|
103
|
+
expiresIn: '1h',
|
|
104
|
+
audience: options?.jwtAudience,
|
|
105
|
+
issuer: options?.jwtIssuer,
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
jwtSecret,
|
|
109
|
+
apiKey,
|
|
110
|
+
apiKeyHashed: hashAPIKey(apiKey),
|
|
111
|
+
sampleToken,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Print auth setup instructions
|
|
116
|
+
*/
|
|
117
|
+
export function printAuthSetupInstructions(type) {
|
|
118
|
+
console.log('\n╔══════════════════════════════════════════════════════════════╗');
|
|
119
|
+
console.log('║ AUTH SETUP INSTRUCTIONS ║');
|
|
120
|
+
console.log('╚══════════════════════════════════════════════════════════════╝\n');
|
|
121
|
+
if (type === 'jwt') {
|
|
122
|
+
console.log('📝 Simple JWT Authentication Setup:\n');
|
|
123
|
+
console.log('1. Generate a secret:');
|
|
124
|
+
console.log(' const creds = generateTestCredentials();');
|
|
125
|
+
console.log(' console.log(creds.jwtSecret);\n');
|
|
126
|
+
console.log('2. Add to .env:');
|
|
127
|
+
console.log(' JWT_SECRET=jwt_secret_...\n');
|
|
128
|
+
console.log('3. Enable in server:');
|
|
129
|
+
console.log(' setupJWTAuth(server.app, {');
|
|
130
|
+
console.log(' secret: process.env.JWT_SECRET!,');
|
|
131
|
+
console.log(' audience: "my-mcp-server",');
|
|
132
|
+
console.log(' });\n');
|
|
133
|
+
console.log('4. Generate tokens:');
|
|
134
|
+
console.log(' const token = generateJWT({');
|
|
135
|
+
console.log(' secret: process.env.JWT_SECRET!,');
|
|
136
|
+
console.log(' payload: { sub: "user123" },');
|
|
137
|
+
console.log(' expiresIn: "1h",');
|
|
138
|
+
console.log(' });\n');
|
|
139
|
+
console.log('5. Use in client:');
|
|
140
|
+
console.log(' Authorization: Bearer <token>\n');
|
|
141
|
+
}
|
|
142
|
+
if (type === 'apikey') {
|
|
143
|
+
console.log('📝 API Key Authentication Setup:\n');
|
|
144
|
+
console.log('1. Generate API keys:');
|
|
145
|
+
console.log(' const key1 = generateAPIKey();');
|
|
146
|
+
console.log(' const key2 = generateAPIKey();\n');
|
|
147
|
+
console.log('2. Add to .env:');
|
|
148
|
+
console.log(' API_KEY_1=sk_...');
|
|
149
|
+
console.log(' API_KEY_2=sk_...\n');
|
|
150
|
+
console.log('3. Enable in server:');
|
|
151
|
+
console.log(' setupAPIKeyAuth(server.app, {');
|
|
152
|
+
console.log(' keys: [');
|
|
153
|
+
console.log(' process.env.API_KEY_1!,');
|
|
154
|
+
console.log(' process.env.API_KEY_2!,');
|
|
155
|
+
console.log(' ],');
|
|
156
|
+
console.log(' });\n');
|
|
157
|
+
console.log('4. Use in client:');
|
|
158
|
+
console.log(' X-API-Key: sk_...\n');
|
|
159
|
+
}
|
|
160
|
+
if (type === 'oauth') {
|
|
161
|
+
console.log('📝 OAuth 2.1 Authentication Setup:\n');
|
|
162
|
+
console.log('1. Deploy an OAuth 2.1 authorization server');
|
|
163
|
+
console.log(' (e.g., Auth0, Keycloak, Azure AD)\n');
|
|
164
|
+
console.log('2. Configure in server:');
|
|
165
|
+
console.log(' setupOAuthAuth(server.app, {');
|
|
166
|
+
console.log(' resourceUri: "https://mcp.example.com",');
|
|
167
|
+
console.log(' authorizationServers: ["https://auth.example.com"],');
|
|
168
|
+
console.log(' tokenIntrospectionEndpoint: "...",');
|
|
169
|
+
console.log(' tokenIntrospectionClientId: "...",');
|
|
170
|
+
console.log(' tokenIntrospectionClientSecret: process.env.SECRET,');
|
|
171
|
+
console.log(' });\n');
|
|
172
|
+
console.log('3. Use the inspector AUTH tab to test\n');
|
|
173
|
+
}
|
|
174
|
+
console.log('═══════════════════════════════════════════════════════════════\n');
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Validate auth environment variables
|
|
178
|
+
*/
|
|
179
|
+
export function validateAuthEnv(type) {
|
|
180
|
+
const missing = [];
|
|
181
|
+
if (type === 'jwt') {
|
|
182
|
+
if (!process.env.JWT_SECRET) {
|
|
183
|
+
missing.push('JWT_SECRET');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (type === 'apikey') {
|
|
187
|
+
if (!process.env.API_KEY_1 && !process.env.API_KEY) {
|
|
188
|
+
missing.push('API_KEY_1 or API_KEY');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (type === 'oauth') {
|
|
192
|
+
const required = [
|
|
193
|
+
'OAUTH_RESOURCE_URI',
|
|
194
|
+
'OAUTH_AUTH_SERVER',
|
|
195
|
+
'OAUTH_INTROSPECTION_ENDPOINT',
|
|
196
|
+
'OAUTH_CLIENT_ID',
|
|
197
|
+
'OAUTH_CLIENT_SECRET',
|
|
198
|
+
];
|
|
199
|
+
for (const key of required) {
|
|
200
|
+
if (!process.env[key]) {
|
|
201
|
+
missing.push(key);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
valid: missing.length === 0,
|
|
207
|
+
missing,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=quick-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-setup.js","sourceRoot":"","sources":["../../src/auth/quick-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure Secret Value
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe way to handle secrets that prevents accidental hardcoding.
|
|
5
|
+
* Secrets must be explicitly created from environment variables or marked as explicit.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // ✅ Recommended: Load from environment variable
|
|
10
|
+
* const secret = SecretValue.fromEnv('JWT_SECRET');
|
|
11
|
+
*
|
|
12
|
+
* // ✅ For testing only: Mark as explicit
|
|
13
|
+
* const testSecret = SecretValue.fromValue('test-secret', { allowHardcoded: true });
|
|
14
|
+
*
|
|
15
|
+
* // ❌ This will fail at runtime:
|
|
16
|
+
* const badSecret = SecretValue.fromValue('hardcoded'); // throws error
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare const SecretBrand: unique symbol;
|
|
20
|
+
/**
|
|
21
|
+
* A branded type representing a secret value.
|
|
22
|
+
* Cannot be created directly - must use factory methods.
|
|
23
|
+
*/
|
|
24
|
+
export type SecretString = string & {
|
|
25
|
+
readonly [SecretBrand]: 'SecretValue';
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Options for creating a secret from a direct value
|
|
29
|
+
*/
|
|
30
|
+
export interface FromValueOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Explicitly allow hardcoded values.
|
|
33
|
+
* Only set to true for testing purposes.
|
|
34
|
+
*/
|
|
35
|
+
allowHardcoded?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Description of why hardcoded is allowed (for audit purposes)
|
|
38
|
+
*/
|
|
39
|
+
reason?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Secure wrapper for secret values
|
|
43
|
+
*/
|
|
44
|
+
export declare class SecretValue {
|
|
45
|
+
private readonly value;
|
|
46
|
+
private readonly source;
|
|
47
|
+
private constructor();
|
|
48
|
+
/**
|
|
49
|
+
* Create a secret from an environment variable.
|
|
50
|
+
* This is the recommended way to handle secrets.
|
|
51
|
+
*
|
|
52
|
+
* @param envVarName - Name of the environment variable
|
|
53
|
+
* @param options - Optional configuration
|
|
54
|
+
* @throws Error if the environment variable is not set
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const jwtSecret = SecretValue.fromEnv('JWT_SECRET');
|
|
59
|
+
* const dbPassword = SecretValue.fromEnv('DATABASE_PASSWORD');
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
static fromEnv(envVarName: string, options?: {
|
|
63
|
+
required?: boolean;
|
|
64
|
+
}): SecretValue;
|
|
65
|
+
/**
|
|
66
|
+
* Create a secret from a direct value.
|
|
67
|
+
*
|
|
68
|
+
* **WARNING**: This should only be used for testing.
|
|
69
|
+
* For production, always use `fromEnv()`.
|
|
70
|
+
*
|
|
71
|
+
* @param value - The secret value
|
|
72
|
+
* @param options - Must set allowHardcoded: true to use this method
|
|
73
|
+
* @throws Error if allowHardcoded is not explicitly set to true
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // For testing only
|
|
78
|
+
* const testSecret = SecretValue.fromValue('test-secret-for-unit-tests', {
|
|
79
|
+
* allowHardcoded: true,
|
|
80
|
+
* reason: 'Unit test fixture'
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
static fromValue(value: string, options?: FromValueOptions): SecretValue;
|
|
85
|
+
/**
|
|
86
|
+
* Create a secret from an environment variable or return undefined.
|
|
87
|
+
* Useful for optional secrets.
|
|
88
|
+
*
|
|
89
|
+
* @param envVarName - Name of the environment variable
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const optionalSecret = SecretValue.fromEnvOptional('OPTIONAL_API_KEY');
|
|
94
|
+
* if (optionalSecret) {
|
|
95
|
+
* // Use the secret
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
static fromEnvOptional(envVarName: string): SecretValue | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* Get the unwrapped secret value.
|
|
102
|
+
*
|
|
103
|
+
* @returns The raw secret string
|
|
104
|
+
*/
|
|
105
|
+
unwrap(): SecretString;
|
|
106
|
+
/**
|
|
107
|
+
* Get the secret value as a plain string.
|
|
108
|
+
* Alias for unwrap() for compatibility.
|
|
109
|
+
*/
|
|
110
|
+
getValue(): string;
|
|
111
|
+
/**
|
|
112
|
+
* Check if this secret was loaded from environment
|
|
113
|
+
*/
|
|
114
|
+
isFromEnvironment(): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Prevent accidental logging of secret values
|
|
117
|
+
*/
|
|
118
|
+
toString(): string;
|
|
119
|
+
/**
|
|
120
|
+
* Prevent accidental JSON serialization of secret values
|
|
121
|
+
*/
|
|
122
|
+
toJSON(): string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Type guard to check if a value is a SecretValue
|
|
126
|
+
*/
|
|
127
|
+
export declare function isSecretValue(value: unknown): value is SecretValue;
|
|
128
|
+
/**
|
|
129
|
+
* Helper to unwrap a secret if it's a SecretValue, or use as-is if string.
|
|
130
|
+
* Useful for backward compatibility.
|
|
131
|
+
*
|
|
132
|
+
* @deprecated Prefer using SecretValue directly
|
|
133
|
+
*/
|
|
134
|
+
export declare function unwrapSecret(secret: SecretValue | string): string;
|
|
135
|
+
export {};
|
|
136
|
+
//# sourceMappingURL=secure-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-secret.d.ts","sourceRoot":"","sources":["../../src/auth/secure-secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAC;AAEzC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,aAAa,CAAA;CAAE,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C,OAAO;IAiBP;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,WAAW;IAkBjF;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,WAAW;IAsBxE;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAQnE;;;;OAIG;IACH,MAAM,IAAI,YAAY;IAItB;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,MAAM,IAAI,MAAM;CAUjB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,CAYjE"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure Secret Value
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe way to handle secrets that prevents accidental hardcoding.
|
|
5
|
+
* Secrets must be explicitly created from environment variables or marked as explicit.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // ✅ Recommended: Load from environment variable
|
|
10
|
+
* const secret = SecretValue.fromEnv('JWT_SECRET');
|
|
11
|
+
*
|
|
12
|
+
* // ✅ For testing only: Mark as explicit
|
|
13
|
+
* const testSecret = SecretValue.fromValue('test-secret', { allowHardcoded: true });
|
|
14
|
+
*
|
|
15
|
+
* // ❌ This will fail at runtime:
|
|
16
|
+
* const badSecret = SecretValue.fromValue('hardcoded'); // throws error
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Secure wrapper for secret values
|
|
21
|
+
*/
|
|
22
|
+
export class SecretValue {
|
|
23
|
+
value;
|
|
24
|
+
source;
|
|
25
|
+
constructor(value, source) {
|
|
26
|
+
if (!value || value.length === 0) {
|
|
27
|
+
throw new Error('Secret value cannot be empty');
|
|
28
|
+
}
|
|
29
|
+
// Minimum length check for security
|
|
30
|
+
if (value.length < 16) {
|
|
31
|
+
console.warn('[SecretValue] Warning: Secret is less than 16 characters. ' +
|
|
32
|
+
'Consider using a longer secret for better security.');
|
|
33
|
+
}
|
|
34
|
+
this.value = value;
|
|
35
|
+
this.source = source;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a secret from an environment variable.
|
|
39
|
+
* This is the recommended way to handle secrets.
|
|
40
|
+
*
|
|
41
|
+
* @param envVarName - Name of the environment variable
|
|
42
|
+
* @param options - Optional configuration
|
|
43
|
+
* @throws Error if the environment variable is not set
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const jwtSecret = SecretValue.fromEnv('JWT_SECRET');
|
|
48
|
+
* const dbPassword = SecretValue.fromEnv('DATABASE_PASSWORD');
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
static fromEnv(envVarName, options) {
|
|
52
|
+
const value = process.env[envVarName];
|
|
53
|
+
const required = options?.required !== false;
|
|
54
|
+
if (!value) {
|
|
55
|
+
if (required) {
|
|
56
|
+
throw new Error(`Environment variable ${envVarName} is not set. ` +
|
|
57
|
+
`Please set it in your environment or .env file.`);
|
|
58
|
+
}
|
|
59
|
+
// Return a placeholder that will fail if used
|
|
60
|
+
throw new Error(`Environment variable ${envVarName} is not set.`);
|
|
61
|
+
}
|
|
62
|
+
return new SecretValue(value, 'env');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a secret from a direct value.
|
|
66
|
+
*
|
|
67
|
+
* **WARNING**: This should only be used for testing.
|
|
68
|
+
* For production, always use `fromEnv()`.
|
|
69
|
+
*
|
|
70
|
+
* @param value - The secret value
|
|
71
|
+
* @param options - Must set allowHardcoded: true to use this method
|
|
72
|
+
* @throws Error if allowHardcoded is not explicitly set to true
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // For testing only
|
|
77
|
+
* const testSecret = SecretValue.fromValue('test-secret-for-unit-tests', {
|
|
78
|
+
* allowHardcoded: true,
|
|
79
|
+
* reason: 'Unit test fixture'
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
static fromValue(value, options) {
|
|
84
|
+
if (!options?.allowHardcoded) {
|
|
85
|
+
throw new Error('Hardcoded secrets are not allowed. ' +
|
|
86
|
+
'Use SecretValue.fromEnv() to load secrets from environment variables. ' +
|
|
87
|
+
'If you must use a hardcoded value (e.g., for testing), ' +
|
|
88
|
+
'set allowHardcoded: true explicitly.');
|
|
89
|
+
}
|
|
90
|
+
// Log warning in non-test environments
|
|
91
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
92
|
+
console.warn(`[SecretValue] Warning: Using hardcoded secret value. ` +
|
|
93
|
+
`Reason: ${options.reason || 'Not specified'}. ` +
|
|
94
|
+
`This should not be used in production.`);
|
|
95
|
+
}
|
|
96
|
+
return new SecretValue(value, 'explicit');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a secret from an environment variable or return undefined.
|
|
100
|
+
* Useful for optional secrets.
|
|
101
|
+
*
|
|
102
|
+
* @param envVarName - Name of the environment variable
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const optionalSecret = SecretValue.fromEnvOptional('OPTIONAL_API_KEY');
|
|
107
|
+
* if (optionalSecret) {
|
|
108
|
+
* // Use the secret
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
static fromEnvOptional(envVarName) {
|
|
113
|
+
const value = process.env[envVarName];
|
|
114
|
+
if (!value) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return new SecretValue(value, 'env');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get the unwrapped secret value.
|
|
121
|
+
*
|
|
122
|
+
* @returns The raw secret string
|
|
123
|
+
*/
|
|
124
|
+
unwrap() {
|
|
125
|
+
return this.value;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the secret value as a plain string.
|
|
129
|
+
* Alias for unwrap() for compatibility.
|
|
130
|
+
*/
|
|
131
|
+
getValue() {
|
|
132
|
+
return this.value;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if this secret was loaded from environment
|
|
136
|
+
*/
|
|
137
|
+
isFromEnvironment() {
|
|
138
|
+
return this.source === 'env';
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Prevent accidental logging of secret values
|
|
142
|
+
*/
|
|
143
|
+
toString() {
|
|
144
|
+
return '[SecretValue: REDACTED]';
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Prevent accidental JSON serialization of secret values
|
|
148
|
+
*/
|
|
149
|
+
toJSON() {
|
|
150
|
+
return '[SecretValue: REDACTED]';
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* For Node.js util.inspect
|
|
154
|
+
*/
|
|
155
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
156
|
+
return `SecretValue { source: '${this.source}', value: [REDACTED] }`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Type guard to check if a value is a SecretValue
|
|
161
|
+
*/
|
|
162
|
+
export function isSecretValue(value) {
|
|
163
|
+
return value instanceof SecretValue;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Helper to unwrap a secret if it's a SecretValue, or use as-is if string.
|
|
167
|
+
* Useful for backward compatibility.
|
|
168
|
+
*
|
|
169
|
+
* @deprecated Prefer using SecretValue directly
|
|
170
|
+
*/
|
|
171
|
+
export function unwrapSecret(secret) {
|
|
172
|
+
if (secret instanceof SecretValue) {
|
|
173
|
+
return secret.getValue();
|
|
174
|
+
}
|
|
175
|
+
// Log warning for raw strings in production
|
|
176
|
+
if (process.env.NODE_ENV === 'production') {
|
|
177
|
+
console.warn('[SecretValue] Warning: Using raw string as secret. ' +
|
|
178
|
+
'Consider migrating to SecretValue.fromEnv() for better security.');
|
|
179
|
+
}
|
|
180
|
+
return secret;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=secure-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-secret.js","sourceRoot":"","sources":["../../src/auth/secure-secret.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Express } from 'express';
|
|
2
|
+
import { McpAuthConfig } from './types.js';
|
|
3
|
+
import { requireScopes } from './middleware.js';
|
|
4
|
+
export type { McpAuthConfig } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Server Integration Utilities
|
|
7
|
+
*
|
|
8
|
+
* Easy integration of OAuth 2.1 auth into MCP servers
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Configure authentication for MCP server
|
|
12
|
+
*
|
|
13
|
+
* This adds:
|
|
14
|
+
* 1. Protected Resource Metadata endpoint
|
|
15
|
+
* 2. Authentication middleware to specified routes
|
|
16
|
+
*
|
|
17
|
+
* @param app - Express application
|
|
18
|
+
* @param config - Auth configuration
|
|
19
|
+
* @param protectRoutes - Routes to protect with auth (default: all /mcp routes)
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const app = express();
|
|
24
|
+
*
|
|
25
|
+
* configureServerAuth(app, {
|
|
26
|
+
* resourceUri: 'https://mcp.example.com',
|
|
27
|
+
* authorizationServers: ['https://auth.example.com'],
|
|
28
|
+
* tokenIntrospectionEndpoint: 'https://auth.example.com/oauth/introspect',
|
|
29
|
+
* tokenIntrospectionClientId: 'mcp-server',
|
|
30
|
+
* tokenIntrospectionClientSecret: process.env.INTROSPECTION_SECRET,
|
|
31
|
+
* audience: 'https://mcp.example.com',
|
|
32
|
+
* scopesSupported: ['mcp:read', 'mcp:write']
|
|
33
|
+
* }, {
|
|
34
|
+
* protectRoutes: ['/mcp/*']
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function configureServerAuth(app: Express, config: McpAuthConfig, options?: {
|
|
39
|
+
protectRoutes?: string[];
|
|
40
|
+
metadataPath?: string;
|
|
41
|
+
}): void;
|
|
42
|
+
/**
|
|
43
|
+
* Scope-based route protection helper
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const scopes = createScopeGuards(['mcp:read', 'mcp:write', 'mcp:admin']);
|
|
48
|
+
*
|
|
49
|
+
* app.get('/mcp/tools', scopes.read, (req, res) => {
|
|
50
|
+
* // List tools - requires mcp:read
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* app.post('/mcp/tools/execute', scopes.write, (req, res) => {
|
|
54
|
+
* // Execute tool - requires mcp:write
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* app.delete('/mcp/resources', scopes.admin, (req, res) => {
|
|
58
|
+
* // Delete resource - requires mcp:admin
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function createScopeGuards(scopeConfig: {
|
|
63
|
+
read?: string[];
|
|
64
|
+
write?: string[];
|
|
65
|
+
admin?: string[];
|
|
66
|
+
[key: string]: string[] | undefined;
|
|
67
|
+
}): Record<string, ReturnType<typeof requireScopes>>;
|
|
68
|
+
/**
|
|
69
|
+
* Create standard MCP scope configuration
|
|
70
|
+
*
|
|
71
|
+
* Returns scope guards for common MCP operations:
|
|
72
|
+
* - read: List tools, resources, prompts
|
|
73
|
+
* - execute: Execute tools, get prompts
|
|
74
|
+
* - write: Modify resources
|
|
75
|
+
* - admin: Server configuration
|
|
76
|
+
*
|
|
77
|
+
* @param scopePrefix - Scope prefix (default: 'mcp')
|
|
78
|
+
*/
|
|
79
|
+
export declare function createMCPScopeGuards(scopePrefix?: string): Record<string, import("express").RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>>;
|
|
80
|
+
/**
|
|
81
|
+
* Generate suggested scopes for MCP server
|
|
82
|
+
*
|
|
83
|
+
* Returns standard scope definitions for MCP operations
|
|
84
|
+
*/
|
|
85
|
+
export declare function getStandardMCPScopes(scopePrefix?: string): {
|
|
86
|
+
scopes: string[];
|
|
87
|
+
descriptions: Record<string, string>;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Helper to validate auth configuration
|
|
91
|
+
*/
|
|
92
|
+
export declare function validateAuthConfig(config: McpAuthConfig): {
|
|
93
|
+
valid: boolean;
|
|
94
|
+
errors: string[];
|
|
95
|
+
warnings: string[];
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=server-integration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-integration.d.ts","sourceRoot":"","sources":["../../src/auth/server-integration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAwB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGtE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,IAAI,CA0BN;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE;IAC7C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;CACrC,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAUnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,GAAE,MAAc,gKAO/D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,GAAE,MAAc,GAAG;IACjE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAgBA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAkEA"}
|