@solongate/proxy 0.1.2 → 0.1.3
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/dist/create.js +247 -0
- package/dist/index.js +1388 -380
- package/dist/inject.js +339 -0
- package/package.json +3 -3
package/dist/create.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/create.ts
|
|
4
|
+
import { mkdirSync, writeFileSync, existsSync } from "fs";
|
|
5
|
+
import { resolve, join } from "path";
|
|
6
|
+
import { execSync } from "child_process";
|
|
7
|
+
function log(msg) {
|
|
8
|
+
process.stderr.write(msg + "\n");
|
|
9
|
+
}
|
|
10
|
+
function parseCreateArgs(argv) {
|
|
11
|
+
const args = argv.slice(2);
|
|
12
|
+
const opts = {
|
|
13
|
+
name: "",
|
|
14
|
+
policy: "restricted",
|
|
15
|
+
noInstall: false
|
|
16
|
+
};
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
switch (args[i]) {
|
|
19
|
+
case "--policy":
|
|
20
|
+
opts.policy = args[++i];
|
|
21
|
+
break;
|
|
22
|
+
case "--no-install":
|
|
23
|
+
opts.noInstall = true;
|
|
24
|
+
break;
|
|
25
|
+
case "--help":
|
|
26
|
+
case "-h":
|
|
27
|
+
printHelp();
|
|
28
|
+
process.exit(0);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
if (!args[i].startsWith("-") && !opts.name) {
|
|
32
|
+
opts.name = args[i];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!opts.name) {
|
|
37
|
+
log("");
|
|
38
|
+
log(" Error: Project name required.");
|
|
39
|
+
log("");
|
|
40
|
+
log(" Usage: npx @solongate/proxy create <name>");
|
|
41
|
+
log("");
|
|
42
|
+
log(" Examples:");
|
|
43
|
+
log(" npx @solongate/proxy create my-mcp-server");
|
|
44
|
+
log(" npx @solongate/proxy create weather-api");
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
return opts;
|
|
48
|
+
}
|
|
49
|
+
function printHelp() {
|
|
50
|
+
log(`
|
|
51
|
+
SolonGate Create \u2014 Scaffold a secure MCP server in seconds
|
|
52
|
+
|
|
53
|
+
USAGE
|
|
54
|
+
npx @solongate/proxy create <name> [options]
|
|
55
|
+
|
|
56
|
+
OPTIONS
|
|
57
|
+
--policy <preset> Policy preset (default: restricted)
|
|
58
|
+
--no-install Skip dependency installation
|
|
59
|
+
-h, --help Show this help message
|
|
60
|
+
|
|
61
|
+
EXAMPLES
|
|
62
|
+
npx @solongate/proxy create my-server
|
|
63
|
+
npx @solongate/proxy create db-tools --policy read-only
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
function createProject(dir, name, _policy) {
|
|
67
|
+
writeFileSync(
|
|
68
|
+
join(dir, "package.json"),
|
|
69
|
+
JSON.stringify(
|
|
70
|
+
{
|
|
71
|
+
name,
|
|
72
|
+
version: "0.1.0",
|
|
73
|
+
type: "module",
|
|
74
|
+
private: true,
|
|
75
|
+
bin: { [name]: "./dist/index.js" },
|
|
76
|
+
scripts: {
|
|
77
|
+
build: "tsup src/index.ts --format esm",
|
|
78
|
+
dev: "tsx src/index.ts",
|
|
79
|
+
start: "node dist/index.js"
|
|
80
|
+
},
|
|
81
|
+
dependencies: {
|
|
82
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
83
|
+
"@solongate/sdk": "latest",
|
|
84
|
+
zod: "^3.25.0"
|
|
85
|
+
},
|
|
86
|
+
devDependencies: {
|
|
87
|
+
tsup: "^8.3.0",
|
|
88
|
+
tsx: "^4.19.0",
|
|
89
|
+
typescript: "^5.7.0"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
null,
|
|
93
|
+
2
|
|
94
|
+
) + "\n"
|
|
95
|
+
);
|
|
96
|
+
writeFileSync(
|
|
97
|
+
join(dir, "tsconfig.json"),
|
|
98
|
+
JSON.stringify(
|
|
99
|
+
{
|
|
100
|
+
compilerOptions: {
|
|
101
|
+
target: "ES2022",
|
|
102
|
+
module: "ESNext",
|
|
103
|
+
moduleResolution: "bundler",
|
|
104
|
+
esModuleInterop: true,
|
|
105
|
+
strict: true,
|
|
106
|
+
outDir: "dist",
|
|
107
|
+
rootDir: "src",
|
|
108
|
+
declaration: true,
|
|
109
|
+
skipLibCheck: true
|
|
110
|
+
},
|
|
111
|
+
include: ["src"]
|
|
112
|
+
},
|
|
113
|
+
null,
|
|
114
|
+
2
|
|
115
|
+
) + "\n"
|
|
116
|
+
);
|
|
117
|
+
mkdirSync(join(dir, "src"), { recursive: true });
|
|
118
|
+
writeFileSync(
|
|
119
|
+
join(dir, "src", "index.ts"),
|
|
120
|
+
`#!/usr/bin/env node
|
|
121
|
+
|
|
122
|
+
// MCP uses stdout for JSON-RPC \u2014 redirect console to stderr
|
|
123
|
+
console.log = (...args: unknown[]) => {
|
|
124
|
+
process.stderr.write(args.map(String).join(' ') + '\\n');
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
import { SecureMcpServer } from '@solongate/sdk';
|
|
128
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
129
|
+
import { z } from 'zod';
|
|
130
|
+
|
|
131
|
+
// Create a secure MCP server (API key from SOLONGATE_API_KEY env var)
|
|
132
|
+
const server = new SecureMcpServer({
|
|
133
|
+
name: '${name}',
|
|
134
|
+
version: '0.1.0',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// \u2500\u2500 Register your tools below \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
138
|
+
|
|
139
|
+
server.tool(
|
|
140
|
+
'hello',
|
|
141
|
+
'Say hello to someone',
|
|
142
|
+
{ name: z.string().describe('Name of the person to greet') },
|
|
143
|
+
async ({ name }) => ({
|
|
144
|
+
content: [{ type: 'text', text: \`Hello, \${name}! Welcome to ${name}.\` }],
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Example: Add more tools here
|
|
149
|
+
// server.tool(
|
|
150
|
+
// 'read_data',
|
|
151
|
+
// 'Read data from a source',
|
|
152
|
+
// { query: z.string().describe('What to read') },
|
|
153
|
+
// async ({ query }) => ({
|
|
154
|
+
// content: [{ type: 'text', text: \`Result for: \${query}\` }],
|
|
155
|
+
// }),
|
|
156
|
+
// );
|
|
157
|
+
|
|
158
|
+
// \u2500\u2500 Start the server \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
159
|
+
|
|
160
|
+
const transport = new StdioServerTransport();
|
|
161
|
+
await server.connect(transport);
|
|
162
|
+
console.log('${name} is running');
|
|
163
|
+
`
|
|
164
|
+
);
|
|
165
|
+
writeFileSync(
|
|
166
|
+
join(dir, ".mcp.json"),
|
|
167
|
+
JSON.stringify(
|
|
168
|
+
{
|
|
169
|
+
mcpServers: {
|
|
170
|
+
[name]: {
|
|
171
|
+
command: "node",
|
|
172
|
+
args: ["dist/index.js"],
|
|
173
|
+
env: {
|
|
174
|
+
SOLONGATE_API_KEY: "sg_test_e4460d32_replace_with_your_key"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
null,
|
|
180
|
+
2
|
|
181
|
+
) + "\n"
|
|
182
|
+
);
|
|
183
|
+
writeFileSync(
|
|
184
|
+
join(dir, ".gitignore"),
|
|
185
|
+
`node_modules/
|
|
186
|
+
dist/
|
|
187
|
+
*.solongate-backup
|
|
188
|
+
.env
|
|
189
|
+
.env.local
|
|
190
|
+
`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
function installDeps(dir) {
|
|
194
|
+
log(" Installing dependencies with npm...");
|
|
195
|
+
try {
|
|
196
|
+
execSync("npm install", { cwd: dir, stdio: "pipe" });
|
|
197
|
+
} catch {
|
|
198
|
+
log(" npm install failed \u2014 run it manually.");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function main() {
|
|
202
|
+
const opts = parseCreateArgs(process.argv);
|
|
203
|
+
const dir = resolve(opts.name);
|
|
204
|
+
log("");
|
|
205
|
+
log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
206
|
+
log(" \u2551 SolonGate \u2014 Create MCP Server \u2551");
|
|
207
|
+
log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
|
|
208
|
+
log("");
|
|
209
|
+
if (existsSync(dir)) {
|
|
210
|
+
log(` Error: Directory "${opts.name}" already exists.`);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
mkdirSync(dir, { recursive: true });
|
|
214
|
+
log(` Project: ${opts.name}`);
|
|
215
|
+
log(` Language: TypeScript`);
|
|
216
|
+
log(` Policy: ${opts.policy}`);
|
|
217
|
+
log("");
|
|
218
|
+
createProject(dir, opts.name, opts.policy);
|
|
219
|
+
log(" Files created:");
|
|
220
|
+
log(" package.json");
|
|
221
|
+
log(" tsconfig.json");
|
|
222
|
+
log(" src/index.ts");
|
|
223
|
+
log(" .mcp.json");
|
|
224
|
+
log(" .gitignore");
|
|
225
|
+
log("");
|
|
226
|
+
if (!opts.noInstall) {
|
|
227
|
+
installDeps(dir);
|
|
228
|
+
log("");
|
|
229
|
+
}
|
|
230
|
+
log(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
231
|
+
log(" \u2502 Project created! \u2502");
|
|
232
|
+
log(" \u2502 \u2502");
|
|
233
|
+
log(` \u2502 cd ${opts.name.padEnd(39)}\u2502`);
|
|
234
|
+
log(" \u2502 \u2502");
|
|
235
|
+
log(" \u2502 npm run build # Build \u2502");
|
|
236
|
+
log(" \u2502 npm run dev # Dev mode (tsx) \u2502");
|
|
237
|
+
log(" \u2502 npm start # Run built server \u2502");
|
|
238
|
+
log(" \u2502 \u2502");
|
|
239
|
+
log(" \u2502 Set your API key: \u2502");
|
|
240
|
+
log(" \u2502 export SOLONGATE_API_KEY=sg_live_xxx \u2502");
|
|
241
|
+
log(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
242
|
+
log("");
|
|
243
|
+
}
|
|
244
|
+
main().catch((err) => {
|
|
245
|
+
log(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
});
|