@mediagraph/mcp 1.0.1 → 1.0.3
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/index.js +133 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
ListToolsRequestSchema,
|
|
11
11
|
ReadResourceRequestSchema
|
|
12
12
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
+
import { exec } from "child_process";
|
|
14
|
+
import { platform } from "os";
|
|
13
15
|
|
|
14
16
|
// src/auth/oauth.ts
|
|
15
17
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -67,10 +69,11 @@ var OAuthHandler = class {
|
|
|
67
69
|
});
|
|
68
70
|
return `${this.config.oauthUrl}/oauth/authorize?${params.toString()}`;
|
|
69
71
|
}
|
|
72
|
+
callbackPromise = null;
|
|
70
73
|
/**
|
|
71
|
-
* Start
|
|
74
|
+
* Start the callback server and wait for it to be ready
|
|
72
75
|
*/
|
|
73
|
-
async
|
|
76
|
+
async startCallbackServer() {
|
|
74
77
|
return new Promise((resolve, reject) => {
|
|
75
78
|
this.callbackServer = createServer((req, res) => {
|
|
76
79
|
const url = new URL2(req.url || "/", `http://localhost:${this.config.redirectPort}`);
|
|
@@ -91,7 +94,8 @@ var OAuthHandler = class {
|
|
|
91
94
|
</html>
|
|
92
95
|
`);
|
|
93
96
|
this.stopCallbackServer();
|
|
94
|
-
reject(new Error(errorDescription || error));
|
|
97
|
+
this.callbackPromise?.reject(new Error(errorDescription || error));
|
|
98
|
+
this.callbackPromise = null;
|
|
95
99
|
return;
|
|
96
100
|
}
|
|
97
101
|
if (!code || !state) {
|
|
@@ -106,7 +110,8 @@ var OAuthHandler = class {
|
|
|
106
110
|
</html>
|
|
107
111
|
`);
|
|
108
112
|
this.stopCallbackServer();
|
|
109
|
-
reject(new Error("Missing authorization code or state"));
|
|
113
|
+
this.callbackPromise?.reject(new Error("Missing authorization code or state"));
|
|
114
|
+
this.callbackPromise = null;
|
|
110
115
|
return;
|
|
111
116
|
}
|
|
112
117
|
if (state !== this.state) {
|
|
@@ -121,7 +126,8 @@ var OAuthHandler = class {
|
|
|
121
126
|
</html>
|
|
122
127
|
`);
|
|
123
128
|
this.stopCallbackServer();
|
|
124
|
-
reject(new Error("State parameter mismatch"));
|
|
129
|
+
this.callbackPromise?.reject(new Error("State parameter mismatch"));
|
|
130
|
+
this.callbackPromise = null;
|
|
125
131
|
return;
|
|
126
132
|
}
|
|
127
133
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
@@ -135,20 +141,43 @@ var OAuthHandler = class {
|
|
|
135
141
|
</html>
|
|
136
142
|
`);
|
|
137
143
|
this.stopCallbackServer();
|
|
138
|
-
resolve({ code, state });
|
|
144
|
+
this.callbackPromise?.resolve({ code, state });
|
|
145
|
+
this.callbackPromise = null;
|
|
139
146
|
} else {
|
|
140
147
|
res.writeHead(404);
|
|
141
148
|
res.end("Not found");
|
|
142
149
|
}
|
|
143
150
|
});
|
|
151
|
+
this.callbackServer.on("error", (err) => {
|
|
152
|
+
reject(err);
|
|
153
|
+
});
|
|
144
154
|
this.callbackServer.listen(this.config.redirectPort, () => {
|
|
155
|
+
resolve();
|
|
145
156
|
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Wait for the OAuth callback (server must be started first)
|
|
161
|
+
*/
|
|
162
|
+
async waitForCallback() {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
this.callbackPromise = { resolve, reject };
|
|
146
165
|
setTimeout(() => {
|
|
147
|
-
this.
|
|
148
|
-
|
|
166
|
+
if (this.callbackPromise) {
|
|
167
|
+
this.stopCallbackServer();
|
|
168
|
+
this.callbackPromise.reject(new Error("Authorization timed out"));
|
|
169
|
+
this.callbackPromise = null;
|
|
170
|
+
}
|
|
149
171
|
}, 5 * 60 * 1e3);
|
|
150
172
|
});
|
|
151
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Start server and wait for callback (convenience method for CLI)
|
|
176
|
+
*/
|
|
177
|
+
async startAndWaitForCallback() {
|
|
178
|
+
await this.startCallbackServer();
|
|
179
|
+
return this.waitForCallback();
|
|
180
|
+
}
|
|
152
181
|
/**
|
|
153
182
|
* Stop the callback server
|
|
154
183
|
*/
|
|
@@ -2941,6 +2970,48 @@ var oauthHandler = new OAuthHandler({
|
|
|
2941
2970
|
redirectPort: config.redirectPort
|
|
2942
2971
|
});
|
|
2943
2972
|
var currentTokens = null;
|
|
2973
|
+
var isAuthInProgress = false;
|
|
2974
|
+
function openBrowser(url) {
|
|
2975
|
+
const command = platform() === "darwin" ? `open "${url}"` : platform() === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
2976
|
+
exec(command, (error) => {
|
|
2977
|
+
if (error) {
|
|
2978
|
+
console.error("Failed to open browser:", error);
|
|
2979
|
+
}
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
async function runAutoAuth() {
|
|
2983
|
+
if (isAuthInProgress) {
|
|
2984
|
+
while (isAuthInProgress) {
|
|
2985
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2986
|
+
}
|
|
2987
|
+
return currentTokens !== null;
|
|
2988
|
+
}
|
|
2989
|
+
isAuthInProgress = true;
|
|
2990
|
+
try {
|
|
2991
|
+
const authUrl = oauthHandler.getAuthorizationUrl();
|
|
2992
|
+
await oauthHandler.startCallbackServer();
|
|
2993
|
+
openBrowser(authUrl);
|
|
2994
|
+
const { code } = await oauthHandler.waitForCallback();
|
|
2995
|
+
const tokens = await oauthHandler.exchangeCode(code);
|
|
2996
|
+
currentTokens = tokens;
|
|
2997
|
+
const whoami = await client.whoami();
|
|
2998
|
+
const storedData = {
|
|
2999
|
+
tokens,
|
|
3000
|
+
organizationId: whoami.organization.id,
|
|
3001
|
+
organizationName: whoami.organization.name,
|
|
3002
|
+
userId: whoami.user.id,
|
|
3003
|
+
userEmail: whoami.user.email
|
|
3004
|
+
};
|
|
3005
|
+
tokenStore.save(storedData);
|
|
3006
|
+
return true;
|
|
3007
|
+
} catch (error) {
|
|
3008
|
+
console.error("Auto-auth failed:", error);
|
|
3009
|
+
oauthHandler.stopCallbackServer();
|
|
3010
|
+
return false;
|
|
3011
|
+
} finally {
|
|
3012
|
+
isAuthInProgress = false;
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
2944
3015
|
async function getAccessToken() {
|
|
2945
3016
|
if (currentTokens && Date.now() < currentTokens.expires_at - 3e5) {
|
|
2946
3017
|
return currentTokens.access_token;
|
|
@@ -2992,27 +3063,32 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2992
3063
|
});
|
|
2993
3064
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2994
3065
|
const { name, arguments: args } = request.params;
|
|
2995
|
-
|
|
3066
|
+
let token = await getAccessToken();
|
|
2996
3067
|
if (!token) {
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3068
|
+
const authSuccess = await runAutoAuth();
|
|
3069
|
+
if (!authSuccess) {
|
|
3070
|
+
return {
|
|
3071
|
+
content: [
|
|
3072
|
+
{
|
|
3073
|
+
type: "text",
|
|
3074
|
+
text: "Failed to authenticate with Mediagraph. Please try again or check your browser for the authorization window."
|
|
3075
|
+
}
|
|
3076
|
+
],
|
|
3077
|
+
isError: true
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
3080
|
+
token = await getAccessToken();
|
|
3081
|
+
if (!token) {
|
|
3082
|
+
return {
|
|
3083
|
+
content: [
|
|
3084
|
+
{
|
|
3085
|
+
type: "text",
|
|
3086
|
+
text: "Authentication completed but failed to retrieve access token. Please try again."
|
|
3087
|
+
}
|
|
3088
|
+
],
|
|
3089
|
+
isError: true
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3016
3092
|
}
|
|
3017
3093
|
const result = await handleTool(name, args || {}, toolContext);
|
|
3018
3094
|
return {
|
|
@@ -3026,7 +3102,14 @@ server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
|
3026
3102
|
};
|
|
3027
3103
|
});
|
|
3028
3104
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
3029
|
-
|
|
3105
|
+
let token = await getAccessToken();
|
|
3106
|
+
if (!token) {
|
|
3107
|
+
const authSuccess = await runAutoAuth();
|
|
3108
|
+
if (!authSuccess) {
|
|
3109
|
+
return { resources: [] };
|
|
3110
|
+
}
|
|
3111
|
+
token = await getAccessToken();
|
|
3112
|
+
}
|
|
3030
3113
|
if (!token) {
|
|
3031
3114
|
return { resources: [] };
|
|
3032
3115
|
}
|
|
@@ -3035,14 +3118,29 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
3035
3118
|
});
|
|
3036
3119
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
3037
3120
|
const { uri } = request.params;
|
|
3038
|
-
|
|
3121
|
+
let token = await getAccessToken();
|
|
3122
|
+
if (!token) {
|
|
3123
|
+
const authSuccess = await runAutoAuth();
|
|
3124
|
+
if (!authSuccess) {
|
|
3125
|
+
return {
|
|
3126
|
+
contents: [
|
|
3127
|
+
{
|
|
3128
|
+
uri,
|
|
3129
|
+
mimeType: "text/plain",
|
|
3130
|
+
text: "Failed to authenticate with Mediagraph. Please try again."
|
|
3131
|
+
}
|
|
3132
|
+
]
|
|
3133
|
+
};
|
|
3134
|
+
}
|
|
3135
|
+
token = await getAccessToken();
|
|
3136
|
+
}
|
|
3039
3137
|
if (!token) {
|
|
3040
3138
|
return {
|
|
3041
3139
|
contents: [
|
|
3042
3140
|
{
|
|
3043
3141
|
uri,
|
|
3044
3142
|
mimeType: "text/plain",
|
|
3045
|
-
text: "
|
|
3143
|
+
text: "Authentication completed but failed to retrieve access token."
|
|
3046
3144
|
}
|
|
3047
3145
|
]
|
|
3048
3146
|
};
|
|
@@ -3062,7 +3160,10 @@ async function runAuthorize() {
|
|
|
3062
3160
|
console.log("Starting Mediagraph OAuth authorization...");
|
|
3063
3161
|
console.log("");
|
|
3064
3162
|
const authUrl = oauthHandler.getAuthorizationUrl();
|
|
3065
|
-
|
|
3163
|
+
await oauthHandler.startCallbackServer();
|
|
3164
|
+
openBrowser(authUrl);
|
|
3165
|
+
console.log("Opening browser for authorization...");
|
|
3166
|
+
console.log("If the browser does not open, please visit:");
|
|
3066
3167
|
console.log("");
|
|
3067
3168
|
console.log(authUrl);
|
|
3068
3169
|
console.log("");
|