fastmcp 3.11.0 → 3.13.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
@@ -18,6 +18,7 @@ A TypeScript framework for building [MCP](https://glama.ai/mcp) servers capable
18
18
  - [Logging](#logging)
19
19
  - [Error handling](#errors)
20
20
  - [HTTP Streaming](#http-streaming) (with SSE compatibility)
21
+ - [Stateless mode](#stateless-mode) for serverless deployments
21
22
  - CORS (enabled by default)
22
23
  - [Progress notifications](#progress)
23
24
  - [Streaming output](#streaming-output)
@@ -178,6 +179,52 @@ const transport = new SSEClientTransport(new URL(`http://localhost:8080/sse`));
178
179
  await client.connect(transport);
179
180
  ```
180
181
 
182
+ #### Stateless Mode
183
+
184
+ FastMCP supports stateless operation for HTTP streaming, where each request is handled independently without maintaining persistent sessions. This is ideal for serverless environments, load-balanced deployments, or when session state isn't required.
185
+
186
+ In stateless mode:
187
+
188
+ - No sessions are tracked on the server
189
+ - Each request creates a temporary session that's discarded after the response
190
+ - Reduced memory usage and better scalability
191
+ - Perfect for stateless deployment environments
192
+
193
+ You can enable stateless mode by adding the `stateless: true` option:
194
+
195
+ ```ts
196
+ server.start({
197
+ transportType: "httpStream",
198
+ httpStream: {
199
+ port: 8080,
200
+ stateless: true,
201
+ },
202
+ });
203
+ ```
204
+
205
+ > **Note:** Stateless mode is only available with HTTP streaming transport. Features that depend on persistent sessions (like session-specific state) will not be available in stateless mode.
206
+
207
+ You can also enable stateless mode using CLI arguments or environment variables:
208
+
209
+ ```bash
210
+ # Via CLI argument
211
+ npx fastmcp dev src/server.ts --transport http-stream --port 8080 --stateless true
212
+
213
+ # Via environment variable
214
+ FASTMCP_STATELESS=true npx fastmcp dev src/server.ts
215
+ ```
216
+
217
+ The `/ready` health check endpoint will indicate when the server is running in stateless mode:
218
+
219
+ ```json
220
+ {
221
+ "mode": "stateless",
222
+ "ready": 1,
223
+ "status": "ready",
224
+ "total": 1
225
+ }
226
+ ```
227
+
181
228
  ## Core Concepts
182
229
 
183
230
  ### Tools
package/dist/FastMCP.d.ts CHANGED
@@ -293,20 +293,147 @@ type ServerOptions<T extends FastMCPSessionAuth> = {
293
293
  */
294
294
  enabled: boolean;
295
295
  /**
296
- * OAuth Protected Resource metadata for /.well-known/oauth-protected-resource
296
+ * OAuth Protected Resource metadata for `/.well-known/oauth-protected-resource`
297
297
  *
298
- * This endpoint follows RFC 9470 (OAuth 2.0 Protected Resource Metadata)
299
- * and provides metadata about the OAuth 2.0 protected resource.
298
+ * This endpoint follows {@link https://www.rfc-editor.org/rfc/rfc9728.html | RFC 9728}
299
+ * and provides metadata describing how an OAuth 2.0 protected resource (in this case,
300
+ * an MCP server) expects to be accessed.
300
301
  *
301
- * Required by MCP Specification 2025-06-18
302
+ * When configured, FastMCP will automatically serve this metadata at the
303
+ * `/.well-known/oauth-protected-resource` endpoint. The `authorizationServers` and `resource`
304
+ * fields are required. All others are optional and will be omitted from the published
305
+ * metadata if not specified.
306
+ *
307
+ * This satisfies the requirements of the MCP Authorization specification's
308
+ * {@link https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#authorization-server-location | Authorization Server Location section}.
309
+ *
310
+ * Clients consuming this metadata MUST validate that any presented values comply with
311
+ * RFC 9728, including strict validation of the `resource` identifier and intended audience
312
+ * when access tokens are issued and presented (per RFC 8707 §2).
313
+ *
314
+ * @remarks Required by MCP Specification version 2025-06-18
302
315
  */
303
316
  protectedResource?: {
317
+ /**
318
+ * Allows for additional metadata fields beyond those defined in RFC 9728.
319
+ *
320
+ * @remarks This supports vendor-specific or experimental extensions.
321
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2.3 | RFC 9728 §2.3}
322
+ */
323
+ [key: string]: unknown;
324
+ /**
325
+ * Supported values for the `authorization_details` parameter (RFC 9396).
326
+ *
327
+ * @remarks Used when fine-grained access control is in play.
328
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.23 | RFC 9728 §2.2.23}
329
+ */
330
+ authorizationDetailsTypesSupported?: string[];
331
+ /**
332
+ * List of OAuth 2.0 authorization server issuer identifiers.
333
+ *
334
+ * These correspond to ASes that can issue access tokens for this protected resource.
335
+ * MCP clients use these values to locate the relevant `/.well-known/oauth-authorization-server`
336
+ * metadata for initiating the OAuth flow.
337
+ *
338
+ * @remarks Required by the MCP spec. MCP servers MUST provide at least one issuer.
339
+ * Clients are responsible for choosing among them (see RFC 9728 §7.6).
340
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.3 | RFC 9728 §2.2.3}
341
+ */
304
342
  authorizationServers: string[];
343
+ /**
344
+ * List of supported methods for presenting OAuth 2.0 bearer tokens.
345
+ *
346
+ * @remarks Valid values are `header`, `body`, and `query`.
347
+ * If omitted, clients MAY assume only `header` is supported, per RFC 6750.
348
+ * This is a client-side interpretation and not a serialization default.
349
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.9 | RFC 9728 §2.2.9}
350
+ */
305
351
  bearerMethodsSupported?: string[];
352
+ /**
353
+ * Whether this resource requires all access tokens to be DPoP-bound.
354
+ *
355
+ * @remarks If omitted, clients SHOULD assume this is `false`.
356
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.27 | RFC 9728 §2.2.27}
357
+ */
358
+ dpopBoundAccessTokensRequired?: boolean;
359
+ /**
360
+ * Supported algorithms for verifying DPoP proofs (RFC 9449).
361
+ *
362
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.25 | RFC 9728 §2.2.25}
363
+ */
364
+ dpopSigningAlgValuesSupported?: string[];
365
+ /**
366
+ * JWKS URI of this resource. Used to validate access tokens or sign responses.
367
+ *
368
+ * @remarks When present, this MUST be an `https:` URI pointing to a valid JWK Set (RFC 7517).
369
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.5 | RFC 9728 §2.2.5}
370
+ */
306
371
  jwksUri?: string;
372
+ /**
373
+ * Canonical OAuth resource identifier for this protected resource (the MCP server).
374
+ *
375
+ * @remarks Typically the base URL of the MCP server. Clients MUST use this as the
376
+ * `resource` parameter in authorization and token requests (per RFC 8707).
377
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.1 | RFC 9728 §2.2.1}
378
+ */
307
379
  resource: string;
380
+ /**
381
+ * URL to developer-accessible documentation for this resource.
382
+ *
383
+ * @remarks This field MAY be localized.
384
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}
385
+ */
308
386
  resourceDocumentation?: string;
387
+ /**
388
+ * Human-readable name for display purposes (e.g., in UIs).
389
+ *
390
+ * @remarks This field MAY be localized using language tags (`resource_name#en`, etc.).
391
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.13 | RFC 9728 §2.2.13}
392
+ */
393
+ resourceName?: string;
394
+ /**
395
+ * URL to a human-readable policy page describing acceptable use.
396
+ *
397
+ * @remarks This field MAY be localized.
398
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.17 | RFC 9728 §2.2.17}
399
+ */
309
400
  resourcePolicyUri?: string;
401
+ /**
402
+ * Supported JWS algorithms for signed responses from this resource (e.g., response signing).
403
+ *
404
+ * @remarks MUST NOT include `none`.
405
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.11 | RFC 9728 §2.2.11}
406
+ */
407
+ resourceSigningAlgValuesSupported?: string[];
408
+ /**
409
+ * URL to the protected resource’s Terms of Service.
410
+ *
411
+ * @remarks This field MAY be localized.
412
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.19 | RFC 9728 §2.2.19}
413
+ */
414
+ resourceTosUri?: string;
415
+ /**
416
+ * Supported OAuth scopes for requesting access to this resource.
417
+ *
418
+ * @remarks Useful for discovery, but clients SHOULD still request the minimal scope required.
419
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.7 | RFC 9728 §2.2.7}
420
+ */
421
+ scopesSupported?: string[];
422
+ /**
423
+ * Developer-accessible documentation for how to use the service (not end-user docs).
424
+ *
425
+ * @remarks Semantically equivalent to `resourceDocumentation`, but included under its
426
+ * alternate name for compatibility with tools or schemas expecting either.
427
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}
428
+ */
429
+ serviceDocumentation?: string;
430
+ /**
431
+ * Whether mutual-TLS-bound access tokens are required.
432
+ *
433
+ * @remarks If omitted, clients SHOULD assume this is `false` (client-side behavior).
434
+ * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.21 | RFC 9728 §2.2.21}
435
+ */
436
+ tlsClientCertificateBoundAccessTokens?: boolean;
310
437
  };
311
438
  };
312
439
  ping?: {
@@ -479,6 +606,7 @@ declare class FastMCP<T extends FastMCPSessionAuth = FastMCPSessionAuth> extends
479
606
  endpoint?: `/${string}`;
480
607
  eventStore?: EventStore;
481
608
  port: number;
609
+ stateless?: boolean;
482
610
  };
483
611
  transportType: "httpStream" | "stdio";
484
612
  }>): Promise<void>;
package/dist/FastMCP.js CHANGED
@@ -751,7 +751,11 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
751
751
  "[FastMCP debug] listRoots method not supported by client"
752
752
  );
753
753
  } else {
754
- console.error("[FastMCP error] Error listing roots", error);
754
+ console.error(
755
+ `[FastMCP error] received error listing roots.
756
+
757
+ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
758
+ );
755
759
  }
756
760
  });
757
761
  }
@@ -1087,109 +1091,71 @@ var FastMCP = class extends FastMCPEventEmitter {
1087
1091
  });
1088
1092
  } else if (config.transportType === "httpStream") {
1089
1093
  const httpConfig = config.httpStream;
1090
- this.#httpStreamServer = await startHTTPServer({
1091
- createServer: async (request) => {
1092
- let auth;
1093
- if (this.#authenticate) {
1094
- auth = await this.#authenticate(request);
1095
- }
1096
- const allowedTools = auth ? this.#tools.filter(
1097
- (tool) => tool.canAccess ? tool.canAccess(auth) : true
1098
- ) : this.#tools;
1099
- return new FastMCPSession({
1100
- auth,
1101
- name: this.#options.name,
1102
- ping: this.#options.ping,
1103
- prompts: this.#prompts,
1104
- resources: this.#resources,
1105
- resourcesTemplates: this.#resourcesTemplates,
1106
- roots: this.#options.roots,
1107
- tools: allowedTools,
1108
- transportType: "httpStream",
1109
- utils: this.#options.utils,
1110
- version: this.#options.version
1111
- });
1112
- },
1113
- enableJsonResponse: httpConfig.enableJsonResponse,
1114
- eventStore: httpConfig.eventStore,
1115
- onClose: async (session) => {
1116
- this.emit("disconnect", {
1117
- session
1118
- });
1119
- },
1120
- onConnect: async (session) => {
1121
- this.#sessions.push(session);
1122
- console.info(`[FastMCP info] HTTP Stream session established`);
1123
- this.emit("connect", {
1124
- session
1125
- });
1126
- },
1127
- onUnhandledRequest: async (req, res) => {
1128
- const healthConfig = this.#options.health ?? {};
1129
- const enabled = healthConfig.enabled === void 0 ? true : healthConfig.enabled;
1130
- if (enabled) {
1131
- const path = healthConfig.path ?? "/health";
1132
- const url = new URL(req.url || "", "http://localhost");
1133
- try {
1134
- if (req.method === "GET" && url.pathname === path) {
1135
- res.writeHead(healthConfig.status ?? 200, {
1136
- "Content-Type": "text/plain"
1137
- }).end(healthConfig.message ?? "\u2713 Ok");
1138
- return;
1139
- }
1140
- if (req.method === "GET" && url.pathname === "/ready") {
1141
- const readySessions = this.#sessions.filter(
1142
- (s) => s.isReady
1143
- ).length;
1144
- const totalSessions = this.#sessions.length;
1145
- const allReady = readySessions === totalSessions && totalSessions > 0;
1146
- const response = {
1147
- ready: readySessions,
1148
- status: allReady ? "ready" : totalSessions === 0 ? "no_sessions" : "initializing",
1149
- total: totalSessions
1150
- };
1151
- res.writeHead(allReady ? 200 : 503, {
1152
- "Content-Type": "application/json"
1153
- }).end(JSON.stringify(response));
1154
- return;
1155
- }
1156
- } catch (error) {
1157
- console.error("[FastMCP error] health endpoint error", error);
1158
- }
1159
- }
1160
- const oauthConfig = this.#options.oauth;
1161
- if (oauthConfig?.enabled && req.method === "GET") {
1162
- const url = new URL(req.url || "", "http://localhost");
1163
- if (url.pathname === "/.well-known/oauth-authorization-server" && oauthConfig.authorizationServer) {
1164
- const metadata = convertObjectToSnakeCase(
1165
- oauthConfig.authorizationServer
1166
- );
1167
- res.writeHead(200, {
1168
- "Content-Type": "application/json"
1169
- }).end(JSON.stringify(metadata));
1170
- return;
1094
+ if (httpConfig.stateless) {
1095
+ console.info(
1096
+ `[FastMCP info] Starting server in stateless mode on HTTP Stream at http://localhost:${httpConfig.port}${httpConfig.endpoint}`
1097
+ );
1098
+ this.#httpStreamServer = await startHTTPServer({
1099
+ createServer: async (request) => {
1100
+ let auth;
1101
+ if (this.#authenticate) {
1102
+ auth = await this.#authenticate(request);
1171
1103
  }
1172
- if (url.pathname === "/.well-known/oauth-protected-resource" && oauthConfig.protectedResource) {
1173
- const metadata = convertObjectToSnakeCase(
1174
- oauthConfig.protectedResource
1175
- );
1176
- res.writeHead(200, {
1177
- "Content-Type": "application/json"
1178
- }).end(JSON.stringify(metadata));
1179
- return;
1104
+ return this.#createSession(auth);
1105
+ },
1106
+ enableJsonResponse: httpConfig.enableJsonResponse,
1107
+ eventStore: httpConfig.eventStore,
1108
+ // In stateless mode, we don't track sessions
1109
+ onClose: async () => {
1110
+ },
1111
+ onConnect: async () => {
1112
+ console.debug(
1113
+ `[FastMCP debug] Stateless HTTP Stream request handled`
1114
+ );
1115
+ },
1116
+ onUnhandledRequest: async (req, res) => {
1117
+ await this.#handleUnhandledRequest(req, res, true);
1118
+ },
1119
+ port: httpConfig.port,
1120
+ stateless: true,
1121
+ streamEndpoint: httpConfig.endpoint
1122
+ });
1123
+ } else {
1124
+ this.#httpStreamServer = await startHTTPServer({
1125
+ createServer: async (request) => {
1126
+ let auth;
1127
+ if (this.#authenticate) {
1128
+ auth = await this.#authenticate(request);
1180
1129
  }
1181
- }
1182
- res.writeHead(404).end();
1183
- },
1184
- port: httpConfig.port,
1185
- streamEndpoint: httpConfig.endpoint
1186
- });
1187
- console.info(
1188
- `[FastMCP info] server is running on HTTP Stream at http://localhost:${httpConfig.port}${httpConfig.endpoint}`
1189
- );
1190
- console.info(
1191
- `[FastMCP info] Transport type: httpStream (Streamable HTTP, not SSE)`
1192
- );
1130
+ return this.#createSession(auth);
1131
+ },
1132
+ enableJsonResponse: httpConfig.enableJsonResponse,
1133
+ eventStore: httpConfig.eventStore,
1134
+ onClose: async (session) => {
1135
+ this.emit("disconnect", {
1136
+ session
1137
+ });
1138
+ },
1139
+ onConnect: async (session) => {
1140
+ this.#sessions.push(session);
1141
+ console.info(`[FastMCP info] HTTP Stream session established`);
1142
+ this.emit("connect", {
1143
+ session
1144
+ });
1145
+ },
1146
+ onUnhandledRequest: async (req, res) => {
1147
+ await this.#handleUnhandledRequest(req, res, false);
1148
+ },
1149
+ port: httpConfig.port,
1150
+ streamEndpoint: httpConfig.endpoint
1151
+ });
1152
+ console.info(
1153
+ `[FastMCP info] server is running on HTTP Stream at http://localhost:${httpConfig.port}${httpConfig.endpoint}`
1154
+ );
1155
+ console.info(
1156
+ `[FastMCP info] Transport type: httpStream (Streamable HTTP, not SSE)`
1157
+ );
1158
+ }
1193
1159
  } else {
1194
1160
  throw new Error("Invalid transport type");
1195
1161
  }
