@creature-ai/sdk 0.1.6 → 0.1.7

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.
@@ -1,6 +1,65 @@
1
1
  import { z } from 'zod';
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
 
4
+ /**
5
+ * Interface for external state storage.
6
+ * Implementations can use Redis, DynamoDB, MongoDB, etc.
7
+ */
8
+ interface StateAdapter {
9
+ /**
10
+ * Get state for an instance.
11
+ */
12
+ get<T>(instanceId: string): Promise<T | undefined>;
13
+ /**
14
+ * Set state for an instance.
15
+ */
16
+ set<T>(instanceId: string, state: T): Promise<void>;
17
+ /**
18
+ * Delete state for an instance.
19
+ */
20
+ delete(instanceId: string): Promise<void>;
21
+ }
22
+ /**
23
+ * Interface for external realtime communication.
24
+ * Implementations can use Pusher, Ably, Redis pub/sub, etc.
25
+ */
26
+ interface RealtimeAdapter {
27
+ /**
28
+ * Send a message to all clients subscribed to an instance.
29
+ */
30
+ send<T>(instanceId: string, message: T): Promise<void>;
31
+ /**
32
+ * Subscribe to messages for an instance.
33
+ */
34
+ subscribe(instanceId: string, handler: (message: unknown) => void): () => void;
35
+ /**
36
+ * Get the WebSocket/channel URL for clients to connect.
37
+ */
38
+ getWebSocketUrl(instanceId: string): string;
39
+ }
40
+ /**
41
+ * Options for configuring adapters.
42
+ */
43
+ interface AdapterOptions {
44
+ /** External state adapter (for stateful features in serverless). */
45
+ stateAdapter?: StateAdapter;
46
+ /** External realtime adapter (for WebSocket-like features in serverless). */
47
+ realtimeAdapter?: RealtimeAdapter;
48
+ }
49
+ /**
50
+ * Options for vercelMcp adapter.
51
+ */
52
+ interface VercelMcpOptions extends AdapterOptions {
53
+ /** Base path for MCP routes (default: '/api'). */
54
+ basePath?: string;
55
+ /** Maximum duration for serverless function (default: 60). */
56
+ maxDuration?: number;
57
+ }
58
+ /**
59
+ * Options for awsLambda adapter.
60
+ */
61
+ interface AwsLambdaOptions extends AdapterOptions {
62
+ }
4
63
  /**
5
64
  * MIME types for cross-platform compatibility.
6
65
  */
@@ -77,16 +136,10 @@ interface ResourceConfig {
77
136
  websocket?: boolean;
78
137
  }
79
138
  /**
80
- * Resource cache configuration.
81
- * Controls caching behavior for UI resource HTML content.
139
+ * Internal resource definition.
82
140
  */
83
- interface ResourceCacheConfig {
84
- /** Maximum number of cached entries (default: 100) */
85
- maxSize?: number;
86
- /** Time-to-live in milliseconds. 0 = no expiry (default: 0) */
87
- ttlMs?: number;
88
- /** Whether caching is enabled (default: true) */
89
- enabled?: boolean;
141
+ interface ResourceDefinition {
142
+ config: ResourceConfig;
90
143
  }
91
144
  /**
92
145
  * Tool configuration.
@@ -139,6 +192,30 @@ interface ToolContext {
139
192
  * Automatically attached to tool result for UI routing.
140
193
  */
141
194
  instanceId: string;
195
+ /**
196
+ * Creature App Token for identity verification.
197
+ * ONLY present when:
198
+ * 1. App opted into Creature-managed auth (`auth: { creatureManaged: true }`)
199
+ * 2. Tool call originated from Creature host
200
+ *
201
+ * Use `verifyCreatureToken(context.creatureToken)` to verify and extract
202
+ * user identity for multi-tenant data access.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * app.tool("save_note", { ... }, async ({ content }, context) => {
207
+ * if (!context.creatureToken) {
208
+ * return { error: "Authentication required" };
209
+ * }
210
+ * const identity = await verifyCreatureToken(context.creatureToken);
211
+ * await db.notes.insert({
212
+ * user_id: identity.user.id,
213
+ * content,
214
+ * });
215
+ * });
216
+ * ```
217
+ */
218
+ creatureToken?: string;
142
219
  /**
143
220
  * Get server-side state for this instance.
144
221
  * State is NOT sent to UI — use for PIDs, connections, handles.
@@ -174,6 +251,13 @@ interface ToolContext {
174
251
  */
175
252
  websocketUrl: string | undefined;
176
253
  }
