fastmcp 4.0.2 → 4.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
@@ -566,6 +566,66 @@ When creating tools that don't require parameters, you have two options:
566
566
  >
567
567
  > Both approaches are fully compatible with all MCP clients, including Cursor. FastMCP automatically generates the proper schema in both cases.
568
568
 
569
+ #### Structured Tool Output
570
+
571
+ Tools can declare an `outputSchema` and return structured data. FastMCP exposes that value as MCP `structuredContent`, while also returning a JSON text fallback for clients that only render text content.
572
+
573
+ ```typescript
574
+ server.addTool({
575
+ name: "get-weather",
576
+ description: "Get weather for a city",
577
+ parameters: z.object({
578
+ city: z.string(),
579
+ }),
580
+ outputSchema: z.object({
581
+ temperature: z.number(),
582
+ humidity: z.number(),
583
+ }),
584
+ execute: async ({ city }) => {
585
+ const weather = await getWeather(city);
586
+
587
+ return {
588
+ temperature: weather.temperature,
589
+ humidity: weather.humidity,
590
+ };
591
+ },
592
+ });
593
+ ```
594
+
595
+ You can also return explicit text content and structured content together:
596
+
597
+ ```typescript
598
+ server.addTool({
599
+ name: "get-weather",
600
+ description: "Get weather for a city",
601
+ parameters: z.object({
602
+ city: z.string(),
603
+ }),
604
+ outputSchema: z.object({
605
+ temperature: z.number(),
606
+ humidity: z.number(),
607
+ }),
608
+ execute: async ({ city }) => {
609
+ const weather = await getWeather(city);
610
+
611
+ return {
612
+ content: [
613
+ {
614
+ type: "text",
615
+ text: `${city}: ${weather.temperature}F`,
616
+ },
617
+ ],
618
+ structuredContent: {
619
+ temperature: weather.temperature,
620
+ humidity: weather.humidity,
621
+ },
622
+ };
623
+ },
624
+ });
625
+ ```
626
+
627
+ When `outputSchema` is provided, FastMCP validates `structuredContent` before sending the tool result. Invalid structured output is returned to the client as a tool error instead of silently violating the advertised schema.
628
+
569
629
  #### Tool Authorization
570
630
 
571
631
  You can control which tools are available to authenticated users by adding an optional `canAccess` function to a tool's definition. This function receives the authentication context and should return `true` if the user is allowed to access the tool.
package/dist/FastMCP.cjs CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkEXZZ3NKLcjs = require('./chunk-EXZZ3NKL.cjs');
10
+ var _chunkC3LTWBG3cjs = require('./chunk-C3LTWBG3.cjs');
11
11
 
12
12
 
13
13
 
@@ -20,7 +20,7 @@ var _chunkEXZZ3NKLcjs = require('./chunk-EXZZ3NKL.cjs');
20
20
 
21
21
 
22
22
 
23
- var _chunkOARN6YYKcjs = require('./chunk-OARN6YYK.cjs');
23
+ var _chunkJFLKZGBGcjs = require('./chunk-JFLKZGBG.cjs');
24
24
 
25
25
 
26
26
 
@@ -41,5 +41,5 @@ var _chunkOARN6YYKcjs = require('./chunk-OARN6YYK.cjs');
41
41
 
42
42
 
43
43
 
