@infimind/video-mcp-cli 1.0.11 → 1.0.13
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 +83 -28
- package/dist/auth/credentialWriter.js +85 -0
- package/dist/auth/exchange.js +67 -0
- package/dist/auth/installationId.js +36 -0
- package/dist/auth/login.js +77 -0
- package/dist/auth/logout.js +34 -0
- package/dist/auth/loopback.js +155 -0
- package/dist/auth/paths.js +30 -0
- package/dist/auth/pkce.js +11 -0
- package/dist/auth/profile.js +15 -0
- package/dist/auth/redact.js +63 -0
- package/dist/auth/status.js +35 -0
- package/dist/creativeTools.js +585 -0
- package/dist/index.js +139 -39
- package/dist/server.js +900 -211
- package/dist/videoRules.js +102 -20
- package/package.json +35 -8
- package/dist/index.d.ts +0 -2
- package/dist/server.d.ts +0 -11
- package/dist/videoRules.d.ts +0 -49
package/dist/index.js
CHANGED
|
@@ -1,50 +1,150 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import { createServer } from "./server.js";
|
|
4
2
|
/**
|
|
5
|
-
* CLI
|
|
3
|
+
* sora-mcp CLI entry point (1.0.13).
|
|
6
4
|
*
|
|
7
|
-
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* - `auth login` — open the browser to authorize WorkBuddy
|
|
7
|
+
* - `auth status` — print JSON status (use --json for the machine-readable form)
|
|
8
|
+
* - `auth logout` — revoke the WorkBuddy token and delete the local credential
|
|
9
|
+
* - `serve` — start the stdio MCP server (default if no subcommand)
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
* SORA_MCP_TOKEN
|
|
11
|
-
*
|
|
11
|
+
* Token resolution for `serve` (highest priority first):
|
|
12
|
+
* 1. --token / SORA_MCP_TOKEN env (legacy Claude Desktop path)
|
|
13
|
+
* 2. WorkBuddy credential file under ~/.workbuddy/connectors/infimind-video/auth/credentials.json
|
|
14
|
+
*
|
|
15
|
+
* Profile filtering:
|
|
16
|
+
* - `--profile=workbuddy` exposes only the 5 stable WorkBuddy tools
|
|
17
|
+
* - `--profile=default` exposes the full tool set (legacy behavior)
|
|
12
18
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
19
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
|
+
import { createServer } from "./server.js";
|
|
21
|
+
import { installRedactingWriters } from "./auth/redact.js";
|
|
22
|
+
import { runLogin } from "./auth/login.js";
|
|
23
|
+
import { runStatus } from "./auth/status.js";
|
|
24
|
+
import { runLogout } from "./auth/logout.js";
|
|
25
|
+
import { readCredentials } from "./auth/credentialWriter.js";
|
|
26
|
+
import { filterToolsForProfile } from "./auth/profile.js";
|
|
27
|
+
import { WORKBUDDY_TOOL_NAMES } from "./auth/profile.js";
|
|
28
|
+
// Install redacting writers BEFORE any process.stdout / stderr write, so
|
|
29
|
+
// that no token, code, or verifier can ever leave the process unwrapped.
|
|
30
|
+
installRedactingWriters();
|
|
31
|
+
function getFlag(name, args) {
|
|
32
|
+
const pref = `--${name}=`;
|
|
33
|
+
for (const a of args) {
|
|
34
|
+
if (a === `--${name}`)
|
|
35
|
+
return "true";
|
|
36
|
+
if (a.startsWith(pref))
|
|
37
|
+
return a.slice(pref.length);
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
function parseProfile(args) {
|
|
42
|
+
const raw = getFlag("profile", args);
|
|
43
|
+
if (raw === "workbuddy")
|
|
44
|
+
return "workbuddy";
|
|
45
|
+
return "default";
|
|
46
|
+
}
|
|
47
|
+
async function mainServe(args) {
|
|
48
|
+
const profile = parseProfile(args);
|
|
49
|
+
const explicitToken = getFlag("token", args);
|
|
50
|
+
const explicitTokenEnvName = getFlag("token-env", args) || "SORA_MCP_TOKEN";
|
|
51
|
+
const envToken = process.env[explicitTokenEnvName];
|
|
52
|
+
let token;
|
|
53
|
+
let tokenSource = "env";
|
|
54
|
+
if (explicitToken) {
|
|
55
|
+
token = explicitToken;
|
|
56
|
+
tokenSource = "flag";
|
|
57
|
+
}
|
|
58
|
+
else if (envToken) {
|
|
59
|
+
token = envToken;
|
|
60
|
+
tokenSource = "env";
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const creds = readCredentials();
|
|
64
|
+
if (creds) {
|
|
65
|
+
token = creds.accessToken;
|
|
66
|
+
tokenSource = "file";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
27
69
|
if (!token) {
|
|
28
|
-
|
|
29
|
-
process.exit(
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
70
|
+
process.stderr.write(`Error: no token available. Run \`sora-mcp auth login\` first or set ${explicitTokenEnvName}.\n`);
|
|
71
|
+
process.exit(2);
|
|
72
|
+
}
|
|
73
|
+
if (tokenSource === "file" && envToken) {
|
|
74
|
+
// Edge case: both env and file are set; env wins. Print a one-line
|
|
75
|
+
// note so the user knows the legacy token is in use.
|
|
76
|
+
process.stderr.write("[workbuddy-auth] note: SORA_MCP_TOKEN env is set; using it instead of the WorkBuddy credential\n");
|
|
77
|
+
}
|
|
78
|
+
const apiBaseUrl = process.env.SORA_API_URL || "https://aigc-next.iclip.cn/api";
|
|
79
|
+
const server = createServer(token, apiBaseUrl, {
|
|
80
|
+
profile,
|
|
81
|
+
filterTools: tools => filterToolsForProfile(tools, profile),
|
|
82
|
+
workbuddyToolNames: [...WORKBUDDY_TOOL_NAMES],
|
|
83
|
+
});
|
|
84
|
+
if (profile === "workbuddy") {
|
|
85
|
+
process.stderr.write(`[workbuddy-auth] profile=workbuddy; exposing ${WORKBUDDY_TOOL_NAMES.length} stable tools\n`);
|
|
86
|
+
}
|
|
37
87
|
const transport = new StdioServerTransport();
|
|
38
|
-
// Connect the server to the transport
|
|
39
88
|
await server.connect(transport);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
89
|
+
const shutdown = async (sig) => {
|
|
90
|
+
try {
|
|
91
|
+
await server.close();
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
process.on("SIGINT", shutdown);
|
|
98
|
+
process.on("SIGTERM", shutdown);
|
|
99
|
+
}
|
|
100
|
+
async function mainAuth(args) {
|
|
101
|
+
const sub = args[0];
|
|
102
|
+
if (sub === "login") {
|
|
103
|
+
const result = await runLogin();
|
|
104
|
+
if (!result.ok) {
|
|
105
|
+
process.stderr.write(`Error: auth login failed: ${result.reason}\n`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
process.stdout.write("[workbuddy-auth] login complete\n");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (sub === "status") {
|
|
112
|
+
const wantJson = args.includes("--json");
|
|
113
|
+
const result = runStatus();
|
|
114
|
+
// Default human-readable output is a single line that WorkBuddy host
|
|
115
|
+
// can grep with `statusMatch: "Authenticated"`. The --json flag still
|
|
116
|
+
// emits the structured form so test scripts keep working.
|
|
117
|
+
if (wantJson) {
|
|
118
|
+
process.stdout.write(`${JSON.stringify({ authenticated: result.authenticated })}\n`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
process.stdout.write(result.authenticated
|
|
122
|
+
? "Authenticated\n"
|
|
123
|
+
: `Not authenticated: ${result.reason ?? "no credentials"}\n`);
|
|
124
|
+
}
|
|
125
|
+
process.exit(result.authenticated ? 0 : 1);
|
|
126
|
+
}
|
|
127
|
+
if (sub === "logout") {
|
|
128
|
+
const result = await runLogout();
|
|
129
|
+
if (!result.ok) {
|
|
130
|
+
process.stderr.write(`Error: revoke failed (${result.reason}). Local credential kept so you can retry.\n`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
process.stdout.write(`Logged out. revoked=${result.revoked} localDeleted=${result.localDeleted}\n`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
process.stderr.write(`Usage: sora-mcp auth <login|status|logout>\n`);
|
|
137
|
+
process.exit(2);
|
|
138
|
+
}
|
|
139
|
+
async function main() {
|
|
140
|
+
const args = process.argv.slice(2);
|
|
141
|
+
if (args[0] === "auth") {
|
|
142
|
+
await mainAuth(args.slice(1));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
await mainServe(args);
|
|
46
146
|
}
|
|
47
|
-
main().catch(
|
|
48
|
-
|
|
147
|
+
main().catch(err => {
|
|
148
|
+
process.stderr.write(`Fatal: ${err.message ?? String(err)}\n`);
|
|
49
149
|
process.exit(1);
|
|
50
150
|
});
|