@winstonsayno/mcp-gateway 0.0.0-stage → 0.4.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/LICENSE +21 -0
  3. package/README.md +432 -2
  4. package/dashboard/README.md +27 -0
  5. package/dashboard/index.html +415 -0
  6. package/dist/auth/middleware.d.ts +24 -0
  7. package/dist/auth/middleware.d.ts.map +1 -0
  8. package/dist/auth/middleware.js +108 -0
  9. package/dist/auth/middleware.js.map +1 -0
  10. package/dist/auth/ratelimit.d.ts +19 -0
  11. package/dist/auth/ratelimit.d.ts.map +1 -0
  12. package/dist/auth/ratelimit.js +81 -0
  13. package/dist/auth/ratelimit.js.map +1 -0
  14. package/dist/cli.d.ts +6 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +129 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/config/loader.d.ts +13 -0
  19. package/dist/config/loader.d.ts.map +1 -0
  20. package/dist/config/loader.js +276 -0
  21. package/dist/config/loader.js.map +1 -0
  22. package/dist/config/watcher.d.ts +29 -0
  23. package/dist/config/watcher.d.ts.map +1 -0
  24. package/dist/config/watcher.js +96 -0
  25. package/dist/config/watcher.js.map +1 -0
  26. package/dist/gateway/api.d.ts +47 -0
  27. package/dist/gateway/api.d.ts.map +1 -0
  28. package/dist/gateway/api.js +324 -0
  29. package/dist/gateway/api.js.map +1 -0
  30. package/dist/gateway/index.d.ts +49 -0
  31. package/dist/gateway/index.d.ts.map +1 -0
  32. package/dist/gateway/index.js +261 -0
  33. package/dist/gateway/index.js.map +1 -0
  34. package/dist/gateway/supervisor.d.ts +58 -0
  35. package/dist/gateway/supervisor.d.ts.map +1 -0
  36. package/dist/gateway/supervisor.js +205 -0
  37. package/dist/gateway/supervisor.js.map +1 -0
  38. package/dist/index.d.ts +18 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +14 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/middleware/cors.d.ts +19 -0
  43. package/dist/middleware/cors.d.ts.map +1 -0
  44. package/dist/middleware/cors.js +65 -0
  45. package/dist/middleware/cors.js.map +1 -0
  46. package/dist/middleware/error-handler.d.ts +40 -0
  47. package/dist/middleware/error-handler.d.ts.map +1 -0
  48. package/dist/middleware/error-handler.js +98 -0
  49. package/dist/middleware/error-handler.js.map +1 -0
  50. package/dist/middleware/request-id.d.ts +23 -0
  51. package/dist/middleware/request-id.d.ts.map +1 -0
  52. package/dist/middleware/request-id.js +30 -0
  53. package/dist/middleware/request-id.js.map +1 -0
  54. package/dist/middleware/timeout.d.ts +12 -0
  55. package/dist/middleware/timeout.d.ts.map +1 -0
  56. package/dist/middleware/timeout.js +39 -0
  57. package/dist/middleware/timeout.js.map +1 -0
  58. package/dist/monitor/index.d.ts +49 -0
  59. package/dist/monitor/index.d.ts.map +1 -0
  60. package/dist/monitor/index.js +204 -0
  61. package/dist/monitor/index.js.map +1 -0
  62. package/dist/proxy/index.d.ts +86 -0
  63. package/dist/proxy/index.d.ts.map +1 -0
  64. package/dist/proxy/index.js +389 -0
  65. package/dist/proxy/index.js.map +1 -0
  66. package/dist/registry/index.d.ts +48 -0
  67. package/dist/registry/index.d.ts.map +1 -0
  68. package/dist/registry/index.js +171 -0
  69. package/dist/registry/index.js.map +1 -0
  70. package/dist/transport/channel.d.ts +61 -0
  71. package/dist/transport/channel.d.ts.map +1 -0
  72. package/dist/transport/channel.js +38 -0
  73. package/dist/transport/channel.js.map +1 -0
  74. package/dist/transport/sse-parser.d.ts +30 -0
  75. package/dist/transport/sse-parser.d.ts.map +1 -0
  76. package/dist/transport/sse-parser.js +107 -0
  77. package/dist/transport/sse-parser.js.map +1 -0
  78. package/dist/transport/sse.d.ts +39 -0
  79. package/dist/transport/sse.d.ts.map +1 -0
  80. package/dist/transport/sse.js +142 -0
  81. package/dist/transport/sse.js.map +1 -0
  82. package/dist/transport/stdio.d.ts +35 -0
  83. package/dist/transport/stdio.d.ts.map +1 -0
  84. package/dist/transport/stdio.js +149 -0
  85. package/dist/transport/stdio.js.map +1 -0
  86. package/dist/transport/streamable-http.d.ts +45 -0
  87. package/dist/transport/streamable-http.d.ts.map +1 -0
  88. package/dist/transport/streamable-http.js +183 -0
  89. package/dist/transport/streamable-http.js.map +1 -0
  90. package/dist/transport/websocket.d.ts +38 -0
  91. package/dist/transport/websocket.d.ts.map +1 -0
  92. package/dist/transport/websocket.js +172 -0
  93. package/dist/transport/websocket.js.map +1 -0
  94. package/dist/utils/logger.d.ts +16 -0
  95. package/dist/utils/logger.d.ts.map +1 -0
  96. package/dist/utils/logger.js +60 -0
  97. package/dist/utils/logger.js.map +1 -0
  98. package/dist/utils/mutex.d.ts +25 -0
  99. package/dist/utils/mutex.d.ts.map +1 -0
  100. package/dist/utils/mutex.js +62 -0
  101. package/dist/utils/mutex.js.map +1 -0
  102. package/dist/utils/semaphore.d.ts +16 -0
  103. package/dist/utils/semaphore.d.ts.map +1 -0
  104. package/dist/utils/semaphore.js +42 -0
  105. package/dist/utils/semaphore.js.map +1 -0
  106. package/dist/utils/tool-filter.d.ts +24 -0
  107. package/dist/utils/tool-filter.d.ts.map +1 -0
  108. package/dist/utils/tool-filter.js +48 -0
  109. package/dist/utils/tool-filter.js.map +1 -0
  110. package/dist/utils/types.d.ts +223 -0
  111. package/dist/utils/types.d.ts.map +1 -0
  112. package/dist/utils/types.js +5 -0
  113. package/dist/utils/types.js.map +1 -0
  114. package/dist/utils/version.d.ts +6 -0
  115. package/dist/utils/version.d.ts.map +1 -0
  116. package/dist/utils/version.js +18 -0
  117. package/dist/utils/version.js.map +1 -0
  118. package/package.json +79 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratelimit.js","sourceRoot":"","sources":["../../src/auth/ratelimit.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mcp-gateway CLI
