effortless-aws 0.33.1 → 0.35.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/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec';
2
+
1
3
  /**
2
4
  * Configuration for an Effortless project.
3
5
  *
@@ -371,6 +373,10 @@ type BucketConfig = {
371
373
  suffix?: string;
372
374
  /** Typed JSON entity definitions for key-value storage */
373
375
  entities?: Record<string, BucketEntityConfig>;
376
+ /** Local directory to seed into bucket on deploy (only uploads files that don't already exist) */
377
+ seed?: string;
378
+ /** Local directory to sync into bucket on every deploy (uploads new/changed, deletes removed) */
379
+ sync?: string;
374
380
  };
375
381
  /**
376
382
  * S3 event record passed to onObjectCreated/onObjectRemoved callbacks.
@@ -417,7 +423,7 @@ type BucketObjectRemovedFn<C = undefined> = (args: {
417
423
  * Internal handler object created by defineBucket
418
424
  * @internal
419
425
  */
420
- type BucketHandler$1<C = any, Entities extends Record<string, any> = {}> = {
426
+ type BucketHandler$1<C = any, _Entities extends Record<string, any> = {}> = {
421
427
  readonly __brand: "effortless-bucket";
422
428
  readonly __spec: BucketConfig;
423
429
  readonly onError?: (...args: any[]) => any;
@@ -435,6 +441,10 @@ type BucketOptions = {
435
441
  prefix?: string;
436
442
  /** S3 key suffix filter for event notifications (e.g., ".jpg") */
437
443
  suffix?: string;
444
+ /** Local directory to seed into bucket on deploy (only uploads files that don't already exist) */
445
+ seed?: string;
446
+ /** Local directory to sync into bucket on every deploy (uploads new/changed, deletes removed) */
447
+ sync?: string;
438
448
  };
439
449
  interface BucketBuilder<D = undefined, P = undefined, C = undefined, HasFiles extends boolean = false, Entities extends Record<string, any> = {}> {
440
450
  /** Declare handler dependencies */
@@ -720,7 +730,7 @@ type WorkerMessageFn<T, C = undefined> = (msg: T, ctx: SpreadCtx$4<C>) => Promis
720
730
  * Handler object created by defineWorker.
721
731
  * @internal
722
732
  */
723
- type WorkerHandler$1<T = any, C = any> = {
733
+ type WorkerHandler$1<_T = any, C = any> = {
724
734
  readonly __brand: "effortless-worker";
725
735
  readonly __spec: WorkerConfig;
726
736
  readonly onError?: (...args: any[]) => any;
@@ -1384,6 +1394,7 @@ type RouteEntry = {
1384
1394
  method: HttpMethod;
1385
1395
  path: string;
1386
1396
  onRequest: (...args: any[]) => any;
1397
+ schema?: unknown;
1387
1398
  public?: boolean;
1388
1399
  cache?: ResolvedCache;
1389
1400
  };
@@ -1391,23 +1402,24 @@ type RouteEntry = {
1391
1402
  type SpreadCtx$2<C> = ([C] extends [undefined] ? {} : Omit<C & {}, 'auth'>) & ([ExtractAuth<C>] extends [undefined] ? {} : {
1392
1403
  auth: AuthHelpers<ExtractAuth<C>>;
1393
1404
  });
1405
+ /** Infer validated output type from a Standard Schema, or fall back to unknown */
1406
+ type InferInput<S> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> : unknown;
1394
1407
  /** Callback args available inside each route — ctx is spread into args */
1395
- type RouteArgs<C, ST> = SpreadCtx$2<C> & {
1408
+ type RouteArgs<C, ST, S = undefined> = SpreadCtx$2<C> & {
1396
1409
  req: HttpRequest;
1397
- input: unknown;
1410
+ input: InferInput<S>;
1398
1411
  ok: OkHelper;
1399
1412
  fail: FailHelper;
1400
1413
  } & ([ST] extends [true] ? {
1401
1414
  stream: ResponseStream;
1402
1415
  } : {});
1403
1416
  /** Route handler function */
1404
- type RouteHandler<C, ST> = (args: RouteArgs<C, ST>) => Promise<HttpResponse | void> | HttpResponse | void;
1405
- /** Route options for all methods */
1406
- type RouteOptions = {
1417
+ type RouteHandler<C, ST, S = undefined> = (args: RouteArgs<C, ST, S>) => Promise<HttpResponse | void> | HttpResponse | void;
1418
+ /** Route definition — pass `input` for typed schema validation */
1419
+ type RouteDef<S extends StandardSchemaV1 | undefined = undefined> = {
1420
+ path: `/${string}`;
1421
+ input?: S;
1407
1422
  public?: boolean;
1408
- };
1409
- /** Route options for GET — supports caching */
1410
- type GetRouteOptions = RouteOptions & {
1411
1423
  cache?: CacheOptions;
1412
1424
  };
1413
1425
  /** Setup factory — receives deps/config/files/enableAuth based on what was declared */
@@ -1459,11 +1471,11 @@ type ApiOptions = {
1459
1471
  * Has `__brand` so CLI discovers it. Each `.get()/.post()` adds a route and returns self.
1460
1472
  */
1461
1473
  interface ApiRoutes<C = undefined, ST extends boolean = false> extends ApiHandler<C> {
1462
- get(path: `/${string}`, handler: RouteHandler<C, ST>, options?: GetRouteOptions): ApiRoutes<C, ST>;
1463
- post(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1464
- put(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1465
- patch(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1466
- delete(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1474
+ get<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1475
+ post<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1476
+ put<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1477
+ patch<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1478
+ delete<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1467
1479
  }
1468
1480
  /**
1469
1481
  * Builder interface for defining API handlers.
@@ -1493,16 +1505,11 @@ interface ApiBuilder<D = undefined, P = undefined, C = undefined, ST extends boo
1493
1505
  } & SpreadCtx$2<C>) => HttpResponse | Promise<HttpResponse>): ApiBuilder<D, P, C, ST, HasFiles>;
1494
1506
  /** Cleanup callback — runs after each invocation, before Lambda freezes */
1495
1507
  onCleanup(fn: (args: SpreadCtx$2<C>) => void | Promise<void>): ApiBuilder<D, P, C, ST, HasFiles>;
1496
- /** Add a GET route (terminal returns finalized handler with route methods) */
1497
- get(path: `/${string}`, handler: RouteHandler<C, ST>, options?: GetRouteOptions): ApiRoutes<C, ST>;
1498
- /** Add a POST route (terminal) */
1499
- post(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1500
- /** Add a PUT route (terminal) */
1501
- put(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1502
- /** Add a PATCH route (terminal) */
1503
- patch(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1504
- /** Add a DELETE route (terminal) */
1505
- delete(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
1508
+ get<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1509
+ post<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1510
+ put<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1511
+ patch<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1512
+ delete<S extends StandardSchemaV1 | undefined = undefined>(def: RouteDef<S>, handler: RouteHandler<C, ST, S>): ApiRoutes<C, ST>;
1506
1513
  }
1507
1514
  /**
1508
1515
  * Define an API with typed routes using a builder pattern.
@@ -1519,8 +1526,8 @@ interface ApiBuilder<D = undefined, P = undefined, C = undefined, ST extends boo
1519
1526
  * auth: enableAuth<Session>({ secret: config.dbUrl }),
1520
1527
  * }))
1521
1528
  * .onError(({ error, fail }) => fail(String(error), 500))
1522
- * .get("/me", async ({ users, auth, ok }) => ok(auth.session))
1523
- * .post("/login", async ({ auth, ok }) => ok(await auth.createSession()), { public: true })
1529
+ * .get({ path: "/me" }, async ({ users, auth, ok }) => ok(auth.session))
1530
+ * .post({ path: "/login", public: true }, async ({ auth, ok }) => ok(await auth.createSession()))
1524
1531
  * ```
1525
1532
  */
1526
1533
  declare function defineApi<const O extends ApiOptions>(options: O): ApiBuilder<undefined, undefined, undefined, O["stream"] extends true ? true : false, false>;
@@ -1649,6 +1656,8 @@ type McpConfig = {
1649
1656
  name: string;
1650
1657
  /** MCP server version (default: "1.0.0") */
1651
1658
  version?: string;
1659
+ /** Human-readable description — sent to clients in initialize response as system prompt context */
1660
+ instructions?: string;
1652
1661
  /** Lambda function settings (memory, timeout, permissions, etc.) */
1653
1662
  lambda?: LambdaWithPermissions;
1654
1663
  };
@@ -1679,17 +1688,133 @@ type McpToolResult = {
1679
1688
  content: McpToolContent[];
1680
1689
  isError?: boolean;
1681
1690
  };
1682
- /** A single MCP tool definition */
1683
- type McpToolDef<C = undefined> = {
1691
+ /** Content returned when reading a resource */
1692
+ type McpResourceContent = {
1693
+ uri: string;
1694
+ mimeType?: string;
1695
+ text: string;
1696
+ } | {
1697
+ uri: string;
1698
+ mimeType?: string;
1699
+ blob: string;
1700
+ };
1701
+ /** Legacy resource content result type used by runtime internals */
1702
+ type McpResourceResult = McpResourceContent | McpResourceContent[] | Promise<McpResourceContent | McpResourceContent[]>;
1703
+ /** Infer resource params type from schema, or fall back to Record<string, string> */
1704
+ type InferResourceParams<S> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> : Record<string, string>;
1705
+ /** Resource definition — pass `params` for typed schema validation on URI template params */
1706
+ type McpResourceDefInput<S extends StandardSchemaV1 | undefined = undefined> = {
1707
+ /** Resource URI or URI template (e.g. "resource://contacts/{id}") */
1708
+ uri: string;
1709
+ /** Human-readable name */
1710
+ name: string;
1711
+ /** Schema for URI template params — provides type inference + validation */
1712
+ params?: S;
1713
+ /** Optional description */
1714
+ description?: string;
1715
+ /** Optional MIME type */
1716
+ mimeType?: string;
1717
+ };
1718
+ /** What resource handlers can return — plain data is auto-wrapped by the runtime */
1719
+ type McpResourceReturn = unknown | Promise<unknown>;
1720
+ /** Resource handler — receives params (typed or Record<string, string>) and ctx */
1721
+ type McpResourceHandler<C, S = undefined> = (params: InferResourceParams<S>, ctx: SpreadCtx<C>) => McpResourceReturn;
1722
+ /** @internal */
1723
+ type McpResourceDef$1<C = undefined> = {
1724
+ name: string;
1725
+ description?: string;
1726
+ mimeType?: string;
1727
+ handler: (ctx: SpreadCtx<C>) => McpResourceResult;
1728
+ };
1729
+ /** @internal */
1730
+ type McpResourceTemplateDef$1<C = undefined> = {
1731
+ name: string;
1732
+ description?: string;
1733
+ mimeType?: string;
1734
+ handler: (params: Record<string, string>, ctx: SpreadCtx<C>) => McpResourceResult;
1735
+ };
1736
+ /** @internal */
1737
+ type McpResourceMap$1<C = undefined> = {
1738
+ [uriOrTemplate: string]: McpResourceDef$1<C> | McpResourceTemplateDef$1<C>;
1739
+ };
1740
+ /** An argument accepted by a prompt */
1741
+ type McpPromptArgument = {
1742
+ /** Argument name */
1743
+ name: string;
1744
+ /** Optional description */
1745
+ description?: string;
1746
+ /** Whether the argument is required (default: false) */
1747
+ required?: boolean;
1748
+ };
1749
+ /** Content block inside a prompt message */
1750
+ type McpPromptContent = {
1751
+ type: "text";
1752
+ text: string;
1753
+ } | {
1754
+ type: "image";
1755
+ data: string;
1756
+ mimeType: string;
1757
+ } | {
1758
+ type: "audio";
1759
+ data: string;
1760
+ mimeType: string;
1761
+ } | {
1762
+ type: "resource";
1763
+ resource: {
1764
+ uri: string;
1765
+ mimeType?: string;
1766
+ text?: string;
1767
+ blob?: string;
1768
+ };
1769
+ };
1770
+ /** A single message returned by a prompt */
1771
+ type McpPromptMessage = {
1772
+ role: "user" | "assistant";
1773
+ content: McpPromptContent;
1774
+ };
1775
+ /** Result returned by a prompt handler */
1776
+ type McpPromptResult = {
1777
+ description?: string;
1778
+ messages: McpPromptMessage[];
1779
+ };
1780
+ /** @internal Legacy prompt definition used by runtime */
1781
+ type McpPromptDef$1<C = undefined> = {
1782
+ description?: string;
1783
+ arguments?: McpPromptArgument[];
1784
+ handler: (args: Record<string, string>, ctx: SpreadCtx<C>) => McpPromptResult | Promise<McpPromptResult>;
1785
+ };
1786
+ /** Infer prompt args type from schema, or fall back to Record<string, string> */
1787
+ type InferPromptArgs<S> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> : Record<string, string>;
1788
+ /** Prompt definition — pass a Standard Schema for `args` for typed validation, or McpPromptArgument[] for untyped */
1789
+ type McpPromptDefInput<S extends StandardSchemaV1 | McpPromptArgument[] | undefined = undefined> = {
1790
+ /** Prompt name */
1791
+ name: string;
1792
+ /** Human-readable description */
1793
+ description?: string;
1794
+ /** Args: Standard Schema for typed validation, or McpPromptArgument[] for untyped */
1795
+ args?: S;
1796
+ };
1797
+ /** Handler return: string auto-wraps as user message, or return full McpPromptResult */
1798
+ type McpPromptReturn = string | McpPromptResult | Promise<string | McpPromptResult>;
1799
+ /** Prompt handler — receives args (typed or Record<string, string>) and ctx */
1800
+ type McpPromptHandler<C, S = undefined> = (args: InferPromptArgs<S>, ctx: SpreadCtx<C>) => McpPromptReturn;
1801
+ /** Infer tool input type from schema, or fall back to any */
1802
+ type InferToolInput<S> = S extends StandardJSONSchemaV1 ? StandardJSONSchemaV1.InferOutput<S> : any;
1803
+ /** Tool definition — pass a StandardJSONSchemaV1 for `input` for typed validation, or McpInputSchema for raw JSON Schema */
1804
+ type McpToolDefInput<S extends StandardJSONSchemaV1 | McpInputSchema = McpInputSchema> = {
1805
+ /** Tool name */
1806
+ name: string;
1684
1807
  /** Human-readable description of the tool */
1685
1808
  description: string;
1686
- /** JSON Schema describing the tool's input parameters */
1687
- input: McpInputSchema;
1688
- /** Handler function called when the tool is invoked */
1689
- handler: (input: any, ctx: SpreadCtx<C>) => McpToolResult | Promise<McpToolResult>;
1809
+ /** Schema for tool input: StandardJSONSchemaV1 (e.g. z.object({...})) or raw McpInputSchema */
1810
+ input: S;
1690
1811
  };
1691
- /** Setup factory — receives deps/config/files based on what was declared */
1692
- type SetupArgs<D, P, HasFiles extends boolean> = ([D] extends [undefined] ? {} : {
1812
+ /** Tool handler — receives input (typed or any) and ctx */
1813
+ type McpToolHandler<C, S = McpInputSchema> = (input: InferToolInput<S>, ctx: SpreadCtx<C>) => unknown | Promise<unknown>;
1814
+ /** Setup factory — receives deps/config/files/enableAuth based on what was declared */
1815
+ type SetupArgs<D, P, HasFiles extends boolean> = {
1816
+ enableAuth: EnableAuth;
1817
+ } & ([D] extends [undefined] ? {} : {
1693
1818
  deps: ResolveDeps<D>;
1694
1819
  }) & ([P] extends [undefined] ? {} : {
1695
1820
  config: ResolveConfig<P & {}>;
@@ -1711,14 +1836,30 @@ type McpHandler$1<C = any> = {
1711
1836
  readonly deps?: Record<string, unknown> | (() => Record<string, unknown>);
1712
1837
  readonly config?: Record<string, unknown>;
1713
1838
  readonly static?: string[];
1839
+ readonly resources?: (...args: any[]) => any;
1840
+ readonly prompts?: (...args: any[]) => any;
1714
1841
  readonly tools?: (...args: any[]) => any;
1715
1842
  };
1843
+ /**
1844
+ * Finalized MCP handler with chainable registration methods.
1845
+ * Has `__brand` so CLI discovers it. Each `.tool()/.resource()/.prompt()` adds an entry and returns self.
1846
+ */
1847
+ interface McpEntries<C = undefined> extends McpHandler$1<C> {
1848
+ /** Register a tool */
1849
+ tool<S extends StandardJSONSchemaV1 | McpInputSchema = McpInputSchema>(def: McpToolDefInput<S>, handler: McpToolHandler<C, S>): McpEntries<C>;
1850
+ /** Register a resource */
1851
+ resource<S extends StandardSchemaV1 | undefined = undefined>(def: McpResourceDefInput<S>, handler: McpResourceHandler<C, S>): McpEntries<C>;
1852
+ /** Register a prompt */
1853
+ prompt<S extends StandardSchemaV1 | McpPromptArgument[] | undefined = undefined>(def: McpPromptDefInput<S>, handler: McpPromptHandler<C, S>): McpEntries<C>;
1854
+ }
1716
1855
  /** Options passed to `defineMcp()` */
1717
1856
  type McpOptions = {
1718
1857
  /** MCP server name (used in server info) */
1719
1858
  name: string;
1720
1859
  /** MCP server version (default: "1.0.0") */
1721
1860
  version?: string;
1861
+ /** Human-readable description — sent to clients in initialize response as system prompt context */
1862
+ instructions?: string;
1722
1863
  };
1723
1864
  interface McpBuilder<D = undefined, P = undefined, C = undefined, HasFiles extends boolean = false> {
1724
1865
  /** Declare handler dependencies (tables, queues, buckets, mailers, workers) */
@@ -1740,33 +1881,32 @@ interface McpBuilder<D = undefined, P = undefined, C = undefined, HasFiles exten
1740
1881
  } & SpreadCtx<C>) => void | Promise<void>): McpBuilder<D, P, C, HasFiles>;
1741
1882
  /** Cleanup callback — runs on shutdown */
1742
1883
  onCleanup(fn: (args: SpreadCtx<C>) => void | Promise<void>): McpBuilder<D, P, C, HasFiles>;
1743
- /** Define MCP tools (terminal) */
1744
- tools(fn: (ctx: SpreadCtx<C>) => Record<string, McpToolDef<C>>): McpHandler$1<C>;
1884
+ /** Register a tool */
1885
+ tool<S extends StandardJSONSchemaV1 | McpInputSchema = McpInputSchema>(def: McpToolDefInput<S>, handler: McpToolHandler<C, S>): McpEntries<C>;
1886
+ /** Register a resource */
1887
+ resource<S extends StandardSchemaV1 | undefined = undefined>(def: McpResourceDefInput<S>, handler: McpResourceHandler<C, S>): McpEntries<C>;
1888
+ /** Register a prompt */
1889
+ prompt<S extends StandardSchemaV1 | McpPromptArgument[] | undefined = undefined>(def: McpPromptDefInput<S>, handler: McpPromptHandler<C, S>): McpEntries<C>;
1890
+ /** Finalize the handler without adding more entries */
1891
+ build(): McpHandler$1<C>;
1745
1892
  }
1746
1893
  /**
1747
1894
  * Define an MCP (Model Context Protocol) server endpoint.
1748
1895
  *
1749
- * Creates a Lambda-backed MCP server that exposes tools for AI models
1750
- * and MCP-compatible clients to discover and invoke.
1896
+ * Creates a Lambda-backed MCP server that exposes tools, resources, and prompts
1897
+ * for AI models and MCP-compatible clients via Streamable HTTP (JSON-RPC over POST).
1751
1898
  *
1752
- * @example
1753
- * ```typescript
1754
- * export const mcp = defineMcp({ name: "my-tools" })
1755
- * .deps(() => ({ users: usersTable }))
1756
- * .setup(({ deps }) => ({ db: deps.users }))
1757
- * .tools(({ db }) => ({
1758
- * get_user: {
1759
- * description: "Get a user by ID",
1760
- * input: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
1761
- * handler: async (input) => ({
1762
- * content: [{ type: "text", text: JSON.stringify(await db.get({ pk: input.id, sk: "profile" })) }]
1763
- * })
1764
- * }
1765
- * }))
1766
- * ```
1899
+ * @see https://modelcontextprotocol.io/specification/2025-03-26 — MCP specification
1900
+ * @see https://effortless-aws.com/use-cases/mcp-server/ — full documentation with examples
1767
1901
  */
1768
1902
  declare function defineMcp(options: McpOptions): McpBuilder;
1769
1903
 
1904
+ type McpToolDef = McpToolDefInput;
1905
+ type McpResourceDef = McpResourceDef$1;
1906
+ type McpResourceTemplateDef = McpResourceTemplateDef$1;
1907
+ type McpResourceMap = McpResourceMap$1;
1908
+ type McpPromptDef = McpPromptDef$1;
1909
+
1770
1910
  type TableHandler<T = Record<string, unknown>> = TableHandler$1<T, any>;
1771
1911
  type FifoQueueHandler<T = unknown> = FifoQueueHandler$1<T, any>;
1772
1912
  type BucketHandler<Entities extends Record<string, any> = {}> = BucketHandler$1<any, Entities>;
@@ -1774,4 +1914,4 @@ type CronHandler = CronHandler$1<any>;
1774
1914
  type WorkerHandler<T = any> = WorkerHandler$1<T, any>;
1775
1915
  type McpHandler = McpHandler$1<any>;
1776
1916
 
1777
- export { type ApiAuthConfig, type ApiConfig, type ApiHandler, type ApiRoutes, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketClientWithEntities, type BucketConfig, type BucketEntityConfig, type BucketEvent, type BucketHandler, type BucketRouteConfig, type CacheOptions, type CdnPolicyOptions, type ConfigHelpers, type ContentType, type CronConfig, type CronHandler, type DefineSecretFn, type Duration, type EffortlessConfig, type EmailClient, type FifoQueueConfig, type FifoQueueHandler, type FifoQueueMessage, type HttpMethod$1 as HttpMethod, type HttpRequest, type HttpResponse, type LogLevel, type MailerConfig, type MailerHandler, type McpConfig, type McpHandler, type McpInputSchema, type McpToolContent, type McpToolDef, type McpToolResult, type MiddlewareDeny, type MiddlewareHandler, type MiddlewareRedirect, type MiddlewareRequest, type MiddlewareResult, type ParamRef, type Permission, type PutInput, type PutOptions, type QueryByTagParams, type QueryParams, type QueueClient, type ResponseStream, type SecretRef, type SendEmailOptions, type SendMessageInput, type SkCondition, type StaticFiles, type StaticSiteConfig, type StaticSiteHandler, type StaticSiteSeo, type StoreEntityClient, type StreamView, type TableClient, type TableConfig, type TableHandler, type TableItem, type TableKey, type TableRecord, type Timezone, type UpdateActions, type WorkerClient, type WorkerConfig, type WorkerHandler, type WorkerSendOptions, defineApi, defineApp, defineBucket, defineConfig, defineCron, defineFifoQueue, defineMailer, defineMcp, defineSecret, defineStaticSite, defineTable, defineWorker, generateBase64, generateHex, generateUuid, isBucketRoute, param, secret, toSeconds };
1917
+ export { type ApiAuthConfig, type ApiConfig, type ApiHandler, type ApiRoutes, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketClientWithEntities, type BucketConfig, type BucketEntityConfig, type BucketEvent, type BucketHandler, type BucketRouteConfig, type CacheOptions, type CdnPolicyOptions, type ConfigHelpers, type ContentType, type CronConfig, type CronHandler, type DefineSecretFn, type Duration, type EffortlessConfig, type EmailClient, type FifoQueueConfig, type FifoQueueHandler, type FifoQueueMessage, type HttpMethod$1 as HttpMethod, type HttpRequest, type HttpResponse, type LogLevel, type MailerConfig, type MailerHandler, type McpConfig, type McpEntries, type McpHandler, type McpInputSchema, type McpPromptArgument, type McpPromptContent, type McpPromptDef, type McpPromptMessage, type McpPromptResult, type McpResourceContent, type McpResourceDef, type McpResourceMap, type McpResourceTemplateDef, type McpToolContent, type McpToolDef, type McpToolResult, type MiddlewareDeny, type MiddlewareHandler, type MiddlewareRedirect, type MiddlewareRequest, type MiddlewareResult, type ParamRef, type Permission, type PutInput, type PutOptions, type QueryByTagParams, type QueryParams, type QueueClient, type ResponseStream, type SecretRef, type SendEmailOptions, type SendMessageInput, type SkCondition, type StaticFiles, type StaticSiteConfig, type StaticSiteHandler, type StaticSiteSeo, type StoreEntityClient, type StreamView, type TableClient, type TableConfig, type TableHandler, type TableItem, type TableKey, type TableRecord, type Timezone, type UpdateActions, type WorkerClient, type WorkerConfig, type WorkerHandler, type WorkerSendOptions, defineApi, defineApp, defineBucket, defineConfig, defineCron, defineFifoQueue, defineMailer, defineMcp, defineSecret, defineStaticSite, defineTable, defineWorker, generateBase64, generateHex, generateUuid, isBucketRoute, param, secret, toSeconds };
package/dist/index.js CHANGED
@@ -301,13 +301,14 @@ function defineApi(options) {
301
301
  },
302
302
  routes: []
303
303
  };
304
- const addRoute = (method, path, handler, opts) => {
305
- const routeCache = opts?.cache != null ? resolveCache(opts.cache) : void 0;
304
+ const addRoute = (method, def, handler) => {
305
+ const routeCache = def.cache != null ? resolveCache(def.cache) : void 0;
306
306
  state.routes.push({
307
307
  method,
308
- path,
308
+ path: def.path,
309
309
  onRequest: handler,
310
- ...opts?.public ? { public: true } : {},
310
+ ...def.input ? { schema: def.input } : {},
311
+ ...def.public ? { public: true } : {},
311
312
  ...routeCache ? { cache: routeCache } : {}
312
313
  });
313
314
  };
@@ -329,8 +330,8 @@ function defineApi(options) {
329
330
  ...state.static ? { static: state.static } : {}
330
331
  };
331
332
  for (const m of ["get", "post", "put", "patch", "delete"]) {
332
- handler[m] = (path, fn, opts) => {
333
- addRoute(m.toUpperCase(), path, fn, opts);
333
+ handler[m] = (def, fn) => {
334
+ addRoute(m.toUpperCase(), def, fn);
334
335
  handler.routes = state.routes;
335
336
  return handler;
336
337
  };
@@ -367,24 +368,24 @@ function defineApi(options) {
367
368
  state.onCleanup = fn;
368
369
  return builder;
369
370
  },
370
- get(path, handler, opts) {
371
- addRoute("GET", path, handler, opts);
371
+ get(def, fn) {
372
+ addRoute("GET", def, fn);
372
373
  return finalize();
373
374
  },
374
- post(path, handler, opts) {
375
- addRoute("POST", path, handler, opts);
375
+ post(def, fn) {
376
+ addRoute("POST", def, fn);
376
377
  return finalize();
377
378
  },
378
- put(path, handler, opts) {
379
- addRoute("PUT", path, handler, opts);
379
+ put(def, fn) {
380
+ addRoute("PUT", def, fn);
380
381
  return finalize();
381
382
  },
382
- patch(path, handler, opts) {
383
- addRoute("PATCH", path, handler, opts);
383
+ patch(def, fn) {
384
+ addRoute("PATCH", def, fn);
384
385
  return finalize();
385
386
  },
386
- delete(path, handler, opts) {
387
- addRoute("DELETE", path, handler, opts);
387
+ delete(def, fn) {
388
+ addRoute("DELETE", def, fn);
388
389
  return finalize();
389
390
  }
390
391
  };
@@ -519,25 +520,57 @@ function defineWorker(options) {
519
520
  function defineMcp(options) {
520
521
  const spec = {
521
522
  name: options.name,
522
- ...options.version ? { version: options.version } : {}
523
+ ...options.version ? { version: options.version } : {},
524
+ ...options.instructions ? { instructions: options.instructions } : {}
523
525
  };
524
- const state = { spec };
526
+ const state = { spec, toolEntries: [], resourceEntries: [], promptEntries: [] };
525
527
  const applyLambdaOptions = (lambda) => {
526
528
  if (Object.keys(lambda).length > 0) {
527
529
  state.spec = { ...state.spec, lambda: { ...state.spec.lambda, ...lambda } };
528
530
  }
529
531
  };
530
- const finalize = () => ({
531
- __brand: "effortless-mcp",
532
- __spec: state.spec,
533
- ...state.onError ? { onError: state.onError } : {},
534
- ...state.onCleanup ? { onCleanup: state.onCleanup } : {},
535
- ...state.setup ? { setup: state.setup } : {},
536
- ...state.deps ? { deps: state.deps } : {},
537
- ...state.config ? { config: state.config } : {},
538
- ...state.static ? { static: state.static } : {},
539
- ...state.tools ? { tools: state.tools } : {}
540
- });
532
+ const buildToolsFactory = () => state.toolEntries.length > 0 ? () => Object.fromEntries(state.toolEntries) : void 0;
533
+ const buildResourcesFactory = () => state.resourceEntries.length > 0 ? () => Object.fromEntries(state.resourceEntries) : void 0;
534
+ const buildPromptsFactory = () => state.promptEntries.length > 0 ? () => Object.fromEntries(state.promptEntries) : void 0;
535
+ const finalize = () => {
536
+ const tools = buildToolsFactory();
537
+ const resources = buildResourcesFactory();
538
+ const prompts = buildPromptsFactory();
539
+ return {
540
+ __brand: "effortless-mcp",
541
+ __spec: state.spec,
542
+ ...state.onError ? { onError: state.onError } : {},
543
+ ...state.onCleanup ? { onCleanup: state.onCleanup } : {},
544
+ ...state.setup ? { setup: state.setup } : {},
545
+ ...state.deps ? { deps: state.deps } : {},
546
+ ...state.config ? { config: state.config } : {},
547
+ ...state.static ? { static: state.static } : {},
548
+ ...resources ? { resources } : {},
549
+ ...prompts ? { prompts } : {},
550
+ ...tools ? { tools } : {}
551
+ };
552
+ };
553
+ const finalizeWithEntries = () => {
554
+ const handler = finalize();
555
+ handler.tool = (def, fn) => {
556
+ state.toolEntries.push([def.name, { description: def.description, input: def.input, handler: fn }]);
557
+ handler.tools = buildToolsFactory();
558
+ return handler;
559
+ };
560
+ handler.resource = (def, fn) => {
561
+ const entry = { name: def.name, ...def.description ? { description: def.description } : {}, ...def.mimeType ? { mimeType: def.mimeType } : {}, handler: fn, ...def.params ? { params: def.params } : {} };
562
+ state.resourceEntries.push([def.uri, entry]);
563
+ handler.resources = buildResourcesFactory();
564
+ return handler;
565
+ };
566
+ handler.prompt = (def, fn) => {
567
+ const entry = { ...def.description ? { description: def.description } : {}, args: def.args, handler: fn };
568
+ state.promptEntries.push([def.name, entry]);
569
+ handler.prompts = buildPromptsFactory();
570
+ return handler;
571
+ };
572
+ return handler;
573
+ };
541
574
  const builder = {
542
575
  deps(fn) {
543
576
  state.deps = fn;
@@ -568,8 +601,21 @@ function defineMcp(options) {
568
601
  state.onCleanup = fn;
569
602
  return builder;
570
603
  },
571
- tools(fn) {
572
- state.tools = fn;
604
+ tool(def, fn) {
605
+ state.toolEntries.push([def.name, { description: def.description, input: def.input, handler: fn }]);
606
+ return finalizeWithEntries();
607
+ },
608
+ resource(def, fn) {
609
+ const entry = { name: def.name, ...def.description ? { description: def.description } : {}, ...def.mimeType ? { mimeType: def.mimeType } : {}, handler: fn, ...def.params ? { params: def.params } : {} };
610
+ state.resourceEntries.push([def.uri, entry]);
611
+ return finalizeWithEntries();
612
+ },
613
+ prompt(def, fn) {
614
+ const entry = { ...def.description ? { description: def.description } : {}, args: def.args, handler: fn };
615
+ state.promptEntries.push([def.name, entry]);
616
+ return finalizeWithEntries();
617
+ },
618
+ build() {
573
619
  return finalize();
574
620
  }
575
621
  };