create-guardio 0.0.5 → 0.0.7

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.
Files changed (2) hide show
  1. package/index.mjs +94 -47
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createInterface } from "node:readline";
3
- import { mkdir, writeFile, chmod } from "node:fs/promises";
3
+ import { mkdir, writeFile } from "node:fs/promises";
4
4
  import { resolve, dirname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
@@ -21,33 +21,83 @@ function ask(question, defaultAnswer = "") {
21
21
  });
22
22
  }
23
23
 
24
+ function askYesNo(question, defaultAnswer = "n") {
25
+ return ask(question + " (y/n)", defaultAnswer).then((a) =>
26
+ /^y(es)?|1$/i.test(a),
27
+ );
28
+ }
29
+
24
30
  async function main() {
25
31
  console.log("\nCreate Guardio\n");
26
32
 
27
33
  const guardioDir = await ask("Guardio directory", "./mcp-server-gated");
28
34
  const guardioPath = resolve(process.cwd(), guardioDir);
29
35
 
30
- const url = await ask("MCP server URL", "https://example.com/mcp");
36
+ // Servers: at least one, with name + URL
37
+ const servers = [];
38
+ let serverName = await ask("First MCP server name", "default");
39
+ let serverUrl = await ask("MCP server URL", "https://example.com/mcp");
40
+ servers.push({ name: serverName, type: "url", url: serverUrl });
41
+
42
+ while (await askYesNo("Add another MCP server?", "n")) {
43
+ serverName = await ask("MCP server name", "server-" + (servers.length + 1));
44
+ serverUrl = await ask("MCP server URL", "https://example.com/mcp");
45
+ servers.push({ name: serverName, type: "url", url: serverUrl });
46
+ }
47
+
31
48
  const portStr = await ask("Guardio HTTP server port", "3939");
32
49
  const port = parseInt(portStr, 10) || 3939;
33
50
 
51
+ const installDashboard = await askYesNo("Install dashboard?", "n");
52
+
53
+ // Built-in plugins: by category
54
+ console.log("\nPolicy plugins:");
55
+ console.log(" 1) none");
56
+ console.log(" 2) deny-tool-access");
57
+ console.log(" 3) regex");
58
+ console.log(" 4) both");
59
+ const policyChoice = await ask("Policy plugins (1-4)", "1");
60
+ const policyNum = parseInt(policyChoice, 10) || 1;
61
+ const policyPlugins = [];
62
+ if (policyNum === 2 || policyNum === 4) policyPlugins.push({ type: "policy", name: "deny-tool-access" });
63
+ if (policyNum === 3 || policyNum === 4) policyPlugins.push({ type: "policy", name: "regex" });
64
+
65
+ const useStorage = await askYesNo("Use storage and events (for dashboard / policy state)?", installDashboard ? "y" : "n");
66
+
67
+ const plugins = [...policyPlugins];
68
+ if (useStorage) {
69
+ console.log(" 1) sqlite (local file)");
70
+ console.log(" 2) postgres");
71
+ const storageBackend = await ask("Storage backend (1-2)", "1");
72
+ if (storageBackend === "2") {
73
+ const pgConnectionString = await ask(
74
+ "PostgreSQL connection string",
75
+ "postgresql://localhost:5432/guardio",
76
+ );
77
+ const pgConfig = { connectionString: pgConnectionString };
78
+ plugins.push({ type: "storage", name: "postgres", config: pgConfig });
79
+ plugins.push({ type: "eventSink", name: "postgres" });
80
+ plugins.push({ type: "eventSinkStore", name: "postgres" });
81
+ } else {
82
+ const sqliteConfig = { database: "guardio.sqlite" };
83
+ plugins.push({ type: "storage", name: "sqlite", config: sqliteConfig });
84
+ plugins.push({ type: "eventSink", name: "sqlite", config: sqliteConfig });
85
+ plugins.push({ type: "eventSinkStore", name: "sqlite", config: sqliteConfig });
86
+ }
87
+ }
88
+
89
+ const addExamplePlugin = await askYesNo("Add example custom policy plugin?", "n");
90
+ if (addExamplePlugin) {
91
+ plugins.push({ type: "policy", name: "example", path: "./plugins/example" });
92
+ }
93
+
34
94
  const config = {
35
- server: { type: "url", url },
36
- client: { mode: "http", port, host: "127.0.0.1" },
37
- plugins: [
38
- { type: "policy", name: "default", config: { blockedTools: [] } },
39
- {
40
- type: "policy",
41
- name: "example",
42
- path: "./plugins/example",
43
- config: {},
44
- },
45
- ],
95
+ servers,
96
+ client: { port, host: "127.0.0.1" },
97
+ plugins,
46
98
  };
47
99
 
48
100
  await mkdir(guardioPath, { recursive: true });
49
- await mkdir(resolve(guardioPath, "bin"), { recursive: true });
50
- await mkdir(resolve(guardioPath, "plugins", "example"), { recursive: true });
51
101
 
52
102
  const packageJson = {
53
103
  name: "guardio-project",
@@ -56,14 +106,20 @@ async function main() {
56
106
  description: "Guardio-gated MCP server with optional local plugins",
57
107
  scripts: {
58
108
  build: "tsc",
59
- guardio: "node bin/guardio.mjs",
109
+ guardio:
110
+ "node --import tsx ./node_modules/@guardiojs/guardio/dist/cli.js --config guardio.config.ts",
60
111
  },
61
112
  dependencies: { "@guardiojs/guardio": "*" },
62
113
  devDependencies: {
63
114
  typescript: "^5.6.0",
64
115
  "@types/node": "^22.0.0",
116
+ tsx: "^4.19.0",
65
117
  },
66
118
  };
119
+ if (installDashboard) {
120
+ packageJson.dependencies["@guardiojs/dashboard"] = "*";
121
+ packageJson.scripts.dashboard = "guardio-dashboard";
122
+ }
67
123
  await writeFile(
68
124
  resolve(guardioPath, "package.json"),
69
125
  JSON.stringify(packageJson, null, 2),
@@ -99,25 +155,9 @@ export default config;
99
155
  "utf-8",
100
156
  );
101
157
 
102
- const binContent = `#!/usr/bin/env node
103
- import { spawnSync } from "child_process";
104
- import path from "path";
105
- import { fileURLToPath } from "url";
106
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
107
- const configPath = path.resolve(__dirname, "..", "guardio.config.ts");
108
- const result = spawnSync(
109
- "npx",
110
- ["-y", "@guardiojs/guardio", "--config", configPath],
111
- { stdio: "inherit" }
112
- );
113
- process.exit(result.status ?? 1);
114
- `;
115
-
116
- const binPath = resolve(guardioPath, "bin", "guardio.mjs");
117
- await writeFile(binPath, binContent, "utf-8");
118
- await chmod(binPath, 0o755);
119
-
120
- const examplePluginContent = `import type {
158
+ if (addExamplePlugin) {
159
+ await mkdir(resolve(guardioPath, "plugins", "example"), { recursive: true });
160
+ const examplePluginContent = `import type {
121
161
  PolicyPluginInterface,
122
162
  PolicyRequestContext,
123
163
  PolicyResult,
@@ -133,30 +173,29 @@ class ExamplePolicyPlugin implements PolicyPluginInterface {
133
173
 
134
174
  evaluate(context: PolicyRequestContext): PolicyResult {
135
175
  // Example: allow all calls. Replace with your policy logic.
136
- return "allowed";
176
+ return { verdict: "allow" };
137
177
  }
138
178
  }
139
179
 
140
180
  export default new ExamplePolicyPlugin();
141
181
  `;
182
+ await writeFile(
183
+ resolve(guardioPath, "plugins", "example", "index.ts"),
184
+ examplePluginContent,
185
+ "utf-8",
186
+ );
187
+ }
142
188
 
143
- await writeFile(
144
- resolve(guardioPath, "plugins", "example", "index.ts"),
145
- examplePluginContent,
146
- "utf-8",
147
- );
148
-
189
+ await mkdir(resolve(guardioPath, "plugins"), { recursive: true });
149
190
  const pluginsReadme = `# Custom plugins (path-based)
150
191
 
151
192
  Add a plugin by setting \`path\` in \`guardio.config.ts\` to a directory that contains \`index.js\` or \`index.mjs\` (compile from \`index.ts\` with \`npm run build\`).
152
193
 
153
194
  - The directory must have \`index.js\` or \`index.mjs\` whose **default export is the plugin instance** (no descriptor).
154
195
  - Policy: implement \`PolicyPluginInterface\` (name, evaluate). Config: \`{ "type": "policy", "name": "my-policy", "path": "./plugins/my-policy" }\`.
155
- - Intervention: implement \`InterventionPluginInterface\` (name, act). Config: \`{ "type": "intervention", "name": "my-intervention", "path": "./plugins/my-intervention" }\`.
156
196
 
157
- Import types from "@guardiojs/guardio". See example/ for a policy plugin.
197
+ Import types from "@guardiojs/guardio".${addExamplePlugin ? " See example/ for a policy plugin." : ""}
158
198
  `;
159
-
160
199
  await writeFile(
161
200
  resolve(guardioPath, "plugins", "README.md"),
162
201
  pluginsReadme,
@@ -166,11 +205,19 @@ Import types from "@guardiojs/guardio". See example/ for a policy plugin.
166
205
  console.log("\n---\n");
167
206
  console.log("Next steps");
168
207
  console.log(" cd " + guardioDir + " && npm install");
169
- console.log(" npm run build # compile plugins (index.ts → index.js)");
208
+ if (addExamplePlugin) {
209
+ console.log(" npm run build # compile plugins (index.ts → index.js)");
210
+ }
170
211
  console.log("");
171
212
  console.log("Run Guardio as HTTP server:");
172
- console.log(" guardio --config guardio.config.ts");
213
+ console.log(" npm run guardio");
173
214
  console.log("");
215
+ if (installDashboard) {
216
+ console.log("Run dashboard (point it at Guardio URL):");
217
+ console.log(" npm run dashboard");
218
+ console.log(" # Dashboard needs Guardio base URL, e.g. http://127.0.0.1:" + port);
219
+ console.log("");
220
+ }
174
221
  console.log("Add to MCP client (use URL):");
175
222
  console.log(' "url": "http://127.0.0.1:' + port + '"');
176
223
  console.log("");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-guardio",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Scaffold a Guardio project",
5
5
  "type": "module",
6
6
  "bin": {