toolception 0.4.0 → 0.5.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
@@ -10,6 +10,7 @@
10
10
  - [Static startup](#static-startup)
11
11
  - [Permission-based starter guide](#permission-based-starter-guide)
12
12
  - [Permission configuration approaches](#permission-configuration-approaches)
13
+ - [Custom HTTP endpoints](#custom-http-endpoints)
13
14
  - [API](#api)
14
15
  - [createMcpServer](#createmcpserveroptions)
15
16
  - [createPermissionBasedMcpServer](#createpermissionbasedmcpserveroptions)
@@ -589,6 +590,135 @@ await start();
589
590
 
590
591
  **Note:** Resolver functions must be synchronous. If you need to fetch permissions from external sources, do so before server creation and cache the results.
591
592
 
593
+ ## Custom HTTP endpoints
594
+
595
+ Toolception supports custom HTTP endpoints alongside MCP protocol endpoints, enabling REST-like APIs with Zod validation and type inference.
596
+
597
+ ### Basic usage
598
+
599
+ ```ts
600
+ import { createMcpServer, defineEndpoint } from "toolception";
601
+ import { z } from "zod";
602
+
603
+ const { start } = await createMcpServer({
604
+ // ... standard options
605
+ http: {
606
+ port: 3000,
607
+ customEndpoints: [
608
+ defineEndpoint({
609
+ method: "GET",
610
+ path: "/api/users",
611
+ querySchema: z.object({
612
+ limit: z.coerce.number().int().positive().default(10),
613
+ role: z.enum(["admin", "user"]).optional(),
614
+ }),
615
+ responseSchema: z.object({
616
+ users: z.array(z.object({ id: z.string(), name: z.string() })),
617
+ }),
618
+ handler: async (req) => {
619
+ // req.query is typed: { limit: number, role?: "admin" | "user" }
620
+ // req.clientId is available from mcp-client-id header
621
+ return { users: [{ id: "1", name: "Alice" }] };
622
+ },
623
+ }),
624
+ ],
625
+ },
626
+ });
627
+ ```
628
+
629
+ ### Validation schemas
630
+
631
+ - **querySchema**: Validates URL query parameters (use `z.coerce` for type conversion)
632
+ - **bodySchema**: Validates request body (POST/PUT/PATCH)
633
+ - **paramsSchema**: Validates path parameters (e.g., `/users/:userId`)
634
+ - **responseSchema**: Validates handler response (prevents invalid data leakage)
635
+
636
+ ### Request context
637
+
638
+ Handlers receive a typed request object:
639
+
640
+ ```ts
641
+ {
642
+ body: TBody, // Validated from bodySchema
643
+ query: TQuery, // Validated from querySchema
644
+ params: TParams, // Validated from paramsSchema
645
+ headers: Record<string, string | string[] | undefined>,
646
+ clientId: string, // From mcp-client-id header or auto-generated
647
+ }
648
+ ```
649
+
650
+ ### Permission-aware endpoints
651
+
652
+ Use `definePermissionAwareEndpoint` in permission-based servers to access client permissions:
653
+
654
+ ```ts
655
+ import { createPermissionBasedMcpServer, definePermissionAwareEndpoint } from "toolception";
656
+
657
+ const { start } = await createPermissionBasedMcpServer({
658
+ // ... permission config
659
+ http: {
660
+ customEndpoints: [
661
+ definePermissionAwareEndpoint({
662
+ method: "GET",
663
+ path: "/api/me",
664
+ responseSchema: z.object({
665
+ clientId: z.string(),
666
+ allowedToolsets: z.array(z.string()),
667
+ isAdmin: z.boolean(),
668
+ }),
669
+ handler: async (req) => {
670
+ // req.allowedToolsets and req.failedToolsets are available
671
+ return {
672
+ clientId: req.clientId,
673
+ allowedToolsets: req.allowedToolsets,
674
+ isAdmin: req.allowedToolsets.includes("admin-tools"),
675
+ };
676
+ },
677
+ }),
678
+ ],
679
+ },
680
+ });
681
+ ```
682
+
683
+ ### Error handling
684
+
685
+ Validation failures return standardized error responses:
686
+
687
+ - **400 VALIDATION_ERROR**: Request validation failed (body, query, or params)
688
+ - **500 INTERNAL_ERROR**: Handler threw an exception
689
+ - **500 RESPONSE_VALIDATION_ERROR**: Response validation failed
690
+
691
+ Example error response:
692
+
693
+ ```json
694
+ {
695
+ "error": {
696
+ "code": "VALIDATION_ERROR",
697
+ "message": "Validation failed for query",
698
+ "details": [
699
+ {
700
+ "code": "invalid_type",
701
+ "path": ["limit"],
702
+ "message": "Expected number, received string"
703
+ }
704
+ ]
705
+ }
706
+ }
707
+ ```
708
+
709
+ ### Reserved paths
710
+
711
+ Custom endpoints cannot override built-in MCP paths:
712
+
713
+ - `/mcp` - MCP JSON-RPC endpoint
714
+ - `/healthz` - Health check
715
+ - `/tools` - Tool listing
716
+ - `/.well-known/mcp-config` - Configuration schema
717
+
718
+ ### Complete example
719
+
720
+ See `examples/custom-endpoints-demo.ts` for a full working example with GET, POST, PUT, DELETE endpoints, pagination, and permission-aware handlers.
721
+
592
722
  ## API
593
723
 
594
724
  ### createMcpServer(options)
@@ -736,9 +866,10 @@ const moduleLoaders = {
736
866
 
737
867
  #### options.http (optional)
738
868
 
739
- `{ host?: string; port?: number; basePath?: string; cors?: boolean; logger?: boolean }`
869
+ `{ host?: string; port?: number; basePath?: string; cors?: boolean; logger?: boolean; customEndpoints?: CustomEndpointDefinition[] }`
740
870
 
741
871
  - Fastify transport configuration. Defaults: host `0.0.0.0`, port `3000`, basePath `/`, CORS enabled, logger disabled.
872
+ - `customEndpoints`: Optional array of custom HTTP endpoints to register alongside MCP protocol endpoints. See [Custom HTTP endpoints](#custom-http-endpoints) for details.
742
873
 
743
874
  #### options.createServer (optional)
744
875
 
@@ -2,6 +2,7 @@ import { FastifyInstance } from 'fastify';
2
2
  import { DynamicToolManager } from '../core/DynamicToolManager.js';
3
3
  import { ServerOrchestrator } from '../core/ServerOrchestrator.js';
4
4
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { CustomEndpointDefinition } from './customEndpoints.js';
5
6
  export interface FastifyTransportOptions {
6
7
  host?: string;
7
8
  port?: number;
@@ -9,6 +10,11 @@ export interface FastifyTransportOptions {
9
10
  cors?: boolean;
10
11
  logger?: boolean;
11
12
  app?: FastifyInstance;
13
+ /**
14
+ * Optional custom HTTP endpoints to register alongside MCP protocol endpoints.
15
+ * Allows adding REST-like endpoints with Zod validation and type inference.
16
+ */
17
+ customEndpoints?: CustomEndpointDefinition[];
12
18
  }
13
19
  export declare class FastifyTransport {
14
20
  private readonly options;
@@ -1 +1 @@
1
- {"version":3,"file":"FastifyTransport.d.ts","sourceRoot":"","sources":["../../src/http/FastifyTransport.ts"],"names":[],"mappings":"AAAA,OAAgB,EACd,KAAK,eAAe,EAGrB,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAIxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,GAAG,CAAC,EAAE,eAAe,CAAC;CACvB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAOtB;IACF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAG3B;IACF,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IAGvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CASzB;gBAGD,cAAc,EAAE,kBAAkB,EAClC,YAAY,EAAE,MAAM;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,YAAY,EAAE,kBAAkB,CAAA;KAAE,EAC3E,OAAO,GAAE,uBAA4B,EACrC,YAAY,CAAC,EAAE,MAAM;IAeV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8LnC;;;OAGG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYlC;;;;;OAKG;IACH,OAAO,CAAC,aAAa;CAkBtB"}
1
+ {"version":3,"file":"FastifyTransport.d.ts","sourceRoot":"","sources":["../../src/http/FastifyTransport.ts"],"names":[],"mappings":"AAAA,OAAgB,EACd,KAAK,eAAe,EAGrB,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAIxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB;;;OAGG;IACH,eAAe,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAC9C;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAQtB;IACF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAG3B;IACF,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IAGvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CASzB;gBAGD,cAAc,EAAE,kBAAkB,EAClC,YAAY,EAAE,MAAM;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,YAAY,EAAE,kBAAkB,CAAA;KAAE,EAC3E,OAAO,GAAE,uBAA4B,EACrC,YAAY,CAAC,EAAE,MAAM;IAgBV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoMnC;;;OAGG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYlC;;;;;OAKG;IACH,OAAO,CAAC,aAAa;CAkBtB"}
@@ -0,0 +1,247 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Supported HTTP methods for custom endpoints
4
+ */
5
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
6
+ /**
7
+ * Request context passed to custom endpoint handlers.
8
+ * Contains validated and typed request data without exposing Fastify types.
9
+ */
10
+ export interface CustomEndpointRequest<TBody = unknown, TQuery = unknown, TParams = unknown> {
11
+ /**
12
+ * Validated request body (typed from bodySchema)
13
+ */
14
+ body: TBody;
15
+ /**
16
+ * Validated query parameters (typed from querySchema)
17
+ */
18
+ query: TQuery;
19
+ /**
20
+ * Validated path parameters (typed from paramsSchema)
21
+ */
22
+ params: TParams;
23
+ /**
24
+ * Raw request headers
25
+ */
26
+ headers: Record<string, string | string[] | undefined>;
27
+ /**
28
+ * Client ID (from mcp-client-id header or auto-generated for anonymous clients)
29
+ */
30
+ clientId: string;
31
+ }
32
+ /**
33
+ * Permission-aware request context for custom endpoints in permission-based servers.
34
+ * Extends CustomEndpointRequest with permission information.
35
+ */
36
+ export interface PermissionAwareEndpointRequest<TBody = unknown, TQuery = unknown, TParams = unknown> extends CustomEndpointRequest<TBody, TQuery, TParams> {
37
+ /**
38
+ * Toolsets this client is allowed to access (resolved from permissions)
39
+ */
40
+ allowedToolsets: string[];
41
+ /**
42
+ * Toolsets that failed to enable for this client
43
+ */
44
+ failedToolsets: string[];
45
+ }
46
+ /**
47
+ * Handler function type with automatic type inference from Zod schemas.
48
+ * Receives validated and typed request data, returns typed response.
49
+ */
50
+ export type CustomEndpointHandler<TBody extends z.ZodTypeAny, TQuery extends z.ZodTypeAny, TParams extends z.ZodTypeAny, TResponse extends z.ZodTypeAny> = (request: CustomEndpointRequest<TBody extends z.ZodTypeAny ? z.infer<TBody> : never, TQuery extends z.ZodTypeAny ? z.infer<TQuery> : never, TParams extends z.ZodTypeAny ? z.infer<TParams> : never>) => Promise<z.infer<TResponse>> | z.infer<TResponse>;
51
+ /**
52
+ * Permission-aware handler function type for permission-based servers.
53
+ * Receives permission context in addition to validated request data.
54
+ */
55
+ export type PermissionAwareEndpointHandler<TBody extends z.ZodTypeAny, TQuery extends z.ZodTypeAny, TParams extends z.ZodTypeAny, TResponse extends z.ZodTypeAny> = (request: PermissionAwareEndpointRequest<TBody extends z.ZodTypeAny ? z.infer<TBody> : never, TQuery extends z.ZodTypeAny ? z.infer<TQuery> : never, TParams extends z.ZodTypeAny ? z.infer<TParams> : never>) => Promise<z.infer<TResponse>> | z.infer<TResponse>;
56
+ /**
57
+ * Custom HTTP endpoint definition with Zod schema-based validation and type inference.
58
+ * Allows defining REST-like endpoints alongside MCP protocol endpoints.
59
+ *
60
+ * @template TBody - Zod schema for request body validation
61
+ * @template TQuery - Zod schema for query parameter validation
62
+ * @template TParams - Zod schema for path parameter validation
63
+ * @template TResponse - Zod schema for response validation
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const getUserEndpoint = defineEndpoint({
68
+ * method: "GET",
69
+ * path: "/users/:userId",
70
+ * paramsSchema: z.object({
71
+ * userId: z.string().uuid(),
72
+ * }),
73
+ * responseSchema: z.object({
74
+ * id: z.string(),
75
+ * name: z.string(),
76
+ * }),
77
+ * handler: async (req) => {
78
+ * // req.params is typed: { userId: string }
79
+ * const { userId } = req.params;
80
+ * return { id: userId, name: "Alice" };
81
+ * },
82
+ * });
83
+ * ```
84
+ */
85
+ export interface CustomEndpointDefinition<TBody extends z.ZodTypeAny = z.ZodTypeAny, TQuery extends z.ZodTypeAny = z.ZodTypeAny, TParams extends z.ZodTypeAny = z.ZodTypeAny, TResponse extends z.ZodTypeAny = z.ZodTypeAny> {
86
+ /**
87
+ * HTTP method for this endpoint
88
+ */
89
+ method: HttpMethod;
90
+ /**
91
+ * URL path (relative to basePath). Supports path parameters using :param syntax.
92
+ *
93
+ * @example
94
+ * - "/users" - Simple path
95
+ * - "/users/:id" - Path with single parameter
96
+ * - "/items/:category/:id" - Path with multiple parameters
97
+ */
98
+ path: string;
99
+ /**
100
+ * Optional Zod schema for request body validation (typically used with POST, PUT, PATCH).
101
+ * Enables automatic type inference for handler body parameter.
102
+ */
103
+ bodySchema?: TBody;
104
+ /**
105
+ * Optional Zod schema for query parameter validation.
106
+ * Enables automatic type inference for handler query parameter.
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * querySchema: z.object({
111
+ * limit: z.coerce.number().int().positive().default(10),
112
+ * offset: z.coerce.number().int().nonnegative().default(0),
113
+ * })
114
+ * ```
115
+ */
116
+ querySchema?: TQuery;
117
+ /**
118
+ * Optional Zod schema for path parameter validation.
119
+ * Enables automatic type inference for handler params parameter.
120
+ */
121
+ paramsSchema?: TParams;
122
+ /**
123
+ * Optional Zod schema for response validation.
124
+ * Enables automatic type inference for handler return type.
125
+ * If validation fails, returns 500 error to prevent information leakage.
126
+ */
127
+ responseSchema?: TResponse;
128
+ /**
129
+ * Request handler function with inferred types from schemas.
130
+ * Receives validated and typed request data, returns typed response.
131
+ */
132
+ handler: CustomEndpointHandler<TBody, TQuery, TParams, TResponse>;
133
+ /**
134
+ * Optional description for documentation purposes
135
+ */
136
+ description?: string;
137
+ }
138
+ /**
139
+ * Standard error response structure for custom endpoints
140
+ */
141
+ export interface EndpointErrorResponse {
142
+ error: {
143
+ /**
144
+ * Error code indicating the type of error
145
+ * - VALIDATION_ERROR: Request validation failed (400)
146
+ * - INTERNAL_ERROR: Handler threw an error (500)
147
+ * - RESPONSE_VALIDATION_ERROR: Response validation failed (500)
148
+ */
149
+ code: "VALIDATION_ERROR" | "INTERNAL_ERROR" | "RESPONSE_VALIDATION_ERROR";
150
+ /**
151
+ * Human-readable error message
152
+ */
153
+ message: string;
154
+ /**
155
+ * Optional additional error details (e.g., Zod validation errors)
156
+ */
157
+ details?: unknown;
158
+ };
159
+ }
160
+ /**
161
+ * Helper function to create type-safe custom endpoints with automatic type inference.
162
+ * Provides better IntelliSense and type checking for endpoint definitions.
163
+ *
164
+ * @template TBody - Zod schema for request body
165
+ * @template TQuery - Zod schema for query parameters
166
+ * @template TParams - Zod schema for path parameters
167
+ * @template TResponse - Zod schema for response
168
+ *
169
+ * @param definition - Endpoint definition with schemas and handler
170
+ * @returns The same endpoint definition with full type inference
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * import { z } from "zod";
175
+ * import { defineEndpoint } from "toolception";
176
+ *
177
+ * const getUsersEndpoint = defineEndpoint({
178
+ * method: "GET",
179
+ * path: "/users",
180
+ * querySchema: z.object({
181
+ * limit: z.coerce.number().int().positive().default(10),
182
+ * role: z.enum(["admin", "user"]).optional(),
183
+ * }),
184
+ * responseSchema: z.object({
185
+ * users: z.array(z.object({
186
+ * id: z.string(),
187
+ * name: z.string(),
188
+ * })),
189
+ * total: z.number(),
190
+ * }),
191
+ * handler: async (req) => {
192
+ * // req.query is fully typed: { limit: number, role?: "admin" | "user" }
193
+ * const { limit, role } = req.query;
194
+ *
195
+ * return {
196
+ * users: [{ id: "1", name: "Alice" }],
197
+ * total: 1,
198
+ * };
199
+ * },
200
+ * });
201
+ * ```
202
+ */
203
+ export declare function defineEndpoint<TBody extends z.ZodTypeAny = z.ZodNever, TQuery extends z.ZodTypeAny = z.ZodNever, TParams extends z.ZodTypeAny = z.ZodNever, TResponse extends z.ZodTypeAny = z.ZodAny>(definition: CustomEndpointDefinition<TBody, TQuery, TParams, TResponse>): CustomEndpointDefinition<TBody, TQuery, TParams, TResponse>;
204
+ /**
205
+ * Helper function to create permission-aware custom endpoints for permission-based servers.
206
+ * Similar to defineEndpoint but with access to permission context in the handler.
207
+ *
208
+ * @template TBody - Zod schema for request body
209
+ * @template TQuery - Zod schema for query parameters
210
+ * @template TParams - Zod schema for path parameters
211
+ * @template TResponse - Zod schema for response
212
+ *
213
+ * @param definition - Endpoint definition with permission-aware handler
214
+ * @returns Endpoint definition compatible with permission-based servers
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * import { definePermissionAwareEndpoint } from "toolception";
219
+ *
220
+ * const statsEndpoint = definePermissionAwareEndpoint({
221
+ * method: "GET",
222
+ * path: "/my-permissions",
223
+ * responseSchema: z.object({
224
+ * toolsets: z.array(z.string()),
225
+ * count: z.number(),
226
+ * }),
227
+ * handler: async (req) => {
228
+ * // req.allowedToolsets and req.failedToolsets are available
229
+ * return {
230
+ * toolsets: req.allowedToolsets,
231
+ * count: req.allowedToolsets.length,
232
+ * };
233
+ * },
234
+ * });
235
+ * ```
236
+ */
237
+ export declare function definePermissionAwareEndpoint<TBody extends z.ZodTypeAny = z.ZodNever, TQuery extends z.ZodTypeAny = z.ZodNever, TParams extends z.ZodTypeAny = z.ZodNever, TResponse extends z.ZodTypeAny = z.ZodAny>(definition: {
238
+ method: HttpMethod;
239
+ path: string;
240
+ bodySchema?: TBody;
241
+ querySchema?: TQuery;
242
+ paramsSchema?: TParams;
243
+ responseSchema?: TResponse;
244
+ handler: PermissionAwareEndpointHandler<TBody, TQuery, TParams, TResponse>;
245
+ description?: string;
246
+ }): CustomEndpointDefinition<TBody, TQuery, TParams, TResponse>;
247
+ //# sourceMappingURL=customEndpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customEndpoints.d.ts","sourceRoot":"","sources":["../../src/http/customEndpoints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import { CustomEndpointDefinition } from './customEndpoints.js';
3
+ /**
4
+ * Options for registering custom endpoints
5
+ */
6
+ export interface RegisterCustomEndpointsOptions {
7
+ /**
8
+ * Optional function to extract additional context for each request.
9
+ * Used by permission-aware transport to inject permission data.
10
+ */
11
+ contextExtractor?: (req: FastifyRequest) => Promise<Record<string, any>> | Record<string, any>;
12
+ }
13
+ /**
14
+ * Registers custom endpoints on a Fastify instance.
15
+ * Handles Zod validation, error responses, and type-safe request mapping.
16
+ *
17
+ * @param app - Fastify instance to register endpoints on
18
+ * @param basePath - Base path for all endpoints (e.g., "/" or "/api")
19
+ * @param endpoints - Array of custom endpoint definitions
20
+ * @param options - Optional configuration for endpoint registration
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * registerCustomEndpoints(app, "/api", [
25
+ * defineEndpoint({
26
+ * method: "GET",
27
+ * path: "/users",
28
+ * querySchema: z.object({ limit: z.coerce.number() }),
29
+ * handler: async (req) => ({ users: [] }),
30
+ * }),
31
+ * ]);
32
+ * ```
33
+ */
34
+ export declare function registerCustomEndpoints(app: FastifyInstance, basePath: string, endpoints: CustomEndpointDefinition[], options?: RegisterCustomEndpointsOptions): void;
35
+ //# sourceMappingURL=endpointRegistration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpointRegistration.d.ts","sourceRoot":"","sources":["../../src/http/endpointRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAgB,MAAM,SAAS,CAAC;AAG7E,OAAO,KAAK,EACV,wBAAwB,EAGzB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CACjB,GAAG,EAAE,cAAc,KAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,wBAAwB,EAAE,EACrC,OAAO,CAAC,EAAE,8BAA8B,GACvC,IAAI,CAgIN"}
package/dist/index.d.ts CHANGED
@@ -2,4 +2,6 @@ export { createMcpServer } from './server/createMcpServer.js';
2
2
  export type { CreateMcpServerOptions } from './server/createMcpServer.js';
3
3
  export { createPermissionBasedMcpServer } from './server/createPermissionBasedMcpServer.js';
4
4
  export type { ToolSetCatalog, ToolSetDefinition, McpToolDefinition, ExposurePolicy, Mode, ModuleLoader, PermissionConfig, CreatePermissionBasedMcpServerOptions, } from './types/index.js';
5
+ export type { CustomEndpointDefinition, CustomEndpointRequest, PermissionAwareEndpointRequest, CustomEndpointHandler, PermissionAwareEndpointHandler, HttpMethod, EndpointErrorResponse, } from './http/customEndpoints.js';
6
+ export { defineEndpoint, definePermissionAwareEndpoint, } from './http/customEndpoints.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAG1E,OAAO,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAG5F,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,qCAAqC,GACtC,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAG1E,OAAO,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAG5F,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,qCAAqC,GACtC,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,8BAA8B,EAC9B,qBAAqB,EACrB,8BAA8B,EAC9B,UAAU,EACV,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,cAAc,EACd,6BAA6B,GAC9B,MAAM,2BAA2B,CAAC"}