mcpstore-gateway 1.0.0 → 1.2.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/dist/index.d.ts +9 -2
- package/dist/index.js +211 -100
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* MCP Store Gateway
|
|
3
|
+
* MCP Store Gateway v1.2.0
|
|
4
4
|
*
|
|
5
5
|
* A single MCP server that gives Claude Code access to ALL your installed MCPs
|
|
6
6
|
* from mcpclaudecode.com. Install MCPs on the website, they appear here instantly.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Hosted MCPs: tools proxied through our backend (e.g. AI Brain)
|
|
10
|
+
* - External MCPs: auto-configured in ~/.mcp.json (e.g. GitHub, Playwright)
|
|
11
|
+
*
|
|
12
|
+
* Setup (one command, that's it):
|
|
13
|
+
* npx mcpstore-gateway --setup YOUR_API_KEY
|
|
14
|
+
*
|
|
15
|
+
* Runtime (called automatically by Claude Code):
|
|
9
16
|
* npx mcpstore-gateway --api-key YOUR_API_KEY
|
|
10
17
|
*/
|
|
11
18
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,41 +1,150 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* MCP Store Gateway
|
|
3
|
+
* MCP Store Gateway v1.2.0
|
|
4
4
|
*
|
|
5
5
|
* A single MCP server that gives Claude Code access to ALL your installed MCPs
|
|
6
6
|
* from mcpclaudecode.com. Install MCPs on the website, they appear here instantly.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Hosted MCPs: tools proxied through our backend (e.g. AI Brain)
|
|
10
|
+
* - External MCPs: auto-configured in ~/.mcp.json (e.g. GitHub, Playwright)
|
|
11
|
+
*
|
|
12
|
+
* Setup (one command, that's it):
|
|
13
|
+
* npx mcpstore-gateway --setup YOUR_API_KEY
|
|
14
|
+
*
|
|
15
|
+
* Runtime (called automatically by Claude Code):
|
|
9
16
|
* npx mcpstore-gateway --api-key YOUR_API_KEY
|
|
10
17
|
*/
|
|
11
18
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
19
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
import * as fs from "node:fs";
|
|
21
|
+
import * as path from "node:path";
|
|
22
|
+
import * as os from "node:os";
|
|
16
23
|
const GATEWAY_URL = process.env.MCPSTORE_GATEWAY_URL ||
|
|
17
24
|
"https://rshsqjofouqyhzvzezos.supabase.co/functions/v1";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
// Prefix for auto-managed MCP entries in .mcp.json
|
|
26
|
+
const MANAGED_PREFIX = "mcpstore-";
|
|
27
|
+
async function syncExternalMcps(apiKey) {
|
|
28
|
+
try {
|
|
29
|
+
// 1. Fetch installed external MCPs from the API
|
|
30
|
+
const res = await fetch(`${GATEWAY_URL}/gateway-sync`, {
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: `Bearer ${apiKey}`,
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
return; // Silently fail — sync is best-effort
|
|
38
|
+
const data = (await res.json());
|
|
39
|
+
const installedSlugs = new Set(data.external_mcps.map((m) => m.slug));
|
|
40
|
+
// 2. Read current ~/.mcp.json
|
|
41
|
+
const mcpJsonPath = path.join(os.homedir(), ".mcp.json");
|
|
42
|
+
let config = {};
|
|
43
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
44
|
+
try {
|
|
45
|
+
config = JSON.parse(fs.readFileSync(mcpJsonPath, "utf-8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return; // Don't mess with a broken config
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!config.mcpServers) {
|
|
52
|
+
config.mcpServers = {};
|
|
53
|
+
}
|
|
54
|
+
let changed = false;
|
|
55
|
+
// 3. Add new external MCPs (prefixed with mcpstore-)
|
|
56
|
+
for (const mcp of data.external_mcps) {
|
|
57
|
+
const key = `${MANAGED_PREFIX}${mcp.slug}`;
|
|
58
|
+
if (!config.mcpServers[key]) {
|
|
59
|
+
config.mcpServers[key] = mcp.config;
|
|
60
|
+
changed = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// 4. Remove uninstalled MCPs (only those with our prefix)
|
|
64
|
+
for (const key of Object.keys(config.mcpServers)) {
|
|
65
|
+
if (key.startsWith(MANAGED_PREFIX)) {
|
|
66
|
+
const slug = key.slice(MANAGED_PREFIX.length);
|
|
67
|
+
if (!installedSlugs.has(slug)) {
|
|
68
|
+
delete config.mcpServers[key];
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// 5. Write back if changed
|
|
74
|
+
if (changed) {
|
|
75
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
76
|
+
}
|
|
23
77
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return process.env.MCPSTORE_API_KEY;
|
|
78
|
+
catch {
|
|
79
|
+
// Sync is best-effort, never block the server from starting
|
|
27
80
|
}
|
|
28
|
-
console.error("Error: No API key provided.\n" +
|
|
29
|
-
"Usage: mcpstore-gateway --api-key YOUR_KEY\n" +
|
|
30
|
-
" or: MCPSTORE_API_KEY=YOUR_KEY mcpstore-gateway\n\n" +
|
|
31
|
-
"Get your API key at https://www.mcpclaudecode.com/dashboard");
|
|
32
|
-
process.exit(1);
|
|
33
81
|
}
|
|
34
|
-
|
|
35
|
-
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Setup mode: auto-configure .mcp.json
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
async function runSetup(apiKey) {
|
|
86
|
+
console.log("");
|
|
87
|
+
console.log(" MCP Store — Configuration automatique");
|
|
88
|
+
console.log(" ======================================");
|
|
89
|
+
console.log("");
|
|
90
|
+
// 1. Validate the API key
|
|
91
|
+
console.log(" [1/3] Verification de la cle API...");
|
|
92
|
+
try {
|
|
93
|
+
const res = await fetch(`${GATEWAY_URL}/gateway-tools`, {
|
|
94
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
95
|
+
});
|
|
96
|
+
if (!res.ok) {
|
|
97
|
+
const body = await res.json().catch(() => ({}));
|
|
98
|
+
console.error(`\n Erreur: ${body.error || "Cle API invalide"}`);
|
|
99
|
+
console.error(" Verifiez votre cle sur https://www.mcpclaudecode.com/dashboard\n");
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
const data = (await res.json());
|
|
103
|
+
console.log(` OK — ${data.count || 0} outil(s) disponible(s)`);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
console.error("\n Erreur: impossible de contacter MCP Store.");
|
|
107
|
+
console.error(" Verifiez votre connexion internet.\n");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
// 2. Find or create .mcp.json
|
|
111
|
+
console.log(" [2/3] Configuration de Claude Code...");
|
|
112
|
+
const mcpJsonPath = path.join(os.homedir(), ".mcp.json");
|
|
113
|
+
let config = {};
|
|
114
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
115
|
+
try {
|
|
116
|
+
config = JSON.parse(fs.readFileSync(mcpJsonPath, "utf-8"));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// File exists but isn't valid JSON — we'll create a fresh one
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (!config.mcpServers) {
|
|
123
|
+
config.mcpServers = {};
|
|
124
|
+
}
|
|
125
|
+
config.mcpServers.mcpstore = {
|
|
126
|
+
command: "npx",
|
|
127
|
+
args: ["-y", "mcpstore-gateway", "--api-key", apiKey],
|
|
128
|
+
};
|
|
129
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
130
|
+
console.log(` OK — ${mcpJsonPath}`);
|
|
131
|
+
// 3. Done!
|
|
132
|
+
console.log(" [3/3] Termine !");
|
|
133
|
+
console.log("");
|
|
134
|
+
console.log(" +--------------------------------------------------+");
|
|
135
|
+
console.log(" | MCP Store est configure ! |");
|
|
136
|
+
console.log(" | |");
|
|
137
|
+
console.log(" | Redemarrez Claude Code pour activer vos MCPs. |");
|
|
138
|
+
console.log(" | |");
|
|
139
|
+
console.log(" | Installez des MCPs : |");
|
|
140
|
+
console.log(" | https://www.mcpclaudecode.com/browse |");
|
|
141
|
+
console.log(" +--------------------------------------------------+");
|
|
142
|
+
console.log("");
|
|
143
|
+
}
|
|
144
|
+
async function fetchTools(apiKey) {
|
|
36
145
|
const res = await fetch(`${GATEWAY_URL}/gateway-tools`, {
|
|
37
146
|
headers: {
|
|
38
|
-
Authorization: `Bearer ${
|
|
147
|
+
Authorization: `Bearer ${apiKey}`,
|
|
39
148
|
"Content-Type": "application/json",
|
|
40
149
|
},
|
|
41
150
|
});
|
|
@@ -46,11 +155,11 @@ async function fetchTools() {
|
|
|
46
155
|
const data = (await res.json());
|
|
47
156
|
return data.tools || [];
|
|
48
157
|
}
|
|
49
|
-
async function callTool(toolName, args) {
|
|
158
|
+
async function callTool(apiKey, toolName, args) {
|
|
50
159
|
const res = await fetch(`${GATEWAY_URL}/gateway-call`, {
|
|
51
160
|
method: "POST",
|
|
52
161
|
headers: {
|
|
53
|
-
Authorization: `Bearer ${
|
|
162
|
+
Authorization: `Bearer ${apiKey}`,
|
|
54
163
|
"Content-Type": "application/json",
|
|
55
164
|
},
|
|
56
165
|
body: JSON.stringify({ tool: toolName, arguments: args }),
|
|
@@ -62,88 +171,60 @@ async function callTool(toolName, args) {
|
|
|
62
171
|
const data = (await res.json());
|
|
63
172
|
return data.result ?? data;
|
|
64
173
|
}
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
const server = new McpServer({
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
async
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
// Register a dynamic tool handler — we fetch tools from the gateway and
|
|
86
|
-
// register them all. MCP SDK requires registering tools at init time, so we
|
|
87
|
-
// fetch once at startup, then use the call handler to proxy dynamically.
|
|
88
|
-
async function registerTools() {
|
|
89
|
-
const tools = await getTools();
|
|
90
|
-
if (tools.length === 0) {
|
|
91
|
-
// Register a placeholder tool so the server isn't empty
|
|
92
|
-
server.tool("mcpstore__info", "No MCPs installed yet. Visit https://www.mcpclaudecode.com/browse to install MCPs.", {}, async () => ({
|
|
93
|
-
content: [
|
|
94
|
-
{
|
|
95
|
-
type: "text",
|
|
96
|
-
text: "You have no MCPs installed. Visit https://www.mcpclaudecode.com/browse to browse and install MCPs. They will appear here automatically!",
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
}));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
for (const tool of tools) {
|
|
103
|
-
// Build the input schema shape for the MCP SDK
|
|
104
|
-
const shape = {};
|
|
105
|
-
const schema = tool.inputSchema;
|
|
106
|
-
if (schema?.properties) {
|
|
107
|
-
// We pass through the raw JSON Schema — the SDK accepts it
|
|
108
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
109
|
-
shape[key] = value;
|
|
110
|
-
}
|
|
174
|
+
async function runServer(apiKey) {
|
|
175
|
+
// Sync external MCPs to ~/.mcp.json before starting
|
|
176
|
+
await syncExternalMcps(apiKey);
|
|
177
|
+
const server = new McpServer({
|
|
178
|
+
name: "MCP Store",
|
|
179
|
+
version: "1.2.0",
|
|
180
|
+
});
|
|
181
|
+
// Register hosted tools (proxied through our backend)
|
|
182
|
+
try {
|
|
183
|
+
const tools = await fetchTools(apiKey);
|
|
184
|
+
if (tools.length === 0) {
|
|
185
|
+
server.tool("mcpstore__info", "No MCPs installed yet. Visit https://www.mcpclaudecode.com/browse to install MCPs.", {}, async () => ({
|
|
186
|
+
content: [
|
|
187
|
+
{
|
|
188
|
+
type: "text",
|
|
189
|
+
text: "You have no MCPs installed. Visit https://www.mcpclaudecode.com/browse to browse and install MCPs. They will appear here automatically!",
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}));
|
|
111
193
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
194
|
+
else {
|
|
195
|
+
for (const tool of tools) {
|
|
196
|
+
const shape = {};
|
|
197
|
+
const schema = tool.inputSchema;
|
|
198
|
+
if (schema?.properties) {
|
|
199
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
200
|
+
shape[key] = value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
server.tool(tool.name, tool.description, shape, async (args) => {
|
|
204
|
+
try {
|
|
205
|
+
const result = await callTool(apiKey, tool.name, args);
|
|
206
|
+
const text = typeof result === "string"
|
|
207
|
+
? result
|
|
208
|
+
: JSON.stringify(result, null, 2);
|
|
209
|
+
return { content: [{ type: "text", text }] };
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
return {
|
|
213
|
+
content: [
|
|
214
|
+
{
|
|
215
|
+
type: "text",
|
|
216
|
+
text: `Error: ${err.message}`,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
isError: true,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
});
|
|
132
223
|
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// ---------------------------------------------------------------------------
|
|
137
|
-
// Main
|
|
138
|
-
// ---------------------------------------------------------------------------
|
|
139
|
-
async function main() {
|
|
140
|
-
try {
|
|
141
|
-
await registerTools();
|
|
224
|
+
}
|
|
142
225
|
}
|
|
143
226
|
catch (err) {
|
|
144
227
|
console.error("Failed to fetch tools from MCP Store:", err.message);
|
|
145
|
-
console.error("Make sure your API key is valid and you have MCPs installed at https://www.mcpclaudecode.com/browse");
|
|
146
|
-
// Still start the server with an error tool
|
|
147
228
|
server.tool("mcpstore__error", "MCP Store connection error", {}, async () => ({
|
|
148
229
|
content: [
|
|
149
230
|
{
|
|
@@ -157,4 +238,34 @@ async function main() {
|
|
|
157
238
|
const transport = new StdioServerTransport();
|
|
158
239
|
await server.connect(transport);
|
|
159
240
|
}
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
// Entry point
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
async function main() {
|
|
245
|
+
// --setup mode
|
|
246
|
+
const setupIdx = process.argv.indexOf("--setup");
|
|
247
|
+
if (setupIdx !== -1) {
|
|
248
|
+
const key = process.argv[setupIdx + 1];
|
|
249
|
+
if (!key) {
|
|
250
|
+
console.error("Usage: npx mcpstore-gateway --setup YOUR_API_KEY");
|
|
251
|
+
console.error("\nGet your API key at https://www.mcpclaudecode.com/dashboard");
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
await runSetup(key);
|
|
255
|
+
process.exit(0);
|
|
256
|
+
}
|
|
257
|
+
// --api-key runtime mode
|
|
258
|
+
const flagIdx = process.argv.indexOf("--api-key");
|
|
259
|
+
const apiKey = (flagIdx !== -1 && process.argv[flagIdx + 1]) ||
|
|
260
|
+
process.env.MCPSTORE_API_KEY ||
|
|
261
|
+
"";
|
|
262
|
+
if (!apiKey) {
|
|
263
|
+
console.error("Error: No API key provided.\n" +
|
|
264
|
+
"Setup: npx mcpstore-gateway --setup YOUR_KEY\n" +
|
|
265
|
+
"Runtime: npx mcpstore-gateway --api-key YOUR_KEY\n\n" +
|
|
266
|
+
"Get your API key at https://www.mcpclaudecode.com/dashboard");
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
await runServer(apiKey);
|
|
270
|
+
}
|
|
160
271
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcpstore-gateway",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP Store Gateway — One MCP server for all your installed MCPs from mcpclaudecode.com",
|
|
5
5
|
"keywords": ["mcp", "claude", "claude-code", "ai", "gateway", "marketplace"],
|
|
6
6
|
"license": "MIT",
|