@mediagraph/mcp 1.0.0 → 1.0.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/README.md +15 -23
- package/dist/index.js +98 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,22 +25,15 @@ npx @mediagraph/mcp
|
|
|
25
25
|
|
|
26
26
|
## Quick Start
|
|
27
27
|
|
|
28
|
-
### 1.
|
|
29
|
-
|
|
30
|
-
1. Log into your Mediagraph organization
|
|
31
|
-
2. Go to **Settings > API & Integrations**
|
|
32
|
-
3. Create a new OAuth application
|
|
33
|
-
4. Copy the Client ID (and Client Secret if using a confidential client)
|
|
34
|
-
|
|
35
|
-
### 2. Authorize
|
|
28
|
+
### 1. Authorize
|
|
36
29
|
|
|
37
30
|
```bash
|
|
38
|
-
|
|
31
|
+
npx @mediagraph/mcp authorize
|
|
39
32
|
```
|
|
40
33
|
|
|
41
|
-
This will open a browser window for you to authorize the MCP server with your Mediagraph account.
|
|
34
|
+
This will open a browser window for you to log in and authorize the MCP server with your Mediagraph account.
|
|
42
35
|
|
|
43
|
-
###
|
|
36
|
+
### 2. Configure Claude Desktop
|
|
44
37
|
|
|
45
38
|
Add the following to your Claude Desktop configuration file:
|
|
46
39
|
|
|
@@ -52,16 +45,13 @@ Add the following to your Claude Desktop configuration file:
|
|
|
52
45
|
"mcpServers": {
|
|
53
46
|
"mediagraph": {
|
|
54
47
|
"command": "npx",
|
|
55
|
-
"args": ["@mediagraph/mcp"]
|
|
56
|
-
"env": {
|
|
57
|
-
"MEDIAGRAPH_CLIENT_ID": "your-client-id"
|
|
58
|
-
}
|
|
48
|
+
"args": ["@mediagraph/mcp"]
|
|
59
49
|
}
|
|
60
50
|
}
|
|
61
51
|
}
|
|
62
52
|
```
|
|
63
53
|
|
|
64
|
-
###
|
|
54
|
+
### 3. Start Using
|
|
65
55
|
|
|
66
56
|
Restart Claude Desktop and you can now ask Claude to:
|
|
67
57
|
|
|
@@ -121,13 +111,15 @@ npx @mediagraph/mcp help
|
|
|
121
111
|
|
|
122
112
|
## Environment Variables
|
|
123
113
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
|
127
|
-
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
114
|
+
All environment variables are optional. The default configuration works out of the box.
|
|
115
|
+
|
|
116
|
+
| Variable | Default | Description |
|
|
117
|
+
|----------|---------|-------------|
|
|
118
|
+
| `MEDIAGRAPH_CLIENT_ID` | *(built-in)* | OAuth client ID (override for custom apps) |
|
|
119
|
+
| `MEDIAGRAPH_CLIENT_SECRET` | - | OAuth client secret (for confidential clients) |
|
|
120
|
+
| `MEDIAGRAPH_API_URL` | `https://api.mediagraph.io` | API base URL |
|
|
121
|
+
| `MEDIAGRAPH_OAUTH_URL` | `https://mediagraph.io` | OAuth server URL |
|
|
122
|
+
| `MEDIAGRAPH_REDIRECT_PORT` | `52584` | Local callback port for OAuth |
|
|
131
123
|
|
|
132
124
|
## Security
|
|
133
125
|
|
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";
|
|
@@ -2925,8 +2927,9 @@ async function listResources(context) {
|
|
|
2925
2927
|
}
|
|
2926
2928
|
|
|
2927
2929
|
// src/index.ts
|
|
2930
|
+
var DEFAULT_CLIENT_ID = "7Y8rlAetr9IK2N91X4wCvVlo2hQLX6nJvFY1N8CY0GI";
|
|
2928
2931
|
var config = {
|
|
2929
|
-
clientId: process.env.MEDIAGRAPH_CLIENT_ID ||
|
|
2932
|
+
clientId: process.env.MEDIAGRAPH_CLIENT_ID || DEFAULT_CLIENT_ID,
|
|
2930
2933
|
clientSecret: process.env.MEDIAGRAPH_CLIENT_SECRET,
|
|
2931
2934
|
apiUrl: process.env.MEDIAGRAPH_API_URL || "https://api.mediagraph.io",
|
|
2932
2935
|
oauthUrl: process.env.MEDIAGRAPH_OAUTH_URL || "https://mediagraph.io",
|
|
@@ -2940,6 +2943,46 @@ var oauthHandler = new OAuthHandler({
|
|
|
2940
2943
|
redirectPort: config.redirectPort
|
|
2941
2944
|
});
|
|
2942
2945
|
var currentTokens = null;
|
|
2946
|
+
var isAuthInProgress = false;
|
|
2947
|
+
function openBrowser(url) {
|
|
2948
|
+
const command = platform() === "darwin" ? `open "${url}"` : platform() === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
2949
|
+
exec(command, (error) => {
|
|
2950
|
+
if (error) {
|
|
2951
|
+
console.error("Failed to open browser:", error);
|
|
2952
|
+
}
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
async function runAutoAuth() {
|
|
2956
|
+
if (isAuthInProgress) {
|
|
2957
|
+
while (isAuthInProgress) {
|
|
2958
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2959
|
+
}
|
|
2960
|
+
return currentTokens !== null;
|
|
2961
|
+
}
|
|
2962
|
+
isAuthInProgress = true;
|
|
2963
|
+
try {
|
|
2964
|
+
const authUrl = oauthHandler.getAuthorizationUrl();
|
|
2965
|
+
openBrowser(authUrl);
|
|
2966
|
+
const { code } = await oauthHandler.waitForCallback();
|
|
2967
|
+
const tokens = await oauthHandler.exchangeCode(code);
|
|
2968
|
+
currentTokens = tokens;
|
|
2969
|
+
const whoami = await client.whoami();
|
|
2970
|
+
const storedData = {
|
|
2971
|
+
tokens,
|
|
2972
|
+
organizationId: whoami.organization.id,
|
|
2973
|
+
organizationName: whoami.organization.name,
|
|
2974
|
+
userId: whoami.user.id,
|
|
2975
|
+
userEmail: whoami.user.email
|
|
2976
|
+
};
|
|
2977
|
+
tokenStore.save(storedData);
|
|
2978
|
+
return true;
|
|
2979
|
+
} catch (error) {
|
|
2980
|
+
console.error("Auto-auth failed:", error);
|
|
2981
|
+
return false;
|
|
2982
|
+
} finally {
|
|
2983
|
+
isAuthInProgress = false;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2943
2986
|
async function getAccessToken() {
|
|
2944
2987
|
if (currentTokens && Date.now() < currentTokens.expires_at - 3e5) {
|
|
2945
2988
|
return currentTokens.access_token;
|
|
@@ -2991,27 +3034,32 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2991
3034
|
});
|
|
2992
3035
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2993
3036
|
const { name, arguments: args } = request.params;
|
|
2994
|
-
|
|
3037
|
+
let token = await getAccessToken();
|
|
2995
3038
|
if (!token) {
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3039
|
+
const authSuccess = await runAutoAuth();
|
|
3040
|
+
if (!authSuccess) {
|
|
3041
|
+
return {
|
|
3042
|
+
content: [
|
|
3043
|
+
{
|
|
3044
|
+
type: "text",
|
|
3045
|
+
text: "Failed to authenticate with Mediagraph. Please try again or check your browser for the authorization window."
|
|
3046
|
+
}
|
|
3047
|
+
],
|
|
3048
|
+
isError: true
|
|
3049
|
+
};
|
|
3050
|
+
}
|
|
3051
|
+
token = await getAccessToken();
|
|
3052
|
+
if (!token) {
|
|
3053
|
+
return {
|
|
3054
|
+
content: [
|
|
3055
|
+
{
|
|
3056
|
+
type: "text",
|
|
3057
|
+
text: "Authentication completed but failed to retrieve access token. Please try again."
|
|
3058
|
+
}
|
|
3059
|
+
],
|
|
3060
|
+
isError: true
|
|
3061
|
+
};
|
|
3062
|
+
}
|
|
3015
3063
|
}
|
|
3016
3064
|
const result = await handleTool(name, args || {}, toolContext);
|
|
3017
3065
|
return {
|
|
@@ -3025,7 +3073,14 @@ server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
|
3025
3073
|
};
|
|
3026
3074
|
});
|
|
3027
3075
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
3028
|
-
|
|
3076
|
+
let token = await getAccessToken();
|
|
3077
|
+
if (!token) {
|
|
3078
|
+
const authSuccess = await runAutoAuth();
|
|
3079
|
+
if (!authSuccess) {
|
|
3080
|
+
return { resources: [] };
|
|
3081
|
+
}
|
|
3082
|
+
token = await getAccessToken();
|
|
3083
|
+
}
|
|
3029
3084
|
if (!token) {
|
|
3030
3085
|
return { resources: [] };
|
|
3031
3086
|
}
|
|
@@ -3034,14 +3089,29 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
3034
3089
|
});
|
|
3035
3090
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
3036
3091
|
const { uri } = request.params;
|
|
3037
|
-
|
|
3092
|
+
let token = await getAccessToken();
|
|
3093
|
+
if (!token) {
|
|
3094
|
+
const authSuccess = await runAutoAuth();
|
|
3095
|
+
if (!authSuccess) {
|
|
3096
|
+
return {
|
|
3097
|
+
contents: [
|
|
3098
|
+
{
|
|
3099
|
+
uri,
|
|
3100
|
+
mimeType: "text/plain",
|
|
3101
|
+
text: "Failed to authenticate with Mediagraph. Please try again."
|
|
3102
|
+
}
|
|
3103
|
+
]
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3106
|
+
token = await getAccessToken();
|
|
3107
|
+
}
|
|
3038
3108
|
if (!token) {
|
|
3039
3109
|
return {
|
|
3040
3110
|
contents: [
|
|
3041
3111
|
{
|
|
3042
3112
|
uri,
|
|
3043
3113
|
mimeType: "text/plain",
|
|
3044
|
-
text: "
|
|
3114
|
+
text: "Authentication completed but failed to retrieve access token."
|
|
3045
3115
|
}
|
|
3046
3116
|
]
|
|
3047
3117
|
};
|
|
@@ -3159,16 +3229,16 @@ Commands:
|
|
|
3159
3229
|
status Show current authentication status
|
|
3160
3230
|
help Show this help message
|
|
3161
3231
|
|
|
3162
|
-
Environment Variables:
|
|
3163
|
-
MEDIAGRAPH_CLIENT_ID
|
|
3164
|
-
MEDIAGRAPH_CLIENT_SECRET
|
|
3232
|
+
Environment Variables (all optional):
|
|
3233
|
+
MEDIAGRAPH_CLIENT_ID Override default OAuth client ID
|
|
3234
|
+
MEDIAGRAPH_CLIENT_SECRET OAuth client secret (for confidential clients)
|
|
3165
3235
|
MEDIAGRAPH_API_URL API URL (default: https://api.mediagraph.io)
|
|
3166
3236
|
MEDIAGRAPH_OAUTH_URL OAuth URL (default: https://mediagraph.io)
|
|
3167
3237
|
MEDIAGRAPH_REDIRECT_PORT Local callback port (default: 52584)
|
|
3168
3238
|
|
|
3169
3239
|
Example:
|
|
3170
3240
|
# First, authorize with Mediagraph
|
|
3171
|
-
|
|
3241
|
+
npx @mediagraph/mcp authorize
|
|
3172
3242
|
|
|
3173
3243
|
# Then configure Claude Desktop to use the MCP server
|
|
3174
3244
|
# See README for configuration details
|