@olane/o-mcp 0.7.1 → 0.7.2
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/src/mcp.tool.d.ts +1 -1
- package/dist/src/mcp.tool.d.ts.map +1 -1
- package/dist/src/methods/mcp-bridge.methods.js +1 -1
- package/dist/src/oauth/index.d.ts +8 -0
- package/dist/src/oauth/index.d.ts.map +1 -0
- package/dist/src/oauth/index.js +7 -0
- package/dist/src/oauth/interfaces/client-metadata.interface.d.ts +17 -0
- package/dist/src/oauth/interfaces/client-metadata.interface.d.ts.map +1 -0
- package/dist/src/oauth/interfaces/client-metadata.interface.js +1 -0
- package/dist/src/oauth/interfaces/index.d.ts +4 -0
- package/dist/src/oauth/interfaces/index.d.ts.map +1 -0
- package/dist/src/oauth/interfaces/index.js +3 -0
- package/dist/src/oauth/interfaces/oauth-client-info.interface.d.ts +12 -0
- package/dist/src/oauth/interfaces/oauth-client-info.interface.d.ts.map +1 -0
- package/dist/src/oauth/interfaces/oauth-client-info.interface.js +1 -0
- package/dist/src/oauth/interfaces/oauth-tokens.interface.d.ts +10 -0
- package/dist/src/oauth/interfaces/oauth-tokens.interface.d.ts.map +1 -0
- package/dist/src/oauth/interfaces/oauth-tokens.interface.js +1 -0
- package/dist/src/oauth/mcp-dynamic-registration.d.ts +33 -0
- package/dist/src/oauth/mcp-dynamic-registration.d.ts.map +1 -0
- package/dist/src/oauth/mcp-dynamic-registration.js +107 -0
- package/dist/src/oauth/mcp-oauth-callback-server.d.ts +51 -0
- package/dist/src/oauth/mcp-oauth-callback-server.d.ts.map +1 -0
- package/dist/src/oauth/mcp-oauth-callback-server.js +179 -0
- package/dist/src/oauth/mcp-oauth-manager.d.ts +61 -0
- package/dist/src/oauth/mcp-oauth-manager.d.ts.map +1 -0
- package/dist/src/oauth/mcp-oauth-manager.js +289 -0
- package/dist/src/oauth/mcp-oauth-storage.d.ts +60 -0
- package/dist/src/oauth/mcp-oauth-storage.d.ts.map +1 -0
- package/dist/src/oauth/mcp-oauth-storage.js +146 -0
- package/dist/src/oauth/methods/mcp-oauth.methods.d.ts +5 -0
- package/dist/src/oauth/methods/mcp-oauth.methods.d.ts.map +1 -0
- package/dist/src/oauth/methods/mcp-oauth.methods.js +99 -0
- package/dist/src/oauth/oauth-aware-transport.d.ts +50 -0
- package/dist/src/oauth/oauth-aware-transport.d.ts.map +1 -0
- package/dist/src/oauth/oauth-aware-transport.js +120 -0
- package/package.json +20 -15
package/dist/src/mcp.tool.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
|
3
3
|
import { oLaneTool } from '@olane/o-lane';
|
|
4
4
|
import { oNodeToolConfig } from '@olane/o-node';
|
|
5
5
|
export declare class McpTool extends oLaneTool {
|
|
6
|
-
|
|
6
|
+
protected mcpClient: Client;
|
|
7
7
|
constructor(config: oNodeToolConfig & {
|
|
8
8
|
address: oAddress;
|
|
9
9
|
mcpClient: Client;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.tool.d.ts","sourceRoot":"","sources":["../../src/mcp.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAiC,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,qBAAa,OAAQ,SAAQ,SAAS;IACpC,
|
|
1
|
+
{"version":3,"file":"mcp.tool.d.ts","sourceRoot":"","sources":["../../src/mcp.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAiC,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,qBAAa,OAAQ,SAAQ,SAAS;IACpC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;gBAG1B,MAAM,EAAE,eAAe,GAAG;QAAE,OAAO,EAAE,QAAQ,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAa9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC3B,OAAO;IAQP,KAAK;;;;;;;IAuBL,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC;CAoB7B"}
|
|
@@ -78,7 +78,7 @@ export const MCP_BRIDGE_METHODS = {
|
|
|
78
78
|
},
|
|
79
79
|
add_local_server: {
|
|
80
80
|
name: 'add_local_server',
|
|
81
|
-
description: 'Add a local MCP server to the bridge using command and arguments',
|
|
81
|
+
description: 'Add a local MCP server to the bridge using command and arguments. If a command line argument is provided, use this method.',
|
|
82
82
|
dependencies: [],
|
|
83
83
|
parameters: [
|
|
84
84
|
{
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './interfaces/index.js';
|
|
2
|
+
export * from './mcp-oauth-storage.js';
|
|
3
|
+
export * from './mcp-oauth-callback-server.js';
|
|
4
|
+
export * from './mcp-dynamic-registration.js';
|
|
5
|
+
export * from './oauth-aware-transport.js';
|
|
6
|
+
export * from './mcp-oauth-manager.js';
|
|
7
|
+
export * from './methods/mcp-oauth.methods.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/oauth/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './interfaces/index.js';
|
|
2
|
+
export * from './mcp-oauth-storage.js';
|
|
3
|
+
export * from './mcp-oauth-callback-server.js';
|
|
4
|
+
export * from './mcp-dynamic-registration.js';
|
|
5
|
+
export * from './oauth-aware-transport.js';
|
|
6
|
+
export * from './mcp-oauth-manager.js';
|
|
7
|
+
export * from './methods/mcp-oauth.methods.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ClientMetadata {
|
|
2
|
+
client_name: string;
|
|
3
|
+
redirect_uris: string[];
|
|
4
|
+
grant_types?: string[];
|
|
5
|
+
response_types?: string[];
|
|
6
|
+
scope?: string;
|
|
7
|
+
token_endpoint_auth_method?: string;
|
|
8
|
+
application_type?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface StaticOAuthClientInfo {
|
|
11
|
+
client_id: string;
|
|
12
|
+
client_secret?: string;
|
|
13
|
+
authorization_endpoint?: string;
|
|
14
|
+
token_endpoint?: string;
|
|
15
|
+
scope?: string;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=client-metadata.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-metadata.interface.d.ts","sourceRoot":"","sources":["../../../../src/oauth/interfaces/client-metadata.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/oauth/interfaces/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface OAuthClientInfo {
|
|
2
|
+
client_id: string;
|
|
3
|
+
client_secret?: string;
|
|
4
|
+
authorization_endpoint: string;
|
|
5
|
+
token_endpoint: string;
|
|
6
|
+
registration_endpoint?: string;
|
|
7
|
+
scope?: string;
|
|
8
|
+
redirect_uris?: string[];
|
|
9
|
+
grant_types?: string[];
|
|
10
|
+
response_types?: string[];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=oauth-client-info.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-client-info.interface.d.ts","sourceRoot":"","sources":["../../../../src/oauth/interfaces/oauth-client-info.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-tokens.interface.d.ts","sourceRoot":"","sources":["../../../../src/oauth/interfaces/oauth-tokens.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { OAuthClientInfo } from './interfaces/oauth-client-info.interface.js';
|
|
2
|
+
import { ClientMetadata } from './interfaces/client-metadata.interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* Implements RFC 7591 Dynamic Client Registration for OAuth 2.0
|
|
5
|
+
*
|
|
6
|
+
* This class handles automatic registration of OAuth clients with remote servers
|
|
7
|
+
* that support dynamic client registration.
|
|
8
|
+
*/
|
|
9
|
+
export declare class McpDynamicRegistration {
|
|
10
|
+
/**
|
|
11
|
+
* Register a new OAuth client dynamically
|
|
12
|
+
*/
|
|
13
|
+
registerClient(registrationEndpoint: string, clientMetadata: ClientMetadata): Promise<OAuthClientInfo>;
|
|
14
|
+
/**
|
|
15
|
+
* Discover OAuth endpoints from a server URL
|
|
16
|
+
* Tries to find .well-known/oauth-authorization-server or OpenID Connect discovery
|
|
17
|
+
*/
|
|
18
|
+
discoverEndpoints(serverUrl: string): Promise<{
|
|
19
|
+
authorization_endpoint?: string;
|
|
20
|
+
token_endpoint?: string;
|
|
21
|
+
registration_endpoint?: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Create client metadata for registration
|
|
25
|
+
*/
|
|
26
|
+
createClientMetadata(clientName: string, redirectUri: string, scope?: string): ClientMetadata;
|
|
27
|
+
/**
|
|
28
|
+
* Get or register an OAuth client
|
|
29
|
+
* Returns cached client info if available, otherwise performs registration
|
|
30
|
+
*/
|
|
31
|
+
getOrRegisterClient(serverUrl: string, clientName: string, redirectUri: string, existingClientInfo?: OAuthClientInfo | null, scope?: string): Promise<OAuthClientInfo>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=mcp-dynamic-registration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-dynamic-registration.d.ts","sourceRoot":"","sources":["../../../src/oauth/mcp-dynamic-registration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAE3E;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACG,cAAc,CAClB,oBAAoB,EAAE,MAAM,EAC5B,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,eAAe,CAAC;IAmC3B;;;OAGG;IACG,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAClD,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;IA0BF;;OAEG;IACH,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,cAAc;IAYjB;;;OAGG;IACG,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,kBAAkB,CAAC,EAAE,eAAe,GAAG,IAAI,EAC3C,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC;CAyC5B"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implements RFC 7591 Dynamic Client Registration for OAuth 2.0
|
|
3
|
+
*
|
|
4
|
+
* This class handles automatic registration of OAuth clients with remote servers
|
|
5
|
+
* that support dynamic client registration.
|
|
6
|
+
*/
|
|
7
|
+
export class McpDynamicRegistration {
|
|
8
|
+
/**
|
|
9
|
+
* Register a new OAuth client dynamically
|
|
10
|
+
*/
|
|
11
|
+
async registerClient(registrationEndpoint, clientMetadata) {
|
|
12
|
+
const response = await fetch(registrationEndpoint, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
Accept: 'application/json',
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify(clientMetadata),
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const errorText = await response.text();
|
|
22
|
+
throw new Error(`Dynamic client registration failed: ${response.status} ${errorText}`);
|
|
23
|
+
}
|
|
24
|
+
const registrationResponse = await response.json();
|
|
25
|
+
return {
|
|
26
|
+
client_id: registrationResponse.client_id,
|
|
27
|
+
client_secret: registrationResponse.client_secret,
|
|
28
|
+
authorization_endpoint: registrationResponse.authorization_endpoint ||
|
|
29
|
+
registrationResponse.authorization_url,
|
|
30
|
+
token_endpoint: registrationResponse.token_endpoint || registrationResponse.token_url,
|
|
31
|
+
registration_endpoint: registrationEndpoint,
|
|
32
|
+
scope: clientMetadata.scope,
|
|
33
|
+
redirect_uris: registrationResponse.redirect_uris,
|
|
34
|
+
grant_types: registrationResponse.grant_types,
|
|
35
|
+
response_types: registrationResponse.response_types,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Discover OAuth endpoints from a server URL
|
|
40
|
+
* Tries to find .well-known/oauth-authorization-server or OpenID Connect discovery
|
|
41
|
+
*/
|
|
42
|
+
async discoverEndpoints(serverUrl) {
|
|
43
|
+
const wellKnownUrls = [
|
|
44
|
+
`${serverUrl}/.well-known/oauth-authorization-server`,
|
|
45
|
+
`${serverUrl}/.well-known/openid-configuration`,
|
|
46
|
+
];
|
|
47
|
+
for (const wellKnownUrl of wellKnownUrls) {
|
|
48
|
+
try {
|
|
49
|
+
const response = await fetch(wellKnownUrl);
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
const discovery = await response.json();
|
|
52
|
+
return {
|
|
53
|
+
authorization_endpoint: discovery.authorization_endpoint,
|
|
54
|
+
token_endpoint: discovery.token_endpoint,
|
|
55
|
+
registration_endpoint: discovery.registration_endpoint,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// Try next well-known URL
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create client metadata for registration
|
|
68
|
+
*/
|
|
69
|
+
createClientMetadata(clientName, redirectUri, scope) {
|
|
70
|
+
return {
|
|
71
|
+
client_name: clientName,
|
|
72
|
+
redirect_uris: [redirectUri],
|
|
73
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
74
|
+
response_types: ['code'],
|
|
75
|
+
token_endpoint_auth_method: 'client_secret_basic',
|
|
76
|
+
application_type: 'native',
|
|
77
|
+
scope: scope || 'openid profile email',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get or register an OAuth client
|
|
82
|
+
* Returns cached client info if available, otherwise performs registration
|
|
83
|
+
*/
|
|
84
|
+
async getOrRegisterClient(serverUrl, clientName, redirectUri, existingClientInfo, scope) {
|
|
85
|
+
// Return existing client info if valid
|
|
86
|
+
if (existingClientInfo?.client_id) {
|
|
87
|
+
return existingClientInfo;
|
|
88
|
+
}
|
|
89
|
+
// Discover endpoints
|
|
90
|
+
const endpoints = await this.discoverEndpoints(serverUrl);
|
|
91
|
+
if (!endpoints.registration_endpoint) {
|
|
92
|
+
throw new Error(`No registration endpoint found for server: ${serverUrl}. ` +
|
|
93
|
+
`Please provide static OAuth client credentials instead.`);
|
|
94
|
+
}
|
|
95
|
+
if (!endpoints.authorization_endpoint || !endpoints.token_endpoint) {
|
|
96
|
+
throw new Error(`Could not discover OAuth endpoints for server: ${serverUrl}`);
|
|
97
|
+
}
|
|
98
|
+
// Create client metadata
|
|
99
|
+
const clientMetadata = this.createClientMetadata(clientName, redirectUri, scope);
|
|
100
|
+
// Register the client
|
|
101
|
+
const clientInfo = await this.registerClient(endpoints.registration_endpoint, clientMetadata);
|
|
102
|
+
// Add discovered endpoints
|
|
103
|
+
clientInfo.authorization_endpoint = endpoints.authorization_endpoint;
|
|
104
|
+
clientInfo.token_endpoint = endpoints.token_endpoint;
|
|
105
|
+
return clientInfo;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
interface CallbackResult {
|
|
2
|
+
code: string;
|
|
3
|
+
state?: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
error_description?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* HTTP server for handling OAuth callbacks
|
|
9
|
+
*
|
|
10
|
+
* This server runs locally to receive the OAuth redirect after user authorization.
|
|
11
|
+
* It automatically shuts down after receiving the callback.
|
|
12
|
+
*/
|
|
13
|
+
export declare class McpOAuthCallbackServer {
|
|
14
|
+
private app;
|
|
15
|
+
private server;
|
|
16
|
+
private port;
|
|
17
|
+
private events;
|
|
18
|
+
private callbackResult;
|
|
19
|
+
constructor(port?: number);
|
|
20
|
+
/**
|
|
21
|
+
* Setup Express routes
|
|
22
|
+
*/
|
|
23
|
+
private setupRoutes;
|
|
24
|
+
/**
|
|
25
|
+
* Start the callback server
|
|
26
|
+
*/
|
|
27
|
+
start(port?: number): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Stop the callback server
|
|
30
|
+
*/
|
|
31
|
+
stop(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Wait for OAuth callback
|
|
34
|
+
* @param timeout Timeout in milliseconds (default: 5 minutes)
|
|
35
|
+
*/
|
|
36
|
+
waitForCallback(timeout?: number): Promise<CallbackResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Get the callback URL
|
|
39
|
+
*/
|
|
40
|
+
getCallbackUrl(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get the current port
|
|
43
|
+
*/
|
|
44
|
+
getPort(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Check if server is running
|
|
47
|
+
*/
|
|
48
|
+
isRunning(): boolean;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=mcp-oauth-callback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-oauth-callback-server.d.ts","sourceRoot":"","sources":["../../../src/oauth/mcp-oauth-callback-server.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,GAAG,CAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAA+B;gBAEzC,IAAI,CAAC,EAAE,MAAM;IASzB;;OAEG;IACH,OAAO,CAAC,WAAW;IAoEnB;;OAEG;IACG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCzC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B;;;OAGG;IACG,eAAe,CAAC,OAAO,GAAE,MAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IA2BxE;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,SAAS,IAAI,OAAO;CAGrB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
/**
|
|
4
|
+
* HTTP server for handling OAuth callbacks
|
|
5
|
+
*
|
|
6
|
+
* This server runs locally to receive the OAuth redirect after user authorization.
|
|
7
|
+
* It automatically shuts down after receiving the callback.
|
|
8
|
+
*/
|
|
9
|
+
export class McpOAuthCallbackServer {
|
|
10
|
+
constructor(port) {
|
|
11
|
+
this.server = null;
|
|
12
|
+
this.port = 3334;
|
|
13
|
+
this.callbackResult = null;
|
|
14
|
+
if (port) {
|
|
15
|
+
this.port = port;
|
|
16
|
+
}
|
|
17
|
+
this.app = express();
|
|
18
|
+
this.events = new EventEmitter();
|
|
19
|
+
this.setupRoutes();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Setup Express routes
|
|
23
|
+
*/
|
|
24
|
+
setupRoutes() {
|
|
25
|
+
// OAuth callback endpoint
|
|
26
|
+
this.app.get('/oauth/callback', (req, res) => {
|
|
27
|
+
const { code, state, error, error_description } = req.query;
|
|
28
|
+
if (error) {
|
|
29
|
+
this.callbackResult = {
|
|
30
|
+
code: '',
|
|
31
|
+
error: error,
|
|
32
|
+
error_description: error_description,
|
|
33
|
+
};
|
|
34
|
+
res.send(`
|
|
35
|
+
<html>
|
|
36
|
+
<head><title>OAuth Error</title></head>
|
|
37
|
+
<body style="font-family: Arial, sans-serif; padding: 40px; text-align: center;">
|
|
38
|
+
<h1 style="color: #d32f2f;">Authentication Failed</h1>
|
|
39
|
+
<p style="color: #666;">Error: ${error}</p>
|
|
40
|
+
<p style="color: #666;">${error_description || ''}</p>
|
|
41
|
+
<p style="margin-top: 40px; color: #999;">You can close this window.</p>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
else if (code) {
|
|
47
|
+
this.callbackResult = {
|
|
48
|
+
code: code,
|
|
49
|
+
state: state,
|
|
50
|
+
};
|
|
51
|
+
res.send(`
|
|
52
|
+
<html>
|
|
53
|
+
<head><title>OAuth Success</title></head>
|
|
54
|
+
<body style="font-family: Arial, sans-serif; padding: 40px; text-align: center;">
|
|
55
|
+
<h1 style="color: #4caf50;">✓ Authentication Successful</h1>
|
|
56
|
+
<p style="color: #666;">You have successfully authenticated with the MCP server.</p>
|
|
57
|
+
<p style="margin-top: 40px; color: #999;">You can close this window.</p>
|
|
58
|
+
<script>
|
|
59
|
+
setTimeout(() => window.close(), 3000);
|
|
60
|
+
</script>
|
|
61
|
+
</body>
|
|
62
|
+
</html>
|
|
63
|
+
`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this.callbackResult = {
|
|
67
|
+
code: '',
|
|
68
|
+
error: 'invalid_request',
|
|
69
|
+
error_description: 'No code or error in callback',
|
|
70
|
+
};
|
|
71
|
+
res.status(400).send(`
|
|
72
|
+
<html>
|
|
73
|
+
<head><title>OAuth Error</title></head>
|
|
74
|
+
<body style="font-family: Arial, sans-serif; padding: 40px; text-align: center;">
|
|
75
|
+
<h1 style="color: #d32f2f;">Invalid Callback</h1>
|
|
76
|
+
<p style="color: #666;">The OAuth callback was missing required parameters.</p>
|
|
77
|
+
<p style="margin-top: 40px; color: #999;">You can close this window.</p>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
// Emit callback event
|
|
83
|
+
this.events.emit('callback', this.callbackResult);
|
|
84
|
+
});
|
|
85
|
+
// Health check endpoint
|
|
86
|
+
this.app.get('/health', (req, res) => {
|
|
87
|
+
res.json({ status: 'ok', port: this.port });
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Start the callback server
|
|
92
|
+
*/
|
|
93
|
+
async start(port) {
|
|
94
|
+
if (port) {
|
|
95
|
+
this.port = port;
|
|
96
|
+
}
|
|
97
|
+
if (this.server) {
|
|
98
|
+
throw new Error('Callback server is already running');
|
|
99
|
+
}
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
try {
|
|
102
|
+
this.server = this.app.listen(this.port, () => {
|
|
103
|
+
console.log(`OAuth callback server listening on http://localhost:${this.port}`);
|
|
104
|
+
resolve();
|
|
105
|
+
});
|
|
106
|
+
this.server.on('error', (error) => {
|
|
107
|
+
if (error.code === 'EADDRINUSE') {
|
|
108
|
+
reject(new Error(`Port ${this.port} is already in use. Please close other OAuth flows or choose a different port.`));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
reject(error);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
reject(error);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Stop the callback server
|
|
122
|
+
*/
|
|
123
|
+
async stop() {
|
|
124
|
+
if (!this.server) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
this.server.close((error) => {
|
|
129
|
+
if (error) {
|
|
130
|
+
reject(error);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.server = null;
|
|
134
|
+
this.callbackResult = null;
|
|
135
|
+
resolve();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Wait for OAuth callback
|
|
142
|
+
* @param timeout Timeout in milliseconds (default: 5 minutes)
|
|
143
|
+
*/
|
|
144
|
+
async waitForCallback(timeout = 300000) {
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
const timeoutId = setTimeout(() => {
|
|
147
|
+
this.events.removeAllListeners('callback');
|
|
148
|
+
reject(new Error('OAuth callback timeout. User did not complete authentication.'));
|
|
149
|
+
}, timeout);
|
|
150
|
+
this.events.once('callback', (result) => {
|
|
151
|
+
clearTimeout(timeoutId);
|
|
152
|
+
if (result.error) {
|
|
153
|
+
reject(new Error(`OAuth error: ${result.error}. ${result.error_description || ''}`));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
resolve(result);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get the callback URL
|
|
163
|
+
*/
|
|
164
|
+
getCallbackUrl() {
|
|
165
|
+
return `http://localhost:${this.port}/oauth/callback`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get the current port
|
|
169
|
+
*/
|
|
170
|
+
getPort() {
|
|
171
|
+
return this.port;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if server is running
|
|
175
|
+
*/
|
|
176
|
+
isRunning() {
|
|
177
|
+
return this.server !== null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { oRequest } from '@olane/o-core';
|
|
2
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
3
|
+
import { oNodeToolConfig } from '@olane/o-node';
|
|
4
|
+
import { ToolResult } from '@olane/o-tool';
|
|
5
|
+
/**
|
|
6
|
+
* MCP OAuth Manager Tool
|
|
7
|
+
*
|
|
8
|
+
* Coordinates OAuth authentication flows for MCP servers:
|
|
9
|
+
* - Dynamic client registration (RFC 7591)
|
|
10
|
+
* - PKCE authorization flow
|
|
11
|
+
* - Token storage and refresh
|
|
12
|
+
* - Callback server management
|
|
13
|
+
*/
|
|
14
|
+
export declare class McpOAuthManager extends oLaneTool {
|
|
15
|
+
private storage;
|
|
16
|
+
private callbackServer;
|
|
17
|
+
private dynamicRegistration;
|
|
18
|
+
private oauthToolAddress;
|
|
19
|
+
constructor(config: oNodeToolConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Authenticate with an OAuth-protected MCP server
|
|
22
|
+
*/
|
|
23
|
+
_tool_authenticate_server(request: oRequest): Promise<ToolResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Refresh OAuth tokens for an MCP server
|
|
26
|
+
*/
|
|
27
|
+
_tool_refresh_tokens(request: oRequest): Promise<ToolResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Check OAuth token status for an MCP server
|
|
30
|
+
*/
|
|
31
|
+
_tool_check_tokens(request: oRequest): Promise<ToolResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Clear OAuth tokens and client info for an MCP server
|
|
34
|
+
*/
|
|
35
|
+
_tool_clear_tokens(request: oRequest): Promise<ToolResult>;
|
|
36
|
+
/**
|
|
37
|
+
* List all authenticated MCP servers
|
|
38
|
+
*/
|
|
39
|
+
_tool_list_authenticated_servers(request: oRequest): Promise<ToolResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Public method for refreshing tokens (used by transport)
|
|
42
|
+
*/
|
|
43
|
+
refreshTokens(serverUrl: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Get service name for OAuth tool
|
|
46
|
+
*/
|
|
47
|
+
private getServiceName;
|
|
48
|
+
/**
|
|
49
|
+
* Hash server URL for service name
|
|
50
|
+
*/
|
|
51
|
+
private hashServerUrl;
|
|
52
|
+
/**
|
|
53
|
+
* Launch browser for OAuth authorization
|
|
54
|
+
*/
|
|
55
|
+
private launchBrowser;
|
|
56
|
+
/**
|
|
57
|
+
* Cleanup on shutdown
|
|
58
|
+
*/
|
|
59
|
+
stop(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=mcp-oauth-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-oauth-manager.d.ts","sourceRoot":"","sources":["../../../src/oauth/mcp-oauth-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C;;;;;;;;GAQG;AACH,qBAAa,eAAgB,SAAQ,SAAS;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,mBAAmB,CAAyB;IACpD,OAAO,CAAC,gBAAgB,CAAW;gBAEvB,MAAM,EAAE,eAAe;IAkBnC;;OAEG;IACG,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAyLvE;;OAEG;IACG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAwClE;;OAEG;IACG,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAehE;;OAEG;IACG,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAahE;;OAEG;IACG,gCAAgC,CACpC,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;IAWtB;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAarD;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;YACW,aAAa;IAY3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAO5B"}
|