44
- exports.AuthProvider = _chunkOARN6YYKcjs.AuthProvider; exports.AzureProvider = _chunkOARN6YYKcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkEXZZ3NKLcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkEXZZ3NKLcjs.FastMCP; exports.FastMCPSession = _chunkEXZZ3NKLcjs.FastMCPSession; exports.GitHubProvider = _chunkOARN6YYKcjs.GitHubProvider; exports.GoogleProvider = _chunkOARN6YYKcjs.GoogleProvider; exports.OAuthProvider = _chunkOARN6YYKcjs.OAuthProvider; exports.ServerState = _chunkEXZZ3NKLcjs.ServerState; exports.UnexpectedStateError = _chunkEXZZ3NKLcjs.UnexpectedStateError; exports.UserError = _chunkEXZZ3NKLcjs.UserError; exports.audioContent = _chunkEXZZ3NKLcjs.audioContent; exports.getAuthSession = _chunkOARN6YYKcjs.getAuthSession; exports.imageContent = _chunkEXZZ3NKLcjs.imageContent; exports.requireAll = _chunkOARN6YYKcjs.requireAll; exports.requireAny = _chunkOARN6YYKcjs.requireAny; exports.requireAuth = _chunkOARN6YYKcjs.requireAuth; exports.requireRole = _chunkOARN6YYKcjs.requireRole; exports.requireScopes = _chunkOARN6YYKcjs.requireScopes;
44
+ exports.AuthProvider = _chunkJFLKZGBGcjs.AuthProvider; exports.AzureProvider = _chunkJFLKZGBGcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkC3LTWBG3cjs.DiscoveryDocumentCache; exports.FastMCP = _chunkC3LTWBG3cjs.FastMCP; exports.FastMCPSession = _chunkC3LTWBG3cjs.FastMCPSession; exports.GitHubProvider = _chunkJFLKZGBGcjs.GitHubProvider; exports.GoogleProvider = _chunkJFLKZGBGcjs.GoogleProvider; exports.OAuthProvider = _chunkJFLKZGBGcjs.OAuthProvider; exports.ServerState = _chunkC3LTWBG3cjs.ServerState; exports.UnexpectedStateError = _chunkC3LTWBG3cjs.UnexpectedStateError; exports.UserError = _chunkC3LTWBG3cjs.UserError; exports.audioContent = _chunkC3LTWBG3cjs.audioContent; exports.getAuthSession = _chunkJFLKZGBGcjs.getAuthSession; exports.imageContent = _chunkC3LTWBG3cjs.imageContent; exports.requireAll = _chunkJFLKZGBGcjs.requireAll; exports.requireAny = _chunkJFLKZGBGcjs.requireAny; exports.requireAuth = _chunkJFLKZGBGcjs.requireAuth; exports.requireRole = _chunkJFLKZGBGcjs.requireRole; exports.requireScopes = _chunkJFLKZGBGcjs.requireScopes;
45
45
  //# sourceMappingURL=FastMCP.cjs.map
@@ -10,8 +10,8 @@ import { Hono } from 'hono';
10
10
  import http from 'http';
11
11
  import { StrictEventEmitter } from 'strict-event-emitter-types';
12
12
  import { z } from 'zod';
13
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BS7O-cik.cjs';
14
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-BS7O-cik.cjs';
13
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-vyjR-9Z7.cjs';
14
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-vyjR-9Z7.cjs';
15
15
  import 'node:http';
16
16
 
