spiceflow 1.1.18 → 1.3.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.
Files changed (49) hide show
  1. package/README.md +245 -10
  2. package/dist/cors.d.ts +2 -0
  3. package/dist/cors.d.ts.map +1 -1
  4. package/dist/cors.js +10 -2
  5. package/dist/cors.js.map +1 -1
  6. package/dist/index.d.ts +2 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp-transport.d.ts +45 -0
  10. package/dist/mcp-transport.d.ts.map +1 -0
  11. package/dist/mcp-transport.js +107 -0
  12. package/dist/mcp-transport.js.map +1 -0
  13. package/dist/mcp.d.ts +36 -0
  14. package/dist/mcp.d.ts.map +1 -0
  15. package/dist/mcp.js +211 -0
  16. package/dist/mcp.js.map +1 -0
  17. package/dist/mcp.test.d.ts +2 -0
  18. package/dist/mcp.test.d.ts.map +1 -0
  19. package/dist/mcp.test.js +224 -0
  20. package/dist/mcp.test.js.map +1 -0
  21. package/dist/openapi.d.ts +14 -27
  22. package/dist/openapi.d.ts.map +1 -1
  23. package/dist/openapi.js +101 -49
  24. package/dist/openapi.js.map +1 -1
  25. package/dist/openapi.test.js +242 -18
  26. package/dist/openapi.test.js.map +1 -1
  27. package/dist/spiceflow.d.ts +5 -3
  28. package/dist/spiceflow.d.ts.map +1 -1
  29. package/dist/spiceflow.js +42 -10
  30. package/dist/spiceflow.js.map +1 -1
  31. package/dist/spiceflow.test.js +21 -3
  32. package/dist/spiceflow.test.js.map +1 -1
  33. package/dist/stream.test.js +4 -2
  34. package/dist/stream.test.js.map +1 -1
  35. package/dist/types.d.ts +7 -13
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/types.js.map +1 -1
  38. package/package.json +20 -5
  39. package/src/cors.ts +14 -2
  40. package/src/index.ts +2 -1
  41. package/src/mcp-transport.ts +148 -0
  42. package/src/mcp.test.ts +273 -0
  43. package/src/mcp.ts +270 -0
  44. package/src/openapi.test.ts +238 -18
  45. package/src/openapi.ts +136 -66
  46. package/src/spiceflow.test.ts +27 -3
  47. package/src/spiceflow.ts +83 -13
  48. package/src/stream.test.ts +4 -2
  49. package/src/types.ts +129 -140
package/README.md CHANGED
@@ -5,7 +5,6 @@
5
5
  <h3>spiceflow</h3>
6
6
  <br/>
7
7
  <p>fast, simple and type safe API framework</p>
8
- <p>still in beata</p>
9
8
  <br/>
10
9
  <br/>
11
10
  </div>
@@ -16,12 +15,14 @@ Spiceflow is a lightweight, type-safe API framework for building web services us
16
15
 
17
16
  ## Features
18
17
 
