@ultimatelemon-eu/mcp-http 2.0.0 → 2.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/README.md CHANGED
@@ -35,15 +35,15 @@ process.once('SIGTERM', () => {
35
35
 
36
36
  ## Options
37
37
 
38
- | Option | Default | Does |
39
- | ----------------- | ----------- | ------------------------------------------------------------ |
40
- | `createMcpServer` | required | Returns a new `McpServer` per request, given `{ apiKey }` |
41
- | `port` | required | `0` picks a free port; read it back from `.port` |
42
- | `host` | `'0.0.0.0'` | `'127.0.0.1'` keeps it local |
43
- | `basePath` | `''` | Also serve `<basePath>/mcp` and `<basePath>/healthz` |
44
- | `health` | always ok | Return `false` for a 503 on `/healthz` |
45
- | `apiKey` | off | Require the caller's key; `hint` is added to the 401 message |
46
- | `logger` | silent | Anything with `error(obj, msg)`, such as pino |
38
+ | Option | Default | Does |
39
+ | ----------------- | ----------- | ----------------------------------------------------------------------------- |
40
+ | `createMcpServer` | required | Returns a new `McpServer` per request, given `{ apiKey }` |
41
+ | `port` | required | `0` picks a free port; read it back from `.port` |
42
+ | `host` | `'0.0.0.0'` | `'127.0.0.1'` keeps it local |
43
+ | `basePath` | `''` | Also serve MCP on `<basePath>` and `<basePath>/mcp`, and `<basePath>/healthz` |
44
+ | `health` | always ok | Return `false` for a 503 on `/healthz` |
45
+ | `apiKey` | off | Require the caller's key; `hint` is added to the 401 message |
46
+ | `logger` | silent | Anything with `error(obj, msg)`, such as pino |
47
47
 
48
48
  It returns `{ url, port, close() }`.
49
49
 
@@ -53,7 +53,8 @@ With `apiKey` set, every request to `/mcp` must carry the caller's own key for
53
53
  the upstream API, in `X-Api-Key` or as `Authorization: Bearer <key>`
54
54
  (`X-Api-Key` wins when both are present). Without one the server answers 401
55
55
  before building an MCP server. The key reaches `createMcpServer` as
56
- `apiKey`; it is never logged or stored.
56
+ `apiKey`; it is never logged or stored. Other per-caller settings can travel
57
+ as headers of their own, read from `headers` in the same context.
57
58
 
58
59
  This suits public servers where each user brings their own credentials: no
59
60
  OAuth, no sessions, no database. In claude.ai, add the connector with
package/dist/server.d.ts CHANGED
@@ -6,6 +6,8 @@ export interface Logger {
6
6
  export interface RequestContext {
7
7
  /** The caller's own key for the upstream API. Set when `apiKey` is configured. */
8
8
  apiKey?: string;
9
+ /** Headers of the HTTP request, for per-caller settings beyond the key. */
10
+ headers: Headers;
9
11
  }
10
12
  export interface ApiKeyOptions {
11
13
  /** Added to the 401 message, e.g. where to get a key. */
@@ -17,7 +19,7 @@ export interface McpHttpOptions {
17
19
  port: number;
18
20
  /** Interface to listen on. Default `0.0.0.0`. */
19
21
  host?: string;
20
- /** Prefix a proxy leaves on the path, e.g. `/ns`. Both `/mcp` and `<basePath>/mcp` are served. */
22
+ /** Prefix a proxy leaves on the path, e.g. `/ns`. MCP is served on `/mcp`, `<basePath>/mcp` and `<basePath>` itself. */
21
23
  basePath?: string;
22
24
  /** Readiness for `/healthz`; return false for a 503. Default: always ready. */
23
25
  health?: () => boolean | Promise<boolean>;
package/dist/server.js CHANGED
@@ -77,10 +77,15 @@ export async function startMcpHttpServer(options) {
77
77
  const logger = options.logger ?? silent;
78
78
  const base = normalizeBasePath(options.basePath);
79
79
  const mcpPaths = new Set([`${base}/mcp`, '/mcp']);
80
+ if (base)
81
+ mcpPaths.add(base);
80
82
  const healthPaths = new Set([`${base}/healthz`, '/healthz']);
81
83
  // The key travels as pass-through authInfo, the SDK's channel from the
82
84
  // HTTP request to the per-request factory.
83
- const mcpHandler = createMcpHandler(({ authInfo }) => options.createMcpServer(authInfo ? { apiKey: authInfo.token } : {}), {
85
+ const mcpHandler = createMcpHandler(({ authInfo, requestInfo }) => options.createMcpServer({
86
+ ...(authInfo ? { apiKey: authInfo.token } : {}),
87
+ headers: requestInfo?.headers ?? new Headers()
88
+ }), {
84
89
  onerror: (error) => {
85
90
  logger.error({ err: String(error) }, 'mcp request failed');
86
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimatelemon-eu/mcp-http",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Run an MCP server over stateless Streamable HTTP: /mcp, /healthz, a base path for proxies, the caller's own API key per request, and errors that never leak a stack trace.",
5
5
  "license": "MIT",
6
6
  "repository": {