254
+ /**
255
+ * Internal tool definition with handler.
256
+ */
257
+ interface ToolDefinition<TInput = unknown> {
258
+ config: ToolConfig;
259
+ handler: ToolHandler<TInput>;
260
+ }
177
261
  /**
178
262
  * Context passed to onInstanceDestroy callback.
179
263
  */
@@ -199,6 +283,25 @@ interface TransportSessionInfo {
199
283
  /** The transport type for this session */
200
284
  transport: TransportType;
201
285
  }
286
+ /**
287
+ * Creature-managed authentication configuration.
288
+ * When enabled, Creature provides user identity and tokens to your app.
289
+ */
290
+ interface CreatureAuthConfig {
291
+ /**
292
+ * Enable Creature-managed authentication.
293
+ * When true, your app receives user identity (id, email, name) and
294
+ * organization/project context via hostContext.creature.
295
+ *
296
+ * Apps can use this for:
297
+ * - Auto-registering users without login screens
298
+ * - Scoping data to users/orgs/projects
299
+ * - Backend API calls with verified identity
300
+ *
301
+ * @default false
302
+ */
303
+ creatureManaged?: boolean;
304
+ }
202
305
  /**
203
306
  * App configuration.
204
307
  */
@@ -207,6 +310,14 @@ interface AppConfig {
207
310
  name: string;
208
311
  /** App version */
209
312
  version: string;
313
+ /**
314
+ * Authentication configuration.
315
+ * Enable Creature-managed auth to receive user identity automatically.
316
+ *
317
+ * @example
318
+ * auth: { creatureManaged: true }
319
+ */
320
+ auth?: CreatureAuthConfig;
210
321
  /**
211
322
  * High-level instructions for using this MCP.
212
323
  * Sent to the model during initialization to provide context about
@@ -259,11 +370,6 @@ interface AppConfig {
259
370
  * Controls how long to wait for in-flight requests to complete.
260
371
  */
261
372
  keepAliveTimeout?: number;
262
- /**
263
- * Configuration for resource content caching.
264
- * Resources are cached to avoid repeated file reads.
265
- */
266
- resourceCache?: ResourceCacheConfig;
267
373
  }
268
374
  /**
269
375
  * WebSocket connection for an instance.
@@ -302,8 +408,6 @@ declare class App {
302
408
  private callerDir;
303
409
  private shutdownRegistered;
304
410
  private isShuttingDown;
305
- private resourceCache;
306
- private resourceCacheConfig;
307
411
  /** Server-side instance state, keyed by instanceId. */
308
412
  private instanceState;
309
413
  /** Callbacks to invoke when an instance is destroyed. */
