@toolsdk.ai/registry 1.0.132 → 1.0.133
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/dist/api/index.js +4 -0
- package/dist/domains/executor/executor-types.d.ts +3 -1
- package/dist/domains/executor/local-executor.d.ts +1 -1
- package/dist/domains/executor/local-executor.js +3 -3
- package/dist/domains/executor/sandbox-executor.d.ts +1 -1
- package/dist/domains/executor/sandbox-executor.js +3 -3
- package/dist/domains/oauth/__tests__/oauth-session.test.d.ts +1 -0
- package/dist/domains/oauth/__tests__/oauth-session.test.js +272 -0
- package/dist/domains/oauth/__tests__/oauth-utils.test.d.ts +1 -0
- package/dist/domains/oauth/__tests__/oauth-utils.test.js +284 -0
- package/dist/domains/oauth/index.d.ts +9 -0
- package/dist/domains/oauth/index.js +9 -0
- package/dist/domains/oauth/oauth-handler.d.ts +65 -0
- package/dist/domains/oauth/oauth-handler.js +355 -0
- package/dist/domains/oauth/oauth-route.d.ts +11 -0
- package/dist/domains/oauth/oauth-route.js +138 -0
- package/dist/domains/oauth/oauth-schema.d.ts +257 -0
- package/dist/domains/oauth/oauth-schema.js +119 -0
- package/dist/domains/oauth/oauth-session.d.ts +54 -0
- package/dist/domains/oauth/oauth-session.js +116 -0
- package/dist/domains/oauth/oauth-types.d.ts +148 -0
- package/dist/domains/oauth/oauth-types.js +9 -0
- package/dist/domains/oauth/oauth-utils.d.ts +99 -0
- package/dist/domains/oauth/oauth-utils.js +267 -0
- package/dist/domains/package/package-handler.d.ts +2 -2
- package/dist/domains/package/package-handler.js +4 -4
- package/dist/domains/package/package-route.js +5 -5
- package/dist/domains/package/package-schema.d.ts +51 -0
- package/dist/domains/package/package-schema.js +17 -0
- package/dist/domains/package/package-so.d.ts +6 -2
- package/dist/domains/package/package-so.js +4 -3
- package/dist/shared/schemas/common-schema.d.ts +52 -0
- package/dist/shared/schemas/common-schema.js +7 -0
- package/dist/shared/scripts-helpers/index.d.ts +4 -0
- package/dist/shared/utils/mcp-client-util.d.ts +1 -1
- package/dist/shared/utils/mcp-client-util.js +13 -4
- package/package.json +1 -1
- package/packages/developer-tools/github-mcp.json +4 -1
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Schema Definitions
|
|
3
|
+
*
|
|
4
|
+
* Zod schemas for OAuth API request/response validation
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "@hono/zod-openapi";
|
|
7
|
+
export declare const OAuthPrepareRequestSchema: z.ZodObject<{
|
|
8
|
+
packageName: z.ZodString;
|
|
9
|
+
callbackBaseUrl: z.ZodString;
|
|
10
|
+
mcpServerUrl: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
packageName: string;
|
|
13
|
+
callbackBaseUrl: string;
|
|
14
|
+
mcpServerUrl?: string | undefined;
|
|
15
|
+
}, {
|
|
16
|
+
packageName: string;
|
|
17
|
+
callbackBaseUrl: string;
|
|
18
|
+
mcpServerUrl?: string | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
export declare const OAuthRefreshRequestSchema: z.ZodObject<{
|
|
21
|
+
mcpServerUrl: z.ZodString;
|
|
22
|
+
refreshToken: z.ZodString;
|
|
23
|
+
clientId: z.ZodString;
|
|
24
|
+
clientSecret: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
mcpServerUrl: string;
|
|
27
|
+
refreshToken: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
clientSecret?: string | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
mcpServerUrl: string;
|
|
32
|
+
refreshToken: string;
|
|
33
|
+
clientId: string;
|
|
34
|
+
clientSecret?: string | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export declare const OAuthPrepareDataSchema: z.ZodObject<{
|
|
37
|
+
authUrl: z.ZodString;
|
|
38
|
+
sessionId: z.ZodString;
|
|
39
|
+
mcpServerUrl: z.ZodString;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
sessionId: string;
|
|
42
|
+
mcpServerUrl: string;
|
|
43
|
+
authUrl: string;
|
|
44
|
+
}, {
|
|
45
|
+
sessionId: string;
|
|
46
|
+
mcpServerUrl: string;
|
|
47
|
+
authUrl: string;
|
|
48
|
+
}>;
|
|
49
|
+
export declare const OAuthPrepareResponseSchema: z.ZodObject<{
|
|
50
|
+
success: z.ZodBoolean;
|
|
51
|
+
code: z.ZodNumber;
|
|
52
|
+
message: z.ZodString;
|
|
53
|
+
} & {
|
|
54
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
55
|
+
authUrl: z.ZodString;
|
|
56
|
+
sessionId: z.ZodString;
|
|
57
|
+
mcpServerUrl: z.ZodString;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
sessionId: string;
|
|
60
|
+
mcpServerUrl: string;
|
|
61
|
+
authUrl: string;
|
|
62
|
+
}, {
|
|
63
|
+
sessionId: string;
|
|
64
|
+
mcpServerUrl: string;
|
|
65
|
+
authUrl: string;
|
|
66
|
+
}>>;
|
|
67
|
+
}, "strip", z.ZodTypeAny, {
|
|
68
|
+
success: boolean;
|
|
69
|
+
code: number;
|
|
70
|
+
message: string;
|
|
71
|
+
data?: {
|
|
72
|
+
sessionId: string;
|
|
73
|
+
mcpServerUrl: string;
|
|
74
|
+
authUrl: string;
|
|
75
|
+
} | undefined;
|
|
76
|
+
}, {
|
|
77
|
+
success: boolean;
|
|
78
|
+
code: number;
|
|
79
|
+
message: string;
|
|
80
|
+
data?: {
|
|
81
|
+
sessionId: string;
|
|
82
|
+
mcpServerUrl: string;
|
|
83
|
+
authUrl: string;
|
|
84
|
+
} | undefined;
|
|
85
|
+
}>;
|
|
86
|
+
export declare const TokenResponseSchema: z.ZodObject<{
|
|
87
|
+
access_token: z.ZodString;
|
|
88
|
+
token_type: z.ZodString;
|
|
89
|
+
expires_in: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
refresh_token: z.ZodOptional<z.ZodString>;
|
|
91
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
access_token: string;
|
|
94
|
+
token_type: string;
|
|
95
|
+
scope?: string | undefined;
|
|
96
|
+
refresh_token?: string | undefined;
|
|
97
|
+
expires_in?: number | undefined;
|
|
98
|
+
}, {
|
|
99
|
+
access_token: string;
|
|
100
|
+
token_type: string;
|
|
101
|
+
scope?: string | undefined;
|
|
102
|
+
refresh_token?: string | undefined;
|
|
103
|
+
expires_in?: number | undefined;
|
|
104
|
+
}>;
|
|
105
|
+
export declare const OAuthRefreshResponseSchema: z.ZodObject<{
|
|
106
|
+
success: z.ZodBoolean;
|
|
107
|
+
code: z.ZodNumber;
|
|
108
|
+
message: z.ZodString;
|
|
109
|
+
} & {
|
|
110
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
111
|
+
access_token: z.ZodString;
|
|
112
|
+
token_type: z.ZodString;
|
|
113
|
+
expires_in: z.ZodOptional<z.ZodNumber>;
|
|
114
|
+
refresh_token: z.ZodOptional<z.ZodString>;
|
|
115
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
116
|
+
}, "strip", z.ZodTypeAny, {
|
|
117
|
+
access_token: string;
|
|
118
|
+
token_type: string;
|
|
119
|
+
scope?: string | undefined;
|
|
120
|
+
refresh_token?: string | undefined;
|
|
121
|
+
expires_in?: number | undefined;
|
|
122
|
+
}, {
|
|
123
|
+
access_token: string;
|
|
124
|
+
token_type: string;
|
|
125
|
+
scope?: string | undefined;
|
|
126
|
+
refresh_token?: string | undefined;
|
|
127
|
+
expires_in?: number | undefined;
|
|
128
|
+
}>>;
|
|
129
|
+
}, "strip", z.ZodTypeAny, {
|
|
130
|
+
success: boolean;
|
|
131
|
+
code: number;
|
|
132
|
+
message: string;
|
|
133
|
+
data?: {
|
|
134
|
+
access_token: string;
|
|
135
|
+
token_type: string;
|
|
136
|
+
scope?: string | undefined;
|
|
137
|
+
refresh_token?: string | undefined;
|
|
138
|
+
expires_in?: number | undefined;
|
|
139
|
+
} | undefined;
|
|
140
|
+
}, {
|
|
141
|
+
success: boolean;
|
|
142
|
+
code: number;
|
|
143
|
+
message: string;
|
|
144
|
+
data?: {
|
|
145
|
+
access_token: string;
|
|
146
|
+
token_type: string;
|
|
147
|
+
scope?: string | undefined;
|
|
148
|
+
refresh_token?: string | undefined;
|
|
149
|
+
expires_in?: number | undefined;
|
|
150
|
+
} | undefined;
|
|
151
|
+
}>;
|
|
152
|
+
export declare const ClientInfoSchema: z.ZodObject<{
|
|
153
|
+
client_id: z.ZodString;
|
|
154
|
+
client_secret: z.ZodOptional<z.ZodString>;
|
|
155
|
+
client_secret_expires_at: z.ZodOptional<z.ZodNumber>;
|
|
156
|
+
client_id_issued_at: z.ZodOptional<z.ZodNumber>;
|
|
157
|
+
}, "strip", z.ZodTypeAny, {
|
|
158
|
+
client_id: string;
|
|
159
|
+
client_secret?: string | undefined;
|
|
160
|
+
client_secret_expires_at?: number | undefined;
|
|
161
|
+
client_id_issued_at?: number | undefined;
|
|
162
|
+
}, {
|
|
163
|
+
client_id: string;
|
|
164
|
+
client_secret?: string | undefined;
|
|
165
|
+
client_secret_expires_at?: number | undefined;
|
|
166
|
+
client_id_issued_at?: number | undefined;
|
|
167
|
+
}>;
|
|
168
|
+
export declare const OAuthCallbackDataSchema: z.ZodObject<{
|
|
169
|
+
sessionId: z.ZodString;
|
|
170
|
+
tokens: z.ZodObject<{
|
|
171
|
+
access_token: z.ZodString;
|
|
172
|
+
token_type: z.ZodString;
|
|
173
|
+
expires_in: z.ZodOptional<z.ZodNumber>;
|
|
174
|
+
refresh_token: z.ZodOptional<z.ZodString>;
|
|
175
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
176
|
+
}, "strip", z.ZodTypeAny, {
|
|
177
|
+
access_token: string;
|
|
178
|
+
token_type: string;
|
|
179
|
+
scope?: string | undefined;
|
|
180
|
+
refresh_token?: string | undefined;
|
|
181
|
+
expires_in?: number | undefined;
|
|
182
|
+
}, {
|
|
183
|
+
access_token: string;
|
|
184
|
+
token_type: string;
|
|
185
|
+
scope?: string | undefined;
|
|
186
|
+
refresh_token?: string | undefined;
|
|
187
|
+
expires_in?: number | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
clientInfo: z.ZodObject<{
|
|
190
|
+
client_id: z.ZodString;
|
|
191
|
+
client_secret: z.ZodOptional<z.ZodString>;
|
|
192
|
+
client_secret_expires_at: z.ZodOptional<z.ZodNumber>;
|
|
193
|
+
client_id_issued_at: z.ZodOptional<z.ZodNumber>;
|
|
194
|
+
}, "strip", z.ZodTypeAny, {
|
|
195
|
+
client_id: string;
|
|
196
|
+
client_secret?: string | undefined;
|
|
197
|
+
client_secret_expires_at?: number | undefined;
|
|
198
|
+
client_id_issued_at?: number | undefined;
|
|
199
|
+
}, {
|
|
200
|
+
client_id: string;
|
|
201
|
+
client_secret?: string | undefined;
|
|
202
|
+
client_secret_expires_at?: number | undefined;
|
|
203
|
+
client_id_issued_at?: number | undefined;
|
|
204
|
+
}>;
|
|
205
|
+
mcpServerUrl: z.ZodString;
|
|
206
|
+
packageName: z.ZodString;
|
|
207
|
+
}, "strip", z.ZodTypeAny, {
|
|
208
|
+
packageName: string;
|
|
209
|
+
sessionId: string;
|
|
210
|
+
mcpServerUrl: string;
|
|
211
|
+
tokens: {
|
|
212
|
+
access_token: string;
|
|
213
|
+
token_type: string;
|
|
214
|
+
scope?: string | undefined;
|
|
215
|
+
refresh_token?: string | undefined;
|
|
216
|
+
expires_in?: number | undefined;
|
|
217
|
+
};
|
|
218
|
+
clientInfo: {
|
|
219
|
+
client_id: string;
|
|
220
|
+
client_secret?: string | undefined;
|
|
221
|
+
client_secret_expires_at?: number | undefined;
|
|
222
|
+
client_id_issued_at?: number | undefined;
|
|
223
|
+
};
|
|
224
|
+
}, {
|
|
225
|
+
packageName: string;
|
|
226
|
+
sessionId: string;
|
|
227
|
+
mcpServerUrl: string;
|
|
228
|
+
tokens: {
|
|
229
|
+
access_token: string;
|
|
230
|
+
token_type: string;
|
|
231
|
+
scope?: string | undefined;
|
|
232
|
+
refresh_token?: string | undefined;
|
|
233
|
+
expires_in?: number | undefined;
|
|
234
|
+
};
|
|
235
|
+
clientInfo: {
|
|
236
|
+
client_id: string;
|
|
237
|
+
client_secret?: string | undefined;
|
|
238
|
+
client_secret_expires_at?: number | undefined;
|
|
239
|
+
client_id_issued_at?: number | undefined;
|
|
240
|
+
};
|
|
241
|
+
}>;
|
|
242
|
+
export declare const OAuthCallbackQuerySchema: z.ZodObject<{
|
|
243
|
+
code: z.ZodOptional<z.ZodString>;
|
|
244
|
+
state: z.ZodOptional<z.ZodString>;
|
|
245
|
+
error: z.ZodOptional<z.ZodString>;
|
|
246
|
+
error_description: z.ZodOptional<z.ZodString>;
|
|
247
|
+
}, "strip", z.ZodTypeAny, {
|
|
248
|
+
code?: string | undefined;
|
|
249
|
+
error?: string | undefined;
|
|
250
|
+
state?: string | undefined;
|
|
251
|
+
error_description?: string | undefined;
|
|
252
|
+
}, {
|
|
253
|
+
code?: string | undefined;
|
|
254
|
+
error?: string | undefined;
|
|
255
|
+
state?: string | undefined;
|
|
256
|
+
error_description?: string | undefined;
|
|
257
|
+
}>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Schema Definitions
|
|
3
|
+
*
|
|
4
|
+
* Zod schemas for OAuth API request/response validation
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "@hono/zod-openapi";
|
|
7
|
+
import { BaseResponseSchema } from "../../shared/schemas/common-schema";
|
|
8
|
+
// ============ Request Schemas ============
|
|
9
|
+
export const OAuthPrepareRequestSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
packageName: z.string().min(1).openapi({
|
|
12
|
+
example: "github-mcp",
|
|
13
|
+
description: "MCP package name (used as identifier, can be any string if mcpServerUrl is provided)",
|
|
14
|
+
}),
|
|
15
|
+
callbackBaseUrl: z.string().url().openapi({
|
|
16
|
+
example: "https://toolsdk.ai/api/internal/mcp-oauth/complete",
|
|
17
|
+
description: "URL where Registry will POST the OAuth result (tokens + clientInfo)",
|
|
18
|
+
}),
|
|
19
|
+
mcpServerUrl: z.string().url().optional().openapi({
|
|
20
|
+
example: "http://localhost:3001/mcp",
|
|
21
|
+
description: "Optional: MCP Server URL. If provided, this URL will be used instead of looking up from package config.",
|
|
22
|
+
}),
|
|
23
|
+
})
|
|
24
|
+
.openapi("OAuthPrepareRequest");
|
|
25
|
+
export const OAuthRefreshRequestSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
mcpServerUrl: z.string().url().openapi({
|
|
28
|
+
example: "http://localhost:3001/mcp",
|
|
29
|
+
description: "MCP Server URL",
|
|
30
|
+
}),
|
|
31
|
+
refreshToken: z.string().min(1).openapi({
|
|
32
|
+
description: "Refresh token from previous authorization",
|
|
33
|
+
}),
|
|
34
|
+
clientId: z.string().min(1).openapi({
|
|
35
|
+
description: "OAuth client ID",
|
|
36
|
+
}),
|
|
37
|
+
clientSecret: z.string().optional().openapi({
|
|
38
|
+
description: "OAuth client secret (if applicable)",
|
|
39
|
+
}),
|
|
40
|
+
})
|
|
41
|
+
.openapi("OAuthRefreshRequest");
|
|
42
|
+
// ============ Response Schemas ============
|
|
43
|
+
export const OAuthPrepareDataSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
authUrl: z.string().url().openapi({
|
|
46
|
+
description: "Authorization URL to open in browser/popup",
|
|
47
|
+
}),
|
|
48
|
+
sessionId: z.string().openapi({
|
|
49
|
+
description: "Session ID for tracking this OAuth flow",
|
|
50
|
+
}),
|
|
51
|
+
mcpServerUrl: z.string().url().openapi({
|
|
52
|
+
description: "MCP Server URL",
|
|
53
|
+
}),
|
|
54
|
+
})
|
|
55
|
+
.openapi("OAuthPrepareData");
|
|
56
|
+
export const OAuthPrepareResponseSchema = BaseResponseSchema.extend({
|
|
57
|
+
data: OAuthPrepareDataSchema.optional(),
|
|
58
|
+
}).openapi("OAuthPrepareResponse");
|
|
59
|
+
export const TokenResponseSchema = z
|
|
60
|
+
.object({
|
|
61
|
+
access_token: z.string(),
|
|
62
|
+
token_type: z.string(),
|
|
63
|
+
expires_in: z.number().optional(),
|
|
64
|
+
refresh_token: z.string().optional(),
|
|
65
|
+
scope: z.string().optional(),
|
|
66
|
+
})
|
|
67
|
+
.openapi("TokenResponse");
|
|
68
|
+
export const OAuthRefreshResponseSchema = BaseResponseSchema.extend({
|
|
69
|
+
data: TokenResponseSchema.optional(),
|
|
70
|
+
}).openapi("OAuthRefreshResponse");
|
|
71
|
+
// ============ Callback Data Schema ============
|
|
72
|
+
export const ClientInfoSchema = z
|
|
73
|
+
.object({
|
|
74
|
+
client_id: z.string(),
|
|
75
|
+
client_secret: z.string().optional(),
|
|
76
|
+
client_secret_expires_at: z.number().optional(),
|
|
77
|
+
client_id_issued_at: z.number().optional(),
|
|
78
|
+
})
|
|
79
|
+
.openapi("ClientInfo");
|
|
80
|
+
export const OAuthCallbackDataSchema = z
|
|
81
|
+
.object({
|
|
82
|
+
sessionId: z.string(),
|
|
83
|
+
tokens: TokenResponseSchema,
|
|
84
|
+
clientInfo: ClientInfoSchema,
|
|
85
|
+
mcpServerUrl: z.string().url(),
|
|
86
|
+
packageName: z.string(),
|
|
87
|
+
})
|
|
88
|
+
.openapi("OAuthCallbackData");
|
|
89
|
+
// ============ Query Schemas ============
|
|
90
|
+
export const OAuthCallbackQuerySchema = z.object({
|
|
91
|
+
code: z
|
|
92
|
+
.string()
|
|
93
|
+
.optional()
|
|
94
|
+
.openapi({
|
|
95
|
+
param: { name: "code", in: "query" },
|
|
96
|
+
description: "Authorization code from OAuth server",
|
|
97
|
+
}),
|
|
98
|
+
state: z
|
|
99
|
+
.string()
|
|
100
|
+
.optional()
|
|
101
|
+
.openapi({
|
|
102
|
+
param: { name: "state", in: "query" },
|
|
103
|
+
description: "State parameter for CSRF protection",
|
|
104
|
+
}),
|
|
105
|
+
error: z
|
|
106
|
+
.string()
|
|
107
|
+
.optional()
|
|
108
|
+
.openapi({
|
|
109
|
+
param: { name: "error", in: "query" },
|
|
110
|
+
description: "OAuth error code",
|
|
111
|
+
}),
|
|
112
|
+
error_description: z
|
|
113
|
+
.string()
|
|
114
|
+
.optional()
|
|
115
|
+
.openapi({
|
|
116
|
+
param: { name: "error_description", in: "query" },
|
|
117
|
+
description: "OAuth error description",
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Session Storage
|
|
3
|
+
*
|
|
4
|
+
* In-memory session storage for OAuth flow.
|
|
5
|
+
* Sessions expire after 10 minutes and are deleted after successful completion.
|
|
6
|
+
*/
|
|
7
|
+
import type { OAuthSession } from "./oauth-types";
|
|
8
|
+
export declare class OAuthSessionStore {
|
|
9
|
+
private sessions;
|
|
10
|
+
private stateToSessionId;
|
|
11
|
+
private cleanupTimer;
|
|
12
|
+
constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Start periodic cleanup of expired sessions
|
|
15
|
+
*/
|
|
16
|
+
private startCleanup;
|
|
17
|
+
/**
|
|
18
|
+
* Stop cleanup timer (for testing)
|
|
19
|
+
*/
|
|
20
|
+
stopCleanup(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Remove expired sessions
|
|
23
|
+
*/
|
|
24
|
+
private cleanupExpiredSessions;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new session
|
|
27
|
+
*/
|
|
28
|
+
set(session: OAuthSession): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get session by sessionId
|
|
31
|
+
*/
|
|
32
|
+
get(sessionId: string): OAuthSession | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Get session by state parameter
|
|
35
|
+
*/
|
|
36
|
+
getByState(state: string): OAuthSession | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Delete session
|
|
39
|
+
*/
|
|
40
|
+
delete(sessionId: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Check if session exists
|
|
43
|
+
*/
|
|
44
|
+
has(sessionId: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get number of active sessions
|
|
47
|
+
*/
|
|
48
|
+
size(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Clear all sessions (for testing)
|
|
51
|
+
*/
|
|
52
|
+
clear(): void;
|
|
53
|
+
}
|
|
54
|
+
export declare const oauthSessionStore: OAuthSessionStore;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Session Storage
|
|
3
|
+
*
|
|
4
|
+
* In-memory session storage for OAuth flow.
|
|
5
|
+
* Sessions expire after 10 minutes and are deleted after successful completion.
|
|
6
|
+
*/
|
|
7
|
+
// Session expiration time: 10 minutes
|
|
8
|
+
const SESSION_TTL_MS = 10 * 60 * 1000;
|
|
9
|
+
// Cleanup interval: 1 minute
|
|
10
|
+
const CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
11
|
+
export class OAuthSessionStore {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.sessions = new Map();
|
|
14
|
+
this.stateToSessionId = new Map();
|
|
15
|
+
this.cleanupTimer = null;
|
|
16
|
+
this.startCleanup();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Start periodic cleanup of expired sessions
|
|
20
|
+
*/
|
|
21
|
+
startCleanup() {
|
|
22
|
+
if (this.cleanupTimer)
|
|
23
|
+
return;
|
|
24
|
+
this.cleanupTimer = setInterval(() => {
|
|
25
|
+
this.cleanupExpiredSessions();
|
|
26
|
+
}, CLEANUP_INTERVAL_MS);
|
|
27
|
+
// Unref to allow process to exit
|
|
28
|
+
this.cleanupTimer.unref();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Stop cleanup timer (for testing)
|
|
32
|
+
*/
|
|
33
|
+
stopCleanup() {
|
|
34
|
+
if (this.cleanupTimer) {
|
|
35
|
+
clearInterval(this.cleanupTimer);
|
|
36
|
+
this.cleanupTimer = null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Remove expired sessions
|
|
41
|
+
*/
|
|
42
|
+
cleanupExpiredSessions() {
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
45
|
+
if (now - session.createdAt > SESSION_TTL_MS) {
|
|
46
|
+
this.delete(sessionId);
|
|
47
|
+
console.log(`[OAuth] Session ${sessionId} expired and cleaned up`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a new session
|
|
53
|
+
*/
|
|
54
|
+
set(session) {
|
|
55
|
+
this.sessions.set(session.sessionId, session);
|
|
56
|
+
this.stateToSessionId.set(session.state, session.sessionId);
|
|
57
|
+
console.log(`[OAuth] Session ${session.sessionId} created for package ${session.packageName}`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get session by sessionId
|
|
61
|
+
*/
|
|
62
|
+
get(sessionId) {
|
|
63
|
+
const session = this.sessions.get(sessionId);
|
|
64
|
+
if (!session)
|
|
65
|
+
return undefined;
|
|
66
|
+
// Check if expired
|
|
67
|
+
if (Date.now() - session.createdAt > SESSION_TTL_MS) {
|
|
68
|
+
this.delete(sessionId);
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return session;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get session by state parameter
|
|
75
|
+
*/
|
|
76
|
+
getByState(state) {
|
|
77
|
+
const sessionId = this.stateToSessionId.get(state);
|
|
78
|
+
if (!sessionId)
|
|
79
|
+
return undefined;
|
|
80
|
+
return this.get(sessionId);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Delete session
|
|
84
|
+
*/
|
|
85
|
+
delete(sessionId) {
|
|
86
|
+
const session = this.sessions.get(sessionId);
|
|
87
|
+
if (session) {
|
|
88
|
+
this.stateToSessionId.delete(session.state);
|
|
89
|
+
this.sessions.delete(sessionId);
|
|
90
|
+
console.log(`[OAuth] Session ${sessionId} deleted`);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if session exists
|
|
97
|
+
*/
|
|
98
|
+
has(sessionId) {
|
|
99
|
+
return this.sessions.has(sessionId);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get number of active sessions
|
|
103
|
+
*/
|
|
104
|
+
size() {
|
|
105
|
+
return this.sessions.size;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Clear all sessions (for testing)
|
|
109
|
+
*/
|
|
110
|
+
clear() {
|
|
111
|
+
this.sessions.clear();
|
|
112
|
+
this.stateToSessionId.clear();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Singleton instance
|
|
116
|
+
export const oauthSessionStore = new OAuthSessionStore();
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Types for MCP Registry
|
|
3
|
+
*
|
|
4
|
+
* Based on MCP OAuth Specification:
|
|
5
|
+
* - OAuth 2.1 with PKCE
|
|
6
|
+
* - Dynamic Client Registration (RFC 7591)
|
|
7
|
+
* - Protected Resource Metadata (RFC 9728)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* OAuth Authorization Server Metadata
|
|
11
|
+
* Follows RFC 8414 - OAuth 2.0 Authorization Server Metadata
|
|
12
|
+
*/
|
|
13
|
+
export interface OAuthMetadata {
|
|
14
|
+
issuer: string;
|
|
15
|
+
authorization_endpoint: string;
|
|
16
|
+
token_endpoint: string;
|
|
17
|
+
registration_endpoint?: string;
|
|
18
|
+
revocation_endpoint?: string;
|
|
19
|
+
introspection_endpoint?: string;
|
|
20
|
+
jwks_uri?: string;
|
|
21
|
+
scopes_supported?: string[];
|
|
22
|
+
response_types_supported?: string[];
|
|
23
|
+
grant_types_supported?: string[];
|
|
24
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
25
|
+
code_challenge_methods_supported?: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Protected Resource Metadata
|
|
29
|
+
* Follows RFC 9728 - OAuth 2.0 Protected Resource Metadata
|
|
30
|
+
*/
|
|
31
|
+
export interface ProtectedResourceMetadata {
|
|
32
|
+
resource: string;
|
|
33
|
+
authorization_servers: string[];
|
|
34
|
+
scopes_supported?: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Client Information from Dynamic Client Registration
|
|
38
|
+
* Follows RFC 7591 - OAuth 2.0 Dynamic Client Registration
|
|
39
|
+
*/
|
|
40
|
+
export interface ClientInfo {
|
|
41
|
+
client_id: string;
|
|
42
|
+
client_secret?: string;
|
|
43
|
+
client_secret_expires_at?: number;
|
|
44
|
+
client_id_issued_at?: number;
|
|
45
|
+
redirect_uris?: string[];
|
|
46
|
+
token_endpoint_auth_method?: string;
|
|
47
|
+
grant_types?: string[];
|
|
48
|
+
response_types?: string[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Client Registration Request
|
|
52
|
+
*/
|
|
53
|
+
export interface ClientRegistrationRequest {
|
|
54
|
+
redirect_uris: string[];
|
|
55
|
+
client_name?: string;
|
|
56
|
+
client_uri?: string;
|
|
57
|
+
logo_uri?: string;
|
|
58
|
+
token_endpoint_auth_method?: string;
|
|
59
|
+
grant_types?: string[];
|
|
60
|
+
response_types?: string[];
|
|
61
|
+
scope?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* OAuth Token Response
|
|
65
|
+
*/
|
|
66
|
+
export interface TokenResponse {
|
|
67
|
+
access_token: string;
|
|
68
|
+
token_type: string;
|
|
69
|
+
expires_in?: number;
|
|
70
|
+
refresh_token?: string;
|
|
71
|
+
scope?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* PKCE Parameters
|
|
75
|
+
*/
|
|
76
|
+
export interface PKCEParams {
|
|
77
|
+
codeVerifier: string;
|
|
78
|
+
codeChallenge: string;
|
|
79
|
+
codeChallengeMethod: "S256";
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* OAuth Session stored in memory
|
|
83
|
+
* Contains all necessary data for completing the OAuth flow
|
|
84
|
+
*/
|
|
85
|
+
export interface OAuthSession {
|
|
86
|
+
sessionId: string;
|
|
87
|
+
state: string;
|
|
88
|
+
codeVerifier: string;
|
|
89
|
+
codeChallenge: string;
|
|
90
|
+
clientInfo: ClientInfo;
|
|
91
|
+
callbackBaseUrl: string;
|
|
92
|
+
mcpServerUrl: string;
|
|
93
|
+
packageName: string;
|
|
94
|
+
oauthMetadata: OAuthMetadata;
|
|
95
|
+
createdAt: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Request to prepare OAuth flow
|
|
99
|
+
*/
|
|
100
|
+
export interface OAuthPrepareRequest {
|
|
101
|
+
packageName: string;
|
|
102
|
+
callbackBaseUrl: string;
|
|
103
|
+
/** Optional: directly specify MCP Server URL instead of using package config */
|
|
104
|
+
mcpServerUrl?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Response from prepare OAuth endpoint
|
|
108
|
+
*/
|
|
109
|
+
export interface OAuthPrepareResponse {
|
|
110
|
+
authUrl: string;
|
|
111
|
+
sessionId: string;
|
|
112
|
+
mcpServerUrl: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Callback data sent to callbackBaseUrl after successful authorization
|
|
116
|
+
*/
|
|
117
|
+
export interface OAuthCallbackData {
|
|
118
|
+
sessionId: string;
|
|
119
|
+
tokens: TokenResponse;
|
|
120
|
+
clientInfo: ClientInfo;
|
|
121
|
+
mcpServerUrl: string;
|
|
122
|
+
packageName: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Request to refresh token
|
|
126
|
+
*/
|
|
127
|
+
export interface OAuthRefreshRequest {
|
|
128
|
+
mcpServerUrl: string;
|
|
129
|
+
refreshToken: string;
|
|
130
|
+
clientId: string;
|
|
131
|
+
clientSecret?: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* OAuth Error response
|
|
135
|
+
*/
|
|
136
|
+
export interface OAuthError {
|
|
137
|
+
error: string;
|
|
138
|
+
error_description?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* MCP Package with OAuth support info
|
|
142
|
+
*/
|
|
143
|
+
export interface MCPPackageOAuthInfo {
|
|
144
|
+
packageName: string;
|
|
145
|
+
mcpServerUrl: string;
|
|
146
|
+
supportsOAuth: boolean;
|
|
147
|
+
oauthMetadata?: OAuthMetadata;
|
|
148
|
+
}
|