@ni-c/mcp-hub 0.10.0 → 0.11.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 (77) hide show
  1. package/CHANGELOG.md +388 -0
  2. package/README.md +77 -12
  3. package/dist/admin.js +1 -1
  4. package/dist/admin.js.map +1 -1
  5. package/dist/auth/api-tokens.js +27 -0
  6. package/dist/auth/api-tokens.js.map +1 -0
  7. package/dist/auth/headers.js +22 -1
  8. package/dist/auth/headers.js.map +1 -1
  9. package/dist/auth/oidc/adapter.js +135 -0
  10. package/dist/auth/oidc/adapter.js.map +1 -0
  11. package/dist/auth/oidc/interactions.js +187 -0
  12. package/dist/auth/oidc/interactions.js.map +1 -0
  13. package/dist/auth/oidc/mount.js +144 -0
  14. package/dist/auth/oidc/mount.js.map +1 -0
  15. package/dist/auth/oidc/provider.js +440 -0
  16. package/dist/auth/oidc/provider.js.map +1 -0
  17. package/dist/auth/oidc/quirks.js +234 -0
  18. package/dist/auth/oidc/quirks.js.map +1 -0
  19. package/dist/auth/oidc/verifier.js +121 -0
  20. package/dist/auth/oidc/verifier.js.map +1 -0
  21. package/dist/auth/protected-resource.js +41 -0
  22. package/dist/auth/protected-resource.js.map +1 -0
  23. package/dist/auth/rate-limit.js +115 -2
  24. package/dist/auth/rate-limit.js.map +1 -1
  25. package/dist/auth/redirect-uri.js +33 -1
  26. package/dist/auth/redirect-uri.js.map +1 -1
  27. package/dist/auth/registration.js +1 -1
  28. package/dist/auth/registration.js.map +1 -1
  29. package/dist/auth/session.js +43 -0
  30. package/dist/auth/session.js.map +1 -0
  31. package/dist/auth/store.js +160 -1
  32. package/dist/auth/store.js.map +1 -1
  33. package/dist/config.js +55 -2
  34. package/dist/config.js.map +1 -1
  35. package/dist/docker-proxy/policy.js +1 -0
  36. package/dist/docker-proxy/policy.js.map +1 -1
  37. package/dist/docker-proxy/server.js +1 -0
  38. package/dist/docker-proxy/server.js.map +1 -1
  39. package/dist/elicitation.js +0 -0
  40. package/dist/elicitation.js.map +1 -0
  41. package/dist/forward.js +0 -0
  42. package/dist/forward.js.map +1 -0
  43. package/dist/hub.js +309 -29
  44. package/dist/hub.js.map +1 -1
  45. package/dist/index.js +103 -21
  46. package/dist/index.js.map +1 -1
  47. package/dist/limits.js +13 -1
  48. package/dist/limits.js.map +1 -1
  49. package/dist/mcp-limits.js +14 -2
  50. package/dist/mcp-limits.js.map +1 -1
  51. package/dist/proxy.js +246 -40
  52. package/dist/proxy.js.map +1 -1
  53. package/dist/stdio.js +71 -6
  54. package/dist/stdio.js.map +1 -1
  55. package/dist/subscriptions.js +236 -0
  56. package/dist/subscriptions.js.map +1 -0
  57. package/dist/supervisor.js +322 -22
  58. package/dist/supervisor.js.map +1 -1
  59. package/dist/timings.js +61 -0
  60. package/dist/timings.js.map +1 -0
  61. package/dist/tool-filter.js +1 -0
  62. package/dist/tool-filter.js.map +1 -1
  63. package/dist/transports/docker.js.map +1 -1
  64. package/dist/transports/stream.js +33 -20
  65. package/dist/transports/stream.js.map +1 -1
  66. package/dist/upstream/auth.js +1 -1
  67. package/dist/upstream/auth.js.map +1 -1
  68. package/dist/upstream/provider.js.map +1 -1
  69. package/dist/upstream/routes.js +3 -2
  70. package/dist/upstream/routes.js.map +1 -1
  71. package/package.json +19 -6
  72. package/dist/auth/private-key-jwt.js +0 -213
  73. package/dist/auth/private-key-jwt.js.map +0 -1
  74. package/dist/auth/provider.js +0 -437
  75. package/dist/auth/provider.js.map +0 -1
  76. package/dist/auth/routes.js +0 -249
  77. package/dist/auth/routes.js.map +0 -1
