spiceflow 1.13.3 → 1.14.1

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
@@ -1,4 +1,4 @@
1
- # DO NOT EDIT: This file is auto-generated from root README.md
1
+ <!-- DO NOT EDIT: This file is auto-generated from root README.md -->
2
2
 
3
3
  <div align='center' className='w-full'>
4
4
  <br/>
@@ -239,6 +239,68 @@ async function exampleUsage() {
239
239
  }
240
240
  ```
241
241
 
242
+
243
+ ### Path Matching - Supported Features
244
+
245
+ - **Named parameters**: `:param` - Captures dynamic segments like `/users/:id` or `/api/:version/users/:userId`
246
+ - **Wildcards**: `*` - Matches any remaining path segments like `/files/*` or `/proxy/*`
247
+
248
+ ### Path Matching - Unsupported Features
249
+
250
+ - **Optional parameters**: `/:param?` - Use separate routes instead - IS NOT SUPPORTED
251
+ - **Named wildcards**: `/files/*name` - Use unnamed `*` only - IS NOT SUPPORTED
252
+ - **Partial parameters**: `/:param-suffix` or `/prefix-:param` - Use full segment parameters only - IS NOT SUPPORTED
253
+ - **Regex patterns**: `/users/(\\d+)` - Use string parameters with validation in handlers - IS NOT SUPPORTED
254
+ - **Multiple wildcards**: `/*/files/*` - Use single wildcard only - IS NOT SUPPORTED
255
+
256
+ ## Storing Spiceflow in Class Instances
257
+
258
+ If you need to store a Spiceflow router as a property in a class instance, use the `AnySpiceflow` type:
259
+
260
+ **Important**: Do not use `this` inside route handlers to reference the parent class. The `this` context inside handlers always refers to the Spiceflow instance, not your class instance. Instead, capture the parent class reference in a variable outside the handlers:
261
+
262
+ ```ts
263
+ import { Spiceflow, AnySpiceflow } from 'spiceflow'
264
+
265
+ export class ChatDurableObject {
266
+ private router: AnySpiceflow
267
+ private state: DurableObjectState
268
+
269
+ constructor(state: DurableObjectState, env: Env) {
270
+ this.state = state
271
+ const self = this // Capture parent class reference - IMPORTANT!
272
+
273
+ this.router = new Spiceflow()
274
+ .route({
275
+ method: 'GET',
276
+ path: '/messages',
277
+ async handler() {
278
+ // Use 'self' instead of 'this' to access parent class
279
+ // this.state would NOT work here - 'this' refers to Spiceflow instance
280
+ const messages = await self.state.storage.get('messages') || []
281
+ return { messages }
282
+ },
283
+ })
284
+ .route({
285
+ method: 'POST',
286
+ path: '/messages',
287
+ async handler({ request }) {
288
+ const { message } = await request.json()
289
+ // Use 'self' to access parent class properties
290
+ const messages = await self.state.storage.get('messages') || []
291
+ messages.push({ id: Date.now(), text: message })
292
+ await self.state.storage.put('messages', messages)
293
+ return { success: true }
294
+ },
295
+ })
296
+ }
297
+
298
+ fetch(request: Request) {
299
+ return this.router.handle(request)
300
+ }
301
+ }
302
+ ```
303
+
242
304
  ## Safe Path Building
243
305
 
244
306
  The `safePath` method provides a type-safe way to build URLs with parameters. It helps prevent runtime errors by ensuring all required parameters are provided and properly substituted into the path.
@@ -269,7 +331,7 @@ const userPath = app.safePath('/users/:id', { id: '123' })
269
331
  // Building URLs with required parameters
270
332
  const userPostPath = app.safePath('/users/:id/posts/:postId', {
271
333
  id: '456',
272
- postId: 'abc'
334
+ postId: 'abc',
273
335
  })
274
336
  // Result: '/users/456/posts/abc'
275
337
  ```
@@ -294,7 +356,7 @@ const app = new Spiceflow()
294
356
  provider,
295
357
  userId,
296
358
  authCode: code,
297
- state
359
+ state,
298
360
  }
299
361
  },
300
362
  })
@@ -309,13 +371,14 @@ const app = new Spiceflow()
309
371
  const callbackUrl = new URL(
310
372
  app.safePath('/auth/callback/:provider/:userId', {
311
373
  provider,
312
- userId
374
+ userId,
313
375
  }),
314
- 'https://myapp.com'
376
+ 'https://myapp.com',
315
377
  ).toString()
316
378
 
317
379
  // Redirect to OAuth provider with callback URL
318
- const oauthUrl = `https://accounts.google.com/oauth/authorize?` +
380
+ const oauthUrl =
381
+ `https://accounts.google.com/oauth/authorize?` +
319
382
  `client_id=your-client-id&` +
320
383
  `redirect_uri=${encodeURIComponent(callbackUrl)}&` +
321
384
  `response_type=code&` +
@@ -327,6 +390,7 @@ const app = new Spiceflow()
327
390
  ```
328
391
 
329
392
  In this example:
393
+
330
394
  - The callback URL is built safely using `safePath` with type checking
331
395
  - Required parameters like `provider` and `userId` must be provided
332
396
  - The resulting URL is guaranteed to be properly formatted
@@ -942,7 +1006,7 @@ interface Env {
942
1006
  }
943
1007
 
944
1008
  const app = new Spiceflow()
945
- .state('env', null as Env | null)
1009
+ .state('env', {} as Env)
946
1010
  .route({
947
1011
  method: 'GET',
948
1012
  path: '/kv/:key',
@@ -964,7 +1028,7 @@ const app = new Spiceflow()
964
1028
  export default {
965
1029
  fetch(request: Request, env: Env, ctx: ExecutionContext) {
966
1030
  // Pass the env bindings to the app
967
- return app.handle(request, { env })
1031
+ return app.handle(request, { state: { env } })
968
1032
  },
969
1033
  }
970
1034
  ```
@@ -993,71 +1057,207 @@ const response = await sdk.getUsers()
993
1057
  console.log('Users:', response)
994
1058
  ```
995
1059
 
996
- ## Background tasks with waitUntil
1060
+ ## Working with Cookies
997
1061
 
998
- Spiceflow provides a `waitUntil` function in the handler context that allows you to schedule tasks in the background in a cross platform way. It will use the Cloudflare workers waitUntil if present. It's currently a no op in Node.js.
999
-
1000
- ### Basic Usage
1062
+ Spiceflow works with standard Request and Response objects, so you can use any cookie library like the `cookie` npm package to handle cookies:
1001
1063
 
1002
1064
  ```ts
1003
1065
  import { Spiceflow } from 'spiceflow'
1066
+ import { parse, serialize } from 'cookie'
1004
1067
 
1005
1068
  const app = new Spiceflow()
1069
+ .route({
1070
+ method: 'GET',
1071
+ path: '/set-cookie',
1072
+ handler({ request }) {
1073
+ // Read existing cookies from the request
1074
+ const cookies = parse(request.headers.get('Cookie') || '')
1075
+
1076
+ // Create response with a new cookie
1077
+ const response = new Response(
1078
+ JSON.stringify({
1079
+ message: 'Cookie set!',
1080
+ existingCookies: cookies,
1081
+ }),
1082
+ {
1083
+ headers: {
1084
+ 'Content-Type': 'application/json',
1085
+ },
1086
+ },
1087
+ )
1088
+
1089
+ // Set a new cookie
1090
+ response.headers.set(
1091
+ 'Set-Cookie',
1092
+ serialize('session', 'abc123', {
1093
+ httpOnly: true,
1094
+ secure: true,
1095
+ sameSite: 'strict',
1096
+ maxAge: 60 * 60 * 24 * 7, // 7 days
1097
+ path: '/',
1098
+ }),
1099
+ )
1100
+
1101
+ return response
1102
+ },
1103
+ })
1104
+ .route({
1105
+ method: 'GET',
1106
+ path: '/get-cookie',
1107
+ handler({ request }) {
1108
+ // Parse cookies from the request
1109
+ const cookies = parse(request.headers.get('Cookie') || '')
1110
+
1111
+ return {
1112
+ sessionId: cookies.session || null,
1113
+ allCookies: cookies,
1114
+ }
1115
+ },
1116
+ })
1006
1117
  .route({
1007
1118
  method: 'POST',
1008
- path: '/process',
1009
- async handler({ request, waitUntil }) {
1010
- const data = await request.json()
1011
-
1012
- // Schedule background task
1013
- waitUntil(
1014
- fetch('https://analytics.example.com/track', {
1015
- method: 'POST',
1016
- body: JSON.stringify({ event: 'data_processed', data }),
1017
- })
1119
+ path: '/clear-cookie',
1120
+ handler({ request }) {
1121
+ const response = new Response(
1122
+ JSON.stringify({ message: 'Cookie cleared!' }),
1123
+ {
1124
+ headers: {
1125
+ 'Content-Type': 'application/json',
1126
+ },
1127
+ },
1018
1128
  )
1019
1129
 
1020
- // Return response immediately
1021
- return { success: true, id: Math.random().toString(36) }
1130
+ // Clear a cookie by setting it with an expired date
1131
+ response.headers.set(
1132
+ 'Set-Cookie',
1133
+ serialize('session', '', {
1134
+ httpOnly: true,
1135
+ secure: true,
1136
+ sameSite: 'strict',
1137
+ expires: new Date(0),
1138
+ path: '/',
1139
+ }),
1140
+ )
1141
+
1142
+ return response
1022
1143
  },
1023
1144
  })
1024
- ```
1025
1145
 
1026
- ### Cloudflare Workers Integration
1146
+ app.listen(3000)
1147
+ ```
1027
1148
 
1028
- In Cloudflare Workers, `waitUntil` is automatically detected from the global context:
1149
+ You can also use cookies in middleware for authentication or session handling:
1029
1150
 
1030
1151
  ```ts
1031
1152
  import { Spiceflow } from 'spiceflow'
1153
+ import { parse, serialize } from 'cookie'
1032
1154
 
1033
1155
  const app = new Spiceflow()
1034
- .route({
1035
- method: 'POST',
1036
- path: '/webhook',
1037
- async handler({ request, waitUntil }) {
1038
- const payload = await request.json()
1039
-
1040
- // Process webhook data in background
1041
- waitUntil(
1042
- processWebhookData(payload)
1043
- .then(() => console.log('Webhook processed'))
1044
- .catch(err => console.error('Webhook processing failed:', err))
1156
+ .state('userId', null as string | null)
1157
+ .use(async ({ request, state }, next) => {
1158
+ // Parse cookies from incoming request
1159
+ const cookies = parse(request.headers.get('Cookie') || '')
1160
+
1161
+ // Extract user ID from session cookie
1162
+ if (cookies.session) {
1163
+ // In a real app, you'd verify the session token
1164
+ state.userId = cookies.session
1165
+ }
1166
+
1167
+ const response = await next()
1168
+
1169
+ // Optionally refresh the session cookie
1170
+ if (state.userId && response) {
1171
+ response.headers.set(
1172
+ 'Set-Cookie',
1173
+ serialize('session', state.userId, {
1174
+ httpOnly: true,
1175
+ secure: true,
1176
+ sameSite: 'strict',
1177
+ maxAge: 60 * 60 * 24, // 24 hours
1178
+ path: '/',
1179
+ }),
1045
1180
  )
1181
+ }
1182
+
1183
+ return response
1184
+ })
1185
+ .route({
1186
+ method: 'GET',
1187
+ path: '/profile',
1188
+ handler({ state }) {
1189
+ if (!state.userId) {
1190
+ return new Response('Unauthorized', { status: 401 })
1191
+ }
1046
1192
 
1047
- // Respond immediately to webhook sender
1048
- return new Response('OK', { status: 200 })
1193
+ return { userId: state.userId, message: 'Welcome back!' }
1049
1194
  },
1050
1195
  })
1196
+ ```
1197
+
1198
+ ## Background tasks with waitUntil
1199
+
1200
+ Spiceflow provides a `waitUntil` function in the handler context that allows you to schedule tasks in the background in a cross platform way. It will use the Cloudflare workers waitUntil if present. It's currently a no op in Node.js.
1201
+
1202
+ ### Basic Usage
1203
+
1204
+ ```ts
1205
+ import { Spiceflow } from 'spiceflow'
1206
+
1207
+ const app = new Spiceflow().route({
1208
+ method: 'POST',
1209
+ path: '/process',
1210
+ async handler({ request, waitUntil }) {
1211
+ const data = await request.json()
1212
+
1213
+ // Schedule background task
1214
+ waitUntil(
1215
+ fetch('https://analytics.example.com/track', {
1216
+ method: 'POST',
1217
+ body: JSON.stringify({ event: 'data_processed', data }),
1218
+ }),
1219
+ )
1220
+
1221
+ // Return response immediately
1222
+ return { success: true, id: Math.random().toString(36) }
1223
+ },
1224
+ })
1225
+ ```
1226
+
1227
+ ### Cloudflare Workers Integration
1228
+
1229
+ In Cloudflare Workers, `waitUntil` is automatically detected from the global context:
1230
+
1231
+ ```ts
1232
+ import { Spiceflow } from 'spiceflow'
1233
+
1234
+ const app = new Spiceflow().route({
1235
+ method: 'POST',
1236
+ path: '/webhook',
1237
+ async handler({ request, waitUntil }) {
1238
+ const payload = await request.json()
1239
+
1240
+ // Process webhook data in background
1241
+ waitUntil(
1242
+ processWebhookData(payload)
1243
+ .then(() => console.log('Webhook processed'))
1244
+ .catch((err) => console.error('Webhook processing failed:', err)),
1245
+ )
1246
+
1247
+ // Respond immediately to webhook sender
1248
+ return new Response('OK', { status: 200 })
1249
+ },
1250
+ })
1051
1251
 
1052
1252
  async function processWebhookData(payload: any) {
1053
1253
  // Simulate time-consuming processing
1054
- await new Promise(resolve => setTimeout(resolve, 1000))
1254
+ await new Promise((resolve) => setTimeout(resolve, 1000))
1055
1255
  // Save to database, send notifications, etc.
1056
1256
  }
1057
1257
 
1058
1258
  export default {
1059
1259
  fetch(request: Request, env: any, ctx: ExecutionContext) {
1060
- return app.handle(request)
1260
+ return app.handle(request, { state: { env } })
1061
1261
  },
1062
1262
  }
1063
1263
  ```
@@ -1072,21 +1272,18 @@ import { Spiceflow } from 'spiceflow'
1072
1272
  const app = new Spiceflow({
1073
1273
  waitUntil: (promise) => {
1074
1274
  // Custom implementation for non-Cloudflare environments
1075
- promise.catch(err => console.error('Background task failed:', err))
1076
- }
1077
- })
1078
- .route({
1079
- method: 'GET',
1080
- path: '/analytics',
1081
- async handler({ waitUntil }) {
1082
- // Schedule analytics tracking
1083
- waitUntil(
1084
- trackPageView('/analytics')
1085
- )
1275
+ promise.catch((err) => console.error('Background task failed:', err))
1276
+ },
1277
+ }).route({
1278
+ method: 'GET',
1279
+ path: '/analytics',
1280
+ async handler({ waitUntil }) {
1281
+ // Schedule analytics tracking
1282
+ waitUntil(trackPageView('/analytics'))
1086
1283
 
1087
- return { message: 'Analytics page loaded' }
1088
- },
1089
- })
1284
+ return { message: 'Analytics page loaded' }
1285
+ },
1286
+ })
1090
1287
 
1091
1288
  async function trackPageView(path: string) {
1092
1289
  // Track page view in analytics system
@@ -1,6 +1,9 @@
1
1
  import { type Server, type IncomingMessage, type ServerResponse } from 'node:http';
2
2
  import { AnySpiceflow } from './spiceflow.ts';
3
- export declare function listenForNode(app: AnySpiceflow, port: number, hostname?: string): Promise<Server<typeof IncomingMessage, typeof ServerResponse>>;
3
+ export declare function listenForNode(app: AnySpiceflow, port: number, hostname?: string): Promise<{
4
+ port: number;
5
+ server: Server<typeof IncomingMessage, typeof ServerResponse>;
6
+ }>;
4
7
  export declare function handleForNode(app: AnySpiceflow, req: IncomingMessage, res: ServerResponse, context?: {
5
8
  state?: {} | undefined;
6
9
  }): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"_node-server.d.ts","sourceRoot":"","sources":["../src/_node-server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,YAAY,EAAoC,MAAM,gBAAgB,CAAA;AAE/E,wBAAsB,aAAa,CACjC,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,OAAO,eAAe,EAAE,OAAO,cAAc,CAAC,CAAC,CAkBhE;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,EAAE,GAAG,SAAS,CAAA;CAAO,GACvC,OAAO,CAAC,IAAI,CAAC,CA2Ef"}
1
+ {"version":3,"file":"_node-server.d.ts","sourceRoot":"","sources":["../src/_node-server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,YAAY,EAAoC,MAAM,gBAAgB,CAAA;AAE/E,wBAAsB,aAAa,CACjC,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAkB,GAC3B,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,OAAO,eAAe,EAAE,OAAO,cAAc,CAAC,CAAA;CAAC,CAAC,CAmBxF;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,EAAE,GAAG,SAAS,CAAA;CAAO,GACvC,OAAO,CAAC,IAAI,CAAC,CA2Ef"}
@@ -14,7 +14,8 @@ export async function listenForNode(app, port, hostname = '0.0.0.0') {
14
14
  resolve(null);
15
15
  });
16
16
  });
17
- return server;
17
+ const actualPort = server.address().port;
18
+ return { port: actualPort, server };
18
19
  }
19
20
  export async function handleForNode(app, req, res, context = {}) {
20
21
  if (req?.['body']) {
@@ -1 +1 @@
1
- {"version":3,"file":"_node-server.js","sourceRoot":"","sources":["../src/_node-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"_node-server.js","sourceRoot":"","sources":["../src/_node-server.ts"],"names":[],"mappings":"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"}
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { SSEServerTransportSpiceflow } from './mcp-transport.ts';
2
2
  import { Spiceflow } from './spiceflow.ts';
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
+ export declare function addMcpTools({ mcpServer, app, }: {
5
+ mcpServer: Server;
6
+ app: Spiceflow;
7
+ }): Promise<Server>;
3
8
  export declare const mcp: <Path extends string = "/mcp">({ path, name, version, transports, }?: {
4
9
  path?: Path | undefined;
5
10
  name?: string | undefined;
package/dist/mcp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI1C,eAAO,MAAM,GAAG,GAAI,IAAI,SAAS,MAAM,GAAG,MAAM,EAAE;;;;;CAQ5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiFL,CAAA"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAGhE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAIlE,wBAAsB,WAAW,CAAC,EAChC,SAAS,EACT,GAAG,GACJ,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,SAAS,CAAA;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAqClB;AAED,eAAO,MAAM,GAAG,GAAI,IAAI,SAAS,MAAM,GAAG,MAAM,EAAE;;;;;CAQ5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAgFL,CAAA"}
package/dist/mcp.js CHANGED
@@ -3,6 +3,38 @@ import { createMCPServer } from "./openapi-to-mcp.js";
3
3
  import { openapi } from "./openapi.js";
4
4
  import { Spiceflow } from "./spiceflow.js";
5
5
  const defaultTransports = new Map();
6
+ export async function addMcpTools({ mcpServer, app, }) {
7
+ const basePath = app.topLevelApp?.basePath || '';
8
+ const [openapi, mcpConfig] = await Promise.all([
9
+ app
10
+ .topLevelApp.handle(new Request(`http://localhost${basePath}/_mcp_openapi`))
11
+ .then((r) => r.json()),
12
+ app
13
+ .topLevelApp.handle(new Request(`http://localhost${basePath}/_mcp_config`))
14
+ .then((r) => r.json()),
15
+ ]);
16
+ const mcpPath = mcpConfig?.path;
17
+ if (!mcpPath) {
18
+ throw new Error('Missing MCP path from app, make sure to use the mcp() Spiceflow plugin');
19
+ }
20
+ const { server: configuredServer } = createMCPServer({
21
+ name: mcpConfig.name,
22
+ version: mcpConfig.version,
23
+ server: mcpServer,
24
+ ignorePaths: [
25
+ '/_mcp_openapi',
26
+ '/_mcp_config',
27
+ mcpPath,
28
+ mcpPath + '/message',
29
+ ],
30
+ fetch: (url, init) => {
31
+ const req = new Request(url, init);
32
+ return app.handle(req);
33
+ },
34
+ openapi,
35
+ });
36
+ return configuredServer;
37
+ }
6
38
  export const mcp = ({ path = '/mcp', name = 'spiceflow', version = '1.0.0',
7
39
  /**
8
40
  * Map to get a transport from a sessionId and
@@ -53,7 +85,7 @@ transports = defaultTransports, } = {}) => {
53
85
  '/_mcp_openapi',
54
86
  '/_mcp_config',
55
87
  mcpPath,
56
- mcpPath + '/message', //
88
+ mcpPath + '/message',
57
89
  ],
58
90
  fetch: (url, init) => {
59
91
  const req = new Request(url, init);
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { OpenAPIV3 } from 'openapi-types';
3
3
  type Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
4
- export declare function createMCPServer({ name, version, openapi, fetch, paths, ignorePaths, baseUrl, }: {
4
+ export declare function createMCPServer({ name, version, openapi, server, fetch, paths, ignorePaths, baseUrl, }: {
5
5
  name?: string;
6
6
  version?: string;
7
- fetch?: Fetch;
8
7
  openapi: OpenAPIV3.Document;
8
+ server?: Server;
9
+ fetch?: Fetch;
9
10
  paths?: string[];
10
11
  ignorePaths?: string[];
11
12
  baseUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"openapi-to-mcp.d.ts","sourceRoot":"","sources":["../src/openapi-to-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AASlE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AA8JzC,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAGhF,wBAAgB,eAAe,CAAC,EAC9B,IAAkB,EAClB,OAAiB,EACjB,OAAO,EAEP,KAAoB,EACpB,KAAK,EACL,WAAW,EACX,OAAY,GACb,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;;;;;;;;;;;;;;;;;;;;;;;;EA4OA"}
1
+ {"version":3,"file":"openapi-to-mcp.d.ts","sourceRoot":"","sources":["../src/openapi-to-mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AASlE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AA8JzC,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAGhF,wBAAgB,eAAe,CAAC,EAC9B,IAAkB,EAClB,OAAiB,EACjB,OAAO,EACP,MAAM,EACN,KAAoB,EACpB,KAAK,EACL,WAAW,EACX,OAAY,GACb,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;;;;;;;;;;;;;;;;;;;;;;;;EA4OA"}
@@ -133,8 +133,8 @@ function getAuthHeaders(openapi, operation) {
133
133
  return headers;
134
134
  }
135
135
  const defaultFetch = fetch;
136
- export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi, fetch = defaultFetch, paths, ignorePaths, baseUrl = '', }) {
137
- const server = new Server({ name, version }, {
136
+ export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi, server, fetch = defaultFetch, paths, ignorePaths, baseUrl = '', }) {
137
+ const mcpServer = server || new Server({ name, version }, {
138
138
  capabilities: {
139
139
  tools: {},
140
140
  resources: {},
@@ -176,7 +176,7 @@ export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi
176
176
  headers: finalHeaders,
177
177
  });
178
178
  }
179
- server.setRequestHandler(ListToolsRequestSchema, async () => {
179
+ mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
180
180
  const filteredPaths = Object.entries(openapi.paths).filter(([path]) => {
181
181
  if (ignorePaths?.includes(path))
182
182
  return false;
@@ -227,7 +227,7 @@ export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi
227
227
  }));
228
228
  return { tools };
229
229
  });
230
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
230
+ mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
231
231
  const toolName = request.params.name;
232
232
  let { path, method } = getPathFromToolName(toolName);
233
233
  const pathObj = openapi.paths[path];
@@ -288,7 +288,7 @@ export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi
288
288
  };
289
289
  }
290
290
  });
291
- server.setRequestHandler(ListResourcesRequestSchema, async () => {
291
+ mcpServer.setRequestHandler(ListResourcesRequestSchema, async () => {
292
292
  const resources = [];
293
293
  for (const [path, pathObj] of Object.entries(openapi.paths)) {
294
294
  if (path.startsWith('/mcp')) {
@@ -311,10 +311,10 @@ export function createMCPServer({ name = 'spiceflow', version = '1.0.0', openapi
311
311
  }
312
312
  return { resources: [] };
313
313
  });
314
- server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
314
+ mcpServer.setRequestHandler(ReadResourceRequestSchema, async (request) => {
315
315
  throw new Error('Resources are not supported - use tools instead');
316
316
  });
317
- return { server };
317
+ return { server: mcpServer };
318
318
  }
319
319
  function getRouteName({ method, path, }) {
320
320
  return formatToolName(`${method.toUpperCase()} ${path}`, method, path);