17
17
  declare class DiscoveryDocumentCache {
@@ -168,6 +168,7 @@ type Content = AudioContent | ImageContent | ResourceContent | ResourceLink | Te
168
168
  type ContentResult = {
169
169
  content: Content[];
170
170
  isError?: boolean;
171
+ structuredContent?: Record<string, unknown>;
171
172
  };
172
173
  type Completion = {
173
174
  hasMore?: boolean;
@@ -603,7 +604,7 @@ type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolPara
603
604
  } & ToolAnnotations;
604
605
  canAccess?: (auth: T) => boolean;
605
606
  description?: string;
606
- execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<AudioContent | ContentResult | ImageContent | ResourceContent | ResourceLink | string | TextContent | void>;
607
+ execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<AudioContent | ContentResult | ImageContent | ResourceContent | ResourceLink | StandardSchemaV1.InferOutput<OutputParams> | string | TextContent | void>;
607
608
  name: string;
608
609
  outputSchema?: OutputParams;
609
610
  parameters?: Params;
package/dist/FastMCP.d.ts CHANGED
@@ -10,8 +10,8 @@ import { Hono } from 'hono';
10
10
  import http from 'http';
11
11
  import { StrictEventEmitter } from 'strict-event-emitter-types';
12
12
  import { z } from 'zod';
13
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BS7O-cik.js';
14
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-BS7O-cik.js';
13
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-vyjR-9Z7.js';
14
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-vyjR-9Z7.js';
15
15
  import 'node:http';
16
16
 
17
17
  declare class DiscoveryDocumentCache {
@@ -168,6 +168,7 @@ type Content = AudioContent | ImageContent | ResourceContent | ResourceLink | Te
168
168
  type ContentResult = {
169
169
  content: Content[];
170
170
  isError?: boolean;
171
+ structuredContent?: Record<string, unknown>;
171
172
  };
172
173
  type Completion = {
173
174
  hasMore?: boolean;
@@ -603,7 +604,7 @@ type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolPara
603
604
  } & ToolAnnotations;
604
605
  canAccess?: (auth: T) => boolean;
605
606
  description?: string;
606
- execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<AudioContent | ContentResult | ImageContent | ResourceContent | ResourceLink | string | TextContent | void>;
607
+ execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<AudioContent | ContentResult | ImageContent | ResourceContent | ResourceLink | StandardSchemaV1.InferOutput<OutputParams> | string | TextContent | void>;
607
608
  name: string;
608
609
  outputSchema?: OutputParams;
609
610
  parameters?: Params;
package/dist/FastMCP.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  UserError,
8
8
  audioContent,
9
9
  imageContent
10
- } from "./chunk-TNX4H4LB.js";
10
+ } from "./chunk-DNGQLQWS.js";
11
11
  import {
12
12
  AuthProvider,
13
13
  AzureProvider,
@@ -20,7 +20,7 @@ import {
20
20
  requireAuth,
21
21
  requireRole,
22
22
  requireScopes
23
- } from "./chunk-HGUUOYR4.js";
23
+ } from "./chunk-KHM5DJG7.js";
24
24
  export {
25
25
  AuthProvider,
26
26
  AzureProvider,
@@ -226,6 +226,18 @@ interface OAuthProxyConfig {
226
226
  enableTokenSwap?: boolean;
227
227
  /** Encryption key for token storage (default: auto-generated). Set to false to disable encryption. */
228
228
  encryptionKey?: false | string;
229
+ /**
230
+ * Extra query parameters appended to the upstream authorization URL.
231
+ * Required by providers such as Google, which only issues a refresh_token
232
+ * when the authorization request carries `access_type=offline` (and
233
+ * re-issues it on re-auth with `prompt=consent`). Without these, access
234
+ * expires after the upstream token TTL and can never be renewed.
235
+ *
236
+ * Core OAuth parameters managed by the proxy (client_id, redirect_uri,
237
+ * response_type, state, scope, code_challenge, code_challenge_method)
238
+ * cannot be overridden — entries with those keys are ignored.
239
+ */
240
+ extraAuthorizationParams?: Record<string, string>;
229
241
  /** Forward client's PKCE to upstream (default: false) */
230
242
  forwardPkce?: boolean;
231
243
  /** Secret key for signing JWTs when token swap is enabled */
@@ -226,6 +226,18 @@ interface OAuthProxyConfig {
226
226
  enableTokenSwap?: boolean;
227
227
  /** Encryption key for token storage (default: auto-generated). Set to false to disable encryption. */
228
228
  encryptionKey?: false | string;
229
+ /**
230
+ * Extra query parameters appended to the upstream authorization URL.
231
+ * Required by providers such as Google, which only issues a refresh_token
232
+ * when the authorization request carries `access_type=offline` (and
233
+ * re-issues it on re-auth with `prompt=consent`). Without these, access
234
+ * expires after the upstream token TTL and can never be renewed.
235
+ *
236
+ * Core OAuth parameters managed by the proxy (client_id, redirect_uri,
237
+ * response_type, state, scope, code_challenge, code_challenge_method)
238
+ * cannot be overridden — entries with those keys are ignored.
239
+ */
240
+ extraAuthorizationParams?: Record<string, string>;
229
241
  /** Forward client's PKCE to upstream (default: false) */
230
242
  forwardPkce?: boolean;
231
243
  /** Secret key for signing JWTs when token swap is enabled */
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- var _chunkOARN6YYKcjs = require('../chunk-OARN6YYK.cjs');
27
+ var _chunkJFLKZGBGcjs = require('../chunk-JFLKZGBG.cjs');
28
28
 
29
29
 
30
30
 
@@ -51,5 +51,5 @@ var _chunkOARN6YYKcjs = require('../chunk-OARN6YYK.cjs');
51
51
 
52
52
 
53
53
 
54
- exports.AuthProvider = _chunkOARN6YYKcjs.AuthProvider; exports.AzureProvider = _chunkOARN6YYKcjs.AzureProvider; exports.ConsentManager = _chunkOARN6YYKcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkOARN6YYKcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkOARN6YYKcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkOARN6YYKcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkOARN6YYKcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkOARN6YYKcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkOARN6YYKcjs.DiskStore; exports.EncryptedTokenStorage = _chunkOARN6YYKcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkOARN6YYKcjs.GitHubProvider; exports.GoogleProvider = _chunkOARN6YYKcjs.GoogleProvider; exports.JWKSVerifier = _chunkOARN6YYKcjs.JWKSVerifier; exports.JWTIssuer = _chunkOARN6YYKcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkOARN6YYKcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkOARN6YYKcjs.OAuthProvider; exports.OAuthProxy = _chunkOARN6YYKcjs.OAuthProxy; exports.OAuthProxyError = _chunkOARN6YYKcjs.OAuthProxyError; exports.PKCEUtils = _chunkOARN6YYKcjs.PKCEUtils; exports.getAuthSession = _chunkOARN6YYKcjs.getAuthSession; exports.requireAll = _chunkOARN6YYKcjs.requireAll; exports.requireAny = _chunkOARN6YYKcjs.requireAny; exports.requireAuth = _chunkOARN6YYKcjs.requireAuth; exports.requireRole = _chunkOARN6YYKcjs.requireRole; exports.requireScopes = _chunkOARN6YYKcjs.requireScopes;
54
+ exports.AuthProvider = _chunkJFLKZGBGcjs.AuthProvider; exports.AzureProvider = _chunkJFLKZGBGcjs.AzureProvider; exports.ConsentManager = _chunkJFLKZGBGcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkJFLKZGBGcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkJFLKZGBGcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkJFLKZGBGcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkJFLKZGBGcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkJFLKZGBGcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkJFLKZGBGcjs.DiskStore; exports.EncryptedTokenStorage = _chunkJFLKZGBGcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkJFLKZGBGcjs.GitHubProvider; exports.GoogleProvider = _chunkJFLKZGBGcjs.GoogleProvider; exports.JWKSVerifier = _chunkJFLKZGBGcjs.JWKSVerifier; exports.JWTIssuer = _chunkJFLKZGBGcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkJFLKZGBGcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkJFLKZGBGcjs.OAuthProvider; exports.OAuthProxy = _chunkJFLKZGBGcjs.OAuthProxy; exports.OAuthProxyError = _chunkJFLKZGBGcjs.OAuthProxyError; exports.PKCEUtils = _chunkJFLKZGBGcjs.PKCEUtils; exports.getAuthSession = _chunkJFLKZGBGcjs.getAuthSession; exports.requireAll = _chunkJFLKZGBGcjs.requireAll; exports.requireAny = _chunkJFLKZGBGcjs.requireAny; exports.requireAuth = _chunkJFLKZGBGcjs.requireAuth; exports.requireRole = _chunkJFLKZGBGcjs.requireRole; exports.requireScopes = _chunkJFLKZGBGcjs.requireScopes;
55
55
  //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BS7O-cik.cjs';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-BS7O-cik.cjs';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-vyjR-9Z7.cjs';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-vyjR-9Z7.cjs';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BS7O-cik.js';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-BS7O-cik.js';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-vyjR-9Z7.js';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-vyjR-9Z7.js';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "../chunk-HGUUOYR4.js";
27
+ } from "../chunk-KHM5DJG7.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -287,7 +287,8 @@ var ContentZodSchema = _zod.z.discriminatedUnion("type", [
287
287
  ]);