@@ -1,249 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import express, { Router } from 'express';
3
- import bcrypt from 'bcryptjs';
4
- import { mcpAuthRouter, createOAuthMetadata } from '@modelcontextprotocol/sdk/server/auth/router.js';
5
- import { SESSION_TTL_MS } from './provider.js';
6
- import { renderLoginPage } from './login-page.js';
7
- import { allowFormActionTo, contentSecurityPolicy } from './headers.js';
8
- import { isLoopbackOnly } from './redirect-uri.js';
9
- import { logSafe } from './text.js';
10
- import { privateKeyJwtAuth } from './private-key-jwt.js';
11
- import { earlyRateLimit } from './rate-limit.js';
12
- import { createRegistrationManagementRoutes } from './registration.js';
13
- const LOGIN_MAX_ATTEMPTS = 10;
14
- const LOGIN_WINDOW_MS = 15 * 60_000;
15
- const LOGIN_MAX_ATTEMPTS_TOTAL = 100;
16
- export class LoginRateLimiter {
17
- attempts = new Map();
18
- total = { count: 0, resetAt: 0 };
19
- isBlocked(ip) {
20
- if (this.total.resetAt > Date.now() && this.total.count >= LOGIN_MAX_ATTEMPTS_TOTAL)
21
- return true;
22
- const entry = this.attempts.get(ip);
23
- if (!entry || entry.resetAt < Date.now())
24
- return false;
25
- return entry.count >= LOGIN_MAX_ATTEMPTS;
26
- }
27
- recordFailure(ip) {
28
- this.sweepExpired(); // entries are otherwise only dropped on a successful login from that exact IP
29
- const now = Date.now();
30
- // Behind a reverse proxy req.ip is the proxy for every request, and a
31
- // spoofable X-Forwarded-For makes the per-IP counter meaningless — this
32
- // caps the total either way.
33
- if (this.total.resetAt < now)
34
- this.total = { count: 1, resetAt: now + LOGIN_WINDOW_MS };
35
- else
36
- this.total.count++;
37
- const entry = this.attempts.get(ip);
38
- if (!entry || entry.resetAt < now) {
39
- this.attempts.set(ip, { count: 1, resetAt: now + LOGIN_WINDOW_MS });
40
- }
41
- else {
42
- entry.count++;
43
- }
44
- }
45
- sweepExpired() {
46
- const now = Date.now();
47
- for (const [ip, entry] of this.attempts) {
48
- if (entry.resetAt < now)
49
- this.attempts.delete(ip);
50
- }
51
- }
52
- reset(ip) {
53
- this.attempts.delete(ip);
54
- this.total = { count: 0, resetAt: 0 };
55
- }
56
- }
57
- export function createAuthRoutes(options) {
58
- const { provider, externalUrl } = options;
59
- if (!options.passwordHash && !options.password) {
60
- throw new Error('Either PASSWORD_HASH (bcrypt) or PASSWORD must be set');
61
- }
62
- const issuerUrl = new URL(externalUrl);
63
- const router = Router();
64
- const rateLimiter = new LoginRateLimiter();
65
- // Keep the password login/consent pages and the OAuth token responses out of
66
- // any shared or browser cache (RFC 6749 §5.1 requires no-store on token
67
- // responses; the login form has no business being cached either). The CSP
68
- // and legacy frame header keep an attacker from clickjacking approval or
69
- // password entry. This application has no legitimate framing use case.
70
- router.use((_req, res, next) => {
71
- res.set('Cache-Control', 'no-store');
72
- res.set('Content-Security-Policy', contentSecurityPolicy());
73
- res.set('X-Frame-Options', 'DENY');
74
- res.set('X-Content-Type-Options', 'nosniff');
75
- res.set('Referrer-Policy', 'no-referrer');
76
- next();
77
- });
78
- // RFC 7592 registration management. It goes first for two reasons: the SDK's
79
- // registration router is mounted on the /register prefix and answers 405 to
80
- // anything that is not a POST, and the registration budget below is also
81
- // prefix-scoped — routine management would otherwise use up a client's
82
- // ability to register at all. It brings its own, more generous limit.
83
- if (provider.clientsStore.registerClient) {
84
- router.use(createRegistrationManagementRoutes({ store: options.store, externalUrl: issuerUrl.href }));
85
- }
86
- // These run before the SDK's JSON/form parsers. The SDK applies its own
87
- // endpoint limits too, but those otherwise happen only after body parsing.
88
- router.use('/register', earlyRateLimit(60 * 60_000, 20, 200));
89
- router.use('/authorize', earlyRateLimit(15 * 60_000, 100, 1_000));
90
- router.use('/token', earlyRateLimit(15 * 60_000, 50, 500));
91
- router.use('/login', earlyRateLimit(15 * 60_000, 100, 500));
92
- router.use('/consent', earlyRateLimit(15 * 60_000, 100, 500));
93
- // Advertised capabilities. The SDK's document knows nothing about Client ID
94
- // Metadata Documents, so the two fields clients key their registration
95
- // choice on are added here: client_id_metadata_document_supported is what
96
- // makes a spec-compliant client prefer CIMD over dynamic registration, and
97
- // private_key_jwt is how a CIMD client authenticates at the token endpoint —
98
- // it can hold no shared secret.
99
- const asMetadata = {
100
- ...createOAuthMetadata({ provider, issuerUrl }),
101
- ...(options.cimd
102
- ? {
103
- client_id_metadata_document_supported: true,
104
- token_endpoint_auth_methods_supported: ['client_secret_post', 'none', 'private_key_jwt'],
105
- token_endpoint_auth_signing_alg_values_supported: ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512', 'ES256', 'ES384', 'ES512', 'EdDSA']
106
- }
107
- : {})
108
- };
109
- if (options.cimd) {
110
- // Ahead of mcpAuthRouter so it wins the route, and ahead of the SDK's own
111
- // body parser — which is harmless, because body-parser leaves an
112
- // already-read request alone and req.body survives into the SDK handler.
113
- router.use('/token', express.urlencoded({ extended: false }), privateKeyJwtAuth({ resolver: options.cimd, externalUrl: issuerUrl.href, tokenEndpoint: asMetadata.token_endpoint }));
114
- // mcpAuthRouter serves the root RFC 8414 document itself, so the enriched
115
- // one has to be registered before it to take precedence.
116
- router.get('/.well-known/oauth-authorization-server', (_req, res) => {
117
- res.json(asMetadata);
118
- });
119
- }
120
- if (!provider.clientsStore.registerClient) {
121
- // With dynamic registration off the SDK never mounts /register, and the
122
- // request would otherwise fall through to the MCP routes and come back as
123
- // a 401 — telling a client to authenticate at an endpoint that no longer
124
- // exists. Say what actually happened instead.
125
- router.all('/register', (_req, res) => {
126
- res
127
- .status(404)
128
- .json({ error: 'not_found', error_description: 'Dynamic client registration is disabled; use a client ID metadata document' });
129
- });
130
- }
131
- // Standard AS endpoints: /.well-known/*, /authorize, /token, /register, /revoke
132
- router.use(mcpAuthRouter({ provider, issuerUrl, resourceName: 'mcp-hub' }));
133
- // Path-scoped metadata (RFC 9728 §3.1): clients connected to /<name>/mcp look
134
- // up /.well-known/oauth-protected-resource/<name>/mcp before falling back to
135
- // the root document, and RFC 8414 has an equivalent path-insertion form for
136
- // AS metadata. Serve both for any suffix; one AS covers all resources.
137
- router.get('/.well-known/oauth-authorization-server/{*splat}', (_req, res) => {
138
- res.json(asMetadata);
139
- });
140
- // OIDC Discovery alias: some clients (ChatGPT among them) probe
141
- // /.well-known/openid-configuration instead of — or before — the RFC 8414
142
- // path, and the MCP spec requires clients to support both. The RFC 8414
143
- // document is a compatible answer for the fields such clients read.
144
- router.get('/.well-known/openid-configuration', (_req, res) => {
145
- res.json(asMetadata);
146
- });
147
- router.get('/.well-known/openid-configuration/{*splat}', (_req, res) => {
148
- res.json(asMetadata);
149
- });
150
- router.get('/.well-known/oauth-protected-resource/{*splat}', (req, res) => {
151
- const suffix = req.path.replace('/.well-known/oauth-protected-resource', '');
152
- res.json({
153
- resource: issuerUrl.origin + suffix,
154
- authorization_servers: [externalUrl],
155
- bearer_methods_supported: ['header'],
156
- resource_name: 'mcp-hub'
157
- });
158
- });
159
- const checkPassword = (password) => {
160
- if (options.passwordHash)
161
- return bcrypt.compareSync(password, options.passwordHash);
162
- const expected = Buffer.from(options.password);
163
- const given = Buffer.from(password);
164
- return expected.length === given.length && crypto.timingSafeEqual(expected, given);
165
- };
166
- router.post('/login', express.urlencoded({ extended: false }), async (req, res) => {
167
- const ip = req.ip ?? 'unknown';
168
- const { password, request } = req.body;
169
- const pending = typeof request === 'string' ? provider.decodePendingAuthorization(request) : undefined;
170
- if (!pending) {
171
- res.status(400).type('html').send('<p>Authorization request expired. Close this window and connect again.</p>');
172
- return;
173
- }
174
- if (rateLimiter.isBlocked(ip)) {
175
- console.warn(`mcp-hub: login rate limit exceeded from ${logSafe(ip)}`);
176
- res.status(429).type('html').send('<p>Too many attempts. Try again later.</p>');
177
- return;
178
- }
179
- if (typeof password !== 'string' || !checkPassword(password)) {
180
- rateLimiter.recordFailure(ip);
181
- console.warn(`mcp-hub: authentication failure from ${logSafe(ip)}`);
182
- // The retry form has to reach the same redirect as the first attempt,
183
- // and say the same things about who is asking.
184
- const retryClient = await provider.clientsStore.getClient(pending.clientId);
185
- allowFormActionTo(res, pending.redirectUri);
186
- res
187
- .status(401)
188
- .type('html')
189
- .send(renderLoginPage(request, pending.redirectUri, {
190
- clientName: retryClient?.client_name,
191
- resource: pending.resource,
192
- clientId: provider.isMetadataDocumentClient(pending.clientId) ? pending.clientId : undefined,
193
- loopbackOnly: isLoopbackOnly(retryClient?.redirect_uris)
194
- }, 'Wrong password'));
195
- return;
196
- }
197
- rateLimiter.reset(ip);
198
- console.log(`mcp-hub: successful login from ${logSafe(ip)}`);
199
- res.cookie(provider.sessionCookieName, provider.createSessionCookie(), {
200
- httpOnly: true,
201
- secure: issuerUrl.protocol === 'https:',
202
- sameSite: 'lax',
203
- maxAge: SESSION_TTL_MS,
204
- path: '/'
205
- });
206
- const client = await provider.clientsStore.getClient(pending.clientId);
207
- if (!client) {
208
- res.status(400).type('html').send('<p>Unknown client. Close this window and connect again.</p>');
209
- return;
210
- }
211
- provider.approve(client, pending.redirectUri); // typing the password is the consent
212
- provider.redirectWithCode(client, pending, res);
213
- });
214
- // Reached from the consent page when a signed-in user authorizes a client
215
- // for the first time. Everything here has to hold even though the request
216
- // may have been triggered by a page the user did not expect to land on.
217
- router.post('/consent', express.urlencoded({ extended: false }), async (req, res) => {
218
- const { request, csrf, action } = req.body;
219
- const pending = typeof request === 'string' ? provider.decodePendingAuthorization(request) : undefined;
220
- if (!pending) {
221
- res.status(400).type('html').send('<p>Authorization request expired. Close this window and connect again.</p>');
222
- return;
223
- }
224
- const session = provider.readSessionCookie(req.headers.cookie);
225
- if (!session) {
226
- res.status(401).type('html').send('<p>Session expired. Close this window and connect again.</p>');
227
- return;
228
- }
229
- if (!provider.verifyCsrfToken(session, csrf)) {
230
- console.warn(`mcp-hub: consent with an invalid CSRF token from ${logSafe(req.ip ?? 'unknown')}`);
231
- res.status(403).type('html').send('<p>Invalid request. Close this window and connect again.</p>');
232
- return;
233
- }
234
- if (action !== 'approve') {
235
- console.log(`mcp-hub: authorization denied for client ${pending.clientId}`);
236
- provider.redirectWithError(pending.redirectUri, pending.state, 'access_denied', res);
237
- return;
238
- }
239
- const client = await provider.clientsStore.getClient(pending.clientId);
240
- if (!client) {
241
- res.status(400).type('html').send('<p>Unknown client. Close this window and connect again.</p>');
242
- return;
243
- }
244
- provider.approve(client, pending.redirectUri);
245
- provider.redirectWithCode(client, pending, res);
246
- });
247
- return router;
248
- }
249
- //# sourceMappingURL=routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/auth/routes.ts"],"names":[],"mappings":"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"}