@nifrajs/mcp 3.3.0 → 4.0.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/src/server.ts CHANGED
@@ -15,9 +15,10 @@
15
15
  * {@link McpServer.handle} dispatches a single JSON-RPC message directly (for headless verification / tests).
16
16
  *
17
17
  * SECURITY: this has NO built-in authentication - once mounted, every tool is callable by anyone who can
18
- * reach the route (the CORS header is `*` and no credentials are used, so it is effectively public). That
19
- * is fine for read-only/public tools; if any tool mutates state or returns private data, gate the route
20
- * yourself (check an `Authorization` header / session in the nifra handler before calling `mcp.fetch`).
18
+ * reach the route. Browser access is same-origin by default; set `allowAnyOrigin: true` only for a
19
+ * secret-free public server. Same-origin does not stop DNS rebinding: a server on localhost or a
20
+ * private network should also set `allowedHosts`. If any tool mutates state or returns private data, gate the route yourself
21
+ * (check an `Authorization` header / session in the nifra handler before calling `mcp.fetch`).
21
22
  */
22
23
 
23
24
  import { type McpHttpOptions, respondMcpHttp } from "./http.ts"
@@ -26,6 +27,7 @@ import {
26
27
  type JsonRpcRequest,
27
28
  type JsonRpcResponse,
28
29
  type McpPrompt,
30
+ type McpProtocolState,
29
31
  type McpResource,
30
32
  type McpServerFeatures,
31
33
  type McpTool,
@@ -46,11 +48,20 @@ export interface CreateMcpServerOptions {
46
48
  readonly health?: string
47
49
  /** Max JSON-RPC body size in bytes (default 1 MB). */
48
50
  readonly maxBodyBytes?: number
51
+ /** Max serialized JSON-RPC response or SSE frame size (default 1 MB). */
52
+ readonly maxResponseBytes?: number
49
53
  /** Natural-language guidance for LLMs, surfaced in the modern `server/discover` result (2026-07-28). */
50
54
  readonly instructions?: string
51
- /** Origin allowlist for the DNS-rebinding guard. Omit to allow any origin; set it to reject other
52
- * browser origins with 403 (e.g. a hardened, non-public mount). */
55
+ /** Explicitly allow browser clients from any origin. Omit for the secure same-origin default. */
56
+ readonly allowAnyOrigin?: boolean
57
+ /** Origin allowlist for the DNS-rebinding guard. Set it to permit exact cross-origin clients. */
53
58
  readonly allowedOrigins?: readonly string[]
59
+ /** Host allowlist; set it for a server on localhost or a private network. See {@link McpHttpOptions}. */
60
+ readonly allowedHosts?: readonly string[]
61
+ /** Shared state for one authenticated MCP session; prefer `resolveState` for multi-session hosts. */
62
+ readonly state?: McpProtocolState
63
+ /** Resolve a session-scoped request registry after per-message authorization. */
64
+ readonly resolveState?: McpHttpOptions["resolveState"]
54
65
  /**
55
66
  * Per-message authorization, applied after the message parses and before any tool runs. Return
56
67
  * `false` to answer 403 with a JSON-RPC `unauthorized` error (`MCP_ERROR.UNAUTHORIZED`) and no result.
@@ -71,7 +82,10 @@ export interface McpServer {
71
82
  readonly features: McpServerFeatures
72
83
  readonly serverInfo: { name: string; version: string }
73
84
  /** Web `fetch` handler - mount at `POST /mcp` (GET is a health page, OPTIONS the CORS preflight). */
74
- fetch(request: Request, overrides?: Pick<McpHttpOptions, "authorizeMessage">): Promise<Response>
85
+ fetch(
86
+ request: Request,
87
+ overrides?: Pick<McpHttpOptions, "authorizeMessage" | "state" | "resolveState">,
88
+ ): Promise<Response>
75
89
  /** Dispatch one JSON-RPC message directly (no HTTP) - for headless verification and unit tests. */
76
90
  handle(message: JsonRpcRequest): Promise<JsonRpcResponse | null>
77
91
  /**
@@ -103,12 +117,22 @@ export function createMcpServer(opts: CreateMcpServerOptions): McpServer {
103
117
  features,
104
118
  ...(opts.health !== undefined ? { health: opts.health } : {}),
105
119
  ...(opts.maxBodyBytes !== undefined ? { maxBodyBytes: opts.maxBodyBytes } : {}),
120
+ ...(opts.maxResponseBytes !== undefined ? { maxResponseBytes: opts.maxResponseBytes } : {}),
121
+ ...(opts.allowAnyOrigin === true ? { allowAnyOrigin: true } : {}),
106
122
  ...(opts.allowedOrigins !== undefined ? { allowedOrigins: opts.allowedOrigins } : {}),
123
+ ...(opts.allowedHosts !== undefined ? { allowedHosts: opts.allowedHosts } : {}),
124
+ ...(opts.state === undefined ? {} : { state: opts.state }),
125
+ ...(opts.resolveState === undefined ? {} : { resolveState: opts.resolveState }),
107
126
  ...(opts.authorizeMessage !== undefined ? { authorizeMessage: opts.authorizeMessage } : {}),
108
127
  ...(overrides?.authorizeMessage !== undefined
109
128
  ? { authorizeMessage: overrides.authorizeMessage }
110
129
  : {}),
130
+ ...(overrides?.state === undefined ? {} : { state: overrides.state }),
131
+ ...(overrides?.resolveState === undefined ? {} : { resolveState: overrides.resolveState }),
132
+ }),
133
+ handle: (message) =>
134
+ handleRpc(message, tools, serverInfo, features, {
135
+ ...(opts.state === undefined ? {} : { state: opts.state }),
111
136
  }),
112
- handle: (message) => handleRpc(message, tools, serverInfo, features),
113
137
  }
114
138
  }