@cloudinary/asset-management-mcp 0.7.0 → 0.8.0
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 +46 -2
- package/bin/mcp-server.js +6852 -5586
- package/bin/mcp-server.js.map +30 -25
- package/esm/funcs/foldersAssignFolderRoles.d.ts +19 -0
- package/esm/funcs/foldersAssignFolderRoles.d.ts.map +1 -0
- package/esm/funcs/foldersAssignFolderRoles.js +101 -0
- package/esm/funcs/foldersAssignFolderRoles.js.map +1 -0
- package/esm/funcs/foldersGetFolderRoles.d.ts +15 -0
- package/esm/funcs/foldersGetFolderRoles.d.ts.map +1 -0
- package/esm/funcs/foldersGetFolderRoles.js +99 -0
- package/esm/funcs/foldersGetFolderRoles.js.map +1 -0
- package/esm/funcs/peopleGetPerson.d.ts +16 -0
- package/esm/funcs/peopleGetPerson.d.ts.map +1 -0
- package/esm/funcs/peopleGetPerson.js +95 -0
- package/esm/funcs/peopleGetPerson.js.map +1 -0
- package/esm/funcs/peopleListPeople.d.ts +19 -0
- package/esm/funcs/peopleListPeople.d.ts.map +1 -0
- package/esm/funcs/peopleListPeople.js +107 -0
- package/esm/funcs/peopleListPeople.js.map +1 -0
- package/esm/funcs/peopleUpdatePerson.d.ts +18 -0
- package/esm/funcs/peopleUpdatePerson.d.ts.map +1 -0
- package/esm/funcs/peopleUpdatePerson.js +98 -0
- package/esm/funcs/peopleUpdatePerson.js.map +1 -0
- package/esm/funcs/videoAnalyticsGetVideoViews.d.ts +2 -2
- package/esm/funcs/videoAnalyticsGetVideoViews.d.ts.map +1 -1
- package/esm/funcs/videoAnalyticsGetVideoViews.js.map +1 -1
- package/esm/landing-page.js +1 -1
- package/esm/lib/config.d.ts +4 -4
- package/esm/lib/config.js +4 -4
- package/esm/lib/security.d.ts.map +1 -1
- package/esm/lib/security.js.map +1 -1
- package/esm/mcp-server/cli/serve/command.d.ts +2 -0
- package/esm/mcp-server/cli/serve/command.d.ts.map +1 -0
- package/esm/mcp-server/cli/serve/command.js +140 -0
- package/esm/mcp-server/cli/serve/command.js.map +1 -0
- package/esm/mcp-server/cli/serve/impl.d.ts +12 -0
- package/esm/mcp-server/cli/serve/impl.d.ts.map +1 -0
- package/esm/mcp-server/cli/serve/impl.js +85 -0
- package/esm/mcp-server/cli/serve/impl.js.map +1 -0
- package/esm/mcp-server/mcp-server.d.ts.map +1 -1
- package/esm/mcp-server/mcp-server.js +3 -1
- package/esm/mcp-server/mcp-server.js.map +1 -1
- package/esm/mcp-server/server.js +1 -1
- package/esm/mcp-server/tools.d.ts +4 -0
- package/esm/mcp-server/tools.d.ts.map +1 -1
- package/esm/mcp-server/tools.js +40 -0
- package/esm/mcp-server/tools.js.map +1 -1
- package/esm/models/assignfolderrolesop.d.ts +16 -0
- package/esm/models/assignfolderrolesop.d.ts.map +1 -0
- package/esm/models/assignfolderrolesop.js +20 -0
- package/esm/models/assignfolderrolesop.js.map +1 -0
- package/esm/models/assignfolderrolesrequest.d.ts +33 -0
- package/esm/models/assignfolderrolesrequest.d.ts.map +1 -0
- package/esm/models/assignfolderrolesrequest.js +26 -0
- package/esm/models/assignfolderrolesrequest.js.map +1 -0
- package/esm/models/destroyassetop.d.ts +5 -3
- package/esm/models/destroyassetop.d.ts.map +1 -1
- package/esm/models/destroyassetop.js +5 -3
- package/esm/models/destroyassetop.js.map +1 -1
- package/esm/models/explicitassetop.d.ts +1 -67
- package/esm/models/explicitassetop.d.ts.map +1 -1
- package/esm/models/explicitassetop.js +1 -44
- package/esm/models/explicitassetop.js.map +1 -1
- package/esm/models/folderrole.d.ts +9 -0
- package/esm/models/folderrole.d.ts.map +1 -0
- package/esm/models/folderrole.js +11 -0
- package/esm/models/folderrole.js.map +1 -0
- package/esm/models/folderroleassignment.d.ts +11 -0
- package/esm/models/folderroleassignment.d.ts.map +1 -0
- package/esm/models/folderroleassignment.js +14 -0
- package/esm/models/folderroleassignment.js.map +1 -0
- package/esm/models/folderrolesresponse.d.ts +9 -0
- package/esm/models/folderrolesresponse.d.ts.map +1 -0
- package/esm/models/folderrolesresponse.js +12 -0
- package/esm/models/folderrolesresponse.js.map +1 -0
- package/esm/models/getfolderrolesop.d.ts +15 -0
- package/esm/models/getfolderrolesop.d.ts.map +1 -0
- package/esm/models/getfolderrolesop.js +18 -0
- package/esm/models/getfolderrolesop.js.map +1 -0
- package/esm/models/getpersonop.d.ts +21 -0
- package/esm/models/getpersonop.d.ts.map +1 -0
- package/esm/models/getpersonop.js +21 -0
- package/esm/models/getpersonop.js.map +1 -0
- package/esm/models/getvideoviewsop.d.ts +4 -4
- package/esm/models/getvideoviewsop.d.ts.map +1 -1
- package/esm/models/getvideoviewsop.js +3 -3
- package/esm/models/getvideoviewsop.js.map +1 -1
- package/esm/models/info.d.ts +25 -12
- package/esm/models/info.d.ts.map +1 -1
- package/esm/models/info.js +26 -8
- package/esm/models/info.js.map +1 -1
- package/esm/models/listpeopleop.d.ts +69 -0
- package/esm/models/listpeopleop.d.ts.map +1 -0
- package/esm/models/listpeopleop.js +60 -0
- package/esm/models/listpeopleop.js.map +1 -0
- package/esm/models/listresourcesbymoderationkindandstatusop.d.ts +1 -1
- package/esm/models/parametersdirection.d.ts +18 -0
- package/esm/models/parametersdirection.d.ts.map +1 -0
- package/esm/models/parametersdirection.js +16 -0
- package/esm/models/parametersdirection.js.map +1 -0
- package/esm/models/permittedrole.d.ts +8 -0
- package/esm/models/permittedrole.d.ts.map +1 -0
- package/esm/models/permittedrole.js +10 -0
- package/esm/models/permittedrole.js.map +1 -0
- package/esm/models/persondetails.d.ts +16 -0
- package/esm/models/persondetails.d.ts.map +1 -0
- package/esm/models/persondetails.js +15 -0
- package/esm/models/persondetails.js.map +1 -0
- package/esm/models/personstatus.d.ts +18 -0
- package/esm/models/personstatus.d.ts.map +1 -0
- package/esm/models/personstatus.js +16 -0
- package/esm/models/personstatus.js.map +1 -0
- package/esm/models/principaltype.d.ts +20 -0
- package/esm/models/principaltype.d.ts.map +1 -0
- package/esm/models/principaltype.js +18 -0
- package/esm/models/principaltype.js.map +1 -0
- package/esm/models/resourceupdaterequest.d.ts +4 -68
- package/esm/models/resourceupdaterequest.d.ts.map +1 -1
- package/esm/models/resourceupdaterequest.js +4 -53
- package/esm/models/resourceupdaterequest.js.map +1 -1
- package/esm/models/searchparameters.d.ts +1 -1
- package/esm/models/searchresponse.d.ts +4 -0
- package/esm/models/searchresponse.d.ts.map +1 -1
- package/esm/models/searchresponse.js +4 -0
- package/esm/models/searchresponse.js.map +1 -1
- package/esm/models/successresponse.d.ts +6 -0
- package/esm/models/successresponse.d.ts.map +1 -0
- package/esm/models/successresponse.js +8 -0
- package/esm/models/successresponse.js.map +1 -0
- package/esm/models/textop.d.ts +15 -15
- package/esm/models/textop.d.ts.map +1 -1
- package/esm/models/textop.js +15 -15
- package/esm/models/textop.js.map +1 -1
- package/esm/models/thumbnail.d.ts +15 -0
- package/esm/models/thumbnail.d.ts.map +1 -0
- package/esm/models/thumbnail.js +14 -0
- package/esm/models/thumbnail.js.map +1 -0
- package/esm/models/updatepersonop.d.ts +30 -0
- package/esm/models/updatepersonop.d.ts.map +1 -0
- package/esm/models/updatepersonop.js +31 -0
- package/esm/models/updatepersonop.js.map +1 -0
- package/esm/models/uploadrequest.d.ts +4 -136
- package/esm/models/uploadrequest.d.ts.map +1 -1
- package/esm/models/uploadrequest.js +4 -96
- package/esm/models/uploadrequest.js.map +1 -1
- package/package.json +1 -1
- package/src/funcs/foldersAssignFolderRoles.ts +173 -0
- package/src/funcs/foldersGetFolderRoles.ts +170 -0
- package/src/funcs/peopleGetPerson.ts +161 -0
- package/src/funcs/peopleListPeople.ts +195 -0
- package/src/funcs/peopleUpdatePerson.ts +168 -0
- package/src/funcs/videoAnalyticsGetVideoViews.ts +3 -3
- package/src/landing-page.ts +1 -1
- package/src/lib/config.ts +4 -4
- package/src/lib/security.ts +4 -1
- package/src/mcp-server/cli/serve/command.ts +147 -0
- package/src/mcp-server/cli/serve/impl.ts +114 -0
- package/src/mcp-server/mcp-server.ts +3 -1
- package/src/mcp-server/server.ts +1 -1
- package/src/mcp-server/tools.ts +89 -0
- package/src/models/assignfolderrolesop.ts +46 -0
- package/src/models/assignfolderrolesrequest.ts +52 -0
- package/src/models/destroyassetop.ts +7 -5
- package/src/models/explicitassetop.ts +2 -74
- package/src/models/folderrole.ts +19 -0
- package/src/models/folderroleassignment.ts +22 -0
- package/src/models/folderrolesresponse.ts +21 -0
- package/src/models/getfolderrolesop.ts +43 -0
- package/src/models/getpersonop.ts +43 -0
- package/src/models/getvideoviewsop.ts +5 -5
- package/src/models/info.ts +53 -17
- package/src/models/listpeopleop.ts +114 -0
- package/src/models/parametersdirection.ts +23 -0
- package/src/models/permittedrole.ts +13 -0
- package/src/models/persondetails.ts +28 -0
- package/src/models/personstatus.ts +23 -0
- package/src/models/principaltype.ts +25 -0
- package/src/models/resourceupdaterequest.ts +8 -87
- package/src/models/searchresponse.ts +4 -0
- package/src/models/successresponse.ts +11 -0
- package/src/models/textop.ts +30 -30
- package/src/models/thumbnail.ts +28 -0
- package/src/models/updatepersonop.ts +66 -0
- package/src/models/uploadrequest.ts +8 -162
- package/_speakeasy/.github/action-inputs-config.json +0 -53
- package/_speakeasy/.github/action-security-config.json +0 -88
- package/manifest.json +0 -169
- package/tsconfig.json +0 -35
|
@@ -21,7 +21,7 @@ import { SDKValidationError } from "../models/errors/sdkvalidationerror.js";
|
|
|
21
21
|
import {
|
|
22
22
|
GetVideoViewsRequest,
|
|
23
23
|
GetVideoViewsRequest$zodSchema,
|
|
24
|
-
|
|
24
|
+
GetVideoViewsSortBy,
|
|
25
25
|
} from "../models/getvideoviewsop.js";
|
|
26
26
|
import { APICall, APIPromise } from "../types/async.js";
|
|
27
27
|
import { Result } from "../types/fp.js";
|
|
@@ -37,7 +37,7 @@ export function videoAnalyticsGetVideoViews(
|
|
|
37
37
|
client$: CloudinaryAssetMgmtCore,
|
|
38
38
|
expression?: string | undefined,
|
|
39
39
|
max_results?: number | undefined,
|
|
40
|
-
sort_by?:
|
|
40
|
+
sort_by?: GetVideoViewsSortBy | undefined,
|
|
41
41
|
next_cursor?: string | undefined,
|
|
42
42
|
options?: RequestOptions,
|
|
43
43
|
): APIPromise<
|
|
@@ -66,7 +66,7 @@ async function $do(
|
|
|
66
66
|
client$: CloudinaryAssetMgmtCore,
|
|
67
67
|
expression?: string | undefined,
|
|
68
68
|
max_results?: number | undefined,
|
|
69
|
-
sort_by?:
|
|
69
|
+
sort_by?: GetVideoViewsSortBy | undefined,
|
|
70
70
|
next_cursor?: string | undefined,
|
|
71
71
|
options?: RequestOptions,
|
|
72
72
|
): Promise<
|
package/src/landing-page.ts
CHANGED
|
@@ -932,7 +932,7 @@ http_headers = { "api-key" = "YOUR_API_KEY", "api-secret" = "YOUR_API_SECRET", "
|
|
|
932
932
|
<h1>Instructions</h1>
|
|
933
933
|
<p>One-click installation for Claude Desktop users</p>
|
|
934
934
|
<div class="instruction-item">
|
|
935
|
-
<a href="https://github.com/cloudinary/asset-management-mcp/releases/download/v0.
|
|
935
|
+
<a href="https://github.com/cloudinary/asset-management-mcp/releases/download/v0.8.0/mcp-server.mcpb" download="mcp-server.mcpb" class="action-button header-action" style="display: inline-flex; margin-bottom: 16px;">
|
|
936
936
|
📥 Download MCP Bundle
|
|
937
937
|
</a>
|
|
938
938
|
</div>
|
package/src/lib/config.ts
CHANGED
|
@@ -111,9 +111,9 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
|
|
|
111
111
|
|
|
112
112
|
export const SDK_METADATA = {
|
|
113
113
|
language: "typescript",
|
|
114
|
-
openapiDocVersion: "0.
|
|
115
|
-
sdkVersion: "0.
|
|
116
|
-
genVersion: "2.
|
|
114
|
+
openapiDocVersion: "0.4.0",
|
|
115
|
+
sdkVersion: "0.8.0",
|
|
116
|
+
genVersion: "2.865.2",
|
|
117
117
|
userAgent:
|
|
118
|
-
"speakeasy-sdk/mcp-typescript 0.
|
|
118
|
+
"speakeasy-sdk/mcp-typescript 0.8.0 2.865.2 0.4.0 @cloudinary/asset-management-mcp",
|
|
119
119
|
} as const;
|
package/src/lib/security.ts
CHANGED
|
@@ -84,7 +84,10 @@ type SecurityInputOAuth2 = {
|
|
|
84
84
|
type SecurityInputOAuth2ClientCredentials = {
|
|
85
85
|
type: "oauth2:client_credentials";
|
|
86
86
|
value:
|
|
87
|
-
| {
|
|
87
|
+
| {
|
|
88
|
+
clientID?: string | undefined;
|
|
89
|
+
clientSecret?: string | undefined;
|
|
90
|
+
}
|
|
88
91
|
| null
|
|
89
92
|
| string
|
|
90
93
|
| undefined;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { buildCommand } from "@stricli/core";
|
|
6
|
+
import { numberParser } from "@stricli/core";
|
|
7
|
+
import * as z from "zod";
|
|
8
|
+
import { ServerRegion } from "../../../lib/config.js";
|
|
9
|
+
import { consoleLoggerLevels } from "../../console-logger.js";
|
|
10
|
+
import { mcpScopes } from "../../scopes.js";
|
|
11
|
+
|
|
12
|
+
export const serveCommand = buildCommand({
|
|
13
|
+
loader: async () => {
|
|
14
|
+
const { main } = await import("./impl.js");
|
|
15
|
+
return main;
|
|
16
|
+
},
|
|
17
|
+
parameters: {
|
|
18
|
+
flags: {
|
|
19
|
+
port: {
|
|
20
|
+
kind: "parsed",
|
|
21
|
+
brief: "The port to listen on for Streamable HTTP connections",
|
|
22
|
+
default: "2718",
|
|
23
|
+
parse: (val: string) =>
|
|
24
|
+
z.coerce.number().int().gte(0).lt(65536).parse(val),
|
|
25
|
+
},
|
|
26
|
+
"disable-static-auth": {
|
|
27
|
+
kind: "boolean",
|
|
28
|
+
brief:
|
|
29
|
+
"Disable static authentication, allowing credentials to be passed via request headers only",
|
|
30
|
+
default: false,
|
|
31
|
+
},
|
|
32
|
+
tool: {
|
|
33
|
+
kind: "parsed",
|
|
34
|
+
brief: "Specify tools to mount on the server",
|
|
35
|
+
optional: true,
|
|
36
|
+
variadic: true,
|
|
37
|
+
parse: (value) => {
|
|
38
|
+
return z.string().parse(value);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
mode: {
|
|
42
|
+
kind: "enum",
|
|
43
|
+
brief:
|
|
44
|
+
"Server mode (dynamic: expose list_tools, describe_tool, and execute_tool instead of individual tools)",
|
|
45
|
+
values: ["dynamic"],
|
|
46
|
+
optional: true,
|
|
47
|
+
},
|
|
48
|
+
scope: {
|
|
49
|
+
kind: "enum",
|
|
50
|
+
brief: "Mount tools/resources that match given scope (repeatable flag)",
|
|
51
|
+
values: mcpScopes,
|
|
52
|
+
variadic: true,
|
|
53
|
+
optional: true,
|
|
54
|
+
},
|
|
55
|
+
"api-key": {
|
|
56
|
+
kind: "parsed",
|
|
57
|
+
brief: "Sets the api_key auth field for the API",
|
|
58
|
+
optional: true,
|
|
59
|
+
parse: (value) => {
|
|
60
|
+
return z.string().parse(value);
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
"api-secret": {
|
|
64
|
+
kind: "parsed",
|
|
65
|
+
brief: "Sets the api_secret auth field for the API",
|
|
66
|
+
optional: true,
|
|
67
|
+
parse: (value) => {
|
|
68
|
+
return z.string().parse(value);
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
oauth2: {
|
|
72
|
+
kind: "parsed",
|
|
73
|
+
brief: "Sets the oauth2 auth field for the API",
|
|
74
|
+
optional: true,
|
|
75
|
+
parse: (value) => {
|
|
76
|
+
return z.string().parse(value);
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
"cloud-name": {
|
|
80
|
+
kind: "parsed",
|
|
81
|
+
brief:
|
|
82
|
+
"Allows setting the cloud_name parameter for all supported operations",
|
|
83
|
+
optional: true,
|
|
84
|
+
parse: (value) => {
|
|
85
|
+
return z.string().parse(value);
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"server-url": {
|
|
89
|
+
kind: "parsed",
|
|
90
|
+
brief: "Overrides the default server URL used by the SDK",
|
|
91
|
+
optional: true,
|
|
92
|
+
parse: (value) => new URL(value).toString(),
|
|
93
|
+
},
|
|
94
|
+
"server-index": {
|
|
95
|
+
kind: "parsed",
|
|
96
|
+
brief: "Selects a predefined server used by the SDK",
|
|
97
|
+
optional: true,
|
|
98
|
+
parse: numberParser,
|
|
99
|
+
},
|
|
100
|
+
region: {
|
|
101
|
+
kind: "enum",
|
|
102
|
+
brief: "Sets the region variable for url substitution",
|
|
103
|
+
optional: true,
|
|
104
|
+
values: Object.values(ServerRegion) as Array<ServerRegion>,
|
|
105
|
+
},
|
|
106
|
+
"api-host": {
|
|
107
|
+
kind: "parsed",
|
|
108
|
+
brief: "Sets the host variable for url substitution",
|
|
109
|
+
optional: true,
|
|
110
|
+
parse: (value) => value,
|
|
111
|
+
},
|
|
112
|
+
"log-level": {
|
|
113
|
+
kind: "enum",
|
|
114
|
+
brief: "The log level to use for the server",
|
|
115
|
+
default: "info",
|
|
116
|
+
values: consoleLoggerLevels,
|
|
117
|
+
},
|
|
118
|
+
env: {
|
|
119
|
+
kind: "parsed",
|
|
120
|
+
brief: "Environment variables made available to the server",
|
|
121
|
+
optional: true,
|
|
122
|
+
variadic: true,
|
|
123
|
+
parse: (val: string) => {
|
|
124
|
+
const sepIdx = val.indexOf("=");
|
|
125
|
+
if (sepIdx === -1) {
|
|
126
|
+
throw new Error("Invalid environment variable format");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const key = val.slice(0, sepIdx);
|
|
130
|
+
const value = val.slice(sepIdx + 1);
|
|
131
|
+
|
|
132
|
+
return [
|
|
133
|
+
z.string().nonempty({
|
|
134
|
+
message: "Environment variable key must be a non-empty string",
|
|
135
|
+
}).parse(key),
|
|
136
|
+
z.string().nonempty({
|
|
137
|
+
message: "Environment variable value must be a non-empty string",
|
|
138
|
+
}).parse(value),
|
|
139
|
+
] satisfies [string, string];
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
docs: {
|
|
145
|
+
brief: "Run the MCP server with Streamable HTTP transport",
|
|
146
|
+
},
|
|
147
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
|
+
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
7
|
+
import express from "express";
|
|
8
|
+
import { LocalContext } from "../../cli.js";
|
|
9
|
+
import {
|
|
10
|
+
ConsoleLoggerLevel,
|
|
11
|
+
createConsoleLogger,
|
|
12
|
+
} from "../../console-logger.js";
|
|
13
|
+
import { MCPServerFlags } from "../../flags.js";
|
|
14
|
+
import { createMCPServer } from "../../server.js";
|
|
15
|
+
import { buildSDK } from "../../tools.js";
|
|
16
|
+
|
|
17
|
+
import { landingPageExpress } from "../../../landing-page.js";
|
|
18
|
+
|
|
19
|
+
interface ServeCommandFlags extends MCPServerFlags {
|
|
20
|
+
readonly port: number;
|
|
21
|
+
readonly "disable-static-auth": boolean;
|
|
22
|
+
readonly "log-level": ConsoleLoggerLevel;
|
|
23
|
+
readonly env?: [string, string][];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function main(this: LocalContext, flags: ServeCommandFlags) {
|
|
27
|
+
flags.env?.forEach(([key, value]) => {
|
|
28
|
+
process.env[key] = value;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await startStreamableHTTP(flags);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function startStreamableHTTP(cliFlags: ServeCommandFlags) {
|
|
35
|
+
const logger = createConsoleLogger(cliFlags["log-level"]);
|
|
36
|
+
const app = express();
|
|
37
|
+
|
|
38
|
+
// Enable CORS for cross-origin requests
|
|
39
|
+
app.use((req, res, next) => {
|
|
40
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
41
|
+
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
42
|
+
res.header("Access-Control-Allow-Headers", "Content-Type, *");
|
|
43
|
+
if (req.method === "OPTIONS") {
|
|
44
|
+
res.sendStatus(204);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
next();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
app.use(express.json());
|
|
51
|
+
|
|
52
|
+
app.post("/mcp", async (req, res) => {
|
|
53
|
+
const headers = new Headers();
|
|
54
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
55
|
+
if (Array.isArray(value)) {
|
|
56
|
+
for (const v of value) headers.append(key, v);
|
|
57
|
+
} else if (value !== undefined) {
|
|
58
|
+
headers.set(key, value);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const transport = new StreamableHTTPServerTransport({});
|
|
63
|
+
|
|
64
|
+
const { server: mcpServer } = createMCPServer({
|
|
65
|
+
logger,
|
|
66
|
+
allowedTools: cliFlags.tool,
|
|
67
|
+
dynamic: cliFlags.mode === "dynamic",
|
|
68
|
+
scopes: cliFlags.scope,
|
|
69
|
+
serverURL: cliFlags["server-url"],
|
|
70
|
+
getSDK: () =>
|
|
71
|
+
buildSDK(headers, cliFlags, cliFlags["disable-static-auth"], logger),
|
|
72
|
+
cloud_name: cliFlags["cloud-name"],
|
|
73
|
+
serverIdx: cliFlags["server-index"],
|
|
74
|
+
region: cliFlags.region,
|
|
75
|
+
host: cliFlags["api-host"],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
mcpServer.server.onerror = (error) => {
|
|
79
|
+
logger.error("MCP protocol error", {
|
|
80
|
+
error: error instanceof Error ? error.message : String(error),
|
|
81
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
await mcpServer.connect(transport as Transport);
|
|
86
|
+
await transport.handleRequest(req, res, req.body);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
app.get("/", landingPageExpress);
|
|
90
|
+
|
|
91
|
+
const httpServer = app.listen(cliFlags.port, "0.0.0.0", () => {
|
|
92
|
+
const ha = httpServer.address();
|
|
93
|
+
const host = typeof ha === "string" ? ha : `${ha?.address}:${ha?.port}`;
|
|
94
|
+
logger.info("MCP Streamable HTTP server started", { host });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const shutdown = () => {
|
|
98
|
+
logger.info("Shutting down HTTP server");
|
|
99
|
+
|
|
100
|
+
const timer = setTimeout(() => {
|
|
101
|
+
logger.info("Forcing shutdown");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}, 5000);
|
|
104
|
+
|
|
105
|
+
httpServer.close(() => {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
logger.info("Graceful shutdown complete");
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
process.on("SIGTERM", shutdown);
|
|
113
|
+
process.on("SIGINT", shutdown);
|
|
114
|
+
}
|
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
import { buildApplication, buildRouteMap, run } from "@stricli/core";
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import { buildContext } from "./cli.js";
|
|
8
|
+
import { serveCommand } from "./cli/serve/command.js";
|
|
8
9
|
import { startCommand } from "./cli/start/command.js";
|
|
9
10
|
|
|
10
11
|
const routes = buildRouteMap({
|
|
11
12
|
routes: {
|
|
12
13
|
start: startCommand,
|
|
14
|
+
serve: serveCommand,
|
|
13
15
|
},
|
|
14
16
|
docs: {
|
|
15
17
|
brief: "MCP server CLI",
|
|
@@ -19,7 +21,7 @@ const routes = buildRouteMap({
|
|
|
19
21
|
export const app = buildApplication(routes, {
|
|
20
22
|
name: "mcp",
|
|
21
23
|
versionInfo: {
|
|
22
|
-
currentVersion: "0.
|
|
24
|
+
currentVersion: "0.8.0",
|
|
23
25
|
},
|
|
24
26
|
});
|
|
25
27
|
|
package/src/mcp-server/server.ts
CHANGED
package/src/mcp-server/tools.ts
CHANGED
|
@@ -15,7 +15,9 @@ import {
|
|
|
15
15
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
16
16
|
import * as z from "zod";
|
|
17
17
|
import { CloudinaryAssetMgmtCore } from "../core.js";
|
|
18
|
+
import { ServerRegion$zodSchema } from "../lib/config.js";
|
|
18
19
|
import { ConsoleLogger } from "./console-logger.js";
|
|
20
|
+
import { MCPServerFlags } from "./flags.js";
|
|
19
21
|
import { MCPScope, mcpScopes } from "./scopes.js";
|
|
20
22
|
import { valueToBase64 } from "./shared.js";
|
|
21
23
|
|
|
@@ -376,3 +378,90 @@ export function registerDynamicTools(
|
|
|
376
378
|
logger.debug("Registered dynamic meta-tool", { name: "list_scopes" });
|
|
377
379
|
}
|
|
378
380
|
}
|
|
381
|
+
function resolveHeader<T>(
|
|
382
|
+
headers: Headers,
|
|
383
|
+
headerName: string,
|
|
384
|
+
schema: z.ZodType<T>,
|
|
385
|
+
cliFlagValue: T | undefined,
|
|
386
|
+
disableStaticAuth: boolean,
|
|
387
|
+
): T | undefined {
|
|
388
|
+
const val = headers.get(headerName);
|
|
389
|
+
if (val != null) {
|
|
390
|
+
return schema.parse(val);
|
|
391
|
+
}
|
|
392
|
+
return disableStaticAuth ? undefined : schema.parse(cliFlagValue);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function buildSDK(
|
|
396
|
+
headers: Headers,
|
|
397
|
+
cliFlags: MCPServerFlags,
|
|
398
|
+
disableStaticAuth: boolean,
|
|
399
|
+
logger: { level: string },
|
|
400
|
+
) {
|
|
401
|
+
const flags = {
|
|
402
|
+
...cliFlags,
|
|
403
|
+
"api-key": resolveHeader(
|
|
404
|
+
headers,
|
|
405
|
+
"api-key",
|
|
406
|
+
z.string(),
|
|
407
|
+
cliFlags["api-key"],
|
|
408
|
+
disableStaticAuth,
|
|
409
|
+
),
|
|
410
|
+
"api-secret": resolveHeader(
|
|
411
|
+
headers,
|
|
412
|
+
"api-secret",
|
|
413
|
+
z.string(),
|
|
414
|
+
cliFlags["api-secret"],
|
|
415
|
+
disableStaticAuth,
|
|
416
|
+
),
|
|
417
|
+
"oauth2": resolveHeader(
|
|
418
|
+
headers,
|
|
419
|
+
"oauth2",
|
|
420
|
+
z.string(),
|
|
421
|
+
cliFlags["oauth2"],
|
|
422
|
+
disableStaticAuth,
|
|
423
|
+
),
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
return new CloudinaryAssetMgmtCore({
|
|
427
|
+
security: {
|
|
428
|
+
cloudinaryAuth: flags["api-key"] != null && flags["api-secret"] != null
|
|
429
|
+
? {
|
|
430
|
+
api_key: flags["api-key"] ?? "",
|
|
431
|
+
api_secret: flags["api-secret"] ?? "",
|
|
432
|
+
}
|
|
433
|
+
: void 0,
|
|
434
|
+
oauth2: flags.oauth2 ?? "",
|
|
435
|
+
},
|
|
436
|
+
serverURL: cliFlags["server-url"],
|
|
437
|
+
cloud_name: resolveHeader(
|
|
438
|
+
headers,
|
|
439
|
+
"cloud-name",
|
|
440
|
+
z.string(),
|
|
441
|
+
cliFlags["cloud-name"],
|
|
442
|
+
disableStaticAuth,
|
|
443
|
+
),
|
|
444
|
+
serverIdx: cliFlags["server-index"],
|
|
445
|
+
region: resolveHeader(
|
|
446
|
+
headers,
|
|
447
|
+
"region",
|
|
448
|
+
ServerRegion$zodSchema,
|
|
449
|
+
cliFlags.region,
|
|
450
|
+
disableStaticAuth,
|
|
451
|
+
),
|
|
452
|
+
host: resolveHeader(
|
|
453
|
+
headers,
|
|
454
|
+
"api-host",
|
|
455
|
+
z.string(),
|
|
456
|
+
cliFlags["api-host"],
|
|
457
|
+
disableStaticAuth,
|
|
458
|
+
),
|
|
459
|
+
debugLogger: logger.level === "debug"
|
|
460
|
+
? {
|
|
461
|
+
log: (...args) => console.log(...args),
|
|
462
|
+
group: (...args) => console.group(...args),
|
|
463
|
+
groupEnd: (...args) => console.groupEnd(...args),
|
|
464
|
+
}
|
|
465
|
+
: undefined,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as z from "zod";
|
|
6
|
+
import { ApiError, ApiError$zodSchema } from "./apierror.js";
|
|
7
|
+
import {
|
|
8
|
+
AssignFolderRolesRequest,
|
|
9
|
+
AssignFolderRolesRequest$zodSchema,
|
|
10
|
+
} from "./assignfolderrolesrequest.js";
|
|
11
|
+
import {
|
|
12
|
+
SuccessResponse,
|
|
13
|
+
SuccessResponse$zodSchema,
|
|
14
|
+
} from "./successresponse.js";
|
|
15
|
+
|
|
16
|
+
export type AssignFolderRolesGlobals = { cloud_name?: string | undefined };
|
|
17
|
+
|
|
18
|
+
export const AssignFolderRolesGlobals$zodSchema: z.ZodType<
|
|
19
|
+
AssignFolderRolesGlobals
|
|
20
|
+
> = z.object({
|
|
21
|
+
cloud_name: z.string().describe("The cloud name of your product environment.")
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export type AssignFolderRolesRequestRequest = {
|
|
26
|
+
folder_id: string;
|
|
27
|
+
assign_folder_roles_request: AssignFolderRolesRequest;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const AssignFolderRolesRequestRequest$zodSchema: z.ZodType<
|
|
31
|
+
AssignFolderRolesRequestRequest
|
|
32
|
+
> = z.object({
|
|
33
|
+
assign_folder_roles_request: AssignFolderRolesRequest$zodSchema,
|
|
34
|
+
folder_id: z.string().describe(
|
|
35
|
+
"The immutable identifier of the folder, returned by the Get root folders and Get subfolders endpoints.",
|
|
36
|
+
),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export type AssignFolderRolesResponse = SuccessResponse | ApiError;
|
|
40
|
+
|
|
41
|
+
export const AssignFolderRolesResponse$zodSchema: z.ZodType<
|
|
42
|
+
AssignFolderRolesResponse
|
|
43
|
+
> = z.union([
|
|
44
|
+
SuccessResponse$zodSchema,
|
|
45
|
+
ApiError$zodSchema,
|
|
46
|
+
]);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as z from "zod";
|
|
6
|
+
import { ClosedEnum } from "../types/enums.js";
|
|
7
|
+
import { PrincipalType, PrincipalType$zodSchema } from "./principaltype.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The user, group, or API key whose role assignments are being modified.
|
|
11
|
+
*/
|
|
12
|
+
export type Principal = { type: PrincipalType; id: string };
|
|
13
|
+
|
|
14
|
+
export const Principal$zodSchema: z.ZodType<Principal> = z.object({
|
|
15
|
+
id: z.string(),
|
|
16
|
+
type: PrincipalType$zodSchema,
|
|
17
|
+
}).describe(
|
|
18
|
+
"The user, group, or API key whose role assignments are being modified.",
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The operation to perform on the principal’s role assignments. `add` grants the specified roles; `remove` revokes them.
|
|
23
|
+
*/
|
|
24
|
+
export const Operation = {
|
|
25
|
+
Add: "add",
|
|
26
|
+
Remove: "remove",
|
|
27
|
+
} as const;
|
|
28
|
+
/**
|
|
29
|
+
* The operation to perform on the principal’s role assignments. `add` grants the specified roles; `remove` revokes them.
|
|
30
|
+
*/
|
|
31
|
+
export type Operation = ClosedEnum<typeof Operation>;
|
|
32
|
+
|
|
33
|
+
export const Operation$zodSchema = z.enum([
|
|
34
|
+
"add",
|
|
35
|
+
"remove",
|
|
36
|
+
]).describe(
|
|
37
|
+
"The operation to perform on the principal’s role assignments. `add` grants the specified roles; `remove` revokes them.",
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
export type AssignFolderRolesRequest = {
|
|
41
|
+
principal: Principal;
|
|
42
|
+
operation: Operation;
|
|
43
|
+
roles: Array<string>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const AssignFolderRolesRequest$zodSchema: z.ZodType<
|
|
47
|
+
AssignFolderRolesRequest
|
|
48
|
+
> = z.object({
|
|
49
|
+
operation: Operation$zodSchema,
|
|
50
|
+
principal: z.lazy(() => Principal$zodSchema),
|
|
51
|
+
roles: z.array(z.string()),
|
|
52
|
+
});
|
|
@@ -32,22 +32,24 @@ export const DestroyAssetRequest$zodSchema: z.ZodType<DestroyAssetRequest> = z
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Result of the deletion operation
|
|
36
36
|
*/
|
|
37
37
|
export const DestroyAssetResult = {
|
|
38
38
|
Ok: "ok",
|
|
39
|
+
NotFound: "not found",
|
|
39
40
|
} as const;
|
|
40
41
|
/**
|
|
41
|
-
*
|
|
42
|
+
* Result of the deletion operation
|
|
42
43
|
*/
|
|
43
44
|
export type DestroyAssetResult = ClosedEnum<typeof DestroyAssetResult>;
|
|
44
45
|
|
|
45
46
|
export const DestroyAssetResult$zodSchema = z.enum([
|
|
46
47
|
"ok",
|
|
47
|
-
|
|
48
|
+
"not found",
|
|
49
|
+
]).describe("Result of the deletion operation");
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
|
-
* Asset/resource destroyed successfully
|
|
52
|
+
* Asset/resource destroyed successfully or not found
|
|
51
53
|
*/
|
|
52
54
|
export type DestroyAssetResponseBody = {
|
|
53
55
|
result?: DestroyAssetResult | undefined;
|
|
@@ -57,7 +59,7 @@ export const DestroyAssetResponseBody$zodSchema: z.ZodType<
|
|
|
57
59
|
DestroyAssetResponseBody
|
|
58
60
|
> = z.object({
|
|
59
61
|
result: DestroyAssetResult$zodSchema.optional(),
|
|
60
|
-
}).describe("Asset/resource destroyed successfully");
|
|
62
|
+
}).describe("Asset/resource destroyed successfully or not found");
|
|
61
63
|
|
|
62
64
|
export type DestroyAssetResponse = ApiError | DestroyAssetResponseBody;
|
|
63
65
|
|