4
+ */
5
+ import 'dotenv/config';
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,eAAe,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mcp-gateway CLI
4
+ */
5
+ import 'dotenv/config';
6
+ import { Command } from 'commander';
7
+ import { existsSync } from 'fs';
8
+ import { writeFile } from 'fs/promises';
9
+ import { loadConfig, generateDefaultConfig, resolveConfigPath } from './config/loader.js';
10
+ import { ConfigWatcher } from './config/watcher.js';
11
+ import { Gateway } from './gateway/index.js';
12
+ import { logger } from './utils/logger.js';
13
+ import { VERSION } from './utils/version.js';
14
+ const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
15
+ const program = new Command();
16
+ program
17
+ .name('mcp-gateway')
18
+ .description('A lightweight gateway for managing multiple MCP servers')
19
+ .version(VERSION);
20
+ // ─── start ────────────────────────────────────────────────────────────────────
21
+ program
22
+ .command('start')
23
+ .description('Start the MCP gateway server')
24
+ .option('-c, --config <path>', 'Path to config file')
25
+ .option('-p, --port <number>', 'Override port from config')
26
+ .option('--log-level <level>', 'Log level (debug|info|warn|error)')
27
+ .option('--no-watch', 'Disable config hot reload')
28
+ .action(async (options) => {
29
+ let gateway;
30
+ let watcher;
31
+ try {
32
+ const config = await loadConfig(options.config);
33
+ if (options.port !== undefined) {
34
+ const port = Number(options.port);
35
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
36
+ throw new Error(`Invalid --port "${options.port}"`);
37
+ }
38
+ config.port = port;
39
+ }
40
+ if (options.logLevel) {
41
+ if (!LOG_LEVELS.includes(options.logLevel)) {
42
+ throw new Error(`Invalid --log-level "${options.logLevel}" (expected ${LOG_LEVELS.join('|')})`);
43
+ }
44
+ config.logLevel = options.logLevel;
45
+ }
46
+ const gw = new Gateway(config);
47
+ gateway = gw;
48
+ // Graceful shutdown (idempotent; a second signal forces exit)
49
+ let shuttingDown = false;
50
+ const shutdown = (signal) => {
51
+ if (shuttingDown) {
52
+ logger.warn(`Received ${signal} again, forcing exit`);
53
+ process.exit(1);
54
+ }
55
+ shuttingDown = true;
56
+ logger.info(`Received ${signal}, shutting down gracefully...`);
57
+ watcher?.stop();
58
+ gw.stop().then(() => process.exit(0), (err) => {
59
+ logger.error(`Error during shutdown: ${err instanceof Error ? err.message : String(err)}`);
60
+ process.exit(1);
61
+ });
62
+ };
63
+ process.on('SIGINT', () => shutdown('SIGINT'));
64
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
65
+ await gw.start();
66
+ const configPath = resolveConfigPath(options.config);
67
+ if (options.watch && configPath) {
68
+ const w = new ConfigWatcher(configPath, logger);
69
+ watcher = w;
70
+ w.on('reload', (next) => {
71
+ // CLI overrides keep precedence over the file
72
+ if (options.logLevel)
73
+ next.logLevel = options.logLevel;
74
+ if (options.port !== undefined)
75
+ next.port = config.port;
76
+ gw.reload(next).catch((err) => {
77
+ logger.error(`Hot reload failed: ${err instanceof Error ? err.message : String(err)}`);
78
+ });
79
+ });
80
+ w.start();
81
+ }
82
+ }
83
+ catch (err) {
84
+ logger.error(`Failed to start gateway: ${err instanceof Error ? err.message : String(err)}`);
85
+ watcher?.stop();
86
+ await gateway?.stop().catch(() => { });
87
+ process.exit(1);
88
+ }
89
+ });
90
+ // ─── init ─────────────────────────────────────────────────────────────────────
91
+ program
92
+ .command('init')
93
+ .description('Generate a default configuration file')
94
+ .option('-o, --output <path>', 'Output path', 'mcp-gateway.yml')
95
+ .option('--force', 'Overwrite existing file')
96
+ .action(async (options) => {
97
+ if (existsSync(options.output) && !options.force) {
98
+ logger.error(`File "${options.output}" already exists. Use --force to overwrite.`);
99
+ process.exit(1);
100
+ }
101
+ await writeFile(options.output, generateDefaultConfig(), 'utf-8');
102
+ logger.info(`Created ${options.output}`);
103
+ console.log('\nNext steps:');
104
+ console.log(` 1. Edit ${options.output} to configure your MCP servers`);
105
+ console.log(' 2. Run: mcp-gateway start\n');
106
+ });
107
+ // ─── validate ─────────────────────────────────────────────────────────────────
108
+ program
109
+ .command('validate')
110
+ .description('Validate a configuration file')
111
+ .option('-c, --config <path>', 'Path to config file')
112
+ .action(async (options) => {
113
+ try {
114
+ const config = await loadConfig(options.config);
115
+ console.log(`✓ Configuration is valid`);
116
+ console.log(` Port: ${config.port}`);
117
+ console.log(` Servers: ${config.servers.length}`);
118
+ console.log(` Auth: ${config.auth?.strategy ?? 'none'}`);
119
+ }
120
+ catch (err) {
121
+ logger.error(`Invalid configuration: ${err instanceof Error ? err.message : String(err)}`);
122
+ process.exit(1);
123
+ }
124
+ });
125
+ program.parse(process.argv);
126
+ if (!process.argv.slice(2).length) {
127
+ program.outputHelp();
128
+ }
129
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Configuration loader
3
+ * Supports YAML, JSON, and environment variable overrides
4
+ */
5
+ import type { GatewayConfig } from '../utils/types.js';
6
+ /**
7
+ * Resolve the config file that `loadConfig` would read: the explicit path if
8
+ * given, otherwise the first match in the default search paths.
9
+ */
10
+ export declare function resolveConfigPath(configPath?: string): string | undefined;
11
+ export declare function loadConfig(configPath?: string): Promise<GatewayConfig>;
12
+ export declare function generateDefaultConfig(): string;
13
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA0IvD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMzE;AAED,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsB5E;AAkCD,wBAAgB,qBAAqB,IAAI,MAAM,CA8E9C"}
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Configuration loader
3
+ * Supports YAML, JSON, and environment variable overrides
4
+ */
5
+ import { readFile } from 'fs/promises';
6
+ import { existsSync } from 'fs';
7
+ import { resolve } from 'path';
8
+ import { parse as parseYaml } from 'yaml';
9
+ import { z } from 'zod';
10
+ // ─── Zod Schema ───────────────────────────────────────────────────────────────
11
+ const ReconnectSchema = z.object({
12
+ enabled: z.boolean().optional(),
13
+ initialDelayMs: z.number().int().positive().optional(),
14
+ maxDelayMs: z.number().int().positive().optional(),
15
+ multiplier: z.number().min(1).optional(),
16
+ jitter: z.number().min(0).max(1).optional(),
17
+ maxAttempts: z.number().int().min(0).optional(),
18
+ });
19
+ const URL_PROTOCOLS = {
20
+ sse: ['http:', 'https:'],
21
+ 'streamable-http': ['http:', 'https:'],
22
+ websocket: ['ws:', 'wss:'],
23
+ };
24
+ function safeProtocol(url) {
25
+ try {
26
+ return new URL(url).protocol;
27
+ }
28
+ catch {
29
+ return '';
30
+ }
31
+ }
32
+ const ToolPatternList = z.array(z.string().min(1, 'patterns must be non-empty'));
33
+ const ToolFilterSchema = z
34
+ .object({
35
+ allow: ToolPatternList.optional(),
36
+ deny: ToolPatternList.optional(),
37
+ })
38
+ .strict();
39
+ const McpServerSchema = z.object({
40
+ id: z.string().min(1),
41
+ name: z.string().min(1),
42
+ description: z.string().optional(),
43
+ transport: z.enum(['stdio', 'sse', 'websocket', 'streamable-http']),
44
+ command: z.string().optional(),
45
+ args: z.array(z.string()).optional(),
46
+ url: z.string().url().optional(),
47
+ env: z.record(z.string()).optional(),
48
+ headers: z.record(z.string()).optional(),
49
+ subprotocol: z.string().optional(),
50
+ reconnect: ReconnectSchema.optional(),
51
+ tags: z.array(z.string()).optional(),
52
+ enabled: z.boolean().default(true),
53
+ timeout: z.number().positive().default(30000),
54
+ maxConcurrency: z.number().int().positive().default(10),
55
+ tools: ToolFilterSchema.optional(),
56
+ }).superRefine((s, ctx) => {
57
+ if (s.transport === 'stdio' && !s.command) {
58
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['command'], message: 'required for stdio transport' });
59
+ }
60
+ const protocols = URL_PROTOCOLS[s.transport];
61
+ if (protocols) {
62
+ if (!s.url) {
63
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['url'], message: `required for ${s.transport} transport` });
64
+ }
65
+ else if (!protocols.includes(safeProtocol(s.url))) {
66
+ ctx.addIssue({
67
+ code: z.ZodIssueCode.custom,
68
+ path: ['url'],
69
+ message: `${s.transport} transport needs a ${protocols.map((p) => p.replace(':', '://')).join(' or ')} URL`,
70
+ });
71
+ }
72
+ }
73
+ });
74
+ const GatewayConfigSchema = z.object({
75
+ port: z.number().int().min(1).max(65535).default(4000),
76
+ host: z.string().default('0.0.0.0'),
77
+ auth: z
78
+ .object({
79
+ strategy: z.enum(['none', 'api-key', 'jwt', 'oauth2']).default('none'),
80
+ apiKeys: z.array(z.string()).optional(),
81
+ jwtSecret: z.string().optional(),
82
+ protect: z
83
+ .object({
84
+ health: z.boolean().default(false),
85
+ metrics: z.boolean().default(false),
86
+ })
87
+ .optional(),
88
+ })
89
+ .superRefine((a, ctx) => {
90
+ if (a.strategy === 'api-key' && !(a.apiKeys ?? []).some((k) => k.length > 0)) {
91
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['apiKeys'], message: 'at least one key is required for api-key strategy' });
92
+ }
93
+ if (a.strategy === 'jwt' && !a.jwtSecret) {
94
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['jwtSecret'], message: 'required for jwt strategy' });
95
+ }
96
+ if (a.strategy === 'oauth2') {
97
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['strategy'], message: 'oauth2 is not implemented yet (refusing to start without auth)' });
98
+ }
99
+ })
100
+ .optional(),
101
+ rateLimit: z
102
+ .object({
103
+ limit: z.number().int().positive().default(100),
104
+ windowSeconds: z.number().positive().default(60),
105
+ perKey: z.boolean().default(true),
106
+ })
107
+ .optional(),
108
+ monitor: z
109
+ .object({
110
+ prometheus: z.boolean().default(false),
111
+ requestLog: z.boolean().default(true),
112
+ retentionHours: z.number().positive().default(24),
113
+ })
114
+ .optional(),
115
+ servers: z.array(McpServerSchema).default([]),
116
+ corsOrigins: z.array(z.string()).optional(),
117
+ logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
118
+ reconnect: ReconnectSchema.optional(),
119
+ healthCheckIntervalMs: z.number().int().min(1000).default(30_000),
120
+ dashboard: z.object({ enabled: z.boolean().default(true) }).optional(),
121
+ }).superRefine((c, ctx) => {
122
+ const seen = new Set();
123
+ c.servers.forEach((s, i) => {
124
+ if (seen.has(s.id)) {
125
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['servers', i, 'id'], message: `duplicate server id "${s.id}"` });
126
+ }
127
+ seen.add(s.id);
128
+ });
129
+ });
130
+ // ─── Loader ───────────────────────────────────────────────────────────────────
131
+ const CONFIG_SEARCH_PATHS = [
132
+ 'mcp-gateway.yml',
133
+ 'mcp-gateway.yaml',
134
+ 'mcp-gateway.json',
135
+ '.mcp-gateway.yml',
136
+ '.mcp-gateway.yaml',
137
+ ];
138
+ /**
139
+ * Resolve the config file that `loadConfig` would read: the explicit path if
140
+ * given, otherwise the first match in the default search paths.
141
+ */
142
+ export function resolveConfigPath(configPath) {
143
+ if (configPath)
144
+ return resolve(configPath);
145
+ for (const searchPath of CONFIG_SEARCH_PATHS) {
146
+ if (existsSync(searchPath))
147
+ return resolve(searchPath);
148
+ }
149
+ return undefined;
150
+ }
151
+ export async function loadConfig(configPath) {
152
+ const filePath = resolveConfigPath(configPath);
153
+ let raw = filePath ? await readConfigFile(filePath) : {};
154
+ // An empty YAML file parses to null
155
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
156
+ if (raw !== null && raw !== undefined) {
157
+ throw new Error(`Invalid configuration: ${filePath} must contain a mapping/object at the top level`);
158
+ }
159
+ raw = {};
160
+ }
161
+ // Apply environment variable overrides
162
+ raw = applyEnvOverrides(raw);
163
+ const result = GatewayConfigSchema.safeParse(raw);
164
+ if (!result.success) {
165
+ throw new Error(`Invalid configuration:\n${result.error.issues.map((i) => ` - ${i.path.join('.')}: ${i.message}`).join('\n')}`);
166
+ }
167
+ return result.data;
168
+ }
169
+ async function readConfigFile(filePath) {
170
+ const content = await readFile(filePath, 'utf-8');
171
+ if (filePath.endsWith('.json')) {
172
+ return JSON.parse(content);
173
+ }
174
+ return parseYaml(content);
175
+ }
176
+ function applyEnvOverrides(config) {
177
+ const overrides = { ...config };
178
+ if (process.env.MCP_GATEWAY_PORT) {
179
+ overrides.port = parseInt(process.env.MCP_GATEWAY_PORT, 10);
180
+ }
181
+ if (process.env.MCP_GATEWAY_HOST) {
182
+ overrides.host = process.env.MCP_GATEWAY_HOST;
183
+ }
184
+ if (process.env.MCP_GATEWAY_LOG_LEVEL) {
185
+ overrides.logLevel = process.env.MCP_GATEWAY_LOG_LEVEL;
186
+ }
187
+ if (process.env.MCP_GATEWAY_API_KEYS) {
188
+ // Keeps other auth settings (e.g. auth.protect) from the file.
189
+ overrides.auth = {
190
+ ...(overrides.auth ?? {}),
191
+ strategy: 'api-key',
192
+ apiKeys: process.env.MCP_GATEWAY_API_KEYS.split(',').map((k) => k.trim()).filter(Boolean),
193
+ };
194
+ }
195
+ return overrides;
196
+ }
197
+ export function generateDefaultConfig() {
198
+ return `# mcp-gateway configuration
199
+ # Documentation: https://github.com/HarrisonCN/mcp-gateway/docs
200
+
201
+ port: 4000
202
+ host: 0.0.0.0
203
+ logLevel: info
204
+
205
+ # Authentication (optional; keys can be changed without a restart)
206
+ # auth:
207
+ # strategy: api-key
208
+ # apiKeys:
209
+ # - your-secret-key-here
210
+ # protect:
211
+ # health: false # true = /api/v1/health requires a key (/health/live stays public)
212
+ # metrics: false # true = /api/v1/metrics requires a key (configure your scraper)
213
+
214
+ # Automatic reconnect of crashed / disconnected servers (defaults shown)
215
+ # reconnect:
216
+ # enabled: true
217
+ # initialDelayMs: 1000
218
+ # maxDelayMs: 60000
219
+ # multiplier: 2
220
+ # jitter: 0.2
221
+ # maxAttempts: 0 # 0 = retry forever
222
+
223
+ # Rate limiting (optional)
224
+ # rateLimit:
225
+ # limit: 100
226
+ # windowSeconds: 60
227
+ # perKey: true
228
+
229
+ # Monitoring
230
+ monitor:
231
+ requestLog: true
232
+ prometheus: false
233
+ retentionHours: 24
234
+
235
+ # MCP Servers to manage
236
+ servers:
237
+ - id: filesystem
238
+ name: Filesystem Server
239
+ description: Access local files and directories
240
+ transport: stdio
241
+ command: npx
242
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
243
+ tags: [files, local]
244
+ enabled: true
245
+
246
+ - id: github
247
+ name: GitHub Server
248
+ description: Interact with GitHub repositories
249
+ transport: stdio
250
+ command: npx
251
+ args: ["-y", "@modelcontextprotocol/server-github"]
252
+ env:
253
+ GITHUB_PERSONAL_ACCESS_TOKEN: \${GITHUB_TOKEN}
254
+ tags: [github, vcs]
255
+ enabled: true
256
+
257
+ # Remote servers
258
+ # - id: remote-http
259
+ # name: Remote (Streamable HTTP)
260
+ # transport: streamable-http
261
+ # url: https://mcp.example.com/mcp
262
+ # headers:
263
+ # Authorization: "Bearer \${REMOTE_MCP_TOKEN}"
264
+ #
265
+ # - id: legacy-sse
266
+ # name: Legacy SSE server
267
+ # transport: sse
268
+ # url: http://localhost:8080/sse
269
+ #
270
+ # - id: websocket
271
+ # name: WebSocket server
272
+ # transport: websocket
273
+ # url: ws://localhost:8081
274
+ `;
275
+ }
276
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Config File Watcher — Hot Reload Support
3
+ *
4
+ * Watches the active config file for changes and emits a 'reload' event
5
+ * so the gateway can apply new server registrations without restarting.
6
+ *
7
+ * Many editors save atomically (write temp file + rename), which surfaces as a
8
+ * 'rename' event and silently detaches an fs.watch handle from the path. The
9
+ * watcher therefore treats 'rename' as a change and re-attaches itself.
10
+ *
11
+ * @module config/watcher
12
+ */
13
+ import { EventEmitter } from 'events';
14
+ import type { Logger } from '../utils/logger.js';
15
+ export declare class ConfigWatcher extends EventEmitter {
16
+ private configPath;
17
+ private logger;
18
+ private watcher;
19
+ private debounceTimer;
20
+ private debounceMs;
21
+ private stopped;
22
+ constructor(configPath: string, logger: Logger, debounceMs?: number);
23
+ start(): void;
24
+ private _attach;
25
+ private _schedule;
26
+ private _reload;
27
+ stop(): void;
28
+ }
29
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIjD,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAQ;gBAEX,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,SAAM;IAOhE,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,SAAS;YAUH,OAAO;IAerB,IAAI,IAAI,IAAI;CAQb"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Config File Watcher — Hot Reload Support
3
+ *
4
+ * Watches the active config file for changes and emits a 'reload' event
5
+ * so the gateway can apply new server registrations without restarting.
6
+ *
7
+ * Many editors save atomically (write temp file + rename), which surfaces as a
8
+ * 'rename' event and silently detaches an fs.watch handle from the path. The
9
+ * watcher therefore treats 'rename' as a change and re-attaches itself.
10
+ *
11
+ * @module config/watcher
12
+ */
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import { EventEmitter } from 'events';
16
+ import { loadConfig } from './loader.js';
17
+ export class ConfigWatcher extends EventEmitter {
18
+ configPath;
19
+ logger;
20
+ watcher = null;
21
+ debounceTimer = null;
22
+ debounceMs;
23
+ stopped = true;
24
+ constructor(configPath, logger, debounceMs = 500) {
25
+ super();
26
+ this.configPath = path.resolve(configPath);
27
+ this.logger = logger;
28
+ this.debounceMs = debounceMs;
29
+ }
30
+ start() {
31
+ if (this.watcher)
32
+ return;
33
+ this.stopped = false;
34
+ this._attach();
35
+ this.logger.info(`Config hot-reload enabled — watching ${this.configPath}`);
36
+ }
37
+ _attach() {
38
+ try {
39
+ this.watcher = fs.watch(this.configPath, (eventType) => {
40
+ if (eventType === 'rename') {
41
+ // File was replaced; the old handle is now stale.
42
+ this.watcher?.close();
43
+ this.watcher = null;
44
+ }
45
+ this._schedule();
46
+ });
47
+ this.watcher.on('error', (err) => {
48
+ this.logger.warn(`Config watcher error: ${err.message}`);
49
+ });
50
+ }
51
+ catch (err) {
52
+ const msg = err instanceof Error ? err.message : String(err);
53
+ this.logger.warn(`Cannot watch ${this.configPath}: ${msg}`);
54
+ this.watcher = null;
55
+ }
56
+ }
57
+ _schedule() {
58
+ if (this.debounceTimer)
59
+ clearTimeout(this.debounceTimer);
60
+ this.debounceTimer = setTimeout(() => {
61
+ this.debounceTimer = null;
62
+ if (this.stopped)
63
+ return;
64
+ if (!this.watcher)
65
+ this._attach();
66
+ void this._reload();
67
+ }, this.debounceMs);
68
+ }
69
+ async _reload() {
70
+ try {
71
+ const newConfig = await loadConfig(this.configPath);
72
+ if (this.stopped)
73
+ return;
74
+ this.logger.info('Config file changed — applying hot reload');
75
+ this.emit('reload', newConfig);
76
+ }
77
+ catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ this.logger.error(`Config reload failed (keeping current config): ${msg}`);
80
+ // Only emit when someone listens: an 'error'-like event without a
81
+ // listener is fine for custom names, but keep it explicit.
82
+ if (this.listenerCount('reload-error') > 0)
83
+ this.emit('reload-error', err);
84
+ }
85
+ }
86
+ stop() {
87
+ this.stopped = true;
88
+ if (this.debounceTimer)
89
+ clearTimeout(this.debounceTimer);
90
+ this.debounceTimer = null;
91
+ this.watcher?.close();
92
+ this.watcher = null;
93
+ this.logger.debug('Config watcher stopped');
94
+ }
95
+ }
96
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/config/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Gateway HTTP API
3
+ * Exposes REST endpoints for tool invocation, server management, and monitoring
4
+ */
5
+ import express from 'express';
6
+ import type { GatewayConfig, McpServerConfig } from '../utils/types.js';
7
+ import type { ServerRegistry } from '../registry/index.js';
8
+ import { type McpProxy } from '../proxy/index.js';
9
+ import type { MetricsCollector, ServerStateSample } from '../monitor/index.js';
10
+ import type { ServerSupervisor } from './supervisor.js';
11
+ export type ApiRouter = express.Router & {
12
+ close(): void;
13
+ /**
14
+ * Apply hot-reloadable settings from a new config: auth (strategy, keys,
15
+ * secret, protect flags), rate limits and monitor flags. Invalid auth keeps
16
+ * the current middleware (fail safe).
17
+ */
18
+ update(next: GatewayConfig): void;
19
+ };
20
+ export interface ApiRouterOptions {
21
+ /** Enables POST /servers/:id/reconnect and reconnect info. */
22
+ supervisor?: ServerSupervisor;
23
+ /** Makes GET /health/ready answer 503 while the gateway is shutting down. */
24
+ isShuttingDown?: () => boolean;
25
+ }
26
+ export interface Readiness {
27
+ ready: boolean;
28
+ /** Enabled servers that are connected and not `degraded`. */
29
+ readyServers: number;
30
+ /** Enabled servers. */
31
+ totalServers: number;
32
+ /** Servers that must be ready (`?min=`, default: all of them). */
33
+ required: number;
34
+ shuttingDown: boolean;
35
+ }
36
+ /**
37
+ * Readiness for load balancers / Kubernetes: ready when at least `min`
38
+ * enabled servers (default: every one) are connected and answering pings.
39
+ * A gateway with no enabled servers is ready; a shutting-down one never is.
40
+ */
41
+ export declare function computeReadiness(registry: ServerRegistry, proxy: McpProxy, min?: number, shuttingDown?: boolean): Readiness;
42
+ /** Never expose env values (tokens are commonly configured there). */
43
+ export declare function redactServer(server: McpServerConfig): McpServerConfig;
44
+ /** Per-server state for /metrics and Prometheus. */
45
+ export declare function serverStateSamples(registry: ServerRegistry, proxy: McpProxy): ServerStateSample[];
46
+ export declare function createApiRouter(config: GatewayConfig, registry: ServerRegistry, proxy: McpProxy, metrics: MetricsCollector, options?: ApiRouterOptions): ApiRouter;
47
+ //# sourceMappingURL=api.d.ts.map