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 +253 -56
- package/dist/_node-server.d.ts +4 -1
- package/dist/_node-server.d.ts.map +1 -1
- package/dist/_node-server.js +2 -1
- package/dist/_node-server.js.map +1 -1
- package/dist/mcp.d.ts +5 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +33 -1
- package/dist/mcp.js.map +1 -1
- package/dist/openapi-to-mcp.d.ts +3 -2
- package/dist/openapi-to-mcp.d.ts.map +1 -1
- package/dist/openapi-to-mcp.js +7 -7
- package/dist/openapi-to-mcp.js.map +1 -1
- package/dist/spiceflow.d.ts +12 -2
- package/dist/spiceflow.d.ts.map +1 -1
- package/dist/spiceflow.js +25 -8
- package/dist/spiceflow.js.map +1 -1
- package/dist/spiceflow.test.js +94 -0
- package/dist/spiceflow.test.js.map +1 -1
- package/package.json +3 -3
- package/src/_node-server.ts +3 -2
- package/src/mcp.ts +47 -2
- package/src/openapi-to-mcp.ts +9 -9
- package/src/spiceflow.test.ts +129 -0
- package/src/spiceflow.ts +28 -8
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
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 =
|
|
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',
|
|
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
|
-
##
|
|
1060
|
+
## Working with Cookies
|
|
997
1061
|
|
|
998
|
-
Spiceflow
|
|
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: '/
|
|
1009
|
-
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
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
|
-
//
|
|
1021
|
-
|
|
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
|
-
|
|
1146
|
+
app.listen(3000)
|
|
1147
|
+
```
|
|
1027
1148
|
|
|
1028
|
-
|
|
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
|
-
.
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
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
|
-
|
|
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
|
package/dist/_node-server.d.ts
CHANGED
|
@@ -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<
|
|
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,
|
|
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"}
|
package/dist/_node-server.js
CHANGED
|
@@ -14,7 +14,8 @@ export async function listenForNode(app, port, hostname = '0.0.0.0') {
|
|
|
14
14
|
resolve(null);
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
|
-
|
|
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']) {
|
package/dist/_node-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_node-server.js","sourceRoot":"","sources":["../src/_node-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,GACb,MAAM,WAAW,CAAA;AAElB,OAAO,EAAgC,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAE/E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAiB,EACjB,IAAY,EACZ,WAAmB,SAAS;IAE5B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,OAAO,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE;YACjC,2EAA2E;YAC3E,iEAAiE;YACjE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,EAAiB,CAAA;YACnD,MAAM,aAAa,GACjB,WAAW,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAA;YACvE,OAAO,CAAC,GAAG,CAAC,uBAAuB,aAAa,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,CAAA;YACvE,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;
|
|
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;
|
|
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":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
package/dist/openapi-to-mcp.d.ts
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/openapi-to-mcp.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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);
|