@cloudinary/environment-config-mcp 0.6.2 → 0.6.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/README.md +3 -2
- package/bin/mcp-server.js +45394 -44720
- package/bin/mcp-server.js.map +53 -238
- package/esm/landing-page.d.ts +2 -1
- package/esm/landing-page.d.ts.map +1 -1
- package/esm/landing-page.js +51 -28
- package/esm/landing-page.js.map +1 -1
- package/esm/lib/config.d.ts +3 -3
- package/esm/lib/config.js +3 -3
- package/esm/mcp-server/cli/serve/impl.js +51 -25
- package/esm/mcp-server/cli/serve/impl.js.map +1 -1
- package/esm/mcp-server/cli/start/impl.js +11 -8
- package/esm/mcp-server/cli/start/impl.js.map +1 -1
- package/esm/mcp-server/extensions.d.ts +3 -3
- package/esm/mcp-server/extensions.d.ts.map +1 -1
- package/esm/mcp-server/mcp-server.js +1 -1
- package/esm/mcp-server/prompts.d.ts +7 -8
- package/esm/mcp-server/prompts.d.ts.map +1 -1
- package/esm/mcp-server/prompts.js +12 -12
- package/esm/mcp-server/prompts.js.map +1 -1
- package/esm/mcp-server/resources.d.ts +6 -7
- package/esm/mcp-server/resources.d.ts.map +1 -1
- package/esm/mcp-server/resources.js +19 -3
- package/esm/mcp-server/resources.js.map +1 -1
- package/esm/mcp-server/server.d.ts +1 -1
- package/esm/mcp-server/server.d.ts.map +1 -1
- package/esm/mcp-server/server.js +2 -2
- package/esm/mcp-server/server.js.map +1 -1
- package/esm/mcp-server/shared.d.ts +7 -0
- package/esm/mcp-server/shared.d.ts.map +1 -1
- package/esm/mcp-server/shared.js +184 -0
- package/esm/mcp-server/shared.js.map +1 -1
- package/esm/mcp-server/tools/streamingProfilesCreateStreamingProfile.js +1 -1
- package/esm/mcp-server/tools/streamingProfilesCreateStreamingProfile.js.map +1 -1
- package/esm/mcp-server/tools/streamingProfilesDeleteStreamingProfile.js +1 -1
- package/esm/mcp-server/tools/streamingProfilesDeleteStreamingProfile.js.map +1 -1
- package/esm/mcp-server/tools/streamingProfilesGetStreamingProfile.js +1 -1
- package/esm/mcp-server/tools/streamingProfilesGetStreamingProfile.js.map +1 -1
- package/esm/mcp-server/tools/streamingProfilesGetStreamingProfiles.js +1 -1
- package/esm/mcp-server/tools/streamingProfilesGetStreamingProfiles.js.map +1 -1
- package/esm/mcp-server/tools/streamingProfilesUpdateStreamingProfile.js +1 -1
- package/esm/mcp-server/tools/streamingProfilesUpdateStreamingProfile.js.map +1 -1
- package/esm/mcp-server/tools/transformationsCreateTransformation.js +1 -1
- package/esm/mcp-server/tools/transformationsCreateTransformation.js.map +1 -1
- package/esm/mcp-server/tools/transformationsDeleteTransformation.js +1 -1
- package/esm/mcp-server/tools/transformationsDeleteTransformation.js.map +1 -1
- package/esm/mcp-server/tools/transformationsGetTransformation.js +1 -1
- package/esm/mcp-server/tools/transformationsGetTransformation.js.map +1 -1
- package/esm/mcp-server/tools/transformationsListTransformations.js +1 -1
- package/esm/mcp-server/tools/transformationsListTransformations.js.map +1 -1
- package/esm/mcp-server/tools/transformationsUpdateTransformation.js +1 -1
- package/esm/mcp-server/tools/transformationsUpdateTransformation.js.map +1 -1
- package/esm/mcp-server/tools/triggersCreateTrigger.js +1 -1
- package/esm/mcp-server/tools/triggersCreateTrigger.js.map +1 -1
- package/esm/mcp-server/tools/triggersDeleteTrigger.js +1 -1
- package/esm/mcp-server/tools/triggersDeleteTrigger.js.map +1 -1
- package/esm/mcp-server/tools/triggersListTrigger.js +1 -1
- package/esm/mcp-server/tools/triggersListTrigger.js.map +1 -1
- package/esm/mcp-server/tools/triggersTestTrigger.js +1 -1
- package/esm/mcp-server/tools/triggersTestTrigger.js.map +1 -1
- package/esm/mcp-server/tools/triggersUpdateTrigger.js +1 -1
- package/esm/mcp-server/tools/triggersUpdateTrigger.js.map +1 -1
- package/esm/mcp-server/tools/uploadMappingsCreateUploadMapping.js +1 -1
- package/esm/mcp-server/tools/uploadMappingsCreateUploadMapping.js.map +1 -1
- package/esm/mcp-server/tools/uploadMappingsDeleteUploadMapping.js +1 -1
- package/esm/mcp-server/tools/uploadMappingsDeleteUploadMapping.js.map +1 -1
- package/esm/mcp-server/tools/uploadMappingsListUploadMappings.js +1 -1
- package/esm/mcp-server/tools/uploadMappingsListUploadMappings.js.map +1 -1
- package/esm/mcp-server/tools/uploadMappingsUpdateUploadMapping.js +1 -1
- package/esm/mcp-server/tools/uploadMappingsUpdateUploadMapping.js.map +1 -1
- package/esm/mcp-server/tools/uploadPresetsCreateUploadPreset.js +1 -1
- package/esm/mcp-server/tools/uploadPresetsCreateUploadPreset.js.map +1 -1
- package/esm/mcp-server/tools/uploadPresetsDeleteUploadPreset.js +1 -1
- package/esm/mcp-server/tools/uploadPresetsDeleteUploadPreset.js.map +1 -1
- package/esm/mcp-server/tools/uploadPresetsGetUploadPreset.js +1 -1
- package/esm/mcp-server/tools/uploadPresetsGetUploadPreset.js.map +1 -1
- package/esm/mcp-server/tools/uploadPresetsListUploadPresets.js +1 -1
- package/esm/mcp-server/tools/uploadPresetsListUploadPresets.js.map +1 -1
- package/esm/mcp-server/tools/uploadPresetsUpdateUploadPreset.js +1 -1
- package/esm/mcp-server/tools/uploadPresetsUpdateUploadPreset.js.map +1 -1
- package/esm/mcp-server/tools.d.ts +11 -9
- package/esm/mcp-server/tools.d.ts.map +1 -1
- package/esm/mcp-server/tools.js +20 -19
- package/esm/mcp-server/tools.js.map +1 -1
- package/package.json +9 -4
- package/src/landing-page.ts +81 -28
- package/src/lib/config.ts +3 -3
- package/src/mcp-server/cli/serve/impl.ts +55 -25
- package/src/mcp-server/cli/start/impl.ts +16 -9
- package/src/mcp-server/extensions.ts +3 -5
- package/src/mcp-server/mcp-server.ts +1 -1
- package/src/mcp-server/prompts.ts +30 -43
- package/src/mcp-server/resources.ts +32 -17
- package/src/mcp-server/server.ts +2 -2
- package/src/mcp-server/shared.ts +201 -0
- package/src/mcp-server/tools/streamingProfilesCreateStreamingProfile.ts +1 -1
- package/src/mcp-server/tools/streamingProfilesDeleteStreamingProfile.ts +1 -1
- package/src/mcp-server/tools/streamingProfilesGetStreamingProfile.ts +1 -1
- package/src/mcp-server/tools/streamingProfilesGetStreamingProfiles.ts +1 -1
- package/src/mcp-server/tools/streamingProfilesUpdateStreamingProfile.ts +1 -1
- package/src/mcp-server/tools/transformationsCreateTransformation.ts +1 -1
- package/src/mcp-server/tools/transformationsDeleteTransformation.ts +1 -1
- package/src/mcp-server/tools/transformationsGetTransformation.ts +1 -1
- package/src/mcp-server/tools/transformationsListTransformations.ts +1 -1
- package/src/mcp-server/tools/transformationsUpdateTransformation.ts +1 -1
- package/src/mcp-server/tools/triggersCreateTrigger.ts +1 -1
- package/src/mcp-server/tools/triggersDeleteTrigger.ts +1 -1
- package/src/mcp-server/tools/triggersListTrigger.ts +1 -1
- package/src/mcp-server/tools/triggersTestTrigger.ts +1 -1
- package/src/mcp-server/tools/triggersUpdateTrigger.ts +1 -1
- package/src/mcp-server/tools/uploadMappingsCreateUploadMapping.ts +1 -1
- package/src/mcp-server/tools/uploadMappingsDeleteUploadMapping.ts +1 -1
- package/src/mcp-server/tools/uploadMappingsListUploadMappings.ts +1 -1
- package/src/mcp-server/tools/uploadMappingsUpdateUploadMapping.ts +1 -1
- package/src/mcp-server/tools/uploadPresetsCreateUploadPreset.ts +1 -1
- package/src/mcp-server/tools/uploadPresetsDeleteUploadPreset.ts +1 -1
- package/src/mcp-server/tools/uploadPresetsGetUploadPreset.ts +1 -1
- package/src/mcp-server/tools/uploadPresetsListUploadPresets.ts +1 -1
- package/src/mcp-server/tools/uploadPresetsUpdateUploadPreset.ts +1 -1
- package/src/mcp-server/tools.ts +42 -45
package/src/landing-page.ts
CHANGED
|
@@ -12,13 +12,28 @@ import { toolNames } from "./tool-names.js";
|
|
|
12
12
|
// Cloudflare-specific wrapper
|
|
13
13
|
export function landingPage(req: Request): Response {
|
|
14
14
|
const origin = new URL(req.url).origin;
|
|
15
|
-
return new Response(landingPageHTML(origin), {
|
|
15
|
+
return new Response(landingPageHTML(origin, "http", "cloudflare"), {
|
|
16
16
|
headers: { "Content-Type": "text/html" },
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// express wrapper
|
|
21
21
|
export function landingPageExpress(req: ExpressRequest, res: ExpressResponse) {
|
|
22
|
+
sendLandingPage(req, res, "sse");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function landingPageExpressHTTP(
|
|
26
|
+
req: ExpressRequest,
|
|
27
|
+
res: ExpressResponse,
|
|
28
|
+
) {
|
|
29
|
+
sendLandingPage(req, res, "http");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sendLandingPage(
|
|
33
|
+
req: ExpressRequest,
|
|
34
|
+
res: ExpressResponse,
|
|
35
|
+
transport: "sse" | "http",
|
|
36
|
+
) {
|
|
22
37
|
const proto = req.get("x-forwarded-proto")?.split(",")[0]?.trim()
|
|
23
38
|
|| req.protocol;
|
|
24
39
|
const host = req.get("host");
|
|
@@ -26,33 +41,71 @@ export function landingPageExpress(req: ExpressRequest, res: ExpressResponse) {
|
|
|
26
41
|
res.status(400).send("Missing Host header");
|
|
27
42
|
return;
|
|
28
43
|
}
|
|
29
|
-
res.type("html").send(landingPageHTML(`${proto}://${host}
|
|
44
|
+
res.type("html").send(landingPageHTML(`${proto}://${host}`, transport));
|
|
30
45
|
}
|
|
31
46
|
|
|
32
|
-
export function landingPageHTML(
|
|
47
|
+
export function landingPageHTML(
|
|
48
|
+
origin: string,
|
|
49
|
+
transport: "sse" | "http" = "sse",
|
|
50
|
+
runtime: "node" | "cloudflare" = "node",
|
|
51
|
+
): string {
|
|
33
52
|
const o = origin;
|
|
53
|
+
const endpoint = transport === "sse" ? "sse" : "mcp";
|
|
54
|
+
const headers: Array<{ name: string; env: string }> = runtime === "cloudflare"
|
|
55
|
+
? [{ "name": "x-cloudinary-auth", "env": "CLOUDINARY_AUTH" }, {
|
|
56
|
+
"name": "x-oauth2",
|
|
57
|
+
"env": "OAUTH2",
|
|
58
|
+
}]
|
|
59
|
+
: transport === "sse"
|
|
60
|
+
? [{ "name": "api-key", "env": "API_KEY" }, {
|
|
61
|
+
"name": "api-secret",
|
|
62
|
+
"env": "API_SECRET",
|
|
63
|
+
}, { "name": "oauth2", "env": "OAUTH2" }]
|
|
64
|
+
: [
|
|
65
|
+
{ "name": "api-key", "env": "API_KEY" },
|
|
66
|
+
{ "name": "api-secret", "env": "API_SECRET" },
|
|
67
|
+
{ "name": "oauth2", "env": "OAUTH2" },
|
|
68
|
+
{ "name": "cloud-name", "env": "CLOUD_NAME" },
|
|
69
|
+
{ "name": "region", "env": "REGION" },
|
|
70
|
+
{ "name": "api-host", "env": "API_HOST" },
|
|
71
|
+
];
|
|
34
72
|
const mcpConfig = {
|
|
35
|
-
|
|
36
|
-
|
|
73
|
+
command: "npx",
|
|
74
|
+
args: [
|
|
37
75
|
"-y",
|
|
38
76
|
"mcp-remote@0.1.25",
|
|
39
|
-
`${o}
|
|
40
|
-
"--header",
|
|
41
|
-
"api-key:${API_KEY}",
|
|
42
|
-
"--header",
|
|
43
|
-
"api-secret:${API_SECRET}",
|
|
44
|
-
"--header",
|
|
45
|
-
"cloud-name:${CLOUD_NAME}",
|
|
77
|
+
`${o}/${endpoint}`,
|
|
78
|
+
...headers.flatMap(({ name, env }) => ["--header", `${name}:\${${env}}`]),
|
|
46
79
|
],
|
|
47
|
-
|
|
48
|
-
"API_KEY": "YOUR_VALUE_HERE",
|
|
49
|
-
"API_SECRET": "YOUR_VALUE_HERE",
|
|
50
|
-
"CLOUD_NAME": "YOUR_VALUE_HERE",
|
|
51
|
-
},
|
|
80
|
+
env: Object.fromEntries(headers.map(({ env }) => [env, "YOUR_VALUE_HERE"])),
|
|
52
81
|
};
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
const cliHeaders = headers.map(({ name }) => `--header "${name}: ..."`).join(
|
|
83
|
+
" ",
|
|
84
|
+
);
|
|
85
|
+
const codexConfig = transport === "sse"
|
|
86
|
+
? `[mcp_servers.CloudinaryEnvConfig]
|
|
87
|
+
command = ${JSON.stringify(mcpConfig.command)}
|
|
88
|
+
args = ${JSON.stringify(mcpConfig.args)}
|
|
89
|
+
env = { ${
|
|
90
|
+
Object.entries(mcpConfig.env).map(([name, value]) =>
|
|
91
|
+
`${JSON.stringify(name)} = ${JSON.stringify(value)}`
|
|
92
|
+
).join(", ")
|
|
93
|
+
} }`
|
|
94
|
+
: `[mcp_servers.CloudinaryEnvConfig]
|
|
95
|
+
url = ${JSON.stringify(`${o}/${endpoint}`)}
|
|
96
|
+
http_headers = { ${
|
|
97
|
+
headers.map(({ name, env }) =>
|
|
98
|
+
`${JSON.stringify(name)} = ${JSON.stringify(`YOUR_${env}`)}`
|
|
99
|
+
).join(", ")
|
|
100
|
+
} }`;
|
|
101
|
+
const encodedConfig = encodeURIComponent(
|
|
102
|
+
btoa(
|
|
103
|
+
Array.from(
|
|
104
|
+
new TextEncoder().encode(JSON.stringify(mcpConfig)),
|
|
105
|
+
byte => String.fromCharCode(byte),
|
|
106
|
+
).join(""),
|
|
107
|
+
),
|
|
108
|
+
);
|
|
56
109
|
|
|
57
110
|
return `
|
|
58
111
|
<!DOCTYPE html>
|
|
@@ -690,7 +743,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
690
743
|
</svg>
|
|
691
744
|
</button>
|
|
692
745
|
<div class="popover-menu hidden" id="popover-menu">
|
|
693
|
-
<a class="popover-button install-link" href="cursor://anysphere.cursor-deeplink/mcp/install?name=CloudinaryEnvConfig&config
|
|
746
|
+
<a class="popover-button install-link" href="cursor://anysphere.cursor-deeplink/mcp/install?name=CloudinaryEnvConfig&config=${encodedConfig}">
|
|
694
747
|
Cursor
|
|
695
748
|
</a>
|
|
696
749
|
<button class="popover-button" onclick="showModal('claude-code')">
|
|
@@ -699,7 +752,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
699
752
|
<button class="popover-button" onclick="showModal('claude-desktop')">
|
|
700
753
|
Claude Desktop
|
|
701
754
|
</button>
|
|
702
|
-
<a class="popover-button install-link" href="vscode://ms-vscode.vscode-mcp/install?name=CloudinaryEnvConfig&config
|
|
755
|
+
<a class="popover-button install-link" href="vscode://ms-vscode.vscode-mcp/install?name=CloudinaryEnvConfig&config=${encodedConfig}">
|
|
703
756
|
VS Code
|
|
704
757
|
</a>
|
|
705
758
|
<button class="popover-button" onclick="showModal('gemini')">
|
|
@@ -722,7 +775,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
722
775
|
</div>
|
|
723
776
|
</header>
|
|
724
777
|
<div class="install-targets">
|
|
725
|
-
<a tabindex="0" class="card install-target install-link" href="cursor://anysphere.cursor-deeplink/mcp/install?name=CloudinaryEnvConfig&config
|
|
778
|
+
<a tabindex="0" class="card install-target install-link" href="cursor://anysphere.cursor-deeplink/mcp/install?name=CloudinaryEnvConfig&config=${encodedConfig}">
|
|
726
779
|
<div class="target">
|
|
727
780
|
<img src="https://cursor.com/assets/images/logo.svg" alt="Cursor">
|
|
728
781
|
<span>Cursor</span>
|
|
@@ -744,7 +797,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
744
797
|
<span>Claude Desktop</span>
|
|
745
798
|
</div>
|
|
746
799
|
</div>
|
|
747
|
-
<a tabindex="0" class="card install-target install-link" href="vscode://ms-vscode.vscode-mcp/install?name=CloudinaryEnvConfig&config
|
|
800
|
+
<a tabindex="0" class="card install-target install-link" href="vscode://ms-vscode.vscode-mcp/install?name=CloudinaryEnvConfig&config=${encodedConfig}">
|
|
748
801
|
<div class="target">
|
|
749
802
|
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
750
803
|
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
|
|
@@ -866,7 +919,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
866
919
|
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
|
|
867
920
|
</svg>
|
|
868
921
|
</button>
|
|
869
|
-
<code class="code-snippet" id="server-url">${o}
|
|
922
|
+
<code class="code-snippet" id="server-url">${o}/${endpoint}</code>
|
|
870
923
|
</div>
|
|
871
924
|
</section>
|
|
872
925
|
|
|
@@ -923,7 +976,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
923
976
|
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
|
|
924
977
|
</svg>
|
|
925
978
|
</button>
|
|
926
|
-
<code class="code-snippet language-json" id="claude-cli-cmd">claude mcp add
|
|
979
|
+
<code class="code-snippet language-json" id="claude-cli-cmd">claude mcp add --transport ${transport} CloudinaryEnvConfig ${o}/${endpoint} ${cliHeaders}</code>
|
|
927
980
|
</div>
|
|
928
981
|
</div>
|
|
929
982
|
</div>
|
|
@@ -939,7 +992,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
939
992
|
<h1>Instructions</h1>
|
|
940
993
|
<p>One-click installation for Claude Desktop users</p>
|
|
941
994
|
<div class="instruction-item">
|
|
942
|
-
<a href="https://github.com/cloudinary/environment-config-mcp/releases/download/v0.6.
|
|
995
|
+
<a href="https://github.com/cloudinary/environment-config-mcp/releases/download/v0.6.3/mcp-server.mcpb" download="mcp-server.mcpb" class="action-button header-action" style="display: inline-flex; margin-bottom: 16px;">
|
|
943
996
|
📥 Download MCP Bundle
|
|
944
997
|
</a>
|
|
945
998
|
</div>
|
|
@@ -974,7 +1027,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
974
1027
|
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
|
|
975
1028
|
</svg>
|
|
976
1029
|
</button>
|
|
977
|
-
<code class="code-snippet language-json" id="gemini-config">gemini mcp add
|
|
1030
|
+
<code class="code-snippet language-json" id="gemini-config">gemini mcp add --transport ${transport} CloudinaryEnvConfig ${o}/${endpoint} ${cliHeaders}</code>
|
|
978
1031
|
</div>
|
|
979
1032
|
</div>
|
|
980
1033
|
</div>
|
package/src/lib/config.ts
CHANGED
|
@@ -113,8 +113,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
|
|
|
113
113
|
export const SDK_METADATA = {
|
|
114
114
|
language: "typescript",
|
|
115
115
|
openapiDocVersion: "0.5.5",
|
|
116
|
-
sdkVersion: "0.6.
|
|
117
|
-
genVersion: "2.
|
|
116
|
+
sdkVersion: "0.6.3",
|
|
117
|
+
genVersion: "2.950.2",
|
|
118
118
|
userAgent:
|
|
119
|
-
"speakeasy-sdk/mcp-typescript 0.6.
|
|
119
|
+
"speakeasy-sdk/mcp-typescript 0.6.3 2.950.2 0.5.5 @cloudinary/environment-config-mcp",
|
|
120
120
|
} as const;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @generated-id: 03e83f226068
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
6
|
+
import { toNodeHandler } from "@modelcontextprotocol/node";
|
|
7
|
+
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
8
8
|
import express from "express";
|
|
9
9
|
import { LocalContext } from "../../cli.js";
|
|
10
10
|
import {
|
|
@@ -16,7 +16,7 @@ import { createMCPServer } from "../../server.js";
|
|
|
16
16
|
import { buildAnnotationFilter } from "../../tools.js";
|
|
17
17
|
import { buildSDK } from "../../tools.js";
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { landingPageExpressHTTP } from "../../../landing-page.js";
|
|
20
20
|
|
|
21
21
|
interface ServeCommandFlags extends MCPServerFlags {
|
|
22
22
|
readonly port: number;
|
|
@@ -40,7 +40,7 @@ async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
|
40
40
|
// Enable CORS for cross-origin requests
|
|
41
41
|
app.use((req, res, next) => {
|
|
42
42
|
res.header("Access-Control-Allow-Origin", "*");
|
|
43
|
-
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
43
|
+
res.header("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
44
44
|
res.header("Access-Control-Allow-Headers", "*");
|
|
45
45
|
if (req.method === "OPTIONS") {
|
|
46
46
|
res.sendStatus(204);
|
|
@@ -49,19 +49,10 @@ async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
|
49
49
|
next();
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
app.use(express.json());
|
|
52
|
+
app.use(express.json({ inflate: false }));
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
const headers = new Headers();
|
|
56
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
57
|
-
if (Array.isArray(value)) {
|
|
58
|
-
for (const v of value) headers.append(key, v);
|
|
59
|
-
} else if (value !== undefined) {
|
|
60
|
-
headers.set(key, value);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const transport = new StreamableHTTPServerTransport({});
|
|
54
|
+
const handler = createMcpHandler(({ requestInfo }) => {
|
|
55
|
+
const headers = requestInfo?.headers ?? new Headers();
|
|
65
56
|
|
|
66
57
|
const { server: mcpServer } = createMCPServer({
|
|
67
58
|
logger,
|
|
@@ -85,11 +76,41 @@ async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
|
85
76
|
});
|
|
86
77
|
};
|
|
87
78
|
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
return mcpServer;
|
|
80
|
+
});
|
|
81
|
+
const nodeHandler = toNodeHandler(handler);
|
|
82
|
+
const activeResponses = new Set<Promise<void>>();
|
|
83
|
+
let closing = false;
|
|
84
|
+
app.use((_req, res, next) => {
|
|
85
|
+
if (closing) {
|
|
86
|
+
res.set("Connection", "close").status(503).send(
|
|
87
|
+
"Server is shutting down",
|
|
88
|
+
);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
next();
|
|
92
|
+
});
|
|
93
|
+
app.all("/mcp", (req, res) => {
|
|
94
|
+
// Notification streams remain open until handler.close().
|
|
95
|
+
if (req.method !== "GET" && req.body?.method !== "subscriptions/listen") {
|
|
96
|
+
let finish!: () => void;
|
|
97
|
+
const completed = new Promise<void>((resolve) => {
|
|
98
|
+
finish = resolve;
|
|
99
|
+
});
|
|
100
|
+
const done = () => {
|
|
101
|
+
res.off("finish", done);
|
|
102
|
+
res.off("close", done);
|
|
103
|
+
activeResponses.delete(completed);
|
|
104
|
+
finish();
|
|
105
|
+
};
|
|
106
|
+
activeResponses.add(completed);
|
|
107
|
+
res.once("finish", done);
|
|
108
|
+
res.once("close", done);
|
|
109
|
+
}
|
|
110
|
+
return nodeHandler(req, res, req.body);
|
|
90
111
|
});
|
|
91
112
|
|
|
92
|
-
app.get("/",
|
|
113
|
+
app.get("/", landingPageExpressHTTP);
|
|
93
114
|
|
|
94
115
|
const httpServer = app.listen(cliFlags.port, "0.0.0.0", () => {
|
|
95
116
|
const ha = httpServer.address();
|
|
@@ -97,7 +118,11 @@ async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
|
97
118
|
logger.info("MCP Streamable HTTP server started", { host });
|
|
98
119
|
});
|
|
99
120
|
|
|
100
|
-
const shutdown = () => {
|
|
121
|
+
const shutdown = async () => {
|
|
122
|
+
if (closing) {
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
closing = true;
|
|
101
126
|
logger.info("Shutting down HTTP server");
|
|
102
127
|
|
|
103
128
|
const timer = setTimeout(() => {
|
|
@@ -105,11 +130,16 @@ async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
|
105
130
|
process.exit(1);
|
|
106
131
|
}, 5000);
|
|
107
132
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
133
|
+
const stopped = new Promise<void>((resolve) =>
|
|
134
|
+
httpServer.close(() => resolve())
|
|
135
|
+
);
|
|
136
|
+
await Promise.all(activeResponses);
|
|
137
|
+
await handler.close();
|
|
138
|
+
httpServer.closeAllConnections();
|
|
139
|
+
await stopped;
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
logger.info("Graceful shutdown complete");
|
|
142
|
+
process.exit(0);
|
|
113
143
|
};
|
|
114
144
|
|
|
115
145
|
process.on("SIGTERM", shutdown);
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @generated-id: 37494f674015
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { SSEServerTransport } from "@modelcontextprotocol/
|
|
7
|
-
import {
|
|
6
|
+
import { SSEServerTransport } from "@modelcontextprotocol/server-legacy/sse";
|
|
7
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
8
8
|
import express from "express";
|
|
9
9
|
import { LocalContext } from "../../cli.js";
|
|
10
10
|
import {
|
|
@@ -49,8 +49,7 @@ export async function main(this: LocalContext, flags: StartCommandFlags) {
|
|
|
49
49
|
|
|
50
50
|
async function startStdio(flags: StartCommandFlags) {
|
|
51
51
|
const logger = createConsoleLogger(flags["log-level"]);
|
|
52
|
-
const
|
|
53
|
-
const { server } = createMCPServer({
|
|
52
|
+
const createServer = createMCPServerFactory({
|
|
54
53
|
logger,
|
|
55
54
|
allowedTools: flags.tool,
|
|
56
55
|
dynamic: flags.mode === "dynamic",
|
|
@@ -71,16 +70,22 @@ async function startStdio(flags: StartCommandFlags) {
|
|
|
71
70
|
region: flags.region,
|
|
72
71
|
host: flags["api-host"],
|
|
73
72
|
});
|
|
74
|
-
|
|
73
|
+
const handle = serveStdio(createServer);
|
|
75
74
|
|
|
76
75
|
const abort = async () => {
|
|
77
|
-
await
|
|
76
|
+
await handle.close();
|
|
78
77
|
process.exit(0);
|
|
79
78
|
};
|
|
80
79
|
process.on("SIGTERM", abort);
|
|
81
80
|
process.on("SIGINT", abort);
|
|
82
81
|
}
|
|
83
82
|
|
|
83
|
+
function createMCPServerFactory(
|
|
84
|
+
options: Parameters<typeof createMCPServer>[0],
|
|
85
|
+
) {
|
|
86
|
+
return () => createMCPServer(options).server;
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
async function startSSE(cliFlags: StartCommandFlags) {
|
|
85
90
|
const logger = createConsoleLogger(cliFlags["log-level"]);
|
|
86
91
|
const app = express();
|
|
@@ -108,9 +113,11 @@ async function startSSE(cliFlags: StartCommandFlags) {
|
|
|
108
113
|
const flags: StartCommandFlags = {
|
|
109
114
|
...cliFlags,
|
|
110
115
|
// Security fields can be overridden via headers
|
|
111
|
-
"api-key": (req.headers["
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
"api-key": ((req.headers["api-key"] ?? req.headers["api_key"]) as string)
|
|
117
|
+
?? cliFlags["api-key"],
|
|
118
|
+
"api-secret":
|
|
119
|
+
((req.headers["api-secret"] ?? req.headers["api_secret"]) as string)
|
|
120
|
+
?? cliFlags["api-secret"],
|
|
114
121
|
"oauth2": (req.headers["oauth2"] as string) ?? cliFlags["oauth2"],
|
|
115
122
|
};
|
|
116
123
|
|
|
@@ -3,18 +3,16 @@
|
|
|
3
3
|
* @generated-id: 3d9d20ff158f
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import * as z from "zod";
|
|
7
7
|
import { PromptDefinition } from "./prompts.js";
|
|
8
8
|
import { ResourceDefinition, ResourceTemplateDefinition } from "./resources.js";
|
|
9
9
|
import { ToolDefinition } from "./tools.js";
|
|
10
10
|
|
|
11
11
|
export type Register = {
|
|
12
|
-
tool: <A extends
|
|
13
|
-
def: ToolDefinition<A>,
|
|
14
|
-
) => void;
|
|
12
|
+
tool: <A extends z.ZodRawShape | undefined>(def: ToolDefinition<A>) => void;
|
|
15
13
|
resource: (def: ResourceDefinition) => void;
|
|
16
14
|
resourceTemplate: (def: ResourceTemplateDefinition) => void;
|
|
17
|
-
prompt: <A extends
|
|
15
|
+
prompt: <A extends z.ZodRawShape | undefined>(
|
|
18
16
|
prompt: PromptDefinition<A>,
|
|
19
17
|
) => void;
|
|
20
18
|
};
|
|
@@ -3,32 +3,28 @@
|
|
|
3
3
|
* @generated-id: 26f3d73cbf31
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { McpServer } from "@modelcontextprotocol/
|
|
7
|
-
import
|
|
8
|
-
ShapeOutput,
|
|
9
|
-
ZodRawShapeCompat,
|
|
10
|
-
} from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
11
|
-
import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
12
|
-
import {
|
|
13
|
-
GetPromptResult,
|
|
14
|
-
ServerNotification,
|
|
15
|
-
ServerRequest,
|
|
16
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { GetPromptResult, McpServer } from "@modelcontextprotocol/server";
|
|
7
|
+
import * as z from "zod";
|
|
17
8
|
import { CloudinaryEnvConfigCore } from "../core.js";
|
|
18
9
|
import { ConsoleLogger } from "./console-logger.js";
|
|
19
10
|
import { MCPScope } from "./scopes.js";
|
|
11
|
+
import {
|
|
12
|
+
mcpInputSchema,
|
|
13
|
+
MCPServerContext,
|
|
14
|
+
mcpServerContext,
|
|
15
|
+
} from "./shared.js";
|
|
20
16
|
|
|
21
17
|
export type PromptDefinition<
|
|
22
|
-
Args extends undefined |
|
|
23
|
-
> = Args extends
|
|
18
|
+
Args extends undefined | z.ZodRawShape = undefined,
|
|
19
|
+
> = Args extends z.ZodRawShape ? {
|
|
24
20
|
name: string;
|
|
25
21
|
description?: string;
|
|
26
22
|
scopes?: MCPScope[];
|
|
27
23
|
args: Args;
|
|
28
24
|
prompt: (
|
|
29
25
|
client: CloudinaryEnvConfigCore,
|
|
30
|
-
args:
|
|
31
|
-
extra:
|
|
26
|
+
args: z.output<z.ZodObject<Args>>,
|
|
27
|
+
extra: MCPServerContext,
|
|
32
28
|
) => GetPromptResult | Promise<GetPromptResult>;
|
|
33
29
|
}
|
|
34
30
|
: {
|
|
@@ -38,7 +34,7 @@ export type PromptDefinition<
|
|
|
38
34
|
args?: undefined;
|
|
39
35
|
prompt: (
|
|
40
36
|
client: CloudinaryEnvConfigCore,
|
|
41
|
-
extra:
|
|
37
|
+
extra: MCPServerContext,
|
|
42
38
|
) => GetPromptResult | Promise<GetPromptResult>;
|
|
43
39
|
};
|
|
44
40
|
|
|
@@ -62,10 +58,8 @@ export function createRegisterPrompt(
|
|
|
62
58
|
server: McpServer,
|
|
63
59
|
getSDK: () => CloudinaryEnvConfigCore,
|
|
64
60
|
allowedScopes: Set<MCPScope>,
|
|
65
|
-
): <A extends
|
|
66
|
-
|
|
67
|
-
) => void {
|
|
68
|
-
return <A extends ZodRawShapeCompat | undefined>(
|
|
61
|
+
): <A extends z.ZodRawShape | undefined>(prompt: PromptDefinition<A>) => void {
|
|
62
|
+
return <A extends z.ZodRawShape | undefined>(
|
|
69
63
|
prompt: PromptDefinition<A>,
|
|
70
64
|
): void => {
|
|
71
65
|
const scopes = prompt.scopes ?? [];
|
|
@@ -81,30 +75,23 @@ export function createRegisterPrompt(
|
|
|
81
75
|
}
|
|
82
76
|
|
|
83
77
|
if (prompt.args) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
prompt.description
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
prompt.
|
|
94
|
-
|
|
95
|
-
async (args, ctx) => prompt.prompt(getSDK(), args, ctx),
|
|
96
|
-
);
|
|
97
|
-
}
|
|
78
|
+
server.registerPrompt(
|
|
79
|
+
prompt.name,
|
|
80
|
+
{
|
|
81
|
+
...(prompt.description === undefined
|
|
82
|
+
? {}
|
|
83
|
+
: { description: prompt.description }),
|
|
84
|
+
argsSchema: { ...mcpInputSchema(prompt.args), shape: prompt.args },
|
|
85
|
+
},
|
|
86
|
+
async (args, ctx) =>
|
|
87
|
+
prompt.prompt(getSDK(), args, mcpServerContext(ctx)),
|
|
88
|
+
);
|
|
98
89
|
} else {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
prompt.description,
|
|
103
|
-
|
|
104
|
-
);
|
|
105
|
-
} else {
|
|
106
|
-
server.prompt(prompt.name, async (ctx) => prompt.prompt(getSDK(), ctx));
|
|
107
|
-
}
|
|
90
|
+
server.registerPrompt(prompt.name, {
|
|
91
|
+
...(prompt.description === undefined
|
|
92
|
+
? {}
|
|
93
|
+
: { description: prompt.description }),
|
|
94
|
+
}, async (ctx) => prompt.prompt(getSDK(), mcpServerContext(ctx)));
|
|
108
95
|
}
|
|
109
96
|
|
|
110
97
|
logger.debug("Registered prompt", { name: prompt.name });
|
|
@@ -3,27 +3,23 @@
|
|
|
3
3
|
* @generated-id: cb0c57ebeaea
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { ResourceTemplate as LegacyResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import {
|
|
7
8
|
McpServer,
|
|
9
|
+
ReadResourceResult,
|
|
8
10
|
ResourceMetadata,
|
|
9
11
|
ResourceTemplate,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import { Variables } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
|
|
13
|
-
import {
|
|
14
|
-
ReadResourceResult,
|
|
15
|
-
ServerNotification,
|
|
16
|
-
ServerRequest,
|
|
17
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
Variables,
|
|
13
|
+
} from "@modelcontextprotocol/server";
|
|
18
14
|
import { CloudinaryEnvConfigCore } from "../core.js";
|
|
19
15
|
import { ConsoleLogger } from "./console-logger.js";
|
|
20
16
|
import { MCPScope } from "./scopes.js";
|
|
21
|
-
import { valueToBase64 } from "./shared.js";
|
|
17
|
+
import { MCPServerContext, mcpServerContext, valueToBase64 } from "./shared.js";
|
|
22
18
|
|
|
23
19
|
export type ReadResourceCallback = (
|
|
24
20
|
client: CloudinaryEnvConfigCore,
|
|
25
21
|
uri: URL,
|
|
26
|
-
extra:
|
|
22
|
+
extra: MCPServerContext,
|
|
27
23
|
) => ReadResourceResult | Promise<ReadResourceResult>;
|
|
28
24
|
|
|
29
25
|
export type ResourceDefinition = {
|
|
@@ -39,7 +35,7 @@ export type ReadResourceTemplateCallback = (
|
|
|
39
35
|
client: CloudinaryEnvConfigCore,
|
|
40
36
|
uri: URL,
|
|
41
37
|
vars: Variables,
|
|
42
|
-
extra:
|
|
38
|
+
extra: MCPServerContext,
|
|
43
39
|
) => ReadResourceResult | Promise<ReadResourceResult>;
|
|
44
40
|
|
|
45
41
|
export type ResourceTemplateDefinition = {
|
|
@@ -47,7 +43,7 @@ export type ResourceTemplateDefinition = {
|
|
|
47
43
|
description: string;
|
|
48
44
|
metadata?: ResourceMetadata;
|
|
49
45
|
scopes?: MCPScope[];
|
|
50
|
-
resource: ResourceTemplate;
|
|
46
|
+
resource: ResourceTemplate | LegacyResourceTemplate;
|
|
51
47
|
read: ReadResourceTemplateCallback;
|
|
52
48
|
};
|
|
53
49
|
|
|
@@ -95,11 +91,11 @@ export function createRegisterResource(
|
|
|
95
91
|
description: resource.description,
|
|
96
92
|
};
|
|
97
93
|
|
|
98
|
-
server.
|
|
94
|
+
server.registerResource(
|
|
99
95
|
resource.name,
|
|
100
96
|
resource.resource,
|
|
101
97
|
metadata,
|
|
102
|
-
async (uri, ctx) => resource.read(getSDK(), uri, ctx),
|
|
98
|
+
async (uri, ctx) => resource.read(getSDK(), uri, mcpServerContext(ctx)),
|
|
103
99
|
);
|
|
104
100
|
|
|
105
101
|
logger.debug("Registered resource", { name: resource.name });
|
|
@@ -130,13 +126,32 @@ export function createRegisterResourceTemplate(
|
|
|
130
126
|
description: resource.description,
|
|
131
127
|
};
|
|
132
128
|
|
|
133
|
-
server.
|
|
129
|
+
server.registerResource(
|
|
134
130
|
resource.name,
|
|
135
|
-
resource.resource,
|
|
131
|
+
normalizeResourceTemplate(resource.resource),
|
|
136
132
|
metadata,
|
|
137
|
-
async (uri, vars, ctx) =>
|
|
133
|
+
async (uri, vars, ctx) =>
|
|
134
|
+
resource.read(getSDK(), uri, vars, mcpServerContext(ctx)),
|
|
138
135
|
);
|
|
139
136
|
|
|
140
137
|
logger.debug("Registered resource template", { name: resource.name });
|
|
141
138
|
};
|
|
142
139
|
}
|
|
140
|
+
|
|
141
|
+
function normalizeResourceTemplate(
|
|
142
|
+
resource: ResourceTemplate | LegacyResourceTemplate,
|
|
143
|
+
): ResourceTemplate {
|
|
144
|
+
if (resource instanceof ResourceTemplate) return resource;
|
|
145
|
+
const complete: NonNullable<
|
|
146
|
+
ConstructorParameters<typeof ResourceTemplate>[1]["complete"]
|
|
147
|
+
> = {};
|
|
148
|
+
for (const variable of resource.uriTemplate.variableNames) {
|
|
149
|
+
const callback = resource.completeCallback(variable);
|
|
150
|
+
if (callback) complete[variable] = callback;
|
|
151
|
+
}
|
|
152
|
+
const list = resource.listCallback;
|
|
153
|
+
return new ResourceTemplate(resource.uriTemplate.toString(), {
|
|
154
|
+
list: list ? (ctx) => list(mcpServerContext(ctx)) : undefined,
|
|
155
|
+
complete,
|
|
156
|
+
});
|
|
157
|
+
}
|
package/src/mcp-server/server.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @generated-id: 2784dd48e82a
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { McpServer } from "@modelcontextprotocol/
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
7
7
|
import { CloudinaryEnvConfigCore } from "../core.js";
|
|
8
8
|
import { SDKOptions } from "../lib/config.js";
|
|
9
9
|
import type { ConsoleLogger } from "./console-logger.js";
|
|
@@ -60,7 +60,7 @@ export function createMCPServer(deps: {
|
|
|
60
60
|
}) {
|
|
61
61
|
const server = new McpServer({
|
|
62
62
|
name: "CloudinaryEnvConfig",
|
|
63
|
-
version: "0.6.
|
|
63
|
+
version: "0.6.3",
|
|
64
64
|
...serverInfo,
|
|
65
65
|
}, { instructions });
|
|
66
66
|
|