@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
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth-aware transport wrapper for MCP
|
|
3
|
+
*
|
|
4
|
+
* This transport wraps the standard MCP transport and automatically:
|
|
5
|
+
* - Injects OAuth tokens into requests
|
|
6
|
+
* - Refreshes expired tokens
|
|
7
|
+
* - Retries failed requests after token refresh
|
|
8
|
+
*/
|
|
9
|
+
export class OAuthAwareMcpTransport {
|
|
10
|
+
constructor(innerTransport, storage, serverUrl, refreshCallback) {
|
|
11
|
+
this.innerTransport = innerTransport;
|
|
12
|
+
this.storage = storage;
|
|
13
|
+
this.serverUrl = serverUrl;
|
|
14
|
+
this.refreshCallback = refreshCallback;
|
|
15
|
+
// Forward events from inner transport
|
|
16
|
+
this.innerTransport.onclose = () => {
|
|
17
|
+
if (this.onclose) {
|
|
18
|
+
this.onclose();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
this.innerTransport.onerror = (error) => {
|
|
22
|
+
if (this.onerror) {
|
|
23
|
+
this.onerror(error);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
this.innerTransport.onmessage = (message) => {
|
|
27
|
+
if (this.onmessage) {
|
|
28
|
+
this.onmessage(message);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Start the transport and ensure tokens are valid
|
|
34
|
+
*/
|
|
35
|
+
async start() {
|
|
36
|
+
await this.ensureValidTokens();
|
|
37
|
+
return this.innerTransport.start();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Close the transport
|
|
41
|
+
*/
|
|
42
|
+
async close() {
|
|
43
|
+
return this.innerTransport.close();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Send a message with OAuth token injection
|
|
47
|
+
*/
|
|
48
|
+
async send(message) {
|
|
49
|
+
// Ensure we have valid tokens
|
|
50
|
+
await this.ensureValidTokens();
|
|
51
|
+
// Get current tokens
|
|
52
|
+
const tokens = await this.storage.getTokens(this.serverUrl);
|
|
53
|
+
// For HTTP/SSE transports, we'd inject the Authorization header
|
|
54
|
+
// The MCP SDK handles this differently depending on transport type
|
|
55
|
+
// For now, we rely on the transport configuration having the token
|
|
56
|
+
try {
|
|
57
|
+
return await this.innerTransport.send(message);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// Check if it's an authentication error (401)
|
|
61
|
+
if (this.isAuthError(error)) {
|
|
62
|
+
// Try to refresh tokens and retry
|
|
63
|
+
await this.refreshTokens();
|
|
64
|
+
return await this.innerTransport.send(message);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Ensure tokens are valid before making requests
|
|
71
|
+
*/
|
|
72
|
+
async ensureValidTokens() {
|
|
73
|
+
const tokens = await this.storage.getTokens(this.serverUrl);
|
|
74
|
+
if (!tokens) {
|
|
75
|
+
throw new Error(`No OAuth tokens available for ${this.serverUrl}. Please authenticate first.`);
|
|
76
|
+
}
|
|
77
|
+
// Check if token is expired
|
|
78
|
+
const isExpired = await this.storage.areTokensExpired(this.serverUrl);
|
|
79
|
+
if (isExpired && tokens.refresh_token) {
|
|
80
|
+
await this.refreshTokens();
|
|
81
|
+
}
|
|
82
|
+
else if (isExpired) {
|
|
83
|
+
throw new Error(`OAuth token expired and no refresh token available for ${this.serverUrl}. Please re-authenticate.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Refresh OAuth tokens
|
|
88
|
+
*/
|
|
89
|
+
async refreshTokens() {
|
|
90
|
+
try {
|
|
91
|
+
await this.refreshCallback(this.serverUrl);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw new Error(`Failed to refresh OAuth tokens for ${this.serverUrl}: ${error.message}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if an error is an authentication error
|
|
99
|
+
*/
|
|
100
|
+
isAuthError(error) {
|
|
101
|
+
// Check for common authentication error patterns
|
|
102
|
+
if (error.status === 401 || error.statusCode === 401) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (error.code === 'UNAUTHORIZED' || error.code === 'UNAUTHENTICATED') {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const errorMessage = error.message?.toLowerCase() || '';
|
|
109
|
+
return (errorMessage.includes('unauthorized') ||
|
|
110
|
+
errorMessage.includes('authentication') ||
|
|
111
|
+
errorMessage.includes('token expired'));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the current access token (for HTTP transport configuration)
|
|
115
|
+
*/
|
|
116
|
+
async getAccessToken() {
|
|
117
|
+
const tokens = await this.storage.getTokens(this.serverUrl);
|
|
118
|
+
return tokens?.access_token || null;
|
|
119
|
+
}
|
|
120
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -35,10 +35,29 @@
|
|
|
35
35
|
"author": "oLane Inc.",
|
|
36
36
|
"license": "ISC",
|
|
37
37
|
"description": "oLane Core",
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
40
|
+
"@olane/o-config": "^0.7.1",
|
|
41
|
+
"@olane/o-core": "^0.7.1",
|
|
42
|
+
"@olane/o-intelligence": "^0.7.1",
|
|
43
|
+
"@olane/o-lane": "^0.7.1",
|
|
44
|
+
"@olane/o-leader": "^0.7.1",
|
|
45
|
+
"@olane/o-node": "^0.7.1",
|
|
46
|
+
"@olane/o-protocol": "^0.7.1",
|
|
47
|
+
"@olane/o-storage": "^0.7.1",
|
|
48
|
+
"@olane/o-tool": "^0.7.1"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"debug": "^4.4.1",
|
|
52
|
+
"dotenv": "^16.5.0",
|
|
53
|
+
"express": "^4.18.2",
|
|
54
|
+
"open": "^10.0.0"
|
|
55
|
+
},
|
|
38
56
|
"devDependencies": {
|
|
39
57
|
"@eslint/eslintrc": "^3.3.1",
|
|
40
58
|
"@eslint/js": "^9.29.0",
|
|
41
59
|
"@tsconfig/node20": "^20.1.6",
|
|
60
|
+
"@types/express": "^4.17.21",
|
|
42
61
|
"@types/jest": "^30.0.0",
|
|
43
62
|
"@typescript-eslint/eslint-plugin": "^8.34.1",
|
|
44
63
|
"@typescript-eslint/parser": "^8.34.1",
|
|
@@ -54,19 +73,5 @@
|
|
|
54
73
|
"tsconfig-paths": "^4.2.0",
|
|
55
74
|
"tsx": "^4.20.3",
|
|
56
75
|
"typescript": "5.4.5"
|
|
57
|
-
},
|
|
58
|
-
"peerDependencies": {
|
|
59
|
-
"@modelcontextprotocol/sdk": "^1.18.1",
|
|
60
|
-
"@olane/o-config": "^0.7.0",
|
|
61
|
-
"@olane/o-core": "^0.7.0",
|
|
62
|
-
"@olane/o-intelligence": "^0.7.0",
|
|
63
|
-
"@olane/o-leader": "^0.7.0",
|
|
64
|
-
"@olane/o-protocol": "^0.7.0",
|
|
65
|
-
"@olane/o-tool": "^0.7.0",
|
|
66
|
-
"@olane/o-lane": "^0.7.0"
|
|
67
|
-
},
|
|
68
|
-
"dependencies": {
|
|
69
|
-
"debug": "^4.4.1",
|
|
70
|
-
"dotenv": "^16.5.0"
|
|
71
76
|
}
|
|
72
77
|
}
|