@mintmcp/hosted-cli 0.0.4 → 0.0.6
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 +92 -9
- package/dist/api.d.ts +6 -22
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +12 -7
- package/dist/api.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +59 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +16 -7
- package/src/index.ts +99 -68
package/README.md
CHANGED
|
@@ -1,19 +1,102 @@
|
|
|
1
1
|
# MintMCP hosted-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This tool deploys MCP servers to MintMCP.
|
|
4
|
+
|
|
5
|
+
## Javascript / Typescript Server
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
* The server must serve the MCP streamable HTTP protocol on port 8000 at `/mcp`. See the [Streamable
|
|
10
|
+
HTTP section of the modelcontextprotocol/typescript-sdk][typescript-server] for instructions.
|
|
11
|
+
* The default server startup command is `npm run build && npm run start`. If your server requires a different command, pass `--startup-command "<command>"` to `deploy` when you run them below.
|
|
12
|
+
|
|
13
|
+
### Deploy
|
|
14
|
+
|
|
15
|
+
In the server's directory:
|
|
4
16
|
|
|
5
17
|
```sh
|
|
6
|
-
npx @mintmcp/hosted-cli
|
|
18
|
+
npx @mintmcp/hosted-cli deploy -n "<title for new server>"
|
|
7
19
|
```
|
|
8
20
|
|
|
9
|
-
This uploads the entire
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
This uploads the entire conents of the directory to a hosted server on MintMCP, and runs the startup
|
|
22
|
+
command there.
|
|
23
|
+
|
|
24
|
+
Upon successful upload, this prints a server management URL where you can:
|
|
25
|
+
|
|
26
|
+
* View server startup status and logs.
|
|
27
|
+
* Configure environment variables.
|
|
28
|
+
* Configure other server settings.
|
|
29
|
+
|
|
30
|
+
Rerun the command to upload changes as a new revision. The old revision will continue serving
|
|
31
|
+
requests until the new revision starts up successfully.
|
|
32
|
+
|
|
33
|
+
### Troubleshooting
|
|
34
|
+
|
|
35
|
+
TODO: Explain the install thing.
|
|
12
36
|
|
|
13
|
-
|
|
37
|
+
## Python FastMCP Server
|
|
38
|
+
|
|
39
|
+
### Prerequisites
|
|
40
|
+
|
|
41
|
+
The server must serve the MCP streamable HTTP protocol on port 8000 at `/mcp`. You can typically do this by adding at the bottom of your main server file:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
mcp.run(transport="http", host="127.0.0.1", port=8000)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Deploy
|
|
49
|
+
|
|
50
|
+
If your server is a Python package (has a `pyproject.toml` or `setup.py` file), run in the server's directory:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx @mintmcp/hosted-cli deploy -n "<title for new server>" --startup-command "uvx --from . python <path-to-main-file.py>"
|
|
54
|
+
```
|
|
14
55
|
|
|
15
|
-
|
|
56
|
+
Or, if your server is a plain Python file without a package, run in the server's directory:
|
|
16
57
|
|
|
17
58
|
```sh
|
|
18
|
-
|
|
19
|
-
|
|
59
|
+
# If necessary, specify additional dependencies with more `--with <dependency>` flags in the `uvx` command.
|
|
60
|
+
npx @mintmcp/hosted-cli deploy -n "<title for new server>" --startup-command "uvx --with fastmcp python <path-to-main-file.py>"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
These upload the entire conents of the directory to a hosted server on MintMCP, and run the startup
|
|
64
|
+
command there.
|
|
65
|
+
|
|
66
|
+
Upon successful upload, this prints a server management URL where you can:
|
|
67
|
+
|
|
68
|
+
* View server startup status and logs.
|
|
69
|
+
* Configure environment variables.
|
|
70
|
+
* Configure other server settings.
|
|
71
|
+
|
|
72
|
+
Rerun the command to upload changes as a new revision. The old revision will continue serving
|
|
73
|
+
requests until the new revision starts up successfully.
|
|
74
|
+
|
|
75
|
+
## Other Types of Servers
|
|
76
|
+
|
|
77
|
+
### Prerequisites
|
|
78
|
+
|
|
79
|
+
The server must serve the MCP streamable HTTP protocol on port 8000 at `/mcp`. Most MCP server
|
|
80
|
+
frameworks should be able to do this. Check your framework's documentation.
|
|
81
|
+
|
|
82
|
+
### Deploy
|
|
83
|
+
|
|
84
|
+
In the server's directory:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
npx @mintmcp/hosted-cli deploy -n "<title for new server>" --startup-command "<startup command>"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This uploads the entire conents of the directory to a hosted server on MintMCP, and runs the startup
|
|
91
|
+
command there.
|
|
92
|
+
|
|
93
|
+
Upon successful upload, this prints a server management URL where you can:
|
|
94
|
+
|
|
95
|
+
* View server startup status and logs.
|
|
96
|
+
* Configure environment variables.
|
|
97
|
+
* Configure other server settings.
|
|
98
|
+
|
|
99
|
+
Rerun the command to upload changes as a new revision. The old revision will continue serving
|
|
100
|
+
requests until the new revision starts up successfully.
|
|
101
|
+
|
|
102
|
+
[typescript-server]: https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#streamable-http
|
package/dist/api.d.ts
CHANGED
|
@@ -161,32 +161,16 @@ declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
161
161
|
};
|
|
162
162
|
meta: object;
|
|
163
163
|
}>;
|
|
164
|
-
|
|
164
|
+
partialUpdateServer: import("@trpc/server").TRPCMutationProcedure<{
|
|
165
165
|
input: {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
value: {
|
|
171
|
-
type: "copyPreviousValue";
|
|
172
|
-
fromName: string;
|
|
173
|
-
} | {
|
|
174
|
-
value: string;
|
|
175
|
-
type: "set";
|
|
176
|
-
isSecret: boolean;
|
|
177
|
-
};
|
|
178
|
-
name: string;
|
|
179
|
-
}[];
|
|
180
|
-
image?: string | undefined;
|
|
181
|
-
cpu?: number | undefined;
|
|
182
|
-
memoryMiB?: number | undefined;
|
|
183
|
-
urlPath?: string | undefined;
|
|
166
|
+
hostedId: string;
|
|
167
|
+
update: {
|
|
168
|
+
userGivenName?: string | undefined;
|
|
169
|
+
command?: string[] | undefined;
|
|
184
170
|
secretDataZipGcsPath?: string | undefined;
|
|
185
|
-
startupProbe?: "startupProbeOn" | "startupProbeOff" | undefined;
|
|
186
171
|
};
|
|
187
|
-
app: string;
|
|
188
172
|
};
|
|
189
|
-
output:
|
|
173
|
+
output: unknown;
|
|
190
174
|
meta: object;
|
|
191
175
|
}>;
|
|
192
176
|
makeSignedUploadUrl: import("@trpc/server").TRPCMutationProcedure<{
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAQA,OAAO,CAAC,MAAM,KAAK,CAAC;AAKpB,eAAO,MAAM,gBAAgB,EAAG,SAAkB,CAAC;AACnD,eAAO,MAAM,cAAc,qEAOL,CAAC;AACvB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;IAU/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAQA,OAAO,CAAC,MAAM,KAAK,CAAC;AAKpB,eAAO,MAAM,gBAAgB,EAAG,SAAkB,CAAC;AACnD,eAAO,MAAM,cAAc,qEAOL,CAAC;AACvB,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;IAU/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBjC,CAAC;AAKH,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCb,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC"}
|
package/dist/api.js
CHANGED
|
@@ -26,7 +26,9 @@ export const EnvUpdateValueSchema = z.discriminatedUnion("type", [
|
|
|
26
26
|
]);
|
|
27
27
|
export const UserConfigUpdateSchema = z.object({
|
|
28
28
|
userGivenName: z.string().min(1),
|
|
29
|
-
image: z
|
|
29
|
+
image: z
|
|
30
|
+
.string()
|
|
31
|
+
.default("nikolaik/python-nodejs@sha256:d481c61b10a131cb0ae3dfc09adf3beaff76557597010914df48ff1fe1dacbf1"),
|
|
30
32
|
command: z.array(z.string()),
|
|
31
33
|
cpu: z.number().default(1),
|
|
32
34
|
memoryMiB: z.number().default(4096),
|
|
@@ -35,8 +37,7 @@ export const UserConfigUpdateSchema = z.object({
|
|
|
35
37
|
startupProbe: z
|
|
36
38
|
.union([z.literal("startupProbeOn"), z.literal("startupProbeOff")])
|
|
37
39
|
.default("startupProbeOn"),
|
|
38
|
-
replaceEnv: z
|
|
39
|
-
.array(z.object({ name: z.string().min(1), value: EnvUpdateValueSchema })),
|
|
40
|
+
replaceEnv: z.array(z.object({ name: z.string().min(1), value: EnvUpdateValueSchema })),
|
|
40
41
|
});
|
|
41
42
|
const t = initTRPC.context().create({ transformer: superjson });
|
|
42
43
|
const { router, procedure } = t;
|
|
@@ -48,12 +49,16 @@ const appRouter = router({
|
|
|
48
49
|
.mutation(() => {
|
|
49
50
|
throw new Error("stub");
|
|
50
51
|
}),
|
|
51
|
-
|
|
52
|
+
partialUpdateServer: procedure
|
|
52
53
|
.input(z.object({
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
hostedId: HostedIdSchema,
|
|
55
|
+
update: z.object({
|
|
56
|
+
userGivenName: z.string().optional(),
|
|
57
|
+
command: z.array(z.string()).optional(),
|
|
58
|
+
secretDataZipGcsPath: z.string().optional(),
|
|
59
|
+
}),
|
|
55
60
|
}))
|
|
56
|
-
.output(z.
|
|
61
|
+
.output(z.unknown())
|
|
57
62
|
.mutation(() => {
|
|
58
63
|
throw new Error("stub");
|
|
59
64
|
}),
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,uFAAuF;AACvF,EAAE;AACF,kGAAkG;AAClG,oBAAoB;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,MAAM,OAAO,GACX,iEAAiE,CAAC;AAEpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAkB,CAAC;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC;KAC5B,MAAM,EAAE;KACR,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CACrD;KACA,KAAK,EAAc,CAAC;AAGvB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC/D,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC;QACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;KACrB,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;QACtB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,KAAK,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAO1E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAO1E,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AACpE,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import keytar from "keytar";
|
|
|
7
7
|
import * as path from "path";
|
|
8
8
|
import superjson from "superjson";
|
|
9
9
|
import z, { ZodSchema } from "zod";
|
|
10
|
-
import { HostedIdSchema, UserConfigUpdateSchema } from "./api.js";
|
|
10
|
+
import { HostedIdSchema, UserConfigUpdateSchema, } from "./api.js";
|
|
11
11
|
const EnvSchema = z.enum(["staging", "production"]);
|
|
12
12
|
const TRPC_API_URL = {
|
|
13
13
|
staging: "http://localhost:3000/api.trpc",
|
|
@@ -28,7 +28,6 @@ const HOSTED_CONFIG_PATHS = {
|
|
|
28
28
|
};
|
|
29
29
|
const HostedConfigSchema = z.object({
|
|
30
30
|
hostedId: HostedIdSchema,
|
|
31
|
-
config: UserConfigUpdateSchema.omit({ secretDataZipGcsPath: true }),
|
|
32
31
|
// Directory containing data to send to hosted server, relative to "--base".
|
|
33
32
|
mntDataDir: z.string(),
|
|
34
33
|
});
|
|
@@ -51,7 +50,7 @@ async function requestAuth(env) {
|
|
|
51
50
|
if (!deviceCodeResponse.ok) {
|
|
52
51
|
throw new Error(`Failed to get device code: ${await deviceCodeResponse.text()}`);
|
|
53
52
|
}
|
|
54
|
-
const deviceData = await deviceCodeResponse.json();
|
|
53
|
+
const deviceData = (await deviceCodeResponse.json());
|
|
55
54
|
const { device_code: deviceCode, verification_uri_complete: verificationUriComplete, interval = 5, } = deviceData;
|
|
56
55
|
console.log(`To authenticate, visit ${verificationUriComplete}`);
|
|
57
56
|
// Poll for access token.
|
|
@@ -74,7 +73,7 @@ async function requestAuth(env) {
|
|
|
74
73
|
if (!tokenResponse.ok) {
|
|
75
74
|
continue;
|
|
76
75
|
}
|
|
77
|
-
const tokenData = await tokenResponse.json();
|
|
76
|
+
const tokenData = (await tokenResponse.json());
|
|
78
77
|
if (tokenData.error) {
|
|
79
78
|
if (tokenData.error === "authorization_pending") {
|
|
80
79
|
continue;
|
|
@@ -203,6 +202,47 @@ async function uploadData(client, mntDataDir) {
|
|
|
203
202
|
console.log("File uploaded.");
|
|
204
203
|
return { secretDataZipGcsPath: upload.secretDataZipGcsPath };
|
|
205
204
|
}
|
|
205
|
+
function commandFromStartupCommand(startupCommand) {
|
|
206
|
+
return ["bash", "-c", startupCommand];
|
|
207
|
+
}
|
|
208
|
+
async function createNew(client, base, options) {
|
|
209
|
+
const { name, startupCommand = "npm run build && npm run start", mntDataDir = ".", } = options;
|
|
210
|
+
if (name == undefined) {
|
|
211
|
+
throw new Error("--name is a required option when creating a new server");
|
|
212
|
+
}
|
|
213
|
+
const upload = await uploadData(client, path.join(base, mntDataDir));
|
|
214
|
+
const config = UserConfigUpdateSchema.parse({
|
|
215
|
+
userGivenName: name,
|
|
216
|
+
command: commandFromStartupCommand(startupCommand),
|
|
217
|
+
replaceEnv: [],
|
|
218
|
+
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
219
|
+
});
|
|
220
|
+
const createdServer = await client.mcpHost.createServer.mutate({
|
|
221
|
+
config,
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
hostedId: createdServer.hostedId,
|
|
225
|
+
mntDataDir,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async function updateExisting(client, base, config, options) {
|
|
229
|
+
const newConfig = { ...config };
|
|
230
|
+
if (options.mntDataDir != undefined) {
|
|
231
|
+
newConfig.mntDataDir = options.mntDataDir;
|
|
232
|
+
}
|
|
233
|
+
const upload = await uploadData(client, path.join(base, newConfig.mntDataDir));
|
|
234
|
+
await client.mcpHost.partialUpdateServer.mutate({
|
|
235
|
+
hostedId: config.hostedId,
|
|
236
|
+
update: {
|
|
237
|
+
userGivenName: options.name,
|
|
238
|
+
command: options.startupCommand
|
|
239
|
+
? commandFromStartupCommand(options.startupCommand)
|
|
240
|
+
: undefined,
|
|
241
|
+
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
return newConfig;
|
|
245
|
+
}
|
|
206
246
|
const program = new Command()
|
|
207
247
|
.name("hosted")
|
|
208
248
|
.description("Control hosted servers on MintMCP")
|
|
@@ -212,59 +252,27 @@ const program = new Command()
|
|
|
212
252
|
program
|
|
213
253
|
.command("create")
|
|
214
254
|
.description("Create a hosted server.")
|
|
215
|
-
.
|
|
216
|
-
.option("--startup-command <command>", "Command that runs on hosted container to start the server (runs in bash)."
|
|
217
|
-
.option("--mnt-data-dir <directory>", "Directory to copy to /mnt on the server."
|
|
255
|
+
.option("-n, --name <name>", "Name of the hosted server")
|
|
256
|
+
.option("--startup-command <command>", "Command that runs on hosted container to start the server (runs in bash).")
|
|
257
|
+
.option("--mnt-data-dir <directory>", "Directory to copy to /mnt on the server.")
|
|
218
258
|
.action(async (options) => {
|
|
219
|
-
const { name, startupCommand, mntDataDir } = options;
|
|
220
259
|
const { env, base } = program.opts();
|
|
260
|
+
const client = await makeAuthenticatedClient(env);
|
|
221
261
|
const configPath = path.join(base, HOSTED_CONFIG_PATHS[env]);
|
|
262
|
+
let newOrUpdatedConfig;
|
|
222
263
|
if (fs.existsSync(configPath)) {
|
|
223
|
-
|
|
264
|
+
console.log("Updating existing server...");
|
|
265
|
+
const configData = fs.readFileSync(configPath, "utf8");
|
|
266
|
+
newOrUpdatedConfig = await updateExisting(client, base, HostedConfigSchema.parse(configData), options);
|
|
267
|
+
console.log(`Updated ${WEB_CLIENT_URL[env]}/hosted/${newOrUpdatedConfig.hostedId}`);
|
|
224
268
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
userGivenName: name,
|
|
230
|
-
command: ["bash", "-c", startupCommand],
|
|
231
|
-
replaceEnv: [],
|
|
232
|
-
});
|
|
233
|
-
console.log("Creating server...");
|
|
234
|
-
const createdServer = await client.mcpHost.createServer.mutate({
|
|
235
|
-
config: { ...config, secretDataZipGcsPath: upload.secretDataZipGcsPath },
|
|
236
|
-
});
|
|
237
|
-
const hostedConfig = {
|
|
238
|
-
hostedId: createdServer.hostedId,
|
|
239
|
-
config,
|
|
240
|
-
mntDataDir,
|
|
241
|
-
};
|
|
242
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
243
|
-
fs.writeFileSync(configPath, JSON.stringify(hostedConfig, null, 2));
|
|
244
|
-
console.log(`Created ${WEB_CLIENT_URL[env]}/hosted/${createdServer.hostedId}`);
|
|
245
|
-
});
|
|
246
|
-
program
|
|
247
|
-
.command("update")
|
|
248
|
-
.description("Update a hosted server.")
|
|
249
|
-
.action(async () => {
|
|
250
|
-
const { env, base } = program.opts();
|
|
251
|
-
const configPath = path.join(base, HOSTED_CONFIG_PATHS[env]);
|
|
252
|
-
if (!fs.existsSync(configPath)) {
|
|
253
|
-
throw new Error("Hosted server config not found. Run 'create' command first.");
|
|
269
|
+
else {
|
|
270
|
+
console.log("Creating new server...");
|
|
271
|
+
newOrUpdatedConfig = await createNew(client, base, options);
|
|
272
|
+
console.log(`Created ${WEB_CLIENT_URL[env]}/hosted/${newOrUpdatedConfig.hostedId}`);
|
|
254
273
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const client = await makeAuthenticatedClient(env);
|
|
258
|
-
const upload = await uploadData(client, path.join(base, hostedConfig.mntDataDir));
|
|
259
|
-
console.log("Updating server...");
|
|
260
|
-
await client.mcpHost.updateServer.mutate({
|
|
261
|
-
app: hostedConfig.hostedId,
|
|
262
|
-
config: {
|
|
263
|
-
...hostedConfig.config,
|
|
264
|
-
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
265
|
-
},
|
|
266
|
-
});
|
|
267
|
-
console.log(`Updated ${WEB_CLIENT_URL[env]}/hosted/${hostedConfig.hostedId}`);
|
|
274
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
275
|
+
fs.writeFileSync(configPath, JSON.stringify(newOrUpdatedConfig, null, 2));
|
|
268
276
|
});
|
|
269
277
|
program.parse();
|
|
270
278
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -37,7 +37,11 @@ export type EnvUpdateValue = z.infer<typeof EnvUpdateValueSchema>;
|
|
|
37
37
|
|
|
38
38
|
export const UserConfigUpdateSchema = z.object({
|
|
39
39
|
userGivenName: z.string().min(1),
|
|
40
|
-
image: z
|
|
40
|
+
image: z
|
|
41
|
+
.string()
|
|
42
|
+
.default(
|
|
43
|
+
"nikolaik/python-nodejs@sha256:d481c61b10a131cb0ae3dfc09adf3beaff76557597010914df48ff1fe1dacbf1",
|
|
44
|
+
),
|
|
41
45
|
command: z.array(z.string()),
|
|
42
46
|
cpu: z.number().default(1),
|
|
43
47
|
memoryMiB: z.number().default(4096),
|
|
@@ -46,8 +50,9 @@ export const UserConfigUpdateSchema = z.object({
|
|
|
46
50
|
startupProbe: z
|
|
47
51
|
.union([z.literal("startupProbeOn"), z.literal("startupProbeOff")])
|
|
48
52
|
.default("startupProbeOn"),
|
|
49
|
-
replaceEnv: z
|
|
50
|
-
|
|
53
|
+
replaceEnv: z.array(
|
|
54
|
+
z.object({ name: z.string().min(1), value: EnvUpdateValueSchema }),
|
|
55
|
+
),
|
|
51
56
|
});
|
|
52
57
|
|
|
53
58
|
const t = initTRPC.context<{}>().create({ transformer: superjson });
|
|
@@ -61,14 +66,18 @@ const appRouter = router({
|
|
|
61
66
|
.mutation(() => {
|
|
62
67
|
throw new Error("stub");
|
|
63
68
|
}),
|
|
64
|
-
|
|
69
|
+
partialUpdateServer: procedure
|
|
65
70
|
.input(
|
|
66
71
|
z.object({
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
hostedId: HostedIdSchema,
|
|
73
|
+
update: z.object({
|
|
74
|
+
userGivenName: z.string().optional(),
|
|
75
|
+
command: z.array(z.string()).optional(),
|
|
76
|
+
secretDataZipGcsPath: z.string().optional(),
|
|
77
|
+
}),
|
|
69
78
|
}),
|
|
70
79
|
)
|
|
71
|
-
.output(z.
|
|
80
|
+
.output(z.unknown())
|
|
72
81
|
.mutation(() => {
|
|
73
82
|
throw new Error("stub");
|
|
74
83
|
}),
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,11 @@ import keytar from "keytar";
|
|
|
9
9
|
import * as path from "path";
|
|
10
10
|
import superjson from "superjson";
|
|
11
11
|
import z, { ZodSchema } from "zod";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
type AppRouter,
|
|
14
|
+
HostedIdSchema,
|
|
15
|
+
UserConfigUpdateSchema,
|
|
16
|
+
} from "./api.js";
|
|
13
17
|
|
|
14
18
|
export type CliClientAppRouterInputs = inferRouterInputs<AppRouter>;
|
|
15
19
|
export type CliClientAppRouterOutputs = inferRouterOutputs<AppRouter>;
|
|
@@ -41,8 +45,6 @@ const HOSTED_CONFIG_PATHS: Record<Env, string> = {
|
|
|
41
45
|
const HostedConfigSchema = z.object({
|
|
42
46
|
hostedId: HostedIdSchema,
|
|
43
47
|
|
|
44
|
-
config: UserConfigUpdateSchema.omit({ secretDataZipGcsPath: true }),
|
|
45
|
-
|
|
46
48
|
// Directory containing data to send to hosted server, relative to "--base".
|
|
47
49
|
mntDataDir: z.string(),
|
|
48
50
|
});
|
|
@@ -78,7 +80,7 @@ async function requestAuth(env: Env): Promise<Auth> {
|
|
|
78
80
|
);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
const deviceData = await deviceCodeResponse.json() as any;
|
|
83
|
+
const deviceData = (await deviceCodeResponse.json()) as any;
|
|
82
84
|
const {
|
|
83
85
|
device_code: deviceCode,
|
|
84
86
|
verification_uri_complete: verificationUriComplete,
|
|
@@ -113,7 +115,7 @@ async function requestAuth(env: Env): Promise<Auth> {
|
|
|
113
115
|
continue;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
const tokenData = await tokenResponse.json() as any;
|
|
118
|
+
const tokenData = (await tokenResponse.json()) as any;
|
|
117
119
|
|
|
118
120
|
if (tokenData.error) {
|
|
119
121
|
if (tokenData.error === "authorization_pending") {
|
|
@@ -260,6 +262,76 @@ async function uploadData(
|
|
|
260
262
|
return { secretDataZipGcsPath: upload.secretDataZipGcsPath };
|
|
261
263
|
}
|
|
262
264
|
|
|
265
|
+
interface DeployOptions {
|
|
266
|
+
name?: string;
|
|
267
|
+
startupCommand?: string;
|
|
268
|
+
mntDataDir?: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function commandFromStartupCommand(startupCommand: string): string[] {
|
|
272
|
+
return ["bash", "-c", startupCommand];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function createNew(
|
|
276
|
+
client: Awaited<ReturnType<typeof makeAuthenticatedClient>>,
|
|
277
|
+
base: string,
|
|
278
|
+
options: DeployOptions,
|
|
279
|
+
): Promise<HostedConfig> {
|
|
280
|
+
const {
|
|
281
|
+
name,
|
|
282
|
+
startupCommand = "npm run build && npm run start",
|
|
283
|
+
mntDataDir = ".",
|
|
284
|
+
} = options;
|
|
285
|
+
if (name == undefined) {
|
|
286
|
+
throw new Error("--name is a required option when creating a new server");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const upload = await uploadData(client, path.join(base, mntDataDir));
|
|
290
|
+
|
|
291
|
+
const config = UserConfigUpdateSchema.parse({
|
|
292
|
+
userGivenName: name,
|
|
293
|
+
command: commandFromStartupCommand(startupCommand),
|
|
294
|
+
replaceEnv: [],
|
|
295
|
+
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
296
|
+
} satisfies z.input<typeof UserConfigUpdateSchema>);
|
|
297
|
+
|
|
298
|
+
const createdServer = await client.mcpHost.createServer.mutate({
|
|
299
|
+
config,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return {
|
|
303
|
+
hostedId: createdServer.hostedId,
|
|
304
|
+
mntDataDir,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function updateExisting(
|
|
309
|
+
client: Awaited<ReturnType<typeof makeAuthenticatedClient>>,
|
|
310
|
+
base: string,
|
|
311
|
+
config: HostedConfig,
|
|
312
|
+
options: DeployOptions,
|
|
313
|
+
): Promise<HostedConfig> {
|
|
314
|
+
const newConfig = { ...config };
|
|
315
|
+
if (options.mntDataDir != undefined) {
|
|
316
|
+
newConfig.mntDataDir = options.mntDataDir;
|
|
317
|
+
}
|
|
318
|
+
const upload = await uploadData(
|
|
319
|
+
client,
|
|
320
|
+
path.join(base, newConfig.mntDataDir),
|
|
321
|
+
);
|
|
322
|
+
await client.mcpHost.partialUpdateServer.mutate({
|
|
323
|
+
hostedId: config.hostedId,
|
|
324
|
+
update: {
|
|
325
|
+
userGivenName: options.name,
|
|
326
|
+
command: options.startupCommand
|
|
327
|
+
? commandFromStartupCommand(options.startupCommand)
|
|
328
|
+
: undefined,
|
|
329
|
+
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
return newConfig;
|
|
333
|
+
}
|
|
334
|
+
|
|
263
335
|
const program = new Command()
|
|
264
336
|
.name("hosted")
|
|
265
337
|
.description("Control hosted servers on MintMCP")
|
|
@@ -275,84 +347,43 @@ const program = new Command()
|
|
|
275
347
|
program
|
|
276
348
|
.command("create")
|
|
277
349
|
.description("Create a hosted server.")
|
|
278
|
-
.
|
|
350
|
+
.option("-n, --name <name>", "Name of the hosted server")
|
|
279
351
|
.option(
|
|
280
352
|
"--startup-command <command>",
|
|
281
353
|
"Command that runs on hosted container to start the server (runs in bash).",
|
|
282
|
-
"cd /mnt && npm run build && npm run start",
|
|
283
354
|
)
|
|
284
355
|
.option(
|
|
285
356
|
"--mnt-data-dir <directory>",
|
|
286
357
|
"Directory to copy to /mnt on the server.",
|
|
287
|
-
".",
|
|
288
358
|
)
|
|
289
359
|
.action(async (options) => {
|
|
290
|
-
const { name, startupCommand, mntDataDir } = options;
|
|
291
360
|
const { env, base } = program.opts();
|
|
292
|
-
|
|
293
|
-
const configPath = path.join(base, HOSTED_CONFIG_PATHS[env]);
|
|
294
|
-
if (fs.existsSync(configPath)) {
|
|
295
|
-
throw new Error("Hosted server config already exists.");
|
|
296
|
-
}
|
|
297
|
-
|
|
298
361
|
const client = await makeAuthenticatedClient(env);
|
|
299
|
-
const upload = await uploadData(client, path.join(base, mntDataDir));
|
|
300
|
-
|
|
301
|
-
const ConfigWithoutPathSchema = UserConfigUpdateSchema.omit({secretDataZipGcsPath: true});
|
|
302
|
-
const config = ConfigWithoutPathSchema.parse({
|
|
303
|
-
userGivenName: name,
|
|
304
|
-
command: ["bash", "-c", startupCommand],
|
|
305
|
-
replaceEnv: [],
|
|
306
|
-
} satisfies z.input<typeof ConfigWithoutPathSchema>);
|
|
307
|
-
|
|
308
|
-
console.log("Creating server...");
|
|
309
|
-
const createdServer = await client.mcpHost.createServer.mutate({
|
|
310
|
-
config: { ...config, secretDataZipGcsPath: upload.secretDataZipGcsPath },
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
const hostedConfig: HostedConfig = {
|
|
314
|
-
hostedId: createdServer.hostedId,
|
|
315
|
-
config,
|
|
316
|
-
mntDataDir,
|
|
317
|
-
};
|
|
318
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
319
|
-
fs.writeFileSync(configPath, JSON.stringify(hostedConfig, null, 2));
|
|
320
|
-
|
|
321
|
-
console.log(
|
|
322
|
-
`Created ${WEB_CLIENT_URL[env]}/hosted/${createdServer.hostedId}`,
|
|
323
|
-
);
|
|
324
|
-
});
|
|
325
362
|
|
|
326
|
-
program
|
|
327
|
-
.command("update")
|
|
328
|
-
.description("Update a hosted server.")
|
|
329
|
-
.action(async () => {
|
|
330
|
-
const { env, base } = program.opts();
|
|
331
363
|
const configPath = path.join(base, HOSTED_CONFIG_PATHS[env]);
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
364
|
+
|
|
365
|
+
let newOrUpdatedConfig: HostedConfig;
|
|
366
|
+
if (fs.existsSync(configPath)) {
|
|
367
|
+
console.log("Updating existing server...");
|
|
368
|
+
const configData = fs.readFileSync(configPath, "utf8");
|
|
369
|
+
newOrUpdatedConfig = await updateExisting(
|
|
370
|
+
client,
|
|
371
|
+
base,
|
|
372
|
+
HostedConfigSchema.parse(configData),
|
|
373
|
+
options,
|
|
374
|
+
);
|
|
375
|
+
console.log(
|
|
376
|
+
`Updated ${WEB_CLIENT_URL[env]}/hosted/${newOrUpdatedConfig.hostedId}`,
|
|
377
|
+
);
|
|
378
|
+
} else {
|
|
379
|
+
console.log("Creating new server...");
|
|
380
|
+
newOrUpdatedConfig = await createNew(client, base, options);
|
|
381
|
+
console.log(
|
|
382
|
+
`Created ${WEB_CLIENT_URL[env]}/hosted/${newOrUpdatedConfig.hostedId}`,
|
|
335
383
|
);
|
|
336
384
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const client = await makeAuthenticatedClient(env);
|
|
341
|
-
const upload = await uploadData(
|
|
342
|
-
client,
|
|
343
|
-
path.join(base, hostedConfig.mntDataDir),
|
|
344
|
-
);
|
|
345
|
-
console.log("Updating server...");
|
|
346
|
-
await client.mcpHost.updateServer.mutate({
|
|
347
|
-
app: hostedConfig.hostedId,
|
|
348
|
-
config: {
|
|
349
|
-
...hostedConfig.config,
|
|
350
|
-
secretDataZipGcsPath: upload.secretDataZipGcsPath,
|
|
351
|
-
},
|
|
352
|
-
});
|
|
353
|
-
console.log(
|
|
354
|
-
`Updated ${WEB_CLIENT_URL[env]}/hosted/${hostedConfig.hostedId}`,
|
|
355
|
-
);
|
|
385
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
386
|
+
fs.writeFileSync(configPath, JSON.stringify(newOrUpdatedConfig, null, 2));
|
|
356
387
|
});
|
|
357
388
|
|
|
358
389
|
program.parse();
|