288
288
  var ContentResultZodSchema = _zod.z.object({
289
289
  content: ContentZodSchema.array(),
290
- isError: _zod.z.boolean().optional()
290
+ isError: _zod.z.boolean().optional(),
291
+ structuredContent: _zod.z.record(_zod.z.string(), _zod.z.unknown()).optional()
291
292
  }).strict();
292
293
  var CompletionZodSchema = _zod.z.object({
293
294
  /**
@@ -598,6 +599,12 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
598
599
  });
599
600
  });
600
601
  }
602
+ #formatSchemaIssues(issues) {
603
+ return _optionalChain([this, 'access', _12 => _12.#utils, 'optionalAccess', _13 => _13.formatInvalidParamsErrorMessage]) ? this.#utils.formatInvalidParamsErrorMessage(issues) : issues.map((issue) => {
604
+ const path = _optionalChain([issue, 'access', _14 => _14.path, 'optionalAccess', _15 => _15.join, 'call', _16 => _16(".")]) || "root";
605
+ return `${path}: ${issue.message}`;
606
+ }).join(", ");
607
+ }
601
608
  #getPingConfig(transport) {
602
609
  const pingConfig = this.#pingConfig || {};
603
610
  let defaultEnabled = false;
@@ -612,6 +619,18 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
612
619
  logLevel: pingConfig.logLevel || "debug"
613
620
  };
614
621
  }
622
+ async #validateStructuredContent(tool, value, toolName) {
623
+ if (!tool.outputSchema) {
624
+ return value;
625
+ }
626
+ const parsed = await tool.outputSchema["~standard"].validate(value);
627
+ if (parsed.issues) {
628
+ throw new UserError(
629
+ `Tool '${toolName}' structured output validation failed: ${this.#formatSchemaIssues(parsed.issues)}. Please check the result matches the tool's outputSchema.`
630
+ );
631
+ }
632
+ return parsed.value;
633
+ }
615
634
  addPrompt(inputPrompt) {
616
635
  const completers = {};
617
636
  const enums = {};
@@ -929,7 +948,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
929
948
  );
930
949
  }
931
950
  setupRootsHandlers() {
932
- if (_optionalChain([this, 'access', _12 => _12.#rootsConfig, 'optionalAccess', _13 => _13.enabled]) === false) {
951
+ if (_optionalChain([this, 'access', _17 => _17.#rootsConfig, 'optionalAccess', _18 => _18.enabled]) === false) {
933
952
  this.#logger.debug(
934
953
  "[FastMCP debug] roots capability explicitly disabled via config"
935
954
  );
@@ -1013,10 +1032,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1013
1032
  request.params.arguments
1014
1033
  );
1015
1034
  if (parsed.issues) {
1016
- const friendlyErrors = _optionalChain([this, 'access', _14 => _14.#utils, 'optionalAccess', _15 => _15.formatInvalidParamsErrorMessage]) ? this.#utils.formatInvalidParamsErrorMessage(parsed.issues) : parsed.issues.map((issue) => {
1017
- const path = _optionalChain([issue, 'access', _16 => _16.path, 'optionalAccess', _17 => _17.join, 'call', _18 => _18(".")]) || "root";
1018
- return `${path}: ${issue.message}`;
1019
- }).join(", ");
1035
+ const friendlyErrors = this.#formatSchemaIssues(parsed.issues);
1020
1036
  throw new (0, _typesjs.McpError)(
1021
1037
  _typesjs.ErrorCode.InvalidParams,
1022
1038
  `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`
@@ -1150,6 +1166,30 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1150
1166
  result = ContentResultZodSchema.parse({
1151
1167
  content: [maybeStringResult]
1152
1168
  });
1169
+ } else if ("content" in maybeStringResult) {
1170
+ result = ContentResultZodSchema.parse(maybeStringResult);
1171
+ if (result.structuredContent !== void 0 && tool.outputSchema) {
1172
+ result.structuredContent = await this.#validateStructuredContent(
1173
+ tool,
1174
+ result.structuredContent,
1175
+ request.params.name
1176
+ );
1177
+ }
1178
+ } else if (tool.outputSchema) {
1179
+ const structuredContent = await this.#validateStructuredContent(
1180
+ tool,
1181
+ maybeStringResult,
1182
+ request.params.name
1183
+ );
1184
+ result = ContentResultZodSchema.parse({
1185
+ content: [
1186
+ {
1187
+ text: JSON.stringify(structuredContent),
1188
+ type: "text"
1189
+ }
1190
+ ],
1191
+ structuredContent
1192
+ });
1153
1193
  } else {
1154
1194
  result = ContentResultZodSchema.parse(maybeStringResult);
1155
1195
  }
@@ -1745,13 +1785,15 @@ var FastMCP = class extends FastMCPEventEmitter {
1745
1785
  const path = _nullishCoalesce(healthConfig.path, () => ( "/health"));
1746
1786
  const url2 = new URL(req.url || "", `http://${host}`);
1747
1787
  try {
1748
- if (req.method === "GET" && url2.pathname === path) {
1788
+ if ((req.method === "GET" || req.method === "HEAD") && url2.pathname === path) {
1749
1789
  res.writeHead(_nullishCoalesce(healthConfig.status, () => ( 200)), {
1750
1790
  "Content-Type": "text/plain"
1751
- }).end(_nullishCoalesce(healthConfig.message, () => ( "\u2713 Ok")));
1791
+ }).end(
1792
+ req.method === "HEAD" ? void 0 : _nullishCoalesce(healthConfig.message, () => ( "\u2713 Ok"))
1793
+ );
1752
1794
  return;
1753
1795
  }
1754
- if (req.method === "GET" && url2.pathname === "/ready") {
1796
+ if ((req.method === "GET" || req.method === "HEAD") && url2.pathname === "/ready") {
1755
1797
  if (isStateless) {
1756
1798
  const response = {
1757
1799
  mode: "stateless",
@@ -1761,7 +1803,9 @@ var FastMCP = class extends FastMCPEventEmitter {
1761
1803
  };
1762
1804
  res.writeHead(200, {
1763
1805
  "Content-Type": "application/json"
1764
- }).end(JSON.stringify(response));
1806
+ }).end(
1807
+ req.method === "HEAD" ? void 0 : JSON.stringify(response)
1808
+ );
1765
1809
  } else {
1766
1810
  const readySessions = this.#sessions.filter(
1767
1811
  (s) => s.isReady
@@ -1775,7 +1819,9 @@ var FastMCP = class extends FastMCPEventEmitter {
1775
1819
  };
1776
1820
  res.writeHead(allReady ? 200 : 503, {
1777
1821
  "Content-Type": "application/json"
1778
- }).end(JSON.stringify(response));
1822
+ }).end(
1823
+ req.method === "HEAD" ? void 0 : JSON.stringify(response)
1824
+ );
1779
1825
  }
1780
1826
  return;
1781
1827
  }
@@ -2120,4 +2166,4 @@ var FastMCP = class extends FastMCPEventEmitter {
2120
2166
 
2121
2167
 
2122
2168
  exports.DiscoveryDocumentCache = DiscoveryDocumentCache; exports.imageContent = imageContent; exports.audioContent = audioContent; exports.UnexpectedStateError = UnexpectedStateError; exports.UserError = UserError; exports.ServerState = ServerState; exports.FastMCPSession = FastMCPSession; exports.FastMCP = FastMCP;
2123
- //# sourceMappingURL=chunk-EXZZ3NKL.cjs.map
2169
+ //# sourceMappingURL=chunk-C3LTWBG3.cjs.map