@@ -1202,6 +1168,100 @@ var FastMCP = class extends FastMCPEventEmitter {
1202
1168
  await this.#httpStreamServer.close();
1203
1169
  }
1204
1170
  }
1171
+ /**
1172
+ * Creates a new FastMCPSession instance with the current configuration.
1173
+ * Used both for regular sessions and stateless requests.
1174
+ */
1175
+ #createSession(auth) {
1176
+ const allowedTools = auth ? this.#tools.filter(
1177
+ (tool) => tool.canAccess ? tool.canAccess(auth) : true
1178
+ ) : this.#tools;
1179
+ return new FastMCPSession({
1180
+ auth,
1181
+ name: this.#options.name,
1182
+ ping: this.#options.ping,
1183
+ prompts: this.#prompts,
1184
+ resources: this.#resources,
1185
+ resourcesTemplates: this.#resourcesTemplates,
1186
+ roots: this.#options.roots,
1187
+ tools: allowedTools,
1188
+ transportType: "httpStream",
1189
+ utils: this.#options.utils,
1190
+ version: this.#options.version
1191
+ });
1192
+ }
1193
+ /**
1194
+ * Handles unhandled HTTP requests with health, readiness, and OAuth endpoints
1195
+ */
1196
+ #handleUnhandledRequest = async (req, res, isStateless = false) => {
1197
+ const healthConfig = this.#options.health ?? {};
1198
+ const enabled = healthConfig.enabled === void 0 ? true : healthConfig.enabled;
1199
+ if (enabled) {
1200
+ const path = healthConfig.path ?? "/health";
1201
+ const url = new URL(req.url || "", "http://localhost");
1202
+ try {
1203
+ if (req.method === "GET" && url.pathname === path) {
1204
+ res.writeHead(healthConfig.status ?? 200, {
1205
+ "Content-Type": "text/plain"
1206
+ }).end(healthConfig.message ?? "\u2713 Ok");
1207
+ return;
1208
+ }
1209
+ if (req.method === "GET" && url.pathname === "/ready") {
1210
+ if (isStateless) {
1211
+ const response = {
1212
+ mode: "stateless",
1213
+ ready: 1,
1214
+ status: "ready",
1215
+ total: 1
1216
+ };
1217
+ res.writeHead(200, {
1218
+ "Content-Type": "application/json"
1219
+ }).end(JSON.stringify(response));
1220
+ } else {
1221
+ const readySessions = this.#sessions.filter(
1222
+ (s) => s.isReady
1223
+ ).length;
1224
+ const totalSessions = this.#sessions.length;
1225
+ const allReady = readySessions === totalSessions && totalSessions > 0;
1226
+ const response = {
1227
+ ready: readySessions,
1228
+ status: allReady ? "ready" : totalSessions === 0 ? "no_sessions" : "initializing",
1229
+ total: totalSessions
1230
+ };
1231
+ res.writeHead(allReady ? 200 : 503, {
1232
+ "Content-Type": "application/json"
1233
+ }).end(JSON.stringify(response));
1234
+ }
1235
+ return;
1236
+ }
1237
+ } catch (error) {
1238
+ console.error("[FastMCP error] health endpoint error", error);
1239
+ }
1240
+ }
1241
+ const oauthConfig = this.#options.oauth;
1242
+ if (oauthConfig?.enabled && req.method === "GET") {
1243
+ const url = new URL(req.url || "", "http://localhost");
1244
+ if (url.pathname === "/.well-known/oauth-authorization-server" && oauthConfig.authorizationServer) {
1245
+ const metadata = convertObjectToSnakeCase(
1246
+ oauthConfig.authorizationServer
1247
+ );
1248
+ res.writeHead(200, {
1249
+ "Content-Type": "application/json"
1250
+ }).end(JSON.stringify(metadata));
1251
+ return;
1252
+ }
1253
+ if (url.pathname === "/.well-known/oauth-protected-resource" && oauthConfig.protectedResource) {
1254
+ const metadata = convertObjectToSnakeCase(
1255
+ oauthConfig.protectedResource
1256
+ );
1257
+ res.writeHead(200, {
1258
+ "Content-Type": "application/json"
1259
+ }).end(JSON.stringify(metadata));
1260
+ return;
1261
+ }
1262
+ }
1263
+ res.writeHead(404).end();
1264
+ };
1205
1265
  #parseRuntimeConfig(overrides) {
