@monoes/mcp 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/README.md +127 -0
- package/dist/connection-pool.d.ts +36 -0
- package/dist/connection-pool.d.ts.map +1 -0
- package/dist/connection-pool.js +273 -0
- package/dist/connection-pool.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +146 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +318 -0
- package/dist/oauth.js.map +1 -0
- package/dist/prompt-registry.d.ts +90 -0
- package/dist/prompt-registry.d.ts.map +1 -0
- package/dist/prompt-registry.js +209 -0
- package/dist/prompt-registry.js.map +1 -0
- package/dist/rate-limiter.d.ts +86 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +197 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/resource-registry.d.ts +144 -0
- package/dist/resource-registry.d.ts.map +1 -0
- package/dist/resource-registry.js +405 -0
- package/dist/resource-registry.js.map +1 -0
- package/dist/sampling.d.ts +102 -0
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +268 -0
- package/dist/sampling.js.map +1 -0
- package/dist/schema-validator.d.ts +30 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +182 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/server.d.ts +122 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +829 -0
- package/dist/server.js.map +1 -0
- package/dist/session-manager.d.ts +55 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +252 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/task-manager.d.ts +81 -0
- package/dist/task-manager.d.ts.map +1 -0
- package/dist/task-manager.js +337 -0
- package/dist/task-manager.js.map +1 -0
- package/dist/tool-registry.d.ts +88 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +353 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/transport/http.d.ts +71 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +567 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/index.d.ts +50 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +181 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/stdio.d.ts +43 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +194 -0
- package/dist/transport/stdio.js.map +1 -0
- package/dist/transport/websocket.d.ts +87 -0
- package/dist/transport/websocket.d.ts.map +1 -0
- package/dist/transport/websocket.js +408 -0
- package/dist/transport/websocket.js.map +1 -0
- package/dist/types.d.ts +473 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +40 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @monoes/mcp - OAuth 2.1 Authentication
|
|
3
|
+
*
|
|
4
|
+
* MCP 2025-11-25 compliant OAuth 2.1 with PKCE
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import type { ILogger } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* OAuth 2.1 configuration
|
|
10
|
+
*/
|
|
11
|
+
export interface OAuthConfig {
|
|
12
|
+
/** Client ID */
|
|
13
|
+
clientId: string;
|
|
14
|
+
/** Client secret (for confidential clients) */
|
|
15
|
+
clientSecret?: string;
|
|
16
|
+
/** Authorization endpoint */
|
|
17
|
+
authorizationEndpoint: string;
|
|
18
|
+
/** Token endpoint */
|
|
19
|
+
tokenEndpoint: string;
|
|
20
|
+
/** Redirect URI */
|
|
21
|
+
redirectUri: string;
|
|
22
|
+
/** Scopes to request */
|
|
23
|
+
scopes?: string[];
|
|
24
|
+
/** Token storage adapter */
|
|
25
|
+
tokenStorage?: TokenStorage;
|
|
26
|
+
/** Enable PKCE (default: true) */
|
|
27
|
+
usePKCE?: boolean;
|
|
28
|
+
/** State parameter generator */
|
|
29
|
+
stateGenerator?: () => string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* OAuth tokens
|
|
33
|
+
*/
|
|
34
|
+
export interface OAuthTokens {
|
|
35
|
+
accessToken: string;
|
|
36
|
+
refreshToken?: string;
|
|
37
|
+
tokenType: string;
|
|
38
|
+
expiresIn?: number;
|
|
39
|
+
expiresAt?: number;
|
|
40
|
+
scope?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Token storage interface
|
|
44
|
+
*/
|
|
45
|
+
export interface TokenStorage {
|
|
46
|
+
save(key: string, tokens: OAuthTokens): Promise<void>;
|
|
47
|
+
load(key: string): Promise<OAuthTokens | null>;
|
|
48
|
+
delete(key: string): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Authorization request
|
|
52
|
+
*/
|
|
53
|
+
export interface AuthorizationRequest {
|
|
54
|
+
url: string;
|
|
55
|
+
state: string;
|
|
56
|
+
codeVerifier?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* In-memory token storage (for development)
|
|
60
|
+
*/
|
|
61
|
+
export declare class InMemoryTokenStorage implements TokenStorage {
|
|
62
|
+
private tokens;
|
|
63
|
+
save(key: string, tokens: OAuthTokens): Promise<void>;
|
|
64
|
+
load(key: string): Promise<OAuthTokens | null>;
|
|
65
|
+
delete(key: string): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* OAuth 2.1 Manager
|
|
69
|
+
*/
|
|
70
|
+
export declare class OAuthManager extends EventEmitter {
|
|
71
|
+
private readonly logger;
|
|
72
|
+
private readonly config;
|
|
73
|
+
private readonly tokenStorage;
|
|
74
|
+
private pendingRequests;
|
|
75
|
+
private cleanupTimer?;
|
|
76
|
+
constructor(logger: ILogger, config: OAuthConfig);
|
|
77
|
+
/**
|
|
78
|
+
* Generate authorization URL for OAuth flow
|
|
79
|
+
*/
|
|
80
|
+
createAuthorizationRequest(): AuthorizationRequest;
|
|
81
|
+
/**
|
|
82
|
+
* Exchange authorization code for tokens
|
|
83
|
+
*/
|
|
84
|
+
exchangeCode(code: string, state: string): Promise<OAuthTokens>;
|
|
85
|
+
/**
|
|
86
|
+
* Refresh access token using refresh token
|
|
87
|
+
*/
|
|
88
|
+
refreshTokens(storageKey?: string): Promise<OAuthTokens>;
|
|
89
|
+
/**
|
|
90
|
+
* Get valid access token (auto-refresh if expired)
|
|
91
|
+
*/
|
|
92
|
+
getAccessToken(storageKey?: string): Promise<string | null>;
|
|
93
|
+
/**
|
|
94
|
+
* Revoke tokens
|
|
95
|
+
*/
|
|
96
|
+
revokeTokens(storageKey?: string): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Check if authenticated
|
|
99
|
+
*/
|
|
100
|
+
isAuthenticated(storageKey?: string): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* Destroy manager and cleanup
|
|
103
|
+
*/
|
|
104
|
+
destroy(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Parse token response
|
|
107
|
+
*/
|
|
108
|
+
private parseTokenResponse;
|
|
109
|
+
/**
|
|
110
|
+
* Generate PKCE code verifier
|
|
111
|
+
*/
|
|
112
|
+
private generateCodeVerifier;
|
|
113
|
+
/**
|
|
114
|
+
* Generate PKCE code challenge (S256)
|
|
115
|
+
*/
|
|
116
|
+
private generateCodeChallenge;
|
|
117
|
+
/**
|
|
118
|
+
* Generate random string
|
|
119
|
+
*/
|
|
120
|
+
private generateRandomString;
|
|
121
|
+
/**
|
|
122
|
+
* Base64 URL encode
|
|
123
|
+
*/
|
|
124
|
+
private base64UrlEncode;
|
|
125
|
+
/**
|
|
126
|
+
* Start cleanup of expired pending requests
|
|
127
|
+
*/
|
|
128
|
+
private startCleanup;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create OAuth manager
|
|
132
|
+
*/
|
|
133
|
+
export declare function createOAuthManager(logger: ILogger, config: OAuthConfig): OAuthManager;
|
|
134
|
+
/**
|
|
135
|
+
* OAuth middleware for Express/Connect
|
|
136
|
+
*/
|
|
137
|
+
export declare function oauthMiddleware(oauthManager: OAuthManager, storageKey?: string): (req: any, res: any, next: () => void) => Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Create GitHub OAuth provider config
|
|
140
|
+
*/
|
|
141
|
+
export declare function createGitHubOAuthConfig(clientId: string, clientSecret: string, redirectUri: string, scopes?: string[]): OAuthConfig;
|
|
142
|
+
/**
|
|
143
|
+
* Create Google OAuth provider config
|
|
144
|
+
*/
|
|
145
|
+
export declare function createGoogleOAuthConfig(clientId: string, clientSecret: string, redirectUri: string, scopes?: string[]): OAuthConfig;
|
|
146
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @monoes/mcp - OAuth 2.1 Authentication
|
|
3
|
+
*
|
|
4
|
+
* MCP 2025-11-25 compliant OAuth 2.1 with PKCE
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import * as crypto from 'crypto';
|
|
8
|
+
/**
|
|
9
|
+
* In-memory token storage (for development)
|
|
10
|
+
*/
|
|
11
|
+
export class InMemoryTokenStorage {
|
|
12
|
+
tokens = new Map();
|
|
13
|
+
async save(key, tokens) {
|
|
14
|
+
this.tokens.set(key, tokens);
|
|
15
|
+
}
|
|
16
|
+
async load(key) {
|
|
17
|
+
return this.tokens.get(key) || null;
|
|
18
|
+
}
|
|
19
|
+
async delete(key) {
|
|
20
|
+
this.tokens.delete(key);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* OAuth 2.1 Manager
|
|
25
|
+
*/
|
|
26
|
+
export class OAuthManager extends EventEmitter {
|
|
27
|
+
logger;
|
|
28
|
+
config;
|
|
29
|
+
tokenStorage;
|
|
30
|
+
pendingRequests = new Map();
|
|
31
|
+
cleanupTimer;
|
|
32
|
+
constructor(logger, config) {
|
|
33
|
+
super();
|
|
34
|
+
this.logger = logger;
|
|
35
|
+
this.config = {
|
|
36
|
+
usePKCE: true,
|
|
37
|
+
scopes: [],
|
|
38
|
+
stateGenerator: () => this.generateRandomString(32),
|
|
39
|
+
...config,
|
|
40
|
+
};
|
|
41
|
+
this.tokenStorage = config.tokenStorage || new InMemoryTokenStorage();
|
|
42
|
+
this.startCleanup();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Generate authorization URL for OAuth flow
|
|
46
|
+
*/
|
|
47
|
+
createAuthorizationRequest() {
|
|
48
|
+
const state = this.config.stateGenerator();
|
|
49
|
+
let codeVerifier;
|
|
50
|
+
let codeChallenge;
|
|
51
|
+
if (this.config.usePKCE) {
|
|
52
|
+
codeVerifier = this.generateCodeVerifier();
|
|
53
|
+
codeChallenge = this.generateCodeChallenge(codeVerifier);
|
|
54
|
+
}
|
|
55
|
+
const params = new URLSearchParams({
|
|
56
|
+
response_type: 'code',
|
|
57
|
+
client_id: this.config.clientId,
|
|
58
|
+
redirect_uri: this.config.redirectUri,
|
|
59
|
+
state,
|
|
60
|
+
});
|
|
61
|
+
if (this.config.scopes && this.config.scopes.length > 0) {
|
|
62
|
+
params.set('scope', this.config.scopes.join(' '));
|
|
63
|
+
}
|
|
64
|
+
if (codeChallenge) {
|
|
65
|
+
params.set('code_challenge', codeChallenge);
|
|
66
|
+
params.set('code_challenge_method', 'S256');
|
|
67
|
+
}
|
|
68
|
+
// Store pending request for validation
|
|
69
|
+
this.pendingRequests.set(state, {
|
|
70
|
+
codeVerifier,
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
});
|
|
73
|
+
const url = `${this.config.authorizationEndpoint}?${params.toString()}`;
|
|
74
|
+
this.logger.debug('Created authorization request', { state, usePKCE: !!codeVerifier });
|
|
75
|
+
this.emit('authorization:created', { state });
|
|
76
|
+
return { url, state, codeVerifier };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Exchange authorization code for tokens
|
|
80
|
+
*/
|
|
81
|
+
async exchangeCode(code, state) {
|
|
82
|
+
const pending = this.pendingRequests.get(state);
|
|
83
|
+
if (!pending) {
|
|
84
|
+
throw new Error('Invalid or expired state parameter');
|
|
85
|
+
}
|
|
86
|
+
this.pendingRequests.delete(state);
|
|
87
|
+
const params = new URLSearchParams({
|
|
88
|
+
grant_type: 'authorization_code',
|
|
89
|
+
code,
|
|
90
|
+
redirect_uri: this.config.redirectUri,
|
|
91
|
+
client_id: this.config.clientId,
|
|
92
|
+
});
|
|
93
|
+
if (this.config.clientSecret) {
|
|
94
|
+
params.set('client_secret', this.config.clientSecret);
|
|
95
|
+
}
|
|
96
|
+
if (pending.codeVerifier) {
|
|
97
|
+
params.set('code_verifier', pending.codeVerifier);
|
|
98
|
+
}
|
|
99
|
+
const response = await fetch(this.config.tokenEndpoint, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: {
|
|
102
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
103
|
+
},
|
|
104
|
+
body: params.toString(),
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
const error = await response.text();
|
|
108
|
+
this.logger.error('Token exchange failed', { status: response.status, error });
|
|
109
|
+
throw new Error(`Token exchange failed: ${response.status}`);
|
|
110
|
+
}
|
|
111
|
+
const data = (await response.json());
|
|
112
|
+
const tokens = this.parseTokenResponse(data);
|
|
113
|
+
await this.tokenStorage.save('default', tokens);
|
|
114
|
+
this.logger.info('Token exchange successful');
|
|
115
|
+
this.emit('tokens:received', { expiresIn: tokens.expiresIn });
|
|
116
|
+
return tokens;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Refresh access token using refresh token
|
|
120
|
+
*/
|
|
121
|
+
async refreshTokens(storageKey = 'default') {
|
|
122
|
+
const existing = await this.tokenStorage.load(storageKey);
|
|
123
|
+
if (!existing?.refreshToken) {
|
|
124
|
+
throw new Error('No refresh token available');
|
|
125
|
+
}
|
|
126
|
+
const params = new URLSearchParams({
|
|
127
|
+
grant_type: 'refresh_token',
|
|
128
|
+
refresh_token: existing.refreshToken,
|
|
129
|
+
client_id: this.config.clientId,
|
|
130
|
+
});
|
|
131
|
+
if (this.config.clientSecret) {
|
|
132
|
+
params.set('client_secret', this.config.clientSecret);
|
|
133
|
+
}
|
|
134
|
+
const response = await fetch(this.config.tokenEndpoint, {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: {
|
|
137
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
138
|
+
},
|
|
139
|
+
body: params.toString(),
|
|
140
|
+
});
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
const error = await response.text();
|
|
143
|
+
this.logger.error('Token refresh failed', { status: response.status, error });
|
|
144
|
+
// Clear invalid tokens
|
|
145
|
+
await this.tokenStorage.delete(storageKey);
|
|
146
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
147
|
+
}
|
|
148
|
+
const data = (await response.json());
|
|
149
|
+
const tokens = this.parseTokenResponse(data);
|
|
150
|
+
// Preserve refresh token if not returned in response
|
|
151
|
+
if (!tokens.refreshToken && existing.refreshToken) {
|
|
152
|
+
tokens.refreshToken = existing.refreshToken;
|
|
153
|
+
}
|
|
154
|
+
await this.tokenStorage.save(storageKey, tokens);
|
|
155
|
+
this.logger.info('Token refresh successful');
|
|
156
|
+
this.emit('tokens:refreshed', { expiresIn: tokens.expiresIn });
|
|
157
|
+
return tokens;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get valid access token (auto-refresh if expired)
|
|
161
|
+
*/
|
|
162
|
+
async getAccessToken(storageKey = 'default') {
|
|
163
|
+
const tokens = await this.tokenStorage.load(storageKey);
|
|
164
|
+
if (!tokens) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
// Check if token is expired (with 60 second buffer)
|
|
168
|
+
if (tokens.expiresAt && Date.now() >= tokens.expiresAt - 60000) {
|
|
169
|
+
if (tokens.refreshToken) {
|
|
170
|
+
try {
|
|
171
|
+
const refreshed = await this.refreshTokens(storageKey);
|
|
172
|
+
return refreshed.accessToken;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
return tokens.accessToken;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Revoke tokens
|
|
184
|
+
*/
|
|
185
|
+
async revokeTokens(storageKey = 'default') {
|
|
186
|
+
await this.tokenStorage.delete(storageKey);
|
|
187
|
+
this.logger.info('Tokens revoked');
|
|
188
|
+
this.emit('tokens:revoked', { storageKey });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Check if authenticated
|
|
192
|
+
*/
|
|
193
|
+
async isAuthenticated(storageKey = 'default') {
|
|
194
|
+
const token = await this.getAccessToken(storageKey);
|
|
195
|
+
return token !== null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Destroy manager and cleanup
|
|
199
|
+
*/
|
|
200
|
+
destroy() {
|
|
201
|
+
if (this.cleanupTimer) {
|
|
202
|
+
clearInterval(this.cleanupTimer);
|
|
203
|
+
this.cleanupTimer = undefined;
|
|
204
|
+
}
|
|
205
|
+
this.pendingRequests.clear();
|
|
206
|
+
this.removeAllListeners();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Parse token response
|
|
210
|
+
*/
|
|
211
|
+
parseTokenResponse(data) {
|
|
212
|
+
return {
|
|
213
|
+
accessToken: data.access_token,
|
|
214
|
+
refreshToken: data.refresh_token,
|
|
215
|
+
tokenType: data.token_type,
|
|
216
|
+
expiresIn: data.expires_in,
|
|
217
|
+
expiresAt: data.expires_in ? Date.now() + data.expires_in * 1000 : undefined,
|
|
218
|
+
scope: data.scope,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Generate PKCE code verifier
|
|
223
|
+
*/
|
|
224
|
+
generateCodeVerifier() {
|
|
225
|
+
return this.generateRandomString(64);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Generate PKCE code challenge (S256)
|
|
229
|
+
*/
|
|
230
|
+
generateCodeChallenge(verifier) {
|
|
231
|
+
const hash = crypto.createHash('sha256').update(verifier).digest();
|
|
232
|
+
return this.base64UrlEncode(hash);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Generate random string
|
|
236
|
+
*/
|
|
237
|
+
generateRandomString(length) {
|
|
238
|
+
const bytes = crypto.randomBytes(length);
|
|
239
|
+
return this.base64UrlEncode(bytes).substring(0, length);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Base64 URL encode
|
|
243
|
+
*/
|
|
244
|
+
base64UrlEncode(buffer) {
|
|
245
|
+
return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Start cleanup of expired pending requests
|
|
249
|
+
*/
|
|
250
|
+
startCleanup() {
|
|
251
|
+
this.cleanupTimer = setInterval(() => {
|
|
252
|
+
const now = Date.now();
|
|
253
|
+
const expireTime = 10 * 60 * 1000; // 10 minutes
|
|
254
|
+
for (const [state, request] of this.pendingRequests) {
|
|
255
|
+
if (now - request.timestamp > expireTime) {
|
|
256
|
+
this.pendingRequests.delete(state);
|
|
257
|
+
this.logger.debug('Expired pending OAuth request', { state });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}, 60000);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Create OAuth manager
|
|
265
|
+
*/
|
|
266
|
+
export function createOAuthManager(logger, config) {
|
|
267
|
+
return new OAuthManager(logger, config);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* OAuth middleware for Express/Connect
|
|
271
|
+
*/
|
|
272
|
+
export function oauthMiddleware(oauthManager, storageKey = 'default') {
|
|
273
|
+
return async (req, res, next) => {
|
|
274
|
+
const token = await oauthManager.getAccessToken(storageKey);
|
|
275
|
+
if (!token) {
|
|
276
|
+
res.status(401).json({
|
|
277
|
+
jsonrpc: '2.0',
|
|
278
|
+
id: null,
|
|
279
|
+
error: {
|
|
280
|
+
code: -32000,
|
|
281
|
+
message: 'Unauthorized - OAuth authentication required',
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
req.oauthToken = token;
|
|
287
|
+
next();
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Create GitHub OAuth provider config
|
|
292
|
+
*/
|
|
293
|
+
export function createGitHubOAuthConfig(clientId, clientSecret, redirectUri, scopes = ['read:user']) {
|
|
294
|
+
return {
|
|
295
|
+
clientId,
|
|
296
|
+
clientSecret,
|
|
297
|
+
redirectUri,
|
|
298
|
+
scopes,
|
|
299
|
+
authorizationEndpoint: 'https://github.com/login/oauth/authorize',
|
|
300
|
+
tokenEndpoint: 'https://github.com/login/oauth/access_token',
|
|
301
|
+
usePKCE: false, // GitHub doesn't support PKCE for OAuth apps
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Create Google OAuth provider config
|
|
306
|
+
*/
|
|
307
|
+
export function createGoogleOAuthConfig(clientId, clientSecret, redirectUri, scopes = ['openid', 'profile', 'email']) {
|
|
308
|
+
return {
|
|
309
|
+
clientId,
|
|
310
|
+
clientSecret,
|
|
311
|
+
redirectUri,
|
|
312
|
+
scopes,
|
|
313
|
+
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
314
|
+
tokenEndpoint: 'https://oauth2.googleapis.com/token',
|
|
315
|
+
usePKCE: true,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @monoes/mcp - Prompt Registry
|
|
3
|
+
*
|
|
4
|
+
* MCP 2025-11-25 compliant prompt management
|
|
5
|
+
* Supports: list, get, arguments, templates, embedded resources
|
|
6
|
+
*/
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
import type { MCPPrompt, PromptArgument, PromptMessage, PromptListResult, PromptGetResult, ResourceContent, ILogger } from './types.js';
|
|
9
|
+
export type PromptHandler = (args: Record<string, string>) => Promise<PromptMessage[]>;
|
|
10
|
+
export interface PromptDefinition extends MCPPrompt {
|
|
11
|
+
handler: PromptHandler;
|
|
12
|
+
}
|
|
13
|
+
export interface PromptRegistryOptions {
|
|
14
|
+
maxPrompts?: number;
|
|
15
|
+
validateArguments?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare class PromptRegistry extends EventEmitter {
|
|
18
|
+
private readonly logger;
|
|
19
|
+
private prompts;
|
|
20
|
+
private readonly options;
|
|
21
|
+
constructor(logger: ILogger, options?: PromptRegistryOptions);
|
|
22
|
+
/**
|
|
23
|
+
* Register a prompt
|
|
24
|
+
*/
|
|
25
|
+
register(prompt: PromptDefinition): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Unregister a prompt
|
|
28
|
+
*/
|
|
29
|
+
unregister(name: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* List prompts with pagination
|
|
32
|
+
*/
|
|
33
|
+
list(cursor?: string, pageSize?: number): PromptListResult;
|
|
34
|
+
/**
|
|
35
|
+
* Get a prompt with arguments
|
|
36
|
+
*/
|
|
37
|
+
get(name: string, args?: Record<string, string>): Promise<PromptGetResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Get prompt by name
|
|
40
|
+
*/
|
|
41
|
+
getPrompt(name: string): MCPPrompt | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Check if prompt exists
|
|
44
|
+
*/
|
|
45
|
+
hasPrompt(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Get prompt count
|
|
48
|
+
*/
|
|
49
|
+
getPromptCount(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Get stats
|
|
52
|
+
*/
|
|
53
|
+
getStats(): {
|
|
54
|
+
totalPrompts: number;
|
|
55
|
+
promptsWithArgs: number;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Encode cursor for pagination
|
|
59
|
+
*/
|
|
60
|
+
private encodeCursor;
|
|
61
|
+
/**
|
|
62
|
+
* Decode cursor for pagination
|
|
63
|
+
*/
|
|
64
|
+
private decodeCursor;
|
|
65
|
+
/**
|
|
66
|
+
* Emit listChanged notification
|
|
67
|
+
*/
|
|
68
|
+
private emitListChanged;
|
|
69
|
+
}
|
|
70
|
+
export declare function createPromptRegistry(logger: ILogger, options?: PromptRegistryOptions): PromptRegistry;
|
|
71
|
+
/**
|
|
72
|
+
* Helper to define a prompt
|
|
73
|
+
*/
|
|
74
|
+
export declare function definePrompt(name: string, description: string, handler: PromptHandler, options?: {
|
|
75
|
+
title?: string;
|
|
76
|
+
arguments?: PromptArgument[];
|
|
77
|
+
}): PromptDefinition;
|
|
78
|
+
/**
|
|
79
|
+
* Helper to create a text message
|
|
80
|
+
*/
|
|
81
|
+
export declare function textMessage(role: 'user' | 'assistant', text: string): PromptMessage;
|
|
82
|
+
/**
|
|
83
|
+
* Helper to create a message with embedded resource
|
|
84
|
+
*/
|
|
85
|
+
export declare function resourceMessage(role: 'user' | 'assistant', resource: ResourceContent): PromptMessage;
|
|
86
|
+
/**
|
|
87
|
+
* Template string interpolation for prompts
|
|
88
|
+
*/
|
|
89
|
+
export declare function interpolate(template: string, args: Record<string, string>): string;
|
|
90
|
+
//# sourceMappingURL=prompt-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-registry.d.ts","sourceRoot":"","sources":["../src/prompt-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,EAIf,eAAe,EACf,OAAO,EACR,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,aAAa,GAAG,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACzB,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;AAE9B,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,qBAAa,cAAe,SAAQ,YAAY;IAM5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,OAAO,CAA4C;IAE3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAE1D,YACmB,MAAM,EAAE,OAAO,EAChC,OAAO,GAAE,qBAA0B,EAOpC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAkB1C;IAED;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYhC;IAED;;OAEG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,gBAAgB,CAwB7D;IAED;;OAEG;IACG,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAChC,OAAO,CAAC,eAAe,CAAC,CAuB1B;IAED;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAU7C;IAED;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/B;IAED;;OAEG;IACH,cAAc,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,QAAQ,IAAI;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;KACzB,CAYA;IAED;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,eAAe;CAGxB;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,qBAAqB,GAC9B,cAAc,CAEhB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B,GACA,gBAAgB,CAQlB;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,IAAI,EAAE,MAAM,GACX,aAAa,CAQf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,QAAQ,EAAE,eAAe,GACxB,aAAa,CAQf;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,MAAM,CAIR"}
|