@@ -380,27 +484,73 @@ declare class App {
380
484
  */
381
485
  getTransportSessionCount(): number;
382
486
  /**
383
- * Close a specific transport session.
487
+ * Get the app configuration.
384
488
  */
385
- closeTransportSession(sessionId: string): boolean;
489
+ getConfig(): AppConfig;
386
490
  /**
387
- * Clear all cached resource content.
491
+ * Get all tool definitions.
388
492
  */
389
- clearResourceCache(): void;
493
+ getToolDefinitions(): Map<string, ToolDefinition>;
390
494
  /**
391
- * Clear a specific resource from the cache.
495
+ * Get all resource definitions.
392
496
  */
393
- clearResourceCacheEntry(uri: string): boolean;
497
+ getResourceDefinitions(): Map<string, ResourceDefinition>;
394
498
  /**
395
- * Get resource cache statistics.
499
+ * Create a Vercel MCP adapter configuration.
500
+ * For use with Vercel's `mcp-handler` package.
501
+ *
502
+ * Note: This returns a configuration callback. The implementation
503
+ * is inline to avoid circular dependencies.
396
504
  */
397
- getResourceCacheStats(): {
398
- size: number;
399
- maxSize: number;
400
- enabled: boolean;
401
- };
505
+ toVercelMcp(options?: VercelMcpOptions): (server: any, _context: any) => void;
506
+ /**
507
+ * Create an AWS Lambda handler.
508
+ *
509
+ * Note: This returns a Lambda handler function. The implementation
510
+ * is inline to avoid circular dependencies.
511
+ */
512
+ toAwsLambda(options?: AwsLambdaOptions): (event: any, _lambdaContext: any) => Promise<{
513
+ statusCode: number;
514
+ headers: {
515
+ "Access-Control-Allow-Origin": string;
516
+ "Access-Control-Allow-Methods": string;
517
+ "Access-Control-Allow-Headers": string;
518
+ "Content-Type": string;
519
+ };
520
+ body: string;
521
+ }>;
522
+ /**
523
+ * Close a specific transport session.
524
+ */
525
+ closeTransportSession(sessionId: string): boolean;
402
526
  private getPort;
403
527
  private getCallerDir;
528
+ /**
529
+ * Create a ToolContext for serverless environments.
530
+ * Shared between Vercel and Lambda adapters to avoid duplication.
531
+ */
532
+ /**
533
+ * In-memory state for serverless when no external adapter provided.
534
+ * Only useful for local development - won't persist across invocations in production.
535
+ */
536
+ private serverlessMemoryState;
537
+ private serverlessStateWarningLogged;
538
+ private serverlessRealtimeWarningLogged;
539
+ private createServerlessContext;
540
+ /**
541
+ * Format tool result for serverless response.
542
+ * Shared between Vercel and Lambda adapters.
543
+ */
544
+ private formatServerlessResult;
545
+ /**
546
+ * Create a Vercel MCP configuration callback.
547
+ * Returns a function compatible with Vercel's mcp-handler createMcpHandler.
548
+ */
549
+ private createServerlessConfig;
550
+ /**
551
+ * Create an AWS Lambda handler function.
552
+ */
553
+ private createLambdaHandler;
404
554
  private getHmrPort;
405
555
  private generateInstanceId;
406
556
  /**
@@ -421,8 +571,6 @@ declare class App {
421
571
  * Check if a field is required in a Zod schema.
422
572
  */
423
573
  private isFieldRequired;
424
- private getCachedResource;
425
- private setCachedResource;
426
574
  private createExpressApp;
427
575
  private handleMcpPost;
428
576
  private handleMcpGet;
@@ -520,4 +668,120 @@ declare function htmlLoader(filePath: string, basePath?: string): () => string;
520
668
  */
521
669
  declare function wrapServer<T extends McpServer>(server: T): T;
522
670
 
523
- export { App, type AppConfig, type DisplayMode, type IconConfig, type InstanceDestroyContext, MIME_TYPES, type ResourceCacheConfig, type ResourceConfig, type ToolConfig, type ToolContext, type ToolHandler, type ToolResult, type ToolVisibility, type TransportSessionInfo, type TransportType, type WebSocketConnection, createApp, htmlLoader, loadHtml, svgToDataUri, wrapServer };
671
+ /**
672
+ * User identity from a verified Creature token.
673
+ */
674
+ interface CreatureUser {
675
+ /** Unique, stable user identifier */
676
+ id: string;
677
+ /** User's email address */
678
+ email: string;
679
+ /** User's display name (may be undefined) */
680
+ name?: string;
681
+ }
682
+ /**
683
+ * Organization context from a verified Creature token.
684
+ */
685
+ interface CreatureOrganization {
686
+ /** Unique organization identifier */
687
+ id: string;
688
+ /** Organization display name */
689
+ name: string;
690
+ /** URL-safe organization slug */
691
+ slug: string;
692
+ }
693
+ /**
694
+ * Project context from a verified Creature token.
695
+ */
696
+ interface CreatureProject {
697
+ /** Unique project identifier */
698
+ id: string;
699
+ /** Project display name */
700
+ name: string;
701
+ }
702
+ /**
703
+ * Session context from a verified Creature token.
704
+ */
705
+ interface CreatureSession {
706
+ /** Unique session identifier */
707
+ id: string;
708
+ }
709
+ /**
710
+ * Verified identity claims from a Creature App Token.
711
+ * Returned by verifyCreatureToken() on successful verification.
712
+ */
713
+ interface CreatureIdentity {
714
+ /** User identity (always present for valid tokens) */
715
+ user: CreatureUser;
716
+ /** Organization context (present if user was in an org context) */
717
+ organization?: CreatureOrganization;
718
+ /** Project context (present if user was in a project context) */
719
+ project?: CreatureProject;
720
+ /** Session context */
721
+ session?: CreatureSession;
722
+ /** Token expiration time (ISO 8601 string) */
723
+ expiresAt: string;
724
+ }
725
+ /**
726
+ * Error thrown when token verification fails.
727
+ */
728
+ declare class CreatureTokenError extends Error {
729
+ /** Error code from the verification API */
730
+ code: string;
731
+ constructor({ code, message }: {
732
+ code: string;
733
+ message: string;
734
+ });
735
+ }
736
+ /**
737
+ * Configuration for the Creature token verification API.
738
+ */
739
+ interface VerifyConfig {
740
+ /**
741
+ * Base URL for the Creature API.
742
+ * Defaults to https://api.creature.run
743
+ * Can be overridden for testing or custom deployments.
744
+ */
745
+ apiUrl?: string;
746
+ }
747
+ /**
748
+ * Verifies a Creature App Token and returns the identity claims.
749
+ *
750
+ * Use this in your backend API to authenticate requests from your MCP App UI.
751
+ * The token is provided to your UI via `hostContext.creature.token` when you
752
+ * opt into Creature-managed auth.
753
+ *
754
+ * @param tokenOrHeader - The App Token (raw) or Authorization header ("Bearer <token>")
755
+ * @param config - Optional configuration (e.g., custom API URL)
756
+ * @returns The verified identity claims
757
+ * @throws {CreatureTokenError} If verification fails (invalid, expired, or malformed token)
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * import { verifyCreatureToken } from "@creature-ai/sdk/server";
762
+ *
763
+ * // In your Express/Hono/etc. API handler:
764
+ * app.post("/api/notes", async (req, res) => {
765
+ * try {
766
+ * const identity = await verifyCreatureToken(req.headers.authorization);
767
+ *
768
+ * // Use identity to scope data access
769
+ * const notes = await db.notes.find({
770
+ * user_id: identity.user.id,
771
+ * org_id: identity.organization?.id,
772
+ * });
773
+ *
774
+ * res.json({ notes });
775
+ * } catch (err) {
776
+ * if (err instanceof CreatureTokenError) {
777
+ * res.status(401).json({ error: err.code, message: err.message });
778
+ * } else {
779
+ * res.status(500).json({ error: "internal_error" });
780
+ * }
781
+ * }
782
+ * });
783
+ * ```
784
+ */
785
+ declare const verifyCreatureToken: (tokenOrHeader: string | undefined | null, config?: VerifyConfig) => Promise<CreatureIdentity>;
786
+
787
+ export { type AdapterOptions, App, type AppConfig, type AwsLambdaOptions, type CreatureIdentity, type CreatureOrganization, type CreatureProject, type CreatureSession, CreatureTokenError, type CreatureUser, type DisplayMode, type IconConfig, type InstanceDestroyContext, MIME_TYPES, type RealtimeAdapter, type ResourceConfig, type StateAdapter, type ToolConfig, type ToolContext, type ToolHandler, type ToolResult, type ToolVisibility, type TransportSessionInfo, type TransportType, type VercelMcpOptions, type WebSocketConnection, createApp, htmlLoader, loadHtml, svgToDataUri, verifyCreatureToken, wrapServer };