19
- - Type safety
20
- - OpenAPI compatibility
21
- - RPC client generation
18
+ - Type safe schema based validation via Zod
19
+ - Can easily generate OpenAPI document based on your routes
20
+ - Native support for [Fern](https://github.com/fern-api/fern) to generate docs and SDKs (see example docs [here](https://remorses.docs.buildwithfern.com))
21
+ - Support for [Model Context Protocol](https://modelcontextprotocol.io/) to easily wire your app with LLMs
22
+ - Type safe RPC client generation
22
23
  - Simple and intuitive API
23
24
  - Uses web standards for requests and responses
24
- - Supports async generators for streaming
25
+ - Supports async generators for streaming via server sent events
25
26
  - Modular design with `.use()` for mounting sub-apps
26
27
  - Base path support
27
28
 
@@ -33,6 +34,8 @@ npm install spiceflow
33
34
 
34
35
  ## Basic Usage
35
36
 
37
+ Objects returned from route handlers are automatically serialized to JSON
38
+
36
39
  ```ts
37
40
  import { Spiceflow } from 'spiceflow'
38
41
 
@@ -40,20 +43,20 @@ const app = new Spiceflow()
40
43
  .get('/hello', () => 'Hello, World!')
41
44
  .post('/echo', async ({ request }) => {
42
45
  const body = await request.json()
43
- return body
46
+ return { echo: body }
44
47
  })
45
48
 
46
49
  app.listen(3000)
47
50
  ```
48
51
 
49
- > Notice that you should never declare app separately and add routes later, that way you lose the type safety. Instead always declare all routes in one place.
52
+ > Never declare app and add routes separately, that way you lose the type safety. Instead always append routes with .post and .get in a single expression.
50
53
 
51
54
  ```ts
52
55
  // This is an example of what NOT to do when using Spiceflow
53
56
 
54
57
  import { Spiceflow } from 'spiceflow'
55
58
 
56
- // Do NOT declare the app separately and add routes later
59
+ // DO NOT declare the app separately and add routes later
57
60
  const app = new Spiceflow()
58
61
 
59
62
  // Do NOT do this! Adding routes separately like this will lose type safety
@@ -62,7 +65,6 @@ app.post('/echo', async ({ request }) => {
62
65
  const body = await request.json()
63
66
  return body
64
67
  })
65
-
66
68
  ```
67
69
 
68
70
  ## Requests and Responses
@@ -91,7 +93,6 @@ new Spiceflow().post(
91
93
  > Notice that to get the body of the request, you need to call `request.json()` to parse the body as JSON.
92
94
  > Spiceflow does not parse the Body automatically, there is no body field in the Spiceflow route argument, instead you call either `request.json()` or `request.formData()` to get the body and validate it at the same time. This works by wrapping the request in a `SpiceflowRequest` instance, which has a `json()` and `formData()` method that parse the body and validate it. The returned data will have the correct schema type instead of `any`.
93
95
 
94
-
95
96
  ### Response Schema
96
97
 
97
98
  ```ts
@@ -282,6 +283,88 @@ new Spiceflow().use(({ request }) => {
282
283
  })
283
284
  ```
284
285
 
286
+ ## How errors are handled in Spiceflow client
287
+
288
+ The Spiceflow client provides type-safe error handling by returning either a `data` or `error` property. When using the client:
289
+
290
+ - Thrown errors appear in the `error` field
291
+ - Response objects can be thrown or returned
292
+ - Responses with status codes 200-299 appear in the `data` field
293
+ - Responses with status codes <200 or ≥300 appear in the `error` field
294
+
295
+ The example below demonstrates handling different types of responses:
296
+
297
+ ```ts
298
+ import { Spiceflow } from 'spiceflow'
299
+ import { createSpiceflowClient } from 'spiceflow/client'
300
+
301
+ const app = new Spiceflow()
302
+ .get('/error', () => {
303
+ throw new Error('Something went wrong')
304
+ })
305
+ .get('/unauthorized', () => {
306
+ return new Response('Unauthorized access', { status: 401 })
307
+ })
308
+ .get('/success', () => {
309
+ throw new Response('Success message', { status: 200 })
310
+ return ''
311
+ })
312
+
313
+ const client = createSpiceflowClient<typeof app>('http://localhost:3000')
314
+
315
+ async function handleErrors() {
316
+ const errorResponse = await client.error.get()
317
+ console.log('Calling error endpoint...')
318
+ // Logs: Error occurred: Something went wrong
319
+ if (errorResponse.error) {
320
+ console.error('Error occurred:', errorResponse.error)
321
+ }
322
+
323
+ const unauthorizedResponse = await client.unauthorized.get()
324
+ console.log('Calling unauthorized endpoint...')
325
+ // Logs: Unauthorized: Unauthorized access (Status: 401)
326
+ if (unauthorizedResponse.error) {
327
+ console.error('Unauthorized:', unauthorizedResponse.error)
328
+ }
329
+
330
+ const successResponse = await client.success.get()
331
+ console.log('Calling success endpoint...')
332
+ // Logs: Success: Success message
333
+ if (successResponse.data) {
334
+ console.log('Success:', successResponse.data)
335
+ }
336
+ }
337
+ ```
338
+
339
+ ## Using the client server side, without network requests
340
+
341
+ When using the client server-side, you can pass the Spiceflow app instance directly to `createSpiceflowClient()` instead of providing a URL. This allows you to make "virtual" requests that are handled directly by the app without making actual network requests. This is useful for testing, generating documentation, or any other scenario where you want to interact with your API endpoints programmatically without setting up a server.
342
+
343
+ Here's an example:
344
+
345
+ ```tsx
346
+ import { Spiceflow } from 'spiceflow'
347
+ import { createSpiceflowClient } from 'spiceflow/client'
348
+ import { openapi } from 'spiceflow/openapi'
349
+ import { writeFile } from 'node:fs/promises'
350
+
351
+ const app = new Spiceflow()
352
+ .use(openapi({ path: '/openapi' }))
353
+ .get('/users', () => [
354
+ { id: 1, name: 'John' },
355
+ { id: 2, name: 'Jane' },
356
+ ])
357
+ .post('/users', ({ request }) => request.json())
358
+
359
+ // Create client by passing app instance directly
360
+ const client = createSpiceflowClient(app)
361
+
362
+ // Get OpenAPI schema and write to disk
363
+ const { data } = await client.openapi.get()
364
+ await writeFile('openapi.json', JSON.stringify(data, null, 2))
365
+ console.log('OpenAPI schema saved to openapi.json')
366
+ ```
367
+
285
368
  ## Modifying Response with Middleware
286
369
 
287
370
  Middleware in Spiceflow can be used to modify the response before it's sent to the client. This is useful for adding headers, transforming the response body, or performing any other operations on the response.
@@ -434,3 +517,155 @@ new Spiceflow()
434
517
  return { ok: true }
435
518
  })
436
519
  ```
520
+
521
+ ## Model Context Protocol (MCP)
522
+
523
+ Spiceflow includes a Model Context Protocol (MCP) plugin that exposes your API routes as tools and resources that can be used by AI language models like Claude. The MCP plugin makes it easy to let AI assistants interact with your API endpoints in a controlled way.
524
+
525
+ When you mount the MCP plugin (default path is `/mcp`), it automatically:
526
+
527
+ - Exposes all your routes as callable tools with proper input validation
528
+ - Exposes GET routes without query/path parameters as `resources`
529
+ - Provides an SSE-based transport for real-time communication
530
+ - Handles serialization of requests and responses
531
+
532
+ This makes it simple to let AI models like Claude discover and call your API endpoints programmatically. Here's an example:
533
+
534
+ ```tsx
535
+ // Import the MCP plugin and client
536
+ import { mcp } from 'spiceflow/mcp'
537
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js'
538
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
539
+ import { Spiceflow } from 'spiceflow'
540
+ import {
541
+ ListToolsResultSchema,
542
+ CallToolResultSchema,
543
+ ListResourcesResultSchema,
544
+ } from '@modelcontextprotocol/sdk/types.js'
545
+
546
+ // Create a new app with some example routes
547
+ const app = new Spiceflow()
548
+ // Mount the MCP plugin at /mcp (default path)
549
+ .use(mcp())
550
+ // These routes will be available as tools
551
+ .get('/hello', () => 'Hello World')
552
+ .get('/users/:id', ({ params }) => ({ id: params.id }))
553
+ .post('/echo', async ({ request }) => {
554
+ const body = await request.json()
555
+ return body
556
+ })
557
+
558
+ // Start the server
559
+ app.listen(3000)
560
+
561
+ // Example client usage:
562
+ const transport = new SSEClientTransport(new URL('http://localhost:3000/mcp'))
563
+
564
+ const client = new Client(
565
+ { name: 'example-client', version: '1.0.0' },
566
+ { capabilities: {} },
567
+ )
568
+
569
+ await client.connect(transport)
570
+
571
+ // List available tools
572
+ const tools = await client.request(
573
+ { method: 'tools/list' },
574
+ ListToolsResultSchema,
575
+ )
576
+
577
+ // Call a tool
578
+ const result = await client.request(
579
+ {
580
+ method: 'tools/call',
581
+ params: {
582
+ name: 'GET /hello',
583
+ arguments: {},
584
+ },
585
+ },
586
+ CallToolResultSchema,
587
+ )
588
+
589
+ // List available resources (only GET /hello is exposed since it has no params)
590
+ const resources = await client.request(
591
+ { method: 'resources/list' },
592
+ ListResourcesResultSchema,
593
+ )
594
+ ```
595
+
596
+ ## Generating Fern docs and SDK
597
+
598
+ Spiceflow has native support for Fern docs and SDK generation using openapi plugin.
599
+
600
+ The openapi types also have additional types for `x-fern` extensions to help you customize your docs and SDK.
601
+
602
+ Here is an example script to help you generate an openapi.yml file that you can then use with Fern:
603
+
604
+ ```ts
605
+ import fs from 'fs'
606
+ import path from 'path'
607
+ import yaml from 'js-yaml'
608
+ import { Spiceflow } from 'spiceflow'
609
+ import { openapi } from 'spiceflow/openapi'
610
+ import { createSpiceflowClient } from 'spiceflow/client'
611
+
612
+ const app = new Spiceflow()
613
+ .use(openapi({ path: '/openapi' }))
614
+ .get('/hello', () => 'Hello World')
615
+
616
+ async function main() {
617
+ console.log('Creating Spiceflow client...')
618
+ const client = createSpiceflowClient(app)
619
+
620
+ console.log('Fetching OpenAPI spec...')
621
+ const { data: openapiJson, error } = await client.openapi.get()
622
+ if (error) {
623
+ console.error('Failed to fetch OpenAPI spec:', error)
624
+ throw error
625
+ }
626
+
627
+ const outputPath = path.resolve('./openapi.yml')
628
+ console.log('Writing OpenAPI spec to', outputPath)
629
+ fs.writeFileSync(
630
+ outputPath,
631
+ yaml.dump(openapiJson, {
632
+ indent: 2,
633
+ lineWidth: -1,
634
+ }),
635
+ )
636
+ console.log('Successfully wrote OpenAPI spec')
637
+ }
638
+
639
+ main().catch((e) => {
640
+ console.error('Failed to generate OpenAPI spec:', e)
641
+ process.exit(1)
642
+ })
643
+ ```
644
+
645
+ Then follow Fern docs to generate the SDK and docs. You will need to create some Fern yml config files.
646
+
647
+ You can take a look at the [`scripts/example-app.ts`](spiceflow/scripts/example-app.ts) file for an example app that generates the docs and SDK.
648
+
649
+ ## Fern SDK streaming support
650
+
651
+ When you use an async generator in your app, Spiceflow will automatically add the required `x-fern` extensions to the OpenAPI spec to support streaming.
652
+
653
+ Here is what streaming looks like in the Fern generated SDK:
654
+
655
+ ```ts
656
+ import { ExampleSdkClient } from './sdk-typescript'
657
+
658
+ const sdk = new ExampleSdkClient({
659
+ environment: 'http://localhost:3000',
660
+ })
661
+
662
+ // Get stream data
663
+ const stream = await sdk.getStream()
664
+ for await (const data of stream) {
665
+ console.log('Stream data:', data)
666
+ }
667
+
668
+ // Simple GET request
669
+ const response = await sdk.getUsers()
670
+ console.log('Users:', response)
671
+ ```
package/dist/cors.d.ts CHANGED
@@ -16,6 +16,8 @@ type CORSOptions = {
16
16
  credentials?: boolean;
17
17
  /** Configures the Access-Control-Expose-Headers CORS header */
18
18
  exposeHeaders?: string[];
19
+ /** Configures browser and CDN caching duration for CORS preflight requests in seconds. Set to 0 to disable. */
20
+ cacheAge?: number;
19
21
  };
20
22
  export declare const cors: (options?: CORSOptions) => MiddlewareHandler;
21
23
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C;;;GAGG;AACH,KAAK,WAAW,GAAG;IACjB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACzB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,IAAI,aAAc,WAAW,KAAG,iBAyF5C,CAAA"}
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C;;;GAGG;AACH,KAAK,WAAW,GAAG;IACjB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACzB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,+GAA+G;IAC/G,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,IAAI,aAAc,WAAW,KAAG,iBAmG5C,CAAA"}
package/dist/cors.js CHANGED
@@ -4,6 +4,7 @@ export const cors = (options) => {
4
4
  allowMethods: ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'],
5
5
  allowHeaders: [],
6
6
  exposeHeaders: [],
7
+ cacheAge: 21600 // 6 hours default
7
8
  };
8
9
  const opts = Object.assign(Object.assign({}, defaults), options);
9
10
  const findAllowOrigin = ((optsOrigin) => {
@@ -45,8 +46,15 @@ export const cors = (options) => {
45
46
  set('Access-Control-Expose-Headers', opts.exposeHeaders.join(','));
46
47
  }
47
48
  if (c.request.method === 'OPTIONS') {
48
- if (opts.maxAge != null) {
49
- set('Access-Control-Max-Age', opts.maxAge.toString());
49
+ // Set CORS caching headers if enabled
50
+ if (opts.cacheAge && opts.cacheAge > 0) {
51
+ // CORS preflight cache
52
+ set('Access-Control-Max-Age', opts.cacheAge.toString());
53
+ // Browser cache and CDN cache
54
+ set('Cache-Control', `public, max-age=${opts.cacheAge}, s-maxage=${opts.cacheAge}`);
55
+ // Additional CDN-specific headers
56
+ set('CDN-Cache-Control', `public, s-maxage=${opts.cacheAge}`);
57
+ set('Cloudflare-CDN-Cache-Control', `public, s-maxage=${opts.cacheAge}`);
50
58
  }
51
59
  if ((_b = opts.allowMethods) === null || _b === void 0 ? void 0 : _b.length) {
52
60
  set('Access-Control-Allow-Methods', opts.allowMethods.join(','));
package/dist/cors.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cors.js","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAqB,EAAqB,EAAE;IAC/D,MAAM,QAAQ,GAAgB;QAC5B,MAAM,EAAE,GAAG;QACX,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC;QAC/D,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,EAAE;KAClB,CAAA;IACD,MAAM,IAAI,mCACL,QAAQ,GACR,OAAO,CACX,CAAA;IAED,MAAM,eAAe,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACtC,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,GAAG,EAAE,CAAC,UAAU,CAAA;QACzB,CAAC;aAAM,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;YAC5C,OAAO,UAAU,CAAA;QACnB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAc,EAAE,EAAE,CACxB,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACxD,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEf,OAAO,KAAK,UAAU,IAAI,CAAC,CAAC,EAAE,IAAI;;QAChC,IAAI,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAA;QAE3B,SAAS,GAAG,CAAC,GAAW,EAAE,KAAa;YACrC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;QAC1E,IAAI,WAAW,EAAE,CAAC;YAChB,GAAG,CAAC,6BAA6B,EAAE,WAAW,CAAC,CAAA;QACjD,CAAC;QAED,wIAAwI;QACxI,wFAAwF;QACxF,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAElD,IAAI,YAAY,EAAE,CAAC;gBACjB,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;YAC3B,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAA;QACjD,CAAC;QAED,IAAI,MAAA,IAAI,CAAC,aAAa,0CAAE,MAAM,EAAE,CAAC;YAC/B,GAAG,CAAC,+BAA+B,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QACpE,CAAC;QAED,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;gBACxB,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;YACvD,CAAC;YAED,IAAI,MAAA,IAAI,CAAC,YAAY,0CAAE,MAAM,EAAE,CAAC;gBAC9B,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YAClE,CAAC;YAED,IAAI,OAAO,GAAG,IAAI,CAAC,YAAY,CAAA;YAC/B,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,CAAA,EAAE,CAAC;gBACrB,MAAM,cAAc,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAC1C,gCAAgC,CACjC,CAAA;gBACD,IAAI,cAAc,EAAE,CAAC;oBACnB,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;gBAC3C,CAAC;YACH,CAAC;YACD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,EAAE,CAAC;gBACpB,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;gBACtD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAA;YACpE,CAAC;YAED,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;YACzC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YAEvC,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;gBACxB,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,MAAM,EAAE,GAAG;gBACX,UAAU,EAAE,QAAQ,CAAC,UAAU;aAChC,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../src/cors.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { Spiceflow, AnySpiceflow } from './spiceflow.js';
1
+ export { Spiceflow } from './spiceflow.js';
2
+ export type { AnySpiceflow } from './spiceflow.js';
2
3
  export { InternalServerError, ParseError, ValidationError } from './error.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,45 @@
1
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
2
+ import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
3
+ /**
4
+ * Server transport for SSE: this will send messages over an SSE connection and receive messages from HTTP POST requests.
5
+ *
6
+ * This transport is only available in Node.js environments.
7
+ */
8
+ export declare class SSEServerTransportSpiceflow implements Transport {
9
+ private _sessionId;
10
+ private _endpoint;
11
+ private _writableStream?;
12
+ response?: Response;
13
+ onclose?: () => void;
14
+ onerror?: (error: Error) => void;
15
+ onmessage?: (message: JSONRPCMessage) => void;
16
+ /**
17
+ * Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`.
18
+ */
19
+ constructor(endpoint: string);
20
+ /**
21
+ * Handles the initial SSE connection request.
22
+ *
23
+ * This should be called when a GET request is made to establish the SSE stream.
24
+ */
25
+ start(): Promise<void>;
26
+ /**
27
+ * Handles incoming POST messages.
28
+ *
29
+ * This should be called when a POST request is made to send a message to the server.
30
+ */
31
+ handlePostMessage(req: Request, parsedBody?: unknown): Promise<Response>;
32
+ /**
33
+ * Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
34
+ */
35
+ handleMessage(message: unknown): Promise<void>;
36
+ close(): Promise<void>;
37
+ send(message: JSONRPCMessage): Promise<void>;
38
+ /**
39
+ * Returns the session ID for this transport.
40
+ *
41
+ * This can be used to route incoming POST requests.
42
+ */
43
+ get sessionId(): string;
44
+ }
45
+ //# sourceMappingURL=mcp-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-transport.d.ts","sourceRoot":"","sources":["../src/mcp-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AACzE,OAAO,EACL,cAAc,EAEf,MAAM,oCAAoC,CAAA;AAG3C;;;;GAIG;AACH,qBAAa,2BAA4B,YAAW,SAAS;IAC3D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAC,CAAyC;IACjE,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAE7C;;OAEG;gBACS,QAAQ,EAAE,MAAM;IAK5B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC5B;;;;OAIG;IACG,iBAAiB,CACrB,GAAG,EAAE,OAAO,EACZ,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CAAC,QAAQ,CAAC;IAmBpB;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAalD;;;;OAIG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}
@@ -0,0 +1,107 @@
1
+ import { JSONRPCMessageSchema, } from '@modelcontextprotocol/sdk/types.js';
2
+ import { randomUUID } from 'node:crypto';
3
+ /**
4
+ * Server transport for SSE: this will send messages over an SSE connection and receive messages from HTTP POST requests.
5
+ *
6
+ * This transport is only available in Node.js environments.
7
+ */
8
+ export class SSEServerTransportSpiceflow {
9
+ /**
10
+ * Creates a new SSE server transport, which will direct the client to POST messages to the relative or absolute URL identified by `_endpoint`.
11
+ */
12
+ constructor(endpoint) {
13
+ this._sessionId = randomUUID();
14
+ this._endpoint = endpoint;
15
+ }
16
+ /**
17
+ * Handles the initial SSE connection request.
18
+ *
19
+ * This should be called when a GET request is made to establish the SSE stream.
20
+ */
21
+ async start() {
22
+ var _a;
23
+ if (this.response) {
24
+ throw new Error('SSEServerTransport already started! If using Server class, note that connect() calls start() automatically.');
25
+ }
26
+ const headers = new Headers({
27
+ 'Content-Type': 'text/event-stream',
28
+ 'Cache-Control': 'no-cache',
29
+ // https://github.com/vercel/next.js/issues/9965
30
+ 'content-encoding': 'none',
31
+ Connection: 'keep-alive',
32
+ });
33
+ // Create a TransformStream
34
+ const transformStream = new TransformStream();
35
+ const { readable, writable } = transformStream;
36
+ // Create the Response from the readable side
37
+ this.response = new Response(readable, { headers });
38
+ // Obtain a writer from the writable end
39
+ this._writableStream = writable.getWriter();
40
+ (_a = this._writableStream) === null || _a === void 0 ? void 0 : _a.write(new TextEncoder().encode(`event: endpoint\ndata: ${encodeURI(this._endpoint)}?sessionId=${this._sessionId}\n\n`));
41
+ // readable.getReader().closed.then(() => {
42
+ // this.response = undefined
43
+ // this._writableStream = undefined
44
+ // this.onclose?.()
45
+ // })
46
+ }
47
+ /**
48
+ * Handles incoming POST messages.
49
+ *
50
+ * This should be called when a POST request is made to send a message to the server.
51
+ */
52
+ async handlePostMessage(req, parsedBody) {
53
+ if (!this.response) {
54
+ const message = 'SSE connection not established';
55
+ throw new Error(message);
56
+ }
57
+ let body = await req.json();
58
+ try {
59
+ await this.handleMessage(typeof body === 'string' ? JSON.parse(body) : body);
60
+ }
61
+ catch (_a) {
62
+ return new Response(`Invalid message: ${body}`, { status: 400 });
63
+ }
64
+ return new Response('Accepted', { status: 202 });
65
+ }
66
+ /**
67
+ * Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
68
+ */
69
+ async handleMessage(message) {
70
+ var _a, _b;
71
+ let parsedMessage;
72
+ try {
73
+ parsedMessage = JSONRPCMessageSchema.parse(message);
74
+ }
75
+ catch (error) {
76
+ (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
77
+ throw error;
78
+ }
79
+ (_b = this.onmessage) === null || _b === void 0 ? void 0 : _b.call(this, parsedMessage);
80
+ }
81
+ async close() {
82
+ var _a;
83
+ if (this._writableStream) {
84
+ await this._writableStream.close();
85
+ }
86
+ this.response = undefined;
87
+ this._writableStream = undefined;
88
+ (_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
89
+ }
90
+ async send(message) {
91
+ if (!this._writableStream) {
92
+ throw new Error('Not connected');
93
+ }
94
+ const encoder = new TextEncoder();
95
+ const data = encoder.encode(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
96
+ await this._writableStream.write(data);
97
+ }
98
+ /**
99
+ * Returns the session ID for this transport.
100
+ *
101
+ * This can be used to route incoming POST requests.
102
+ */
103
+ get sessionId() {
104
+ return this._sessionId;
105
+ }
106
+ }
107
+ //# sourceMappingURL=mcp-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-transport.js","sourceRoot":"","sources":["../src/mcp-transport.ts"],"names":[],"mappings":"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"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { Spiceflow } from './spiceflow.js';
2
+ export declare const mcp: <Path extends string = "/mcp">({ path, name, version, }?: {
3
+ path?: Path | undefined;
4
+ name?: string | undefined;
5
+ version?: string | undefined;
6
+ }) => Spiceflow<"", true, {
7
+ state: {};
8
+ }, {
9
+ type: {};
10
+ error: {};
11
+ }, {
12
+ schema: {};
13
+ macro: {};
14
+ macroFn: {};
15
+ }, {
16
+ [x: string]: {
17
+ post: {
18
+ body: unknown;
19
+ params: {};
20
+ query: unknown;
21
+ response: {
22
+ 200: Response | "ok";
23
+ };
24
+ };
25
+ };
26
+ } & import("./types.js").CreateClient<`${Path extends "/" ? "/index" : Path extends "" ? Path : Path extends `/${string}` ? Path : Path}`, {
27
+ get: {
28
+ body: unknown;
29
+ params: { [Param in import("./types.js").GetPathParameter<Path> as Param extends `${string}?` ? never : Param]: string; } & { [Param_1 in import("./types.js").GetPathParameter<Path> as Param_1 extends `${infer OptionalParam}?` ? OptionalParam : never]?: string | undefined; } extends infer T ? { [K in keyof T]: ({ [Param in import("./types.js").GetPathParameter<Path> as Param extends `${string}?` ? never : Param]: string; } & { [Param_1 in import("./types.js").GetPathParameter<Path> as Param_1 extends `${infer OptionalParam}?` ? OptionalParam : never]?: string | undefined; })[K]; } : never;
30
+ query: unknown;
31
+ response: {
32
+ 200: Response | undefined;
33
+ };
34
+ };
35
+ }>>;
36
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAUvD,eAAO,MAAM,GAAG,GAAI,IAAI,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkOtC,CAAA"}