1206
1266
  const args = process.argv.slice(2);
1207
1267
  const getArg = (name) => {
@@ -1211,9 +1271,11 @@ var FastMCP = class extends FastMCPEventEmitter {
1211
1271
  const transportArg = getArg("transport");
1212
1272
  const portArg = getArg("port");
1213
1273
  const endpointArg = getArg("endpoint");
1274
+ const statelessArg = getArg("stateless");
1214
1275
  const envTransport = process.env.FASTMCP_TRANSPORT;
1215
1276
  const envPort = process.env.FASTMCP_PORT;
1216
1277
  const envEndpoint = process.env.FASTMCP_ENDPOINT;
1278
+ const envStateless = process.env.FASTMCP_STATELESS;
1217
1279
  const transportType = overrides?.transportType || (transportArg === "http-stream" ? "httpStream" : transportArg) || envTransport || "stdio";
1218
1280
  if (transportType === "httpStream") {
1219
1281
  const port = parseInt(
@@ -1221,11 +1283,13 @@ var FastMCP = class extends FastMCPEventEmitter {
1221
1283
  );
1222
1284
  const endpoint = overrides?.httpStream?.endpoint || endpointArg || envEndpoint || "/mcp";
1223
1285
  const enableJsonResponse = overrides?.httpStream?.enableJsonResponse || false;
1286
+ const stateless = overrides?.httpStream?.stateless || statelessArg === "true" || envStateless === "true" || false;
1224
1287
  return {
1225
1288
  httpStream: {
1226
1289
  enableJsonResponse,
1227
1290
  endpoint,
1228
- port
1291
+ port,
1292
+ stateless
1229
1293
  },
1230
1294
  transportType: "httpStream"
1231
1295
  };