@toolsdk.ai/registry 1.0.132 → 1.0.134
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-handler.test.d.ts +1 -0
- package/dist/domains/oauth/__tests__/oauth-handler.test.js +598 -0
- 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,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Utility Functions
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - PKCE (RFC 7636) with S256 method
|
|
6
|
+
* - Protected Resource Metadata Discovery (RFC 9728)
|
|
7
|
+
* - Authorization Server Metadata Discovery (RFC 8414)
|
|
8
|
+
* - Dynamic Client Registration (RFC 7591)
|
|
9
|
+
* - Token Exchange
|
|
10
|
+
*/
|
|
11
|
+
import type { ClientInfo, ClientRegistrationRequest, OAuthMetadata, PKCEParams, ProtectedResourceMetadata, TokenResponse } from "./oauth-types";
|
|
12
|
+
/**
|
|
13
|
+
* Generate PKCE parameters with S256 method
|
|
14
|
+
* Per MCP spec: MUST use S256 when technically capable
|
|
15
|
+
*/
|
|
16
|
+
export declare function generatePKCE(): PKCEParams;
|
|
17
|
+
/**
|
|
18
|
+
* Generate a cryptographically secure state parameter
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateState(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Generate a session ID
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateSessionId(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Parse WWW-Authenticate header to extract resource_metadata URL
|
|
27
|
+
* Example: Bearer realm="mcp", resource_metadata="http://.../.well-known/oauth-protected-resource"
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseWWWAuthenticate(header: string): {
|
|
30
|
+
realm?: string;
|
|
31
|
+
resourceMetadataUrl?: string;
|
|
32
|
+
scope?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Discover Protected Resource Metadata from an MCP server
|
|
36
|
+
* Per RFC 9728 and MCP spec
|
|
37
|
+
*/
|
|
38
|
+
export declare function discoverProtectedResourceMetadata(mcpServerUrl: string): Promise<ProtectedResourceMetadata>;
|
|
39
|
+
/**
|
|
40
|
+
* Discover Authorization Server Metadata
|
|
41
|
+
* Per RFC 8414 and OpenID Connect Discovery 1.0
|
|
42
|
+
*/
|
|
43
|
+
export declare function discoverAuthServerMetadata(authServerUrl: string): Promise<OAuthMetadata>;
|
|
44
|
+
/**
|
|
45
|
+
* Verify that the authorization server supports PKCE with S256
|
|
46
|
+
* Per MCP spec: MUST refuse to proceed if PKCE not supported
|
|
47
|
+
*
|
|
48
|
+
* Note: Many servers don't advertise code_challenge_methods_supported but still support PKCE.
|
|
49
|
+
* We return { supported: boolean, advertised: boolean } to allow callers to decide.
|
|
50
|
+
*/
|
|
51
|
+
export declare function verifyPKCESupport(metadata: OAuthMetadata): {
|
|
52
|
+
supported: boolean;
|
|
53
|
+
advertised: boolean;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Register client using Dynamic Client Registration
|
|
57
|
+
* Per RFC 7591
|
|
58
|
+
*/
|
|
59
|
+
export declare function registerClient(registrationEndpoint: string, request: ClientRegistrationRequest): Promise<ClientInfo>;
|
|
60
|
+
/**
|
|
61
|
+
* Build authorization URL with all required parameters
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildAuthorizationUrl(params: {
|
|
64
|
+
authorizationEndpoint: string;
|
|
65
|
+
clientId: string;
|
|
66
|
+
redirectUri: string;
|
|
67
|
+
state: string;
|
|
68
|
+
codeChallenge: string;
|
|
69
|
+
codeChallengeMethod: string;
|
|
70
|
+
scope?: string;
|
|
71
|
+
resource?: string;
|
|
72
|
+
}): string;
|
|
73
|
+
/**
|
|
74
|
+
* Exchange authorization code for tokens
|
|
75
|
+
*/
|
|
76
|
+
export declare function exchangeCodeForTokens(params: {
|
|
77
|
+
tokenEndpoint: string;
|
|
78
|
+
code: string;
|
|
79
|
+
redirectUri: string;
|
|
80
|
+
clientId: string;
|
|
81
|
+
clientSecret?: string;
|
|
82
|
+
codeVerifier: string;
|
|
83
|
+
resource?: string;
|
|
84
|
+
}): Promise<TokenResponse>;
|
|
85
|
+
/**
|
|
86
|
+
* Refresh access token using refresh token
|
|
87
|
+
*/
|
|
88
|
+
export declare function refreshAccessToken(params: {
|
|
89
|
+
tokenEndpoint: string;
|
|
90
|
+
refreshToken: string;
|
|
91
|
+
clientId: string;
|
|
92
|
+
clientSecret?: string;
|
|
93
|
+
resource?: string;
|
|
94
|
+
}): Promise<TokenResponse>;
|
|
95
|
+
/**
|
|
96
|
+
* Get canonical resource URI for an MCP server
|
|
97
|
+
* Per RFC 8707 - Resource Indicators
|
|
98
|
+
*/
|
|
99
|
+
export declare function getCanonicalResourceUri(mcpServerUrl: string): string;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Utility Functions
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - PKCE (RFC 7636) with S256 method
|
|
6
|
+
* - Protected Resource Metadata Discovery (RFC 9728)
|
|
7
|
+
* - Authorization Server Metadata Discovery (RFC 8414)
|
|
8
|
+
* - Dynamic Client Registration (RFC 7591)
|
|
9
|
+
* - Token Exchange
|
|
10
|
+
*/
|
|
11
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
12
|
+
/**
|
|
13
|
+
* Generate PKCE parameters with S256 method
|
|
14
|
+
* Per MCP spec: MUST use S256 when technically capable
|
|
15
|
+
*/
|
|
16
|
+
export function generatePKCE() {
|
|
17
|
+
// Generate a random 32-byte code verifier (base64url encoded = 43 chars)
|
|
18
|
+
const codeVerifier = randomBytes(32).toString("base64url");
|
|
19
|
+
// Create S256 code challenge: BASE64URL(SHA256(code_verifier))
|
|
20
|
+
const hash = createHash("sha256").update(codeVerifier).digest();
|
|
21
|
+
const codeChallenge = hash.toString("base64url");
|
|
22
|
+
return {
|
|
23
|
+
codeVerifier,
|
|
24
|
+
codeChallenge,
|
|
25
|
+
codeChallengeMethod: "S256",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate a cryptographically secure state parameter
|
|
30
|
+
*/
|
|
31
|
+
export function generateState() {
|
|
32
|
+
return randomUUID();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate a session ID
|
|
36
|
+
*/
|
|
37
|
+
export function generateSessionId() {
|
|
38
|
+
return randomUUID();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse WWW-Authenticate header to extract resource_metadata URL
|
|
42
|
+
* Example: Bearer realm="mcp", resource_metadata="http://.../.well-known/oauth-protected-resource"
|
|
43
|
+
*/
|
|
44
|
+
export function parseWWWAuthenticate(header) {
|
|
45
|
+
const result = {};
|
|
46
|
+
// Extract realm
|
|
47
|
+
const realmMatch = header.match(/realm="([^"]+)"/);
|
|
48
|
+
if (realmMatch) {
|
|
49
|
+
result.realm = realmMatch[1];
|
|
50
|
+
}
|
|
51
|
+
// Extract resource_metadata
|
|
52
|
+
const metadataMatch = header.match(/resource_metadata="([^"]+)"/);
|
|
53
|
+
if (metadataMatch) {
|
|
54
|
+
result.resourceMetadataUrl = metadataMatch[1];
|
|
55
|
+
}
|
|
56
|
+
// Extract scope
|
|
57
|
+
const scopeMatch = header.match(/scope="([^"]+)"/);
|
|
58
|
+
if (scopeMatch) {
|
|
59
|
+
result.scope = scopeMatch[1];
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Discover Protected Resource Metadata from an MCP server
|
|
65
|
+
* Per RFC 9728 and MCP spec
|
|
66
|
+
*/
|
|
67
|
+
export async function discoverProtectedResourceMetadata(mcpServerUrl) {
|
|
68
|
+
const serverUrl = new URL(mcpServerUrl);
|
|
69
|
+
// First, try to get 401 with WWW-Authenticate header
|
|
70
|
+
const probeResponse = await fetch(mcpServerUrl, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: { "Content-Type": "application/json" },
|
|
73
|
+
body: JSON.stringify({}),
|
|
74
|
+
});
|
|
75
|
+
if (probeResponse.status === 401) {
|
|
76
|
+
const authHeader = probeResponse.headers.get("www-authenticate");
|
|
77
|
+
if (authHeader) {
|
|
78
|
+
const parsed = parseWWWAuthenticate(authHeader);
|
|
79
|
+
if (parsed.resourceMetadataUrl) {
|
|
80
|
+
const metadataResponse = await fetch(parsed.resourceMetadataUrl);
|
|
81
|
+
if (metadataResponse.ok) {
|
|
82
|
+
return (await metadataResponse.json());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Fallback: try well-known URIs
|
|
88
|
+
// Try path-specific first, then root
|
|
89
|
+
const wellKnownPaths = [
|
|
90
|
+
`${serverUrl.origin}/.well-known/oauth-protected-resource${serverUrl.pathname}`,
|
|
91
|
+
`${serverUrl.origin}/.well-known/oauth-protected-resource`,
|
|
92
|
+
];
|
|
93
|
+
for (const path of wellKnownPaths) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch(path);
|
|
96
|
+
if (response.ok) {
|
|
97
|
+
return (await response.json());
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (_a) {
|
|
101
|
+
// Continue to next path
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`Could not discover protected resource metadata for ${mcpServerUrl}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Discover Authorization Server Metadata
|
|
108
|
+
* Per RFC 8414 and OpenID Connect Discovery 1.0
|
|
109
|
+
*/
|
|
110
|
+
export async function discoverAuthServerMetadata(authServerUrl) {
|
|
111
|
+
const serverUrl = new URL(authServerUrl);
|
|
112
|
+
const hasPath = serverUrl.pathname && serverUrl.pathname !== "/";
|
|
113
|
+
// Build discovery URLs based on MCP spec priority order
|
|
114
|
+
const discoveryUrls = [];
|
|
115
|
+
if (hasPath) {
|
|
116
|
+
// For URLs with path components (e.g., https://auth.example.com/tenant1)
|
|
117
|
+
const pathWithoutLeadingSlash = serverUrl.pathname.replace(/^\//, "");
|
|
118
|
+
// 1. OAuth 2.0 Authorization Server Metadata with path insertion
|
|
119
|
+
discoveryUrls.push(`${serverUrl.origin}/.well-known/oauth-authorization-server/${pathWithoutLeadingSlash}`);
|
|
120
|
+
// 2. OpenID Connect Discovery 1.0 with path insertion
|
|
121
|
+
discoveryUrls.push(`${serverUrl.origin}/.well-known/openid-configuration/${pathWithoutLeadingSlash}`);
|
|
122
|
+
// 3. OpenID Connect Discovery 1.0 path appending
|
|
123
|
+
discoveryUrls.push(`${authServerUrl}/.well-known/openid-configuration`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// For URLs without path components
|
|
127
|
+
// 1. OAuth 2.0 Authorization Server Metadata
|
|
128
|
+
discoveryUrls.push(`${serverUrl.origin}/.well-known/oauth-authorization-server`);
|
|
129
|
+
// 2. OpenID Connect Discovery 1.0
|
|
130
|
+
discoveryUrls.push(`${serverUrl.origin}/.well-known/openid-configuration`);
|
|
131
|
+
}
|
|
132
|
+
for (const url of discoveryUrls) {
|
|
133
|
+
try {
|
|
134
|
+
const response = await fetch(url);
|
|
135
|
+
if (response.ok) {
|
|
136
|
+
const metadata = (await response.json());
|
|
137
|
+
return metadata;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (_a) {
|
|
141
|
+
// Continue to next URL
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
throw new Error(`Could not discover authorization server metadata for ${authServerUrl}`);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Verify that the authorization server supports PKCE with S256
|
|
148
|
+
* Per MCP spec: MUST refuse to proceed if PKCE not supported
|
|
149
|
+
*
|
|
150
|
+
* Note: Many servers don't advertise code_challenge_methods_supported but still support PKCE.
|
|
151
|
+
* We return { supported: boolean, advertised: boolean } to allow callers to decide.
|
|
152
|
+
*/
|
|
153
|
+
export function verifyPKCESupport(metadata) {
|
|
154
|
+
const methods = metadata.code_challenge_methods_supported;
|
|
155
|
+
if (!methods || methods.length === 0) {
|
|
156
|
+
// Not advertised, but might still be supported
|
|
157
|
+
return { supported: true, advertised: false };
|
|
158
|
+
}
|
|
159
|
+
return { supported: methods.includes("S256"), advertised: true };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Register client using Dynamic Client Registration
|
|
163
|
+
* Per RFC 7591
|
|
164
|
+
*/
|
|
165
|
+
export async function registerClient(registrationEndpoint, request) {
|
|
166
|
+
const response = await fetch(registrationEndpoint, {
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: {
|
|
169
|
+
"Content-Type": "application/json",
|
|
170
|
+
},
|
|
171
|
+
body: JSON.stringify(request),
|
|
172
|
+
});
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
const error = await response.text();
|
|
175
|
+
throw new Error(`Client registration failed: ${response.status} ${error}`);
|
|
176
|
+
}
|
|
177
|
+
return (await response.json());
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Build authorization URL with all required parameters
|
|
181
|
+
*/
|
|
182
|
+
export function buildAuthorizationUrl(params) {
|
|
183
|
+
const url = new URL(params.authorizationEndpoint);
|
|
184
|
+
url.searchParams.set("response_type", "code");
|
|
185
|
+
url.searchParams.set("client_id", params.clientId);
|
|
186
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
187
|
+
url.searchParams.set("state", params.state);
|
|
188
|
+
url.searchParams.set("code_challenge", params.codeChallenge);
|
|
189
|
+
url.searchParams.set("code_challenge_method", params.codeChallengeMethod);
|
|
190
|
+
if (params.scope) {
|
|
191
|
+
url.searchParams.set("scope", params.scope);
|
|
192
|
+
}
|
|
193
|
+
// Resource parameter per RFC 8707
|
|
194
|
+
if (params.resource) {
|
|
195
|
+
url.searchParams.set("resource", params.resource);
|
|
196
|
+
}
|
|
197
|
+
return url.toString();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Exchange authorization code for tokens
|
|
201
|
+
*/
|
|
202
|
+
export async function exchangeCodeForTokens(params) {
|
|
203
|
+
const body = new URLSearchParams();
|
|
204
|
+
body.set("grant_type", "authorization_code");
|
|
205
|
+
body.set("code", params.code);
|
|
206
|
+
body.set("redirect_uri", params.redirectUri);
|
|
207
|
+
body.set("client_id", params.clientId);
|
|
208
|
+
body.set("code_verifier", params.codeVerifier);
|
|
209
|
+
if (params.clientSecret) {
|
|
210
|
+
body.set("client_secret", params.clientSecret);
|
|
211
|
+
}
|
|
212
|
+
if (params.resource) {
|
|
213
|
+
body.set("resource", params.resource);
|
|
214
|
+
}
|
|
215
|
+
const response = await fetch(params.tokenEndpoint, {
|
|
216
|
+
method: "POST",
|
|
217
|
+
headers: {
|
|
218
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
219
|
+
},
|
|
220
|
+
body: body.toString(),
|
|
221
|
+
});
|
|
222
|
+
if (!response.ok) {
|
|
223
|
+
const error = await response.text();
|
|
224
|
+
throw new Error(`Token exchange failed: ${response.status} ${error}`);
|
|
225
|
+
}
|
|
226
|
+
return (await response.json());
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Refresh access token using refresh token
|
|
230
|
+
*/
|
|
231
|
+
export async function refreshAccessToken(params) {
|
|
232
|
+
const body = new URLSearchParams();
|
|
233
|
+
body.set("grant_type", "refresh_token");
|
|
234
|
+
body.set("refresh_token", params.refreshToken);
|
|
235
|
+
body.set("client_id", params.clientId);
|
|
236
|
+
if (params.clientSecret) {
|
|
237
|
+
body.set("client_secret", params.clientSecret);
|
|
238
|
+
}
|
|
239
|
+
if (params.resource) {
|
|
240
|
+
body.set("resource", params.resource);
|
|
241
|
+
}
|
|
242
|
+
const response = await fetch(params.tokenEndpoint, {
|
|
243
|
+
method: "POST",
|
|
244
|
+
headers: {
|
|
245
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
246
|
+
},
|
|
247
|
+
body: body.toString(),
|
|
248
|
+
});
|
|
249
|
+
if (!response.ok) {
|
|
250
|
+
const error = await response.text();
|
|
251
|
+
throw new Error(`Token refresh failed: ${response.status} ${error}`);
|
|
252
|
+
}
|
|
253
|
+
return (await response.json());
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get canonical resource URI for an MCP server
|
|
257
|
+
* Per RFC 8707 - Resource Indicators
|
|
258
|
+
*/
|
|
259
|
+
export function getCanonicalResourceUri(mcpServerUrl) {
|
|
260
|
+
const url = new URL(mcpServerUrl);
|
|
261
|
+
// Remove trailing slash unless semantically significant
|
|
262
|
+
let resource = `${url.protocol}//${url.host}${url.pathname}`;
|
|
263
|
+
if (resource.endsWith("/") && resource !== `${url.protocol}//${url.host}/`) {
|
|
264
|
+
resource = resource.slice(0, -1);
|
|
265
|
+
}
|
|
266
|
+
return resource;
|
|
267
|
+
}
|
|
@@ -7,12 +7,12 @@ export declare const packageHandler: {
|
|
|
7
7
|
code: number;
|
|
8
8
|
message: string;
|
|
9
9
|
}>;
|
|
10
|
-
executeTool: (packageName: string, toolKey: string, inputData: Record<string, unknown>, envs?: Record<string, string>, sandboxProvider?: MCPSandboxProvider) => Promise<{
|
|
10
|
+
executeTool: (packageName: string, toolKey: string, inputData: Record<string, unknown>, envs?: Record<string, string>, sandboxProvider?: MCPSandboxProvider, accessToken?: string) => Promise<{
|
|
11
11
|
success: boolean;
|
|
12
12
|
code: number;
|
|
13
13
|
message: string;
|
|
14
14
|
}>;
|
|
15
|
-
listTools: (packageName: string, sandboxProvider?: MCPSandboxProvider) => Promise<{
|
|
15
|
+
listTools: (packageName: string, sandboxProvider?: MCPSandboxProvider, accessToken?: string) => Promise<{
|
|
16
16
|
success: boolean;
|
|
17
17
|
code: number;
|
|
18
18
|
message: string;
|
|
@@ -22,11 +22,11 @@ export const packageHandler = {
|
|
|
22
22
|
throw error;
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
executeTool: async (packageName, toolKey, inputData, envs, sandboxProvider) => {
|
|
25
|
+
executeTool: async (packageName, toolKey, inputData, envs, sandboxProvider, accessToken) => {
|
|
26
26
|
try {
|
|
27
27
|
const executor = ExecutorFactory.create(sandboxProvider);
|
|
28
28
|
const packageSO = await PackageSO.init(packageName, repository, executor);
|
|
29
|
-
const result = await packageSO.executeTool(toolKey, inputData, envs);
|
|
29
|
+
const result = await packageSO.executeTool(toolKey, inputData, envs, accessToken);
|
|
30
30
|
return createResponse(result);
|
|
31
31
|
}
|
|
32
32
|
catch (error) {
|
|
@@ -42,11 +42,11 @@ export const packageHandler = {
|
|
|
42
42
|
throw error;
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
-
listTools: async (packageName, sandboxProvider) => {
|
|
45
|
+
listTools: async (packageName, sandboxProvider, accessToken) => {
|
|
46
46
|
try {
|
|
47
47
|
const executor = ExecutorFactory.create(sandboxProvider);
|
|
48
48
|
const packageSO = await PackageSO.init(packageName, repository, executor);
|
|
49
|
-
const tools = await packageSO.getTools();
|
|
49
|
+
const tools = await packageSO.getTools(accessToken);
|
|
50
50
|
return createResponse(tools);
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
@@ -2,7 +2,7 @@ import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
|
|
2
2
|
import { createResponse, createRouteResponses } from "../../shared/utils/response-util";
|
|
3
3
|
import { getPythonDependencies } from "../../shared/utils/validation-util";
|
|
4
4
|
import { packageHandler } from "./package-handler";
|
|
5
|
-
import { ExecuteToolResponseSchema, PackageDetailResponseSchema, PackagesListResponseSchema, packageNameQuerySchema, ToolExecuteSchema, ToolsResponseSchema, } from "./package-schema";
|
|
5
|
+
import { ExecuteToolResponseSchema, PackageDetailResponseSchema, PackagesListResponseSchema, packageNameQuerySchema, ToolExecuteSchema, ToolsResponseSchema, toolsQuerySchema, } from "./package-schema";
|
|
6
6
|
export const packageRoutes = new OpenAPIHono();
|
|
7
7
|
const packageDetailRoute = createRoute({
|
|
8
8
|
method: "get",
|
|
@@ -20,14 +20,14 @@ packageRoutes.openapi(packageDetailRoute, async (c) => {
|
|
|
20
20
|
const toolsRoute = createRoute({
|
|
21
21
|
method: "get",
|
|
22
22
|
path: "/packages/tools",
|
|
23
|
-
request: { query:
|
|
23
|
+
request: { query: toolsQuerySchema },
|
|
24
24
|
responses: createRouteResponses(ToolsResponseSchema, {
|
|
25
25
|
includeErrorResponses: true,
|
|
26
26
|
}),
|
|
27
27
|
});
|
|
28
28
|
packageRoutes.openapi(toolsRoute, async (c) => {
|
|
29
|
-
const { packageName, sandboxProvider } = c.req.valid("query");
|
|
30
|
-
const result = await packageHandler.listTools(packageName, sandboxProvider);
|
|
29
|
+
const { packageName, sandboxProvider, accessToken } = c.req.valid("query");
|
|
30
|
+
const result = await packageHandler.listTools(packageName, sandboxProvider, accessToken);
|
|
31
31
|
return c.json(result, 200);
|
|
32
32
|
});
|
|
33
33
|
const executeToolRoute = createRoute({
|
|
@@ -49,7 +49,7 @@ const executeToolRoute = createRoute({
|
|
|
49
49
|
});
|
|
50
50
|
packageRoutes.openapi(executeToolRoute, async (c) => {
|
|
51
51
|
const body = c.req.valid("json");
|
|
52
|
-
const result = await packageHandler.executeTool(body.packageName, body.toolKey, body.inputData, body.envs, body.sandboxProvider);
|
|
52
|
+
const result = await packageHandler.executeTool(body.packageName, body.toolKey, body.inputData, body.envs, body.sandboxProvider, body.accessToken);
|
|
53
53
|
return c.json(result, 200);
|
|
54
54
|
});
|
|
55
55
|
const packagesListRoute = createRoute({
|
|
@@ -9,23 +9,40 @@ export declare const packageNameQuerySchema: z.ZodObject<{
|
|
|
9
9
|
packageName: string;
|
|
10
10
|
sandboxProvider?: "SANDOCK" | "DAYTONA" | "E2B" | "LOCAL" | undefined;
|
|
11
11
|
}>;
|
|
12
|
+
export declare const toolsQuerySchema: z.ZodObject<{
|
|
13
|
+
packageName: z.ZodString;
|
|
14
|
+
sandboxProvider: z.ZodOptional<z.ZodEnum<["LOCAL", "DAYTONA", "SANDOCK", "E2B"]>>;
|
|
15
|
+
} & {
|
|
16
|
+
accessToken: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
packageName: string;
|
|
19
|
+
accessToken?: string | undefined;
|
|
20
|
+
sandboxProvider?: "SANDOCK" | "DAYTONA" | "E2B" | "LOCAL" | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
packageName: string;
|
|
23
|
+
accessToken?: string | undefined;
|
|
24
|
+
sandboxProvider?: "SANDOCK" | "DAYTONA" | "E2B" | "LOCAL" | undefined;
|
|
25
|
+
}>;
|
|
12
26
|
export declare const ToolExecuteSchema: z.ZodObject<{
|
|
13
27
|
packageName: z.ZodString;
|
|
14
28
|
toolKey: z.ZodString;
|
|
15
29
|
inputData: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
16
30
|
envs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
17
31
|
sandboxProvider: z.ZodOptional<z.ZodEnum<["LOCAL", "DAYTONA", "SANDOCK", "E2B"]>>;
|
|
32
|
+
accessToken: z.ZodOptional<z.ZodString>;
|
|
18
33
|
}, "strip", z.ZodTypeAny, {
|
|
19
34
|
packageName: string;
|
|
20
35
|
toolKey: string;
|
|
21
36
|
inputData: Record<string, unknown>;
|
|
22
37
|
envs?: Record<string, string> | undefined;
|
|
38
|
+
accessToken?: string | undefined;
|
|
23
39
|
sandboxProvider?: "SANDOCK" | "DAYTONA" | "E2B" | "LOCAL" | undefined;
|
|
24
40
|
}, {
|
|
25
41
|
packageName: string;
|
|
26
42
|
toolKey: string;
|
|
27
43
|
inputData: Record<string, unknown>;
|
|
28
44
|
envs?: Record<string, string> | undefined;
|
|
45
|
+
accessToken?: string | undefined;
|
|
29
46
|
sandboxProvider?: "SANDOCK" | "DAYTONA" | "E2B" | "LOCAL" | undefined;
|
|
30
47
|
}>;
|
|
31
48
|
export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
@@ -43,12 +60,30 @@ export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
|
43
60
|
remotes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
44
61
|
type: z.ZodLiteral<"streamable-http">;
|
|
45
62
|
url: z.ZodString;
|
|
63
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
64
|
+
type: z.ZodEnum<["oauth2"]>;
|
|
65
|
+
scopes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
type: "oauth2";
|
|
68
|
+
scopes?: string[] | undefined;
|
|
69
|
+
}, {
|
|
70
|
+
type: "oauth2";
|
|
71
|
+
scopes?: string[] | undefined;
|
|
72
|
+
}>>;
|
|
46
73
|
}, "strip", z.ZodTypeAny, {
|
|
47
74
|
type: "streamable-http";
|
|
48
75
|
url: string;
|
|
76
|
+
auth?: {
|
|
77
|
+
type: "oauth2";
|
|
78
|
+
scopes?: string[] | undefined;
|
|
79
|
+
} | undefined;
|
|
49
80
|
}, {
|
|
50
81
|
type: "streamable-http";
|
|
51
82
|
url: string;
|
|
83
|
+
auth?: {
|
|
84
|
+
type: "oauth2";
|
|
85
|
+
scopes?: string[] | undefined;
|
|
86
|
+
} | undefined;
|
|
52
87
|
}>, "many">>;
|
|
53
88
|
key: z.ZodOptional<z.ZodString>;
|
|
54
89
|
name: z.ZodOptional<z.ZodString>;
|
|
@@ -116,6 +151,10 @@ export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
|
116
151
|
remotes?: {
|
|
117
152
|
type: "streamable-http";
|
|
118
153
|
url: string;
|
|
154
|
+
auth?: {
|
|
155
|
+
type: "oauth2";
|
|
156
|
+
scopes?: string[] | undefined;
|
|
157
|
+
} | undefined;
|
|
119
158
|
}[] | undefined;
|
|
120
159
|
readme?: string | undefined;
|
|
121
160
|
license?: string | undefined;
|
|
@@ -148,6 +187,10 @@ export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
|
148
187
|
remotes?: {
|
|
149
188
|
type: "streamable-http";
|
|
150
189
|
url: string;
|
|
190
|
+
auth?: {
|
|
191
|
+
type: "oauth2";
|
|
192
|
+
scopes?: string[] | undefined;
|
|
193
|
+
} | undefined;
|
|
151
194
|
}[] | undefined;
|
|
152
195
|
readme?: string | undefined;
|
|
153
196
|
license?: string | undefined;
|
|
@@ -185,6 +228,10 @@ export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
|
185
228
|
remotes?: {
|
|
186
229
|
type: "streamable-http";
|
|
187
230
|
url: string;
|
|
231
|
+
auth?: {
|
|
232
|
+
type: "oauth2";
|
|
233
|
+
scopes?: string[] | undefined;
|
|
234
|
+
} | undefined;
|
|
188
235
|
}[] | undefined;
|
|
189
236
|
readme?: string | undefined;
|
|
190
237
|
license?: string | undefined;
|
|
@@ -222,6 +269,10 @@ export declare const PackageDetailResponseSchema: z.ZodObject<{
|
|
|
222
269
|
remotes?: {
|
|
223
270
|
type: "streamable-http";
|
|
224
271
|
url: string;
|
|
272
|
+
auth?: {
|
|
273
|
+
type: "oauth2";
|
|
274
|
+
scopes?: string[] | undefined;
|
|
275
|
+
} | undefined;
|
|
225
276
|
}[] | undefined;
|
|
226
277
|
readme?: string | undefined;
|
|
227
278
|
license?: string | undefined;
|
|
@@ -18,6 +18,16 @@ export const packageNameQuerySchema = z.object({
|
|
|
18
18
|
description: "Optional sandbox provider to override default (LOCAL, DAYTONA, SANDOCK, E2B)",
|
|
19
19
|
}),
|
|
20
20
|
});
|
|
21
|
+
export const toolsQuerySchema = packageNameQuerySchema.extend({
|
|
22
|
+
accessToken: z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.openapi({
|
|
26
|
+
param: { name: "accessToken", in: "query" },
|
|
27
|
+
description: "OAuth access token for MCP servers that require OAuth authentication. " +
|
|
28
|
+
"This token will be included in the Authorization header when calling the MCP server.",
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
21
31
|
export const ToolExecuteSchema = z
|
|
22
32
|
.object({
|
|
23
33
|
packageName: z.string().openapi({ example: "@modelcontextprotocol/server-filesystem" }),
|
|
@@ -28,6 +38,13 @@ export const ToolExecuteSchema = z
|
|
|
28
38
|
example: "LOCAL",
|
|
29
39
|
description: "Optional sandbox provider to override default (LOCAL, DAYTONA, SANDOCK, E2B)",
|
|
30
40
|
}),
|
|
41
|
+
accessToken: z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.openapi({
|
|
45
|
+
description: "OAuth access token for MCP servers that require OAuth authentication. " +
|
|
46
|
+
"This token will be included in the Authorization header when calling the MCP server.",
|
|
47
|
+
}),
|
|
31
48
|
})
|
|
32
49
|
.openapi("ToolExecute");
|
|
33
50
|
const ToolDataSchema = z.object({
|
|
@@ -27,6 +27,10 @@ export declare class PackageSO {
|
|
|
27
27
|
remotes?: {
|
|
28
28
|
type: "streamable-http";
|
|
29
29
|
url: string;
|
|
30
|
+
auth?: {
|
|
31
|
+
type: "oauth2";
|
|
32
|
+
scopes?: string[] | undefined;
|
|
33
|
+
} | undefined;
|
|
30
34
|
}[] | undefined;
|
|
31
35
|
readme?: string | undefined;
|
|
32
36
|
license?: string | undefined;
|
|
@@ -38,7 +42,7 @@ export declare class PackageSO {
|
|
|
38
42
|
}> | undefined;
|
|
39
43
|
};
|
|
40
44
|
static init(packageName: string, repository: PackageRepository, executor: ToolExecutor): Promise<PackageSO>;
|
|
41
|
-
getTools(): Promise<Tool[]>;
|
|
42
|
-
executeTool(toolKey: string, inputData: Record<string, unknown>, envs?: Record<string, string
|
|
45
|
+
getTools(accessToken?: string): Promise<Tool[]>;
|
|
46
|
+
executeTool(toolKey: string, inputData: Record<string, unknown>, envs?: Record<string, string>, accessToken?: string): Promise<unknown>;
|
|
43
47
|
getDetailWithTools(): Promise<MCPServerPackageConfigWithTools>;
|
|
44
48
|
}
|
|
@@ -36,15 +36,16 @@ export class PackageSO {
|
|
|
36
36
|
const packageInfo = allPackages[packageName] || {};
|
|
37
37
|
return new PackageSO(packageName, config, packageInfo, executor);
|
|
38
38
|
}
|
|
39
|
-
async getTools() {
|
|
40
|
-
return await this._executor.listTools(this.packageName);
|
|
39
|
+
async getTools(accessToken) {
|
|
40
|
+
return await this._executor.listTools(this.packageName, accessToken);
|
|
41
41
|
}
|
|
42
|
-
async executeTool(toolKey, inputData, envs) {
|
|
42
|
+
async executeTool(toolKey, inputData, envs, accessToken) {
|
|
43
43
|
return await this._executor.executeTool({
|
|
44
44
|
packageName: this.packageName,
|
|
45
45
|
toolKey,
|
|
46
46
|
inputData,
|
|
47
47
|
envs,
|
|
48
|
+
accessToken,
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
51
|
async getDetailWithTools() {
|