mcp-surveys-cli 0.1.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 +11 -0
- package/bin/mcp-surveys-cli.js +115 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# mcp-surveys-cli
|
|
2
|
+
|
|
3
|
+
Tiny dependency-free CLI for the hosted mcp-surveys API.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx mcp-surveys-cli schema
|
|
7
|
+
npx mcp-surveys-cli create survey.json
|
|
8
|
+
npx mcp-surveys-cli answers <survey_id> <result_token>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use `MCP_SURVEYS_BASE_URL` or `--base-url` to point at another instance.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const DEFAULT_BASE_URL = "https://mcp.voevoda-sailing.ru";
|
|
8
|
+
|
|
9
|
+
function usage() {
|
|
10
|
+
return `Usage: mcp-surveys-cli [--base-url URL] <command>
|
|
11
|
+
|
|
12
|
+
Commands:
|
|
13
|
+
create <json-file|->
|
|
14
|
+
edit <survey_id> <result_token> <json-file|->
|
|
15
|
+
get <survey_id> <result_token>
|
|
16
|
+
summary <survey_id> <result_token>
|
|
17
|
+
answers <survey_id> <result_token>
|
|
18
|
+
question <survey_id> <result_token> <question_id>
|
|
19
|
+
export <survey_id> <result_token> [--format markdown|json]
|
|
20
|
+
schema`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function parse(argv) {
|
|
24
|
+
const args = [...argv];
|
|
25
|
+
let baseUrl = process.env.MCP_SURVEYS_BASE_URL || DEFAULT_BASE_URL;
|
|
26
|
+
if (args[0] === "--base-url") {
|
|
27
|
+
baseUrl = args[1];
|
|
28
|
+
args.splice(0, 2);
|
|
29
|
+
}
|
|
30
|
+
return { baseUrl, command: args[0], args: args.slice(1) };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function readJson(path, stdin) {
|
|
34
|
+
const text = path === "-" ? stdin : await readFile(path, "utf8");
|
|
35
|
+
const value = JSON.parse(text);
|
|
36
|
+
if (!value || Array.isArray(value) || typeof value !== "object") {
|
|
37
|
+
throw new Error(`${path} must contain a JSON object`);
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function endpoint(baseUrl, path) {
|
|
43
|
+
return `${baseUrl.replace(/\/+$/, "")}${path}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function httpRequest(method, url, body, raw = false) {
|
|
47
|
+
const response = await fetch(url, {
|
|
48
|
+
method,
|
|
49
|
+
headers: body ? { accept: raw ? "text/plain" : "application/json", "content-type": "application/json" } : { accept: raw ? "text/plain" : "application/json" },
|
|
50
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
51
|
+
});
|
|
52
|
+
const text = await response.text();
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
let detail = text;
|
|
55
|
+
try {
|
|
56
|
+
detail = JSON.parse(text).detail || detail;
|
|
57
|
+
} catch {}
|
|
58
|
+
throw new Error(`HTTP ${response.status}: ${detail}`);
|
|
59
|
+
}
|
|
60
|
+
return raw ? text : JSON.parse(text);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function writeJson(write, value) {
|
|
64
|
+
write(`${JSON.stringify(value)}\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function run(argv, io = {}) {
|
|
68
|
+
const write = io.write || ((value) => process.stdout.write(value));
|
|
69
|
+
const error = io.error || ((value) => process.stderr.write(value));
|
|
70
|
+
const request = io.request || httpRequest;
|
|
71
|
+
const stdin = io.stdin ?? "";
|
|
72
|
+
const { baseUrl, command, args } = parse(argv);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
if (command === "create") {
|
|
76
|
+
writeJson(write, await request("POST", endpoint(baseUrl, "/api/agent/surveys"), await readJson(args[0], stdin)));
|
|
77
|
+
} else if (command === "edit") {
|
|
78
|
+
writeJson(
|
|
79
|
+
write,
|
|
80
|
+
await request("PATCH", endpoint(baseUrl, `/api/agent/surveys/${args[0]}`), {
|
|
81
|
+
result_token: args[1],
|
|
82
|
+
...(await readJson(args[2], stdin)),
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
} else if (command === "get") {
|
|
86
|
+
writeJson(write, await request("POST", endpoint(baseUrl, `/api/agent/surveys/${args[0]}/state`), { result_token: args[1] }));
|
|
87
|
+
} else if (command === "summary") {
|
|
88
|
+
writeJson(write, await request("POST", endpoint(baseUrl, `/api/agent/surveys/${args[0]}/summary`), { result_token: args[1] }));
|
|
89
|
+
} else if (command === "answers") {
|
|
90
|
+
writeJson(write, await request("POST", endpoint(baseUrl, `/api/agent/surveys/${args[0]}/answers`), { result_token: args[1] }));
|
|
91
|
+
} else if (command === "question") {
|
|
92
|
+
writeJson(write, await request("POST", endpoint(baseUrl, `/api/agent/surveys/${args[0]}/answers/${args[2]}`), { result_token: args[1] }));
|
|
93
|
+
} else if (command === "export") {
|
|
94
|
+
const formatIndex = args.indexOf("--format");
|
|
95
|
+
const format = formatIndex === -1 ? "markdown" : args[formatIndex + 1];
|
|
96
|
+
write(await request("POST", endpoint(baseUrl, `/api/agent/surveys/${args[0]}/export`), { result_token: args[1], format }, true));
|
|
97
|
+
} else if (command === "schema") {
|
|
98
|
+
writeJson(write, await request("GET", endpoint(baseUrl, "/api/agent/question-schema")));
|
|
99
|
+
} else {
|
|
100
|
+
throw new Error(usage());
|
|
101
|
+
}
|
|
102
|
+
} catch (err) {
|
|
103
|
+
error(`${err.message}\n`);
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
110
|
+
const chunks = [];
|
|
111
|
+
if (!process.stdin.isTTY) {
|
|
112
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
113
|
+
}
|
|
114
|
+
process.exitCode = await run(process.argv.slice(2), { stdin: Buffer.concat(chunks).toString("utf8") });
|
|
115
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-surveys-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Tiny npx CLI for the hosted mcp-surveys API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-surveys-cli": "bin/mcp-surveys-cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node --test"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/EzzySoft/mcp-surveys.git",
|
|
19
|
+
"directory": "packages/mcp-surveys-npx"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"registry": "https://registry.npmjs.org/"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
}
|
|
